mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-14 17:23:25 +01:00
Unstable Features groundwork
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
19B9B7452845E6DF0076EF69 /* SelectTeamViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B9B7442845E6DF0076EF69 /* SelectTeamViewController.swift */; };
|
19B9B7452845E6DF0076EF69 /* SelectTeamViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B9B7442845E6DF0076EF69 /* SelectTeamViewController.swift */; };
|
||||||
4879A95F2861046500FC1BBD /* AltSign in Frameworks */ = {isa = PBXBuildFile; productRef = 4879A95E2861046500FC1BBD /* AltSign */; };
|
4879A95F2861046500FC1BBD /* AltSign in Frameworks */ = {isa = PBXBuildFile; productRef = 4879A95E2861046500FC1BBD /* AltSign */; };
|
||||||
4879A9622861049C00FC1BBD /* OpenSSL in Frameworks */ = {isa = PBXBuildFile; productRef = 4879A9612861049C00FC1BBD /* OpenSSL */; };
|
4879A9622861049C00FC1BBD /* OpenSSL in Frameworks */ = {isa = PBXBuildFile; productRef = 4879A9612861049C00FC1BBD /* OpenSSL */; };
|
||||||
|
990D2AE22A1910CD0055D93C /* UnstableFeatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 990D2AE12A1910CD0055D93C /* UnstableFeatures.swift */; };
|
||||||
9922FFEC29B501C50020F868 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = 9922FFEB29B501C50020F868 /* Starscream */; };
|
9922FFEC29B501C50020F868 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = 9922FFEB29B501C50020F868 /* Starscream */; };
|
||||||
99C4EF4D2979132100CB538D /* SemanticVersion in Frameworks */ = {isa = PBXBuildFile; productRef = 99C4EF4C2979132100CB538D /* SemanticVersion */; };
|
99C4EF4D2979132100CB538D /* SemanticVersion in Frameworks */ = {isa = PBXBuildFile; productRef = 99C4EF4C2979132100CB538D /* SemanticVersion */; };
|
||||||
99F87D0529D8B4E200B40039 /* minimuxer-helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9961EC2D29BE9F2E00AF2C6F /* minimuxer-helpers.swift */; };
|
99F87D0529D8B4E200B40039 /* minimuxer-helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9961EC2D29BE9F2E00AF2C6F /* minimuxer-helpers.swift */; };
|
||||||
@@ -511,6 +512,7 @@
|
|||||||
191E5FD1290A651D001A3B7C /* jsmn.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jsmn.h; path = Dependencies/libplist/src/jsmn.h; sourceTree = SOURCE_ROOT; };
|
191E5FD1290A651D001A3B7C /* jsmn.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jsmn.h; path = Dependencies/libplist/src/jsmn.h; sourceTree = SOURCE_ROOT; };
|
||||||
1920B04E2924AC8300744F60 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
|
1920B04E2924AC8300744F60 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
|
||||||
19B9B7442845E6DF0076EF69 /* SelectTeamViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectTeamViewController.swift; sourceTree = "<group>"; };
|
19B9B7442845E6DF0076EF69 /* SelectTeamViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectTeamViewController.swift; sourceTree = "<group>"; };
|
||||||
|
990D2AE12A1910CD0055D93C /* UnstableFeatures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnstableFeatures.swift; sourceTree = "<group>"; };
|
||||||
9961EC2D29BE9F2E00AF2C6F /* minimuxer-helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "minimuxer-helpers.swift"; path = "Dependencies/minimuxer/minimuxer-helpers.swift"; sourceTree = SOURCE_ROOT; };
|
9961EC2D29BE9F2E00AF2C6F /* minimuxer-helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "minimuxer-helpers.swift"; path = "Dependencies/minimuxer/minimuxer-helpers.swift"; sourceTree = SOURCE_ROOT; };
|
||||||
99F87D1629D8E4C900B40039 /* SwiftBridgeCore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftBridgeCore.swift; path = Dependencies/minimuxer/SwiftBridgeCore.swift; sourceTree = SOURCE_ROOT; };
|
99F87D1629D8E4C900B40039 /* SwiftBridgeCore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftBridgeCore.swift; path = Dependencies/minimuxer/SwiftBridgeCore.swift; sourceTree = SOURCE_ROOT; };
|
||||||
99F87D1729D8E4C900B40039 /* minimuxer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = minimuxer.swift; path = Dependencies/minimuxer/minimuxer.swift; sourceTree = SOURCE_ROOT; };
|
99F87D1729D8E4C900B40039 /* minimuxer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = minimuxer.swift; path = Dependencies/minimuxer/minimuxer.swift; sourceTree = SOURCE_ROOT; };
|
||||||
@@ -971,6 +973,14 @@
|
|||||||
path = "libimobiledevice-glue/src";
|
path = "libimobiledevice-glue/src";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
990D2AE02A1910920055D93C /* Unstable Features */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
990D2AE12A1910CD0055D93C /* UnstableFeatures.swift */,
|
||||||
|
);
|
||||||
|
path = "Unstable Features";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
99F87D1429D8E3F100B40039 /* Generated */ = {
|
99F87D1429D8E3F100B40039 /* Generated */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -1545,6 +1555,7 @@
|
|||||||
BFD2476C2284B9A500981D42 /* AltStore */ = {
|
BFD2476C2284B9A500981D42 /* AltStore */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
990D2AE02A1910920055D93C /* Unstable Features */,
|
||||||
B39F16112918D7B5002E9404 /* Consts */,
|
B39F16112918D7B5002E9404 /* Consts */,
|
||||||
BF219A7E22CAC431007676A6 /* AltStore.entitlements */,
|
BF219A7E22CAC431007676A6 /* AltStore.entitlements */,
|
||||||
BFD2476D2284B9A500981D42 /* AppDelegate.swift */,
|
BFD2476D2284B9A500981D42 /* AppDelegate.swift */,
|
||||||
@@ -2462,6 +2473,7 @@
|
|||||||
D57F2C9426E01BC700B9FA39 /* UIDevice+Vibration.swift in Sources */,
|
D57F2C9426E01BC700B9FA39 /* UIDevice+Vibration.swift in Sources */,
|
||||||
BFD2478F2284C8F900981D42 /* Button.swift in Sources */,
|
BFD2478F2284C8F900981D42 /* Button.swift in Sources */,
|
||||||
BF56D2AC23DF8E170006506D /* FetchAppIDsOperation.swift in Sources */,
|
BF56D2AC23DF8E170006506D /* FetchAppIDsOperation.swift in Sources */,
|
||||||
|
990D2AE22A1910CD0055D93C /* UnstableFeatures.swift in Sources */,
|
||||||
BFC1F38D22AEE3A4003AC21A /* DownloadAppOperation.swift in Sources */,
|
BFC1F38D22AEE3A4003AC21A /* DownloadAppOperation.swift in Sources */,
|
||||||
BFE6073A231ADF82002B0E8E /* SettingsViewController.swift in Sources */,
|
BFE6073A231ADF82002B0E8E /* SettingsViewController.swift in Sources */,
|
||||||
D57F2C9126E0070200B9FA39 /* EnableJITOperation.swift in Sources */,
|
D57F2C9126E0070200B9FA39 /* EnableJITOperation.swift in Sources */,
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
// Register default settings before doing anything else.
|
// Register default settings before doing anything else.
|
||||||
UserDefaults.registerDefaults()
|
UserDefaults.registerDefaults()
|
||||||
|
|
||||||
|
UnstableFeatures.load()
|
||||||
|
|
||||||
DatabaseManager.shared.start { (error) in
|
DatabaseManager.shared.start { (error) in
|
||||||
if let error = error
|
if let error = error
|
||||||
{
|
{
|
||||||
|
|||||||
95
AltStore/Unstable Features/UnstableFeatures.swift
Normal file
95
AltStore/Unstable Features/UnstableFeatures.swift
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
//
|
||||||
|
// UnstableFeatures.swift
|
||||||
|
// SideStore
|
||||||
|
//
|
||||||
|
// Created by naturecodevoid on 5/20/23.
|
||||||
|
// Copyright © 2023 SideStore. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
// I prefixed it with Available to make UnstableFeatures come up first in autocomplete, feel free to rename it if you know a better name
|
||||||
|
enum AvailableUnstableFeature: String, CaseIterable {
|
||||||
|
// The value will be the GitHub Issue number. For example, "123" would correspond to https://github.com/SideStore/SideStore/issues/123
|
||||||
|
//
|
||||||
|
// Unstable features must have a GitHub Issue for tracking progress, PRs and feedback/commenting.
|
||||||
|
|
||||||
|
/// Dummy variant to ensure there is always at least one variant. DO NOT USE!
|
||||||
|
case dummy = "dummy"
|
||||||
|
|
||||||
|
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:
|
||||||
|
//case .yourFeature: return true
|
||||||
|
|
||||||
|
default: return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnstableFeatures {
|
||||||
|
#if UNSTABLE
|
||||||
|
private static var features: [AvailableUnstableFeature: Bool] = [:]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static func load() {
|
||||||
|
#if UNSTABLE
|
||||||
|
|
||||||
|
if features.count > 0 { return print("It seems unstable features have already been loaded, skipping") }
|
||||||
|
|
||||||
|
if let rawFeatures = UserDefaults.shared.unstableFeatures,
|
||||||
|
var 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 }) {
|
||||||
|
features[feature] = rawFeature.value
|
||||||
|
} else {
|
||||||
|
print("Unknown unstable feature: \(rawFeature.key) = \(rawFeature.value)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
features[feature] = false
|
||||||
|
}
|
||||||
|
save()
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
print("Unstable features are not available on this build")
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func save(load: Bool = false) {
|
||||||
|
#if UNSTABLE
|
||||||
|
|
||||||
|
var rawFeatures: [String: Bool] = [:]
|
||||||
|
for feature in features {
|
||||||
|
rawFeatures[String(describing: feature.key)] = feature.value
|
||||||
|
}
|
||||||
|
UserDefaults.shared.unstableFeatures = try! JSONEncoder().encode(rawFeatures)
|
||||||
|
print("\(load ? "Loaded" : "Saved") unstable features: \(String(describing: rawFeatures))")
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static func set(_ feature: AvailableUnstableFeature, enabled: Bool) {
|
||||||
|
#if UNSTABLE
|
||||||
|
|
||||||
|
features[feature] = enabled
|
||||||
|
save()
|
||||||
|
|
||||||
|
#else
|
||||||
|
// we want this to crash, this function should never be triggered on non-unstable builds
|
||||||
|
fatalError("Tried to set unstable feature \(String(describing: feature)) to \(enabled) on non-unstable build!")
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@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
|
||||||
|
features[feature] ?? false
|
||||||
|
#else
|
||||||
|
false
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,6 +44,8 @@ public extension UserDefaults
|
|||||||
@NSManaged var trustedSourceIDs: [String]?
|
@NSManaged var trustedSourceIDs: [String]?
|
||||||
@NSManaged var trustedServerURL: String?
|
@NSManaged var trustedServerURL: String?
|
||||||
|
|
||||||
|
@NSManaged var unstableFeatures: Data?
|
||||||
|
|
||||||
var activeAppsLimit: Int? {
|
var activeAppsLimit: Int? {
|
||||||
get {
|
get {
|
||||||
return self._activeAppsLimit?.intValue
|
return self._activeAppsLimit?.intValue
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
MARKETING_VERSION = 0.3.2
|
MARKETING_VERSION = 0.3.2
|
||||||
CURRENT_PROJECT_VERSION = 3050
|
CURRENT_PROJECT_VERSION = 3050
|
||||||
|
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS[config=Debug] = $(inherited) UNSTABLE
|
||||||
|
|
||||||
// Vars to be overwritten by `CodeSigning.xcconfig` if exists
|
// Vars to be overwritten by `CodeSigning.xcconfig` if exists
|
||||||
DEVELOPMENT_TEAM = S32Z3HMYVQ
|
DEVELOPMENT_TEAM = S32Z3HMYVQ
|
||||||
ORG_IDENTIFIER = com.SideStore
|
ORG_IDENTIFIER = com.SideStore
|
||||||
|
|||||||
Reference in New Issue
Block a user