mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
191 lines
6.7 KiB
Swift
191 lines
6.7 KiB
Swift
//
|
|
// DevModeView.swift
|
|
// SideStore
|
|
//
|
|
// Created by naturecodevoid on 2/16/23.
|
|
// Copyright © 2023 SideStore. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
import LocalConsole
|
|
|
|
// Yes, we know the password is right here. It's also in CONTRIBUTING.md. It's not supposed to be a secret, just something to hopefully prevent people breaking SideStore with dev mode and then complaining to us.
|
|
let DEV_MODE_PASSWORD = "devmode"
|
|
|
|
struct DevModePrompt: View {
|
|
@Binding var isShowingDevModePrompt: Bool
|
|
@Binding var isShowingDevModeMenu: Bool
|
|
|
|
@State var countdown = 0
|
|
@State var isShowingPasswordAlert = false
|
|
@State var isShowingIncorrectPasswordAlert = false
|
|
@State var password = ""
|
|
|
|
var button: some View {
|
|
SwiftUI.Button(action: {
|
|
if #available(iOS 15.0, *) {
|
|
isShowingPasswordAlert = true
|
|
} else {
|
|
// iOS 14 doesn't support .alert, so just go straight to dev mode without asking for a password
|
|
enableDevMode()
|
|
}
|
|
}) {
|
|
Text(countdown <= 0 ? L10n.Action.enable + " " + L10n.DevModeView.title : L10n.DevModeView.read + " (\(countdown))")
|
|
.foregroundColor(.red)
|
|
}
|
|
.disabled(countdown > 0)
|
|
}
|
|
|
|
var text: some View {
|
|
if #available(iOS 15.0, *) {
|
|
do {
|
|
return Text(try AttributedString(markdown: L10n.DevModeView.prompt, options: AttributedString.MarkdownParsingOptions(interpretedSyntax: .inlineOnlyPreservingWhitespace)))
|
|
} catch {
|
|
return Text(L10n.DevModeView.prompt)
|
|
}
|
|
} else {
|
|
return Text(L10n.DevModeView.prompt)
|
|
}
|
|
}
|
|
|
|
var view: some View {
|
|
ScrollView {
|
|
VStack {
|
|
text
|
|
.foregroundColor(.primary)
|
|
.padding(.bottom)
|
|
|
|
if #available(iOS 15.0, *) {
|
|
button.buttonStyle(.bordered)
|
|
} else {
|
|
button
|
|
}
|
|
}
|
|
.padding(.horizontal)
|
|
}
|
|
.frame(maxWidth: .infinity)
|
|
.navigationTitle(L10n.DevModeView.title)
|
|
.toolbar {
|
|
ToolbarItem(placement: .navigationBarTrailing) {
|
|
SwiftUI.Button(action: { isShowingDevModePrompt = false }) {
|
|
Text(L10n.Action.close)
|
|
}
|
|
}
|
|
}
|
|
.onAppear {
|
|
countdown = 20
|
|
tickCountdown()
|
|
}
|
|
}
|
|
|
|
var body: some View {
|
|
NavigationView {
|
|
if #available(iOS 15.0, *) {
|
|
view
|
|
.alert(L10n.DevModeView.password, isPresented: $isShowingPasswordAlert) {
|
|
TextField("Password", text: $password)
|
|
.autocapitalization(.none)
|
|
.autocorrectionDisabled(true)
|
|
SwiftUI.Button("Submit", action: {
|
|
if password == DEV_MODE_PASSWORD {
|
|
enableDevMode()
|
|
} else {
|
|
isShowingIncorrectPasswordAlert = true
|
|
}
|
|
})
|
|
}
|
|
.alert(L10n.DevModeView.incorrectPassword, isPresented: $isShowingIncorrectPasswordAlert) {
|
|
SwiftUI.Button("Try again", action: {
|
|
isShowingIncorrectPasswordAlert = false
|
|
isShowingPasswordAlert = true
|
|
})
|
|
SwiftUI.Button("Cancel", action: {
|
|
isShowingIncorrectPasswordAlert = false
|
|
isShowingDevModePrompt = false
|
|
})
|
|
}
|
|
} else {
|
|
view
|
|
}
|
|
}
|
|
}
|
|
|
|
func enableDevMode() {
|
|
UserDefaults.standard.isDevModeEnabled = true
|
|
isShowingDevModePrompt = false
|
|
isShowingDevModeMenu = true
|
|
}
|
|
|
|
func tickCountdown() {
|
|
if countdown <= 0 { return }
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
|
countdown -= 1
|
|
tickCountdown()
|
|
}
|
|
}
|
|
}
|
|
|
|
struct DevModeMenu: View {
|
|
@ObservedObject private var iO = Inject.observer
|
|
|
|
@AppStorage("isConsoleEnabled")
|
|
var isConsoleEnabled: Bool = false
|
|
|
|
var body: some View {
|
|
List {
|
|
Section {
|
|
Toggle(L10n.DevModeView.console, isOn: self.$isConsoleEnabled)
|
|
.onChange(of: self.isConsoleEnabled) { value in
|
|
LCManager.shared.isVisible = value
|
|
}
|
|
|
|
NavigationLink(L10n.DevModeView.dataExplorer) {
|
|
FileExplorer(url: FileManager.default.altstoreSharedDirectory)
|
|
.navigationTitle(L10n.DevModeView.dataExplorer)
|
|
}.foregroundColor(.red)
|
|
|
|
NavigationLink(L10n.DevModeView.tmpExplorer) {
|
|
FileExplorer(url: FileManager.default.temporaryDirectory)
|
|
.navigationTitle(L10n.DevModeView.tmpExplorer)
|
|
}.foregroundColor(.red)
|
|
|
|
Toggle(L10n.DevModeView.skipResign, isOn: ResignAppOperation.skipResignBinding)
|
|
.foregroundColor(.red)
|
|
} footer: {
|
|
Text(L10n.DevModeView.skipResignInfo)
|
|
}
|
|
|
|
Section {
|
|
NavigationLink(L10n.DevModeView.Minimuxer.stagingExplorer + " (Coming soon, needs minimuxer additions)") {
|
|
FileExplorer(url: FileManager.default.altstoreSharedDirectory)
|
|
.navigationTitle(L10n.DevModeView.Minimuxer.stagingExplorer)
|
|
}.foregroundColor(.red).disabled(true)
|
|
|
|
NavigationLink(L10n.DevModeView.Minimuxer.viewProfiles + " (Coming soon, needs minimuxer additions)") {
|
|
|
|
}.disabled(true)
|
|
|
|
SwiftUI.Button(L10n.DevModeView.Minimuxer.dumpProfiles + " (Coming soon, needs minimuxer additions)", action: {
|
|
// TODO: dump profiles to Documents/ProfileDump/[current time]
|
|
}).disabled(true)
|
|
} header: {
|
|
Text(L10n.DevModeView.minimuxer)
|
|
}
|
|
}
|
|
.navigationTitle(L10n.DevModeView.title)
|
|
.enableInjection()
|
|
}
|
|
}
|
|
|
|
struct DevModeView_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
NavigationView {
|
|
List {
|
|
NavigationLink("DevModeMenu") {
|
|
DevModeMenu()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|