mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
More improvements to unstable features and advanced settings
- added description of what they are and notice if there are none available - move them to advanced settings - add alert for unstable features in dev mode if the build does not have them enabled - move stuff out of the danger zone and into anisette section in advanced settings
This commit is contained in:
@@ -198,17 +198,25 @@ You should only enable Developer Mode if you meet one of the following requireme
|
||||
- It is currently limited to a maximum depth of 3 to ensure it doesn't take too long to iterate over everything when you open it
|
||||
- Very buggy
|
||||
- There are multiple unimplemented actions";
|
||||
"DevModeView.unstableFeaturesNightlyOnly" = "Unstable Features are only available on nightly builds or debug builds";
|
||||
|
||||
/* AsyncFallibleButton */
|
||||
"AsyncFallibleButton.error" = "An error occurred";
|
||||
|
||||
/* AdvancedSettingsView */
|
||||
"AdvancedSettingsView.title" = "Advanced Settings";
|
||||
"AdvancedSettingsView.anisette" = "Anisette Server";
|
||||
"AdvancedSettingsView.anisetteSettings" = "Anisette";
|
||||
"AdvancedSettingsView.AnisetteSettings.server" = "Anisette Server";
|
||||
"AdvancedSettingsView.AnisetteSettings.usePreferred" = "Use preferred servers";
|
||||
"AdvancedSettingsView.AnisetteSettings.anisetteURL" = "Anisette URL";
|
||||
"AdvancedSettingsView.AnisetteSettings.footer" = "If you disable \"Use preferred servers\" then SideStore will use the server you input into the \"Anisette URL\" box rather than one selected in \"Anisette Server\".";
|
||||
"AdvancedSettingsView.dangerZone" = "Danger Zone";
|
||||
"AdvancedSettingsView.dangerZoneInfo" = "If you disable \"Use preferred servers\" then SideStore will use the server you input into the \"Anisette URL\" box rather than one selected in \"Anisette Server\".";
|
||||
"AdvancedSettingsView.DangerZone.usePreferred" = "Use preferred servers";
|
||||
"AdvancedSettingsView.DangerZone.anisetteURL" = "Anisette URL";
|
||||
|
||||
/* UnstableFeaturesView */
|
||||
"UnstableFeaturesView.title" = "Unstable Features";
|
||||
"UnstableFeaturesView.description" = "Unstable Features are features that are currently being tested or still a work-in-progress and not ready for public usage. Because of this, they are only available on nightly builds. By default, all unstable features are off. Additionally, only more stable unstable features are available in Advanced Settings; most are locked behind Developer Mode to ensure normal users don't use them.
|
||||
|
||||
Every unstable feature has a tracking issue, which contains info on what the unstable feature adds and tracks the unstable feature status. To view a tracking issue for an unstable feature, simply click it in the list. **Please use the tracking issue for reporting bugs or giving feedback.**
|
||||
|
||||
**Do not ask for support on using unstable features, you will not receive any help.**";
|
||||
"UnstableFeaturesView.noUnstableFeatures" = "There are currently no unstable features available.";
|
||||
|
||||
@@ -37,19 +37,21 @@ internal enum L10n {
|
||||
internal static let title = L10n.tr("Localizable", "AddSourceView.title", fallback: "Add Source")
|
||||
}
|
||||
internal enum AdvancedSettingsView {
|
||||
/// Anisette Server
|
||||
internal static let anisette = L10n.tr("Localizable", "AdvancedSettingsView.anisette", fallback: "Anisette Server")
|
||||
/// Anisette
|
||||
internal static let anisetteSettings = L10n.tr("Localizable", "AdvancedSettingsView.anisetteSettings", fallback: "Anisette")
|
||||
/// Danger Zone
|
||||
internal static let dangerZone = L10n.tr("Localizable", "AdvancedSettingsView.dangerZone", fallback: "Danger Zone")
|
||||
/// If you disable "Use preferred servers" then SideStore will use the server you input into the "Anisette URL" box rather than one selected in "Anisette Server".
|
||||
internal static let dangerZoneInfo = L10n.tr("Localizable", "AdvancedSettingsView.dangerZoneInfo", fallback: "If you disable \"Use preferred servers\" then SideStore will use the server you input into the \"Anisette URL\" box rather than one selected in \"Anisette Server\".")
|
||||
/// AdvancedSettingsView
|
||||
internal static let title = L10n.tr("Localizable", "AdvancedSettingsView.title", fallback: "Advanced Settings")
|
||||
internal enum DangerZone {
|
||||
internal enum AnisetteSettings {
|
||||
/// Anisette URL
|
||||
internal static let anisetteURL = L10n.tr("Localizable", "AdvancedSettingsView.DangerZone.anisetteURL", fallback: "Anisette URL")
|
||||
internal static let anisetteURL = L10n.tr("Localizable", "AdvancedSettingsView.AnisetteSettings.anisetteURL", fallback: "Anisette URL")
|
||||
/// If you disable "Use preferred servers" then SideStore will use the server you input into the "Anisette URL" box rather than one selected in "Anisette Server".
|
||||
internal static let footer = L10n.tr("Localizable", "AdvancedSettingsView.AnisetteSettings.footer", fallback: "If you disable \"Use preferred servers\" then SideStore will use the server you input into the \"Anisette URL\" box rather than one selected in \"Anisette Server\".")
|
||||
/// Anisette Server
|
||||
internal static let server = L10n.tr("Localizable", "AdvancedSettingsView.AnisetteSettings.server", fallback: "Anisette Server")
|
||||
/// Use preferred servers
|
||||
internal static let usePreferred = L10n.tr("Localizable", "AdvancedSettingsView.DangerZone.usePreferred", fallback: "Use preferred servers")
|
||||
internal static let usePreferred = L10n.tr("Localizable", "AdvancedSettingsView.AnisetteSettings.usePreferred", fallback: "Use preferred servers")
|
||||
}
|
||||
}
|
||||
internal enum AppAction {
|
||||
@@ -281,6 +283,8 @@ internal enum L10n {
|
||||
internal static let title = L10n.tr("Localizable", "DevModeView.title", fallback: "Developer Mode")
|
||||
/// Temporary File Explorer
|
||||
internal static let tmpExplorer = L10n.tr("Localizable", "DevModeView.tmpExplorer", fallback: "Temporary File Explorer")
|
||||
/// Unstable Features are only available on nightly builds or debug builds
|
||||
internal static let unstableFeaturesNightlyOnly = L10n.tr("Localizable", "DevModeView.unstableFeaturesNightlyOnly", fallback: "Unstable Features are only available on nightly builds or debug builds")
|
||||
internal enum Minimuxer {
|
||||
/// AFC File Explorer (check footer for notes)
|
||||
internal static let afcExplorer = L10n.tr("Localizable", "DevModeView.Minimuxer.afcExplorer", fallback: "AFC File Explorer (check footer for notes)")
|
||||
@@ -406,6 +410,14 @@ internal enum L10n {
|
||||
internal static let trustedSources = L10n.tr("Localizable", "SourcesView.trustedSources", fallback: "Trusted Sources")
|
||||
}
|
||||
internal enum UnstableFeaturesView {
|
||||
/// Unstable Features are features that are currently being tested or still a work-in-progress and not ready for public usage. Because of this, they are only available on nightly builds. By default, all unstable features are off. Additionally, only more stable unstable features are available in Advanced Settings; most are locked behind Developer Mode to ensure normal users don't use them.
|
||||
///
|
||||
/// Every unstable feature has a tracking issue, which contains info on what the unstable feature adds and tracks the unstable feature status. To view a tracking issue for an unstable feature, simply click it in the list. **Please use the tracking issue for reporting bugs or giving feedback.**
|
||||
///
|
||||
/// **Do not ask for support on using unstable features, you will not receive any help.**
|
||||
internal static let description = L10n.tr("Localizable", "UnstableFeaturesView.description", fallback: "Unstable Features are features that are currently being tested or still a work-in-progress and not ready for public usage. Because of this, they are only available on nightly builds. By default, all unstable features are off. Additionally, only more stable unstable features are available in Advanced Settings; most are locked behind Developer Mode to ensure normal users don't use them.\n\nEvery unstable feature has a tracking issue, which contains info on what the unstable feature adds and tracks the unstable feature status. To view a tracking issue for an unstable feature, simply click it in the list. **Please use the tracking issue for reporting bugs or giving feedback.**\n\n**Do not ask for support on using unstable features, you will not receive any help.**")
|
||||
/// There are currently no unstable features available.
|
||||
internal static let noUnstableFeatures = L10n.tr("Localizable", "UnstableFeaturesView.noUnstableFeatures", fallback: "There are currently no unstable features available.")
|
||||
/// UnstableFeaturesView
|
||||
internal static let title = L10n.tr("Localizable", "UnstableFeaturesView.title", fallback: "Unstable Features")
|
||||
}
|
||||
|
||||
@@ -40,27 +40,38 @@ struct AdvancedSettingsView: View {
|
||||
var body: some View {
|
||||
List {
|
||||
Section {
|
||||
Picker(L10n.AdvancedSettingsView.anisette, selection: $selectedAnisetteServer) {
|
||||
Picker(L10n.AdvancedSettingsView.AnisetteSettings.server, selection: $selectedAnisetteServer) {
|
||||
ForEach(anisetteServers) { server in
|
||||
Text(server.display)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Section {
|
||||
Toggle(L10n.AdvancedSettingsView.DangerZone.usePreferred, isOn: $usePreferred)
|
||||
|
||||
Toggle(L10n.AdvancedSettingsView.AnisetteSettings.usePreferred, isOn: $usePreferred)
|
||||
|
||||
HStack {
|
||||
Text(L10n.AdvancedSettingsView.DangerZone.anisetteURL)
|
||||
Text(L10n.AdvancedSettingsView.AnisetteSettings.anisetteURL)
|
||||
TextField("", text: $anisetteURL)
|
||||
.autocapitalization(.none)
|
||||
.autocorrectionDisabled(true)
|
||||
}
|
||||
} header: {
|
||||
Text(L10n.AdvancedSettingsView.dangerZone)
|
||||
Text(L10n.AdvancedSettingsView.anisetteSettings)
|
||||
} footer: {
|
||||
Text(L10n.AdvancedSettingsView.dangerZoneInfo)
|
||||
Text(L10n.AdvancedSettingsView.AnisetteSettings.footer)
|
||||
}
|
||||
|
||||
#if UNSTABLE // TODO: remove this once we have more settings for the danger zone.
|
||||
Section {
|
||||
#if UNSTABLE
|
||||
NavigationLink(L10n.UnstableFeaturesView.title) {
|
||||
UnstableFeaturesView(inDevMode: false)
|
||||
}
|
||||
.foregroundColor(.red)
|
||||
#endif
|
||||
} header: {
|
||||
Text(L10n.AdvancedSettingsView.dangerZone)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
.navigationTitle(L10n.AdvancedSettingsView.title)
|
||||
.enableInjection()
|
||||
|
||||
@@ -128,6 +128,10 @@ struct DevModeMenu: View {
|
||||
@AppStorage("isConsoleEnabled")
|
||||
var isConsoleEnabled: Bool = false
|
||||
|
||||
#if !UNSTABLE
|
||||
@State var isUnstableAlertShowing = false
|
||||
#endif
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section {
|
||||
@@ -143,6 +147,10 @@ struct DevModeMenu: View {
|
||||
}
|
||||
#if !UNSTABLE
|
||||
.disabled(true)
|
||||
.alert(isPresented: $isUnstableAlertShowing) {
|
||||
Alert(title: Text(L10n.DevModeView.unstableFeaturesNightlyOnly))
|
||||
}
|
||||
.onTapGesture { isUnstableAlertShowing = true }
|
||||
#endif
|
||||
|
||||
NavigationLink(L10n.DevModeView.dataExplorer) {
|
||||
|
||||
@@ -104,6 +104,10 @@ struct SettingsView: View {
|
||||
}
|
||||
|
||||
Section {
|
||||
NavigationLink("Show Refresh Attempts") {
|
||||
RefreshAttemptsView()
|
||||
}
|
||||
|
||||
Toggle(isOn: self.$isBackgroundRefreshEnabled, label: {
|
||||
Text(L10n.SettingsView.backgroundRefresh)
|
||||
})
|
||||
@@ -113,10 +117,6 @@ struct SettingsView: View {
|
||||
SiriShortcutSetupView(shortcut: shortcut)
|
||||
}
|
||||
}
|
||||
|
||||
NavigationLink("Show Refresh Attempts") {
|
||||
RefreshAttemptsView()
|
||||
}
|
||||
} header: {
|
||||
Text(L10n.SettingsView.refreshingApps)
|
||||
} footer: {
|
||||
@@ -171,12 +171,6 @@ struct SettingsView: View {
|
||||
AdvancedSettingsView()
|
||||
}
|
||||
|
||||
#if UNSTABLE
|
||||
NavigationLink(L10n.UnstableFeaturesView.title) {
|
||||
UnstableFeaturesView(inDevMode: false)
|
||||
}
|
||||
#endif
|
||||
|
||||
Toggle(L10n.SettingsView.debugLogging, isOn: self.$isDebugLoggingEnabled)
|
||||
.onChange(of: self.isDebugLoggingEnabled) { value in
|
||||
UserDefaults.shared.isDebugLoggingEnabled = value
|
||||
|
||||
@@ -10,20 +10,36 @@
|
||||
import SwiftUI
|
||||
|
||||
struct UnstableFeaturesView: View {
|
||||
@ObservedObject private var shared = UnstableFeatures.shared
|
||||
@ObservedObject private var iO = Inject.observer
|
||||
|
||||
var inDevMode: Bool
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
ForEach(shared.features.filter { feature, _ in feature != .dummy && (inDevMode || feature.availableOutsideDevMode()) }.sorted(by: { _, _ in true }), id: \.key) { feature, _ in
|
||||
Toggle(isOn: Binding(get: { UnstableFeatures.enabled(feature) }, set: { newValue in UnstableFeatures.set(feature, enabled: newValue) })) {
|
||||
Text(String(describing: feature))
|
||||
let link = "https://github.com/SideStore/SideStore/issues/\(feature.rawValue)"
|
||||
Link(link, destination: URL(string: link)!)
|
||||
let features = UnstableFeatures.getFeatures(inDevMode)
|
||||
|
||||
let description = L10n.UnstableFeaturesView.description + (features.count <= 0 ? "\n\n" + L10n.UnstableFeaturesView.noUnstableFeatures : "")
|
||||
Section {} footer: {
|
||||
if #available(iOS 15.0, *),
|
||||
let string = try? AttributedString(markdown: description, options: AttributedString.MarkdownParsingOptions(interpretedSyntax: .inlineOnlyPreservingWhitespace)) {
|
||||
Text(string).font(.callout).foregroundColor(.primary)
|
||||
} else {
|
||||
Text(description).font(.callout).foregroundColor(.primary)
|
||||
}
|
||||
}.listRowInsets(EdgeInsets(top: 8, leading: 0, bottom: 8, trailing: 0))
|
||||
|
||||
if features.count > 0 {
|
||||
ForEach(features.sorted(by: { _, _ in true }), id: \.key) { feature, _ in
|
||||
Toggle(isOn: Binding(get: { UnstableFeatures.enabled(feature) }, set: { newValue in UnstableFeatures.set(feature, enabled: newValue) })) {
|
||||
Text(String(describing: feature))
|
||||
let link = "https://github.com/SideStore/SideStore/issues/\(feature.rawValue)"
|
||||
Link(link, destination: URL(string: link)!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.navigationTitle(L10n.UnstableFeaturesView.title)
|
||||
}
|
||||
.navigationTitle(L10n.UnstableFeaturesView.title)
|
||||
.enableInjection()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ enum AvailableUnstableFeature: String, CaseIterable {
|
||||
func availableOutsideDevMode() -> Bool {
|
||||
switch self {
|
||||
// If your unstable feature is stable enough to be used by nightly users who are not alpha testers or developers,
|
||||
// you may want to have it available in the "Unstable Features" menu in Settings (outside of dev mode). To do so, add this:
|
||||
// you may want to have it available in the Unstable Features menu in Advanced Settings (outside of dev mode). To do so, add this:
|
||||
//case .yourFeature: return true
|
||||
case .jitUrlScheme: return true
|
||||
|
||||
@@ -34,31 +34,42 @@ enum AvailableUnstableFeature: String, CaseIterable {
|
||||
|
||||
class UnstableFeatures: ObservableObject {
|
||||
#if UNSTABLE
|
||||
static let shared = UnstableFeatures()
|
||||
@Published var features: [AvailableUnstableFeature: Bool] = [:]
|
||||
private static var features: [AvailableUnstableFeature: Bool] = [:]
|
||||
|
||||
static func getFeatures(_ inDevMode: Bool) -> [(key: AvailableUnstableFeature, value: Bool)] {
|
||||
return features
|
||||
.filter { feature, _ in
|
||||
feature != .dummy &&
|
||||
(inDevMode || feature.availableOutsideDevMode())
|
||||
}.sorted { a, b in a.key.rawValue > b.key.rawValue } // Convert to array of keys and values
|
||||
}
|
||||
|
||||
static func load() {
|
||||
if shared.features.count > 0 { return print("It seems unstable features have already been loaded, skipping") }
|
||||
if features.count > 0 { return print("It seems unstable features have already been loaded, skipping") }
|
||||
|
||||
if let rawFeatures = UserDefaults.shared.unstableFeatures,
|
||||
let rawFeatures = try? JSONDecoder().decode([String: Bool].self, from: rawFeatures) {
|
||||
for rawFeature in rawFeatures {
|
||||
if let feature = AvailableUnstableFeature.allCases.first(where: { feature in String(describing: feature) == rawFeature.key }) {
|
||||
shared.features[feature] = rawFeature.value
|
||||
features[feature] = rawFeature.value
|
||||
} else {
|
||||
print("Unknown unstable feature: \(rawFeature.key) = \(rawFeature.value)")
|
||||
}
|
||||
}
|
||||
|
||||
// If there's a new feature that wasn't saved and therefore wasn't loaded, let's set it to false
|
||||
// Technically we shouldn't have to do this because enabled() will fallback to false
|
||||
for feature in AvailableUnstableFeature.allCases {
|
||||
if shared.features[feature] == nil {
|
||||
shared.features[feature] = false
|
||||
if features[feature] == nil {
|
||||
features[feature] = false
|
||||
}
|
||||
}
|
||||
|
||||
save(load: true)
|
||||
} else {
|
||||
print("Setting all unstable features to false since we couldn't load them from UserDefaults (either they were never saved or there was an error decoding JSON)")
|
||||
for feature in AvailableUnstableFeature.allCases {
|
||||
shared.features[feature] = false
|
||||
features[feature] = false
|
||||
}
|
||||
save()
|
||||
}
|
||||
@@ -66,7 +77,7 @@ class UnstableFeatures: ObservableObject {
|
||||
|
||||
private static func save(load: Bool = false) {
|
||||
var rawFeatures: [String: Bool] = [:]
|
||||
for feature in shared.features {
|
||||
for feature in features {
|
||||
rawFeatures[String(describing: feature.key)] = feature.value
|
||||
}
|
||||
UserDefaults.shared.unstableFeatures = try! JSONEncoder().encode(rawFeatures)
|
||||
@@ -74,7 +85,7 @@ class UnstableFeatures: ObservableObject {
|
||||
}
|
||||
|
||||
static func set(_ feature: AvailableUnstableFeature, enabled: Bool) {
|
||||
shared.features[feature] = enabled
|
||||
features[feature] = enabled
|
||||
save()
|
||||
}
|
||||
#endif
|
||||
@@ -82,7 +93,7 @@ class UnstableFeatures: ObservableObject {
|
||||
@inline(__always) // hopefully this will help the compiler realize that if statements that use this function should be removed on non-unstable builds
|
||||
static func enabled(_ feature: AvailableUnstableFeature) -> Bool {
|
||||
#if UNSTABLE
|
||||
shared.features[feature] ?? false
|
||||
features[feature] ?? false
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user