mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
236 lines
8.3 KiB
Swift
236 lines
8.3 KiB
Swift
//
|
|
// DevModeView.swift
|
|
// SideStore
|
|
//
|
|
// Created by naturecodevoid on 2/16/23.
|
|
// Copyright © 2023 SideStore. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
import LocalConsole
|
|
import minimuxer
|
|
|
|
// Yes, we know the password is right here. 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 16.0, *) {
|
|
isShowingPasswordAlert = true
|
|
} else {
|
|
// iOS 14 doesn't support .alert, so just go straight to dev mode without asking for a password
|
|
// iOS 15 also doesn't seem to support TextField in an alert (the text field was nonexistent)
|
|
enableDevMode()
|
|
}
|
|
}) {
|
|
Text(countdown <= 0 ? L10n.Action.enable + " " + L10n.DevModeView.title : L10n.DevModeView.read + " (\(countdown))")
|
|
.foregroundColor(.red)
|
|
}
|
|
.buttonStyle(FilledButtonStyle(tintColor: Color.gray.opacity(0.5)))
|
|
.disabled(countdown > 0)
|
|
}
|
|
|
|
@ViewBuilder
|
|
var text: some View {
|
|
if #available(iOS 15.0, *),
|
|
let string = try? AttributedString(markdown: L10n.DevModeView.prompt, options: AttributedString.MarkdownParsingOptions(interpretedSyntax: .inlineOnlyPreservingWhitespace)) {
|
|
Text(string)
|
|
} else {
|
|
Text(L10n.DevModeView.prompt)
|
|
}
|
|
}
|
|
|
|
var view: some View {
|
|
ScrollView {
|
|
VStack {
|
|
text
|
|
.foregroundColor(.primary)
|
|
.padding(.bottom)
|
|
|
|
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(L10n.DevModeView.password, text: $password)
|
|
.autocapitalization(.none)
|
|
.autocorrectionDisabled(true)
|
|
SwiftUI.Button(L10n.Action.submit, action: {
|
|
if password == DEV_MODE_PASSWORD {
|
|
enableDevMode()
|
|
} else {
|
|
isShowingIncorrectPasswordAlert = true
|
|
}
|
|
})
|
|
}
|
|
.alert(L10n.DevModeView.incorrectPassword, isPresented: $isShowingIncorrectPasswordAlert) {
|
|
SwiftUI.Button(L10n.Action.tryAgain, action: {
|
|
isShowingIncorrectPasswordAlert = false
|
|
isShowingPasswordAlert = true
|
|
})
|
|
SwiftUI.Button(L10n.Action.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
|
|
|
|
@AppStorage("isDevModeEnabled")
|
|
var isDevModeEnabled: Bool = false
|
|
|
|
#if !UNSTABLE
|
|
@State var isUnstableAlertShowing = false
|
|
#endif
|
|
|
|
var body: some View {
|
|
List {
|
|
Section {
|
|
Toggle(L10n.DevModeView.General.console, isOn: self.$isConsoleEnabled)
|
|
.onChange(of: self.isConsoleEnabled) { value in
|
|
LCManager.shared.isVisible = value
|
|
}
|
|
|
|
NavigationLink(L10n.UnstableFeaturesView.title) {
|
|
#if UNSTABLE
|
|
UnstableFeaturesView(inDevMode: true)
|
|
#endif
|
|
}
|
|
#if !UNSTABLE
|
|
.disabled(true)
|
|
.alert(isPresented: $isUnstableAlertShowing) {
|
|
Alert(title: Text(L10n.DevModeView.General.unstableFeaturesNightlyOnly))
|
|
}
|
|
.onTapGesture { isUnstableAlertShowing = true }
|
|
#endif
|
|
|
|
SwiftUI.Button(action: {
|
|
isDevModeEnabled = false
|
|
}, label: { Text(L10n.DevModeView.General.disableDevMode) }).foregroundColor(.red)
|
|
} header: {
|
|
Text(L10n.DevModeView.General.header)
|
|
}
|
|
|
|
Section {
|
|
NavigationLink(L10n.DevModeView.Files.dataExplorer) {
|
|
FileExplorer.normal(url: FileManager.default.altstoreSharedDirectory)
|
|
.navigationTitle(L10n.DevModeView.Files.dataExplorer)
|
|
}.foregroundColor(.red)
|
|
|
|
NavigationLink(L10n.DevModeView.Files.tmpExplorer) {
|
|
FileExplorer.normal(url: FileManager.default.temporaryDirectory)
|
|
.navigationTitle(L10n.DevModeView.Files.tmpExplorer)
|
|
}.foregroundColor(.red)
|
|
} header: {
|
|
Text(L10n.DevModeView.Files.header)
|
|
}
|
|
|
|
Section {
|
|
AsyncFallibleButton(action: {
|
|
let dir = try dump_profiles(FileManager.default.documentsDirectory.absoluteString)
|
|
DispatchQueue.main.async {
|
|
UIApplication.shared.open(URL(string: "shareddocuments://" + dir.toString())!, options: [:], completionHandler: nil)
|
|
}
|
|
}) { execute in
|
|
Text(L10n.DevModeView.Minimuxer.dumpProfiles)
|
|
}
|
|
|
|
NavigationLink(L10n.DevModeView.Minimuxer.afcExplorer) {
|
|
FileExplorer.afc()
|
|
.navigationTitle(L10n.DevModeView.Minimuxer.afcExplorer)
|
|
}.foregroundColor(.red)
|
|
} header: {
|
|
Text(L10n.DevModeView.Minimuxer.header)
|
|
} footer: {
|
|
Text(L10n.DevModeView.Minimuxer.footer)
|
|
}
|
|
|
|
Section {
|
|
Toggle(L10n.DevModeView.Signing.skipResign, isOn: ResignAppOperation.skipResignBinding)
|
|
.foregroundColor(.red)
|
|
} header: {
|
|
Text(L10n.DevModeView.Signing.header)
|
|
} footer: {
|
|
Text(L10n.DevModeView.Signing.footer)
|
|
}
|
|
|
|
#if MDC
|
|
Section {
|
|
SwiftUI.Button(action: {
|
|
UserDefaults.shared.lastInstalldPatchBootTime = nil
|
|
UIApplication.alert(title: L10n.Action.success)
|
|
}, label: { Text(L10n.DevModeView.Mdc.fakeUndo3AppLimitPatch) }).foregroundColor(.red)
|
|
} header: {
|
|
Text(L10n.DevModeView.Mdc.header)
|
|
}
|
|
#endif
|
|
}
|
|
.navigationTitle(L10n.DevModeView.title)
|
|
.enableInjection()
|
|
}
|
|
}
|
|
|
|
struct DevModeView_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
NavigationView {
|
|
List {
|
|
NavigationLink("DevModeMenu") {
|
|
DevModeMenu()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|