mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-19 03:33:36 +01:00
Merge branch 'SideStore:develop' into develop
This commit is contained in:
@@ -37,6 +37,8 @@
|
|||||||
</array>
|
</array>
|
||||||
<key>BuildRevision</key>
|
<key>BuildRevision</key>
|
||||||
<string>$(BUILD_REVISION)</string>
|
<string>$(BUILD_REVISION)</string>
|
||||||
|
<key>BuildChannel</key>
|
||||||
|
<string>$(BUILD_CHANNEL)</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
|||||||
@@ -65,6 +65,8 @@
|
|||||||
A86315DF2D3EB2DE0048FA40 /* ErrorProcessing.swift in Sources */ = {isa = PBXBuildFile; fileRef = A86315DE2D3EB2D80048FA40 /* ErrorProcessing.swift */; };
|
A86315DF2D3EB2DE0048FA40 /* ErrorProcessing.swift in Sources */ = {isa = PBXBuildFile; fileRef = A86315DE2D3EB2D80048FA40 /* ErrorProcessing.swift */; };
|
||||||
A868CFE42D31999A002F1201 /* SingletonGenericMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868CFE32D319988002F1201 /* SingletonGenericMap.swift */; };
|
A868CFE42D31999A002F1201 /* SingletonGenericMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868CFE32D319988002F1201 /* SingletonGenericMap.swift */; };
|
||||||
A8696EE42D34512C00E96389 /* RemoveAppExtensionsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8696EE32D34512C00E96389 /* RemoveAppExtensionsOperation.swift */; };
|
A8696EE42D34512C00E96389 /* RemoveAppExtensionsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8696EE32D34512C00E96389 /* RemoveAppExtensionsOperation.swift */; };
|
||||||
|
A888EAD52D401D8F0026F7E3 /* BuildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = A888EAD42D401D8A0026F7E3 /* BuildInfo.swift */; };
|
||||||
|
A888EAD62D4020770026F7E3 /* BuildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = A888EAD42D401D8A0026F7E3 /* BuildInfo.swift */; };
|
||||||
A88B8C492D35AD3200F53F9D /* OperationsLoggingContolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A88B8C482D35AD3200F53F9D /* OperationsLoggingContolView.swift */; };
|
A88B8C492D35AD3200F53F9D /* OperationsLoggingContolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A88B8C482D35AD3200F53F9D /* OperationsLoggingContolView.swift */; };
|
||||||
A88B8C552D35F1EC00F53F9D /* OperationsLoggingControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = A88B8C542D35F1EC00F53F9D /* OperationsLoggingControl.swift */; };
|
A88B8C552D35F1EC00F53F9D /* OperationsLoggingControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = A88B8C542D35F1EC00F53F9D /* OperationsLoggingControl.swift */; };
|
||||||
A8945AA62D059B6100D86CBE /* Roxas.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8945AA52D059B6100D86CBE /* Roxas.framework */; };
|
A8945AA62D059B6100D86CBE /* Roxas.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8945AA52D059B6100D86CBE /* Roxas.framework */; };
|
||||||
@@ -649,6 +651,7 @@
|
|||||||
A86315DE2D3EB2D80048FA40 /* ErrorProcessing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorProcessing.swift; sourceTree = "<group>"; };
|
A86315DE2D3EB2D80048FA40 /* ErrorProcessing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorProcessing.swift; sourceTree = "<group>"; };
|
||||||
A868CFE32D319988002F1201 /* SingletonGenericMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingletonGenericMap.swift; sourceTree = "<group>"; };
|
A868CFE32D319988002F1201 /* SingletonGenericMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingletonGenericMap.swift; sourceTree = "<group>"; };
|
||||||
A8696EE32D34512C00E96389 /* RemoveAppExtensionsOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAppExtensionsOperation.swift; sourceTree = "<group>"; };
|
A8696EE32D34512C00E96389 /* RemoveAppExtensionsOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAppExtensionsOperation.swift; sourceTree = "<group>"; };
|
||||||
|
A888EAD42D401D8A0026F7E3 /* BuildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildInfo.swift; sourceTree = "<group>"; };
|
||||||
A88B8C482D35AD3200F53F9D /* OperationsLoggingContolView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationsLoggingContolView.swift; sourceTree = "<group>"; };
|
A88B8C482D35AD3200F53F9D /* OperationsLoggingContolView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationsLoggingContolView.swift; sourceTree = "<group>"; };
|
||||||
A88B8C542D35F1EC00F53F9D /* OperationsLoggingControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationsLoggingControl.swift; sourceTree = "<group>"; };
|
A88B8C542D35F1EC00F53F9D /* OperationsLoggingControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationsLoggingControl.swift; sourceTree = "<group>"; };
|
||||||
A8945AA52D059B6100D86CBE /* Roxas.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Roxas.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
A8945AA52D059B6100D86CBE /* Roxas.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Roxas.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
@@ -1224,6 +1227,14 @@
|
|||||||
path = errors;
|
path = errors;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
A888EAD32D401D7C0026F7E3 /* buildinfo */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
A888EAD42D401D8A0026F7E3 /* BuildInfo.swift */,
|
||||||
|
);
|
||||||
|
path = buildinfo;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
A88B8C532D35F1E800F53F9D /* operations */ = {
|
A88B8C532D35F1E800F53F9D /* operations */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -1288,6 +1299,7 @@
|
|||||||
A8C38C1C2D2068D100E83DBD /* Utils */ = {
|
A8C38C1C2D2068D100E83DBD /* Utils */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
A888EAD32D401D7C0026F7E3 /* buildinfo */,
|
||||||
A8AD35572D31BEB2003A28B4 /* datastructures */,
|
A8AD35572D31BEB2003A28B4 /* datastructures */,
|
||||||
A8A853AD2D3050CC00995795 /* pagination */,
|
A8A853AD2D3050CC00995795 /* pagination */,
|
||||||
A8087E712D2D291B002DB21B /* importexport */,
|
A8087E712D2D291B002DB21B /* importexport */,
|
||||||
@@ -2910,6 +2922,7 @@
|
|||||||
0E05025C2BEC947000879B5C /* String+SideStore.swift in Sources */,
|
0E05025C2BEC947000879B5C /* String+SideStore.swift in Sources */,
|
||||||
0EE7FDCB2BE8D12B00D1E390 /* ALTLocalizedError.swift in Sources */,
|
0EE7FDCB2BE8D12B00D1E390 /* ALTLocalizedError.swift in Sources */,
|
||||||
BF66EEA92501AEC5007EE018 /* Tier.swift in Sources */,
|
BF66EEA92501AEC5007EE018 /* Tier.swift in Sources */,
|
||||||
|
A888EAD62D4020770026F7E3 /* BuildInfo.swift in Sources */,
|
||||||
BF66EEDB2501AECA007EE018 /* StoreApp.swift in Sources */,
|
BF66EEDB2501AECA007EE018 /* StoreApp.swift in Sources */,
|
||||||
D5CE309C2B4C946300DB8151 /* AltStore15ToAltStore16.xcmappingmodel in Sources */,
|
D5CE309C2B4C946300DB8151 /* AltStore15ToAltStore16.xcmappingmodel in Sources */,
|
||||||
BF66EEDE2501AECA007EE018 /* AppID.swift in Sources */,
|
BF66EEDE2501AECA007EE018 /* AppID.swift in Sources */,
|
||||||
@@ -3054,6 +3067,7 @@
|
|||||||
BFF00D302501BD7D00746320 /* Intents.intentdefinition in Sources */,
|
BFF00D302501BD7D00746320 /* Intents.intentdefinition in Sources */,
|
||||||
D5B6F6AB2AD76541007EED5A /* PreviewAppScreenshotsViewController.swift in Sources */,
|
D5B6F6AB2AD76541007EED5A /* PreviewAppScreenshotsViewController.swift in Sources */,
|
||||||
BFD2476E2284B9A500981D42 /* AppDelegate.swift in Sources */,
|
BFD2476E2284B9A500981D42 /* AppDelegate.swift in Sources */,
|
||||||
|
A888EAD52D401D8F0026F7E3 /* BuildInfo.swift in Sources */,
|
||||||
BF41B806233423AE00C593A3 /* TabBarController.swift in Sources */,
|
BF41B806233423AE00C593A3 /* TabBarController.swift in Sources */,
|
||||||
BFE00A202503097F00EB4D0C /* INInteraction+AltStore.swift in Sources */,
|
BFE00A202503097F00EB4D0C /* INInteraction+AltStore.swift in Sources */,
|
||||||
BFDB6A0B22AAEDB7007EA6D6 /* Operation.swift in Sources */,
|
BFDB6A0B22AAEDB7007EA6D6 /* Operation.swift in Sources */,
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ extension AppIDsViewController: UICollectionViewDelegateFlowLayout
|
|||||||
|
|
||||||
// NOTE: double dequeue of cell has been discontinued
|
// NOTE: double dequeue of cell has been discontinued
|
||||||
// TODO: Using harcoded value until this is fixed
|
// TODO: Using harcoded value until this is fixed
|
||||||
return CGSize(width: collectionView.bounds.width, height: 260)
|
return CGSize(width: collectionView.bounds.width, height: 200)
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize
|
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize
|
||||||
|
|||||||
@@ -65,13 +65,23 @@ class ToastView: RSTToastView
|
|||||||
self.opensErrorLog = opensLog
|
self.opensErrorLog = opensLog
|
||||||
}
|
}
|
||||||
|
|
||||||
convenience init(error: Error)
|
enum InfoMode: String {
|
||||||
|
case fullError
|
||||||
|
case localizedDescription
|
||||||
|
}
|
||||||
|
|
||||||
|
convenience init(error: Error){
|
||||||
|
self.init(error: error, mode: .localizedDescription)
|
||||||
|
}
|
||||||
|
|
||||||
|
convenience init(error: Error, mode: InfoMode)
|
||||||
{
|
{
|
||||||
let error = error as NSError
|
let error = error as NSError
|
||||||
|
let mode = mode == .fullError ? ErrorProcessing.InfoMode.fullError : ErrorProcessing.InfoMode.localizedDescription
|
||||||
|
|
||||||
let text = error.localizedTitle ?? NSLocalizedString("Operation Failed", comment: "")
|
let text = error.localizedTitle ?? NSLocalizedString("Operation Failed", comment: "")
|
||||||
let detailText = ErrorProcessing(.fullError).getDescription(error: error)
|
let detailText = ErrorProcessing(mode).getDescription(error: error)
|
||||||
|
|
||||||
self.init(text: text, detailText: detailText)
|
self.init(text: text, detailText: detailText)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,8 @@
|
|||||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
<key>BuildRevision</key>
|
<key>BuildRevision</key>
|
||||||
<string>$(BUILD_REVISION)</string>
|
<string>$(BUILD_REVISION)</string>
|
||||||
|
<key>BuildChannel</key>
|
||||||
|
<string>$(BUILD_CHANNEL)</string>
|
||||||
<key>INIntentsSupported</key>
|
<key>INIntentsSupported</key>
|
||||||
<array>
|
<array>
|
||||||
<string>RefreshAllIntent</string>
|
<string>RefreshAllIntent</string>
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ extension LaunchViewController
|
|||||||
let errorDesc = ErrorProcessing(.fullError).getDescription(error: error as NSError)
|
let errorDesc = ErrorProcessing(.fullError).getDescription(error: error as NSError)
|
||||||
print("Failed to update sources on launch. \(errorDesc)")
|
print("Failed to update sources on launch. \(errorDesc)")
|
||||||
|
|
||||||
let toastView = ToastView(error: error)
|
let toastView = ToastView(error: error, mode: .fullError)
|
||||||
toastView.addTarget(self.destinationViewController, action: #selector(TabBarController.presentSources), for: .touchUpInside)
|
toastView.addTarget(self.destinationViewController, action: #selector(TabBarController.presentSources), for: .touchUpInside)
|
||||||
toastView.show(in: self.destinationViewController.selectedViewController ?? self.destinationViewController)
|
toastView.show(in: self.destinationViewController.selectedViewController ?? self.destinationViewController)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -593,30 +593,30 @@ extension AppManager
|
|||||||
|
|
||||||
func updatePatronsIfNeeded()
|
func updatePatronsIfNeeded()
|
||||||
{
|
{
|
||||||
guard self.operationQueue.operations.allSatisfy({ !($0 is UpdatePatronsOperation) }) else {
|
// guard self.operationQueue.operations.allSatisfy({ !($0 is UpdatePatronsOperation) }) else {
|
||||||
// There's already an UpdatePatronsOperation running.
|
// // There's already an UpdatePatronsOperation running.
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
self.updatePatronsResult = nil
|
// self.updatePatronsResult = nil
|
||||||
|
//
|
||||||
let updatePatronsOperation = UpdatePatronsOperation()
|
// let updatePatronsOperation = UpdatePatronsOperation()
|
||||||
updatePatronsOperation.resultHandler = { (result) in
|
// updatePatronsOperation.resultHandler = { (result) in
|
||||||
do
|
// do
|
||||||
{
|
// {
|
||||||
try result.get()
|
// try result.get()
|
||||||
self.updatePatronsResult = .success(())
|
// self.updatePatronsResult = .success(())
|
||||||
}
|
// }
|
||||||
catch
|
// catch
|
||||||
{
|
// {
|
||||||
print("Error updating Friend Zone Patrons:", error)
|
// print("Error updating Friend Zone Patrons:", error)
|
||||||
self.updatePatronsResult = .failure(error)
|
// self.updatePatronsResult = .failure(error)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
NotificationCenter.default.post(name: AppManager.didUpdatePatronsNotification, object: self)
|
// NotificationCenter.default.post(name: AppManager.didUpdatePatronsNotification, object: self)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
self.run([updatePatronsOperation], context: nil)
|
// self.run([updatePatronsOperation], context: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateAllSources(completion: @escaping (Result<Void, Error>) -> Void)
|
func updateAllSources(completion: @escaping (Result<Void, Error>) -> Void)
|
||||||
@@ -634,6 +634,9 @@ extension AppManager
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
let (_, context) = try result.get()
|
let (_, context) = try result.get()
|
||||||
|
// print("\n\n\n\(context.insertedObjects)\n\n\n")
|
||||||
|
// print("\n\n\n\(context.updatedObjects)\n\n\n")
|
||||||
|
// print("\n\n\n\(context.deletedObjects)\n\n\n")
|
||||||
try context.save()
|
try context.save()
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
@@ -1228,13 +1231,17 @@ private extension AppManager
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DispatchQueue.main.schedule {
|
// Disable the idleTimeout
|
||||||
UIApplication.shared.isIdleTimerDisabled = UserDefaults.standard.isIdleTimeoutDisableEnabled
|
if !UIApplication.shared.isIdleTimerDisabled { // accept only once if concurrent
|
||||||
|
DispatchQueue.main.schedule {
|
||||||
|
UIApplication.shared.isIdleTimerDisabled = UserDefaults.standard.isIdleTimeoutDisableEnabled
|
||||||
|
}
|
||||||
}
|
}
|
||||||
performAppOperations()
|
performAppOperations()
|
||||||
DispatchQueue.main.schedule {
|
// Moved to self.finish()
|
||||||
UIApplication.shared.isIdleTimerDisabled = false
|
// DispatchQueue.main.schedule {
|
||||||
}
|
// UIApplication.shared.isIdleTimerDisabled = false
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return group
|
return group
|
||||||
@@ -2095,6 +2102,16 @@ private extension AppManager
|
|||||||
|
|
||||||
func finish(_ operation: AppOperation, result: Result<InstalledApp, Error>, group: RefreshGroup, progress: Progress?)
|
func finish(_ operation: AppOperation, result: Result<InstalledApp, Error>, group: RefreshGroup, progress: Progress?)
|
||||||
{
|
{
|
||||||
|
// Remove disableIdleTimeout
|
||||||
|
// TODO: This should disable for the last finish() request not the first though for batches
|
||||||
|
// probably if we are in batch mode, we can count expected no of finishes() to arrive
|
||||||
|
// and schedule disabling only on last request by matching it with count.
|
||||||
|
if UIApplication.shared.isIdleTimerDisabled { // accept only once if concurrent
|
||||||
|
DispatchQueue.main.schedule {
|
||||||
|
UIApplication.shared.isIdleTimerDisabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Must remove before saving installedApp.
|
// Must remove before saving installedApp.
|
||||||
if let currentProgress = self.progress(for: operation), currentProgress == progress
|
if let currentProgress = self.progress(for: operation), currentProgress == progress
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -238,10 +238,10 @@ struct OperationError: ALTLocalizedError {
|
|||||||
|
|
||||||
case .invalidParameters:
|
case .invalidParameters:
|
||||||
let message = self._failureReason.map { ": \n\($0)" } ?? "."
|
let message = self._failureReason.map { ": \n\($0)" } ?? "."
|
||||||
return String(format: NSLocalizedString("Invalid parameters\n%@", comment: ""), message)
|
return String(format: NSLocalizedString("Invalid parameters%@", comment: ""), message)
|
||||||
case .invalidOperationContext:
|
case .invalidOperationContext:
|
||||||
let message = self._failureReason.map { ": \n\($0)" } ?? "."
|
let message = self._failureReason.map { ": \n\($0)" } ?? "."
|
||||||
return String(format: NSLocalizedString("Invalid Operation Context\n%@", comment: ""), message)
|
return String(format: NSLocalizedString("Invalid Operation Context%@", comment: ""), message)
|
||||||
case .serverNotFound: return NSLocalizedString("AltServer could not be found.", comment: "")
|
case .serverNotFound: return NSLocalizedString("AltServer could not be found.", comment: "")
|
||||||
case .connectionFailed: return NSLocalizedString("A connection to AltServer could not be established.", comment: "")
|
case .connectionFailed: return NSLocalizedString("A connection to AltServer could not be established.", comment: "")
|
||||||
case .connectionDropped: return NSLocalizedString("The connection to AltServer was dropped.", comment: "")
|
case .connectionDropped: return NSLocalizedString("The connection to AltServer was dropped.", comment: "")
|
||||||
|
|||||||
@@ -155,11 +155,11 @@ struct VerificationError: ALTLocalizedError
|
|||||||
|
|
||||||
case .mismatchedVersion:
|
case .mismatchedVersion:
|
||||||
let appName = self.$app.name ?? NSLocalizedString("the app", comment: "")
|
let appName = self.$app.name ?? NSLocalizedString("the app", comment: "")
|
||||||
return String(format: NSLocalizedString("The downloaded version of %@ does not match the version specified by the source.", comment: ""), appName)
|
return String(format: NSLocalizedString("The downloaded version of %@ does not match the version specified by the source.\nExpected version: %@\nFound version: %@", comment: ""), appName, expectedVersion ?? "nil", version ?? "nil")
|
||||||
|
|
||||||
case .mismatchedBuildVersion:
|
case .mismatchedBuildVersion:
|
||||||
let appName = self.$app.name ?? NSLocalizedString("the app", comment: "")
|
let appName = self.$app.name ?? NSLocalizedString("the app", comment: "")
|
||||||
return String(format: NSLocalizedString("The downloaded version of %@ does not match the build number specified by the source.", comment: ""), appName)
|
return String(format: NSLocalizedString("The downloaded version of %@ does not match the build number specified by the source.\nExpected version: %@\nFound version: %@", comment: ""), appName, expectedVersion ?? "nil", version ?? "nil")
|
||||||
|
|
||||||
case .undeclaredPermissions:
|
case .undeclaredPermissions:
|
||||||
let appName = self.$app.name ?? NSLocalizedString("The app", comment: "")
|
let appName = self.$app.name ?? NSLocalizedString("The app", comment: "")
|
||||||
|
|||||||
@@ -119,6 +119,36 @@ class FetchProvisioningProfilesOperation: ResultOperation<[String: ALTProvisioni
|
|||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal func fetchProvisioningProfile(for appID: ALTAppID, app: ALTApplication, team: ALTTeam, session: ALTAppleAPISession, completionHandler: @escaping (Result<ALTProvisioningProfile, Error>) -> Void)
|
||||||
|
{
|
||||||
|
ALTAppleAPI.shared.fetchProvisioningProfile(for: appID, deviceType: .iphone, team: team, session: session) { (profile, error) in
|
||||||
|
switch Result(profile, error)
|
||||||
|
{
|
||||||
|
case .failure(let error): completionHandler(.failure(error))
|
||||||
|
case .success(let profile):
|
||||||
|
|
||||||
|
// Delete existing profile
|
||||||
|
ALTAppleAPI.shared.delete(profile, for: team, session: session) { (success, error) in
|
||||||
|
switch Result(success, error)
|
||||||
|
{
|
||||||
|
case .failure:
|
||||||
|
// As of March 20, 2023, the free provisioning profile is re-generated each fetch, and you can no longer delete it.
|
||||||
|
// So instead, we just return the fetched profile from above.
|
||||||
|
completionHandler(.success(profile))
|
||||||
|
|
||||||
|
case .success:
|
||||||
|
Logger.sideload.notice("Generating new free provisioning profile for App ID \(appID.bundleIdentifier, privacy: .public).")
|
||||||
|
|
||||||
|
// Fetch new provisioning profile
|
||||||
|
ALTAppleAPI.shared.fetchProvisioningProfile(for: appID, deviceType: .iphone, team: team, session: session) { (profile, error) in
|
||||||
|
completionHandler(Result(profile, error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension FetchProvisioningProfilesOperation
|
extension FetchProvisioningProfilesOperation
|
||||||
@@ -223,7 +253,7 @@ extension FetchProvisioningProfilesOperation
|
|||||||
|
|
||||||
//process
|
//process
|
||||||
self.fetchProvisioningProfile(
|
self.fetchProvisioningProfile(
|
||||||
for: appID, team: team, session: session, completionHandler: completionHandler
|
for: appID, app: app, team: team, session: session, completionHandler: completionHandler
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,36 +358,6 @@ extension FetchProvisioningProfilesOperation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal func fetchProvisioningProfile(for appID: ALTAppID, team: ALTTeam, session: ALTAppleAPISession, completionHandler: @escaping (Result<ALTProvisioningProfile, Error>) -> Void)
|
|
||||||
{
|
|
||||||
ALTAppleAPI.shared.fetchProvisioningProfile(for: appID, deviceType: .iphone, team: team, session: session) { (profile, error) in
|
|
||||||
switch Result(profile, error)
|
|
||||||
{
|
|
||||||
case .failure(let error): completionHandler(.failure(error))
|
|
||||||
case .success(let profile):
|
|
||||||
|
|
||||||
// Delete existing profile
|
|
||||||
ALTAppleAPI.shared.delete(profile, for: team, session: session) { (success, error) in
|
|
||||||
switch Result(success, error)
|
|
||||||
{
|
|
||||||
case .failure:
|
|
||||||
// As of March 20, 2023, the free provisioning profile is re-generated each fetch, and you can no longer delete it.
|
|
||||||
// So instead, we just return the fetched profile from above.
|
|
||||||
completionHandler(.success(profile))
|
|
||||||
|
|
||||||
case .success:
|
|
||||||
Logger.sideload.notice("Generating new free provisioning profile for App ID \(appID.bundleIdentifier, privacy: .public).")
|
|
||||||
|
|
||||||
// Fetch new provisioning profile
|
|
||||||
ALTAppleAPI.shared.fetchProvisioningProfile(for: appID, deviceType: .iphone, team: team, session: session) { (profile, error) in
|
|
||||||
completionHandler(Result(profile, error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class FetchProvisioningProfilesRefreshOperation: FetchProvisioningProfilesOperation, @unchecked Sendable {
|
class FetchProvisioningProfilesRefreshOperation: FetchProvisioningProfilesOperation, @unchecked Sendable {
|
||||||
@@ -374,8 +374,8 @@ class FetchProvisioningProfilesInstallOperation: FetchProvisioningProfilesOperat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// modify Operations are allowed for the app groups and other stuffs
|
// modify Operations are allowed for the app groups and other stuffs
|
||||||
func fetchProvisioningProfile(appID: ALTAppID,
|
override func fetchProvisioningProfile(for appID: ALTAppID,
|
||||||
for app: ALTApplication,
|
app: ALTApplication,
|
||||||
team: ALTTeam,
|
team: ALTTeam,
|
||||||
session: ALTAppleAPISession,
|
session: ALTAppleAPISession,
|
||||||
completionHandler: @escaping (Result<ALTProvisioningProfile, Error>) -> Void)
|
completionHandler: @escaping (Result<ALTProvisioningProfile, Error>) -> Void)
|
||||||
@@ -396,7 +396,7 @@ class FetchProvisioningProfilesInstallOperation: FetchProvisioningProfilesOperat
|
|||||||
case .success(let appID):
|
case .success(let appID):
|
||||||
|
|
||||||
// Fetch Provisioning Profile
|
// Fetch Provisioning Profile
|
||||||
super.fetchProvisioningProfile(for: appID, team: team, session: session, completionHandler: completionHandler)
|
super.fetchProvisioningProfile(for: appID, app: app, team: team, session: session, completionHandler: completionHandler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ final class RemoveAppExtensionsOperation: ResultOperation<Void>
|
|||||||
presentingViewController.present(alertController, animated: true){
|
presentingViewController.present(alertController, animated: true){
|
||||||
|
|
||||||
// if for any reason the view wasn't presented, then just signal that as error
|
// if for any reason the view wasn't presented, then just signal that as error
|
||||||
if presentingViewController.presentedViewController == nil {
|
if presentingViewController.presentedViewController == nil && !alertController.isViewLoaded {
|
||||||
let errMsg = "RemoveAppExtensionsOperation: unable to present dialog, view context not available." +
|
let errMsg = "RemoveAppExtensionsOperation: unable to present dialog, view context not available." +
|
||||||
"\nDid you move to different screen or background after starting the operation?"
|
"\nDid you move to different screen or background after starting the operation?"
|
||||||
self.finish(.failure(
|
self.finish(.failure(
|
||||||
|
|||||||
@@ -211,20 +211,11 @@ private extension SettingsViewController
|
|||||||
{
|
{
|
||||||
|
|
||||||
private func getVersionLabel() -> String {
|
private func getVersionLabel() -> String {
|
||||||
let MARKETING_VERSION_KEY = "CFBundleShortVersionString"
|
let buildInfo = BuildInfo()
|
||||||
let BUILD_REVISION = "CFBundleRevision" // commit ID for now (but could be any, set by build env vars
|
|
||||||
let CURRENT_PROJECT_VERSION = kCFBundleVersionKey as String
|
|
||||||
|
|
||||||
func getXcodeVersion() -> String {
|
func getXcodeVersion() -> String {
|
||||||
let XCODE_VERSION = "DTXcode"
|
var xcodeVersion = buildInfo.xcode.map { version in
|
||||||
let XCODE_REVISION = "DTXcodeBuild"
|
"Xcode \(version)" + (buildInfo.xcode_revision.map { revision in " - \(revision)" } ?? "") // Ex: "0.6.0 - Xcode 16.2 - 21ac1ef"
|
||||||
|
|
||||||
let xcode = Bundle.main.object(forInfoDictionaryKey: XCODE_VERSION) as? String
|
|
||||||
let build = Bundle.main.object(forInfoDictionaryKey: XCODE_REVISION) as? String
|
|
||||||
|
|
||||||
var xcodeVersion = xcode.map { version in
|
|
||||||
// " - Xcode \(version) - " + (build.map { revision in "\(revision)" } ?? "") // Ex: "0.6.0 - Xcode 16.2 - 21ac1ef"
|
|
||||||
"Xcode \(version) - " + (build.map { revision in "\(revision)" } ?? "") // Ex: "0.6.0 - Xcode 16.2 - 21ac1ef"
|
|
||||||
} ?? ""
|
} ?? ""
|
||||||
|
|
||||||
if let pairing = Bundle.main.object(forInfoDictionaryKey: "ALTPairingFile") as? String,
|
if let pairing = Bundle.main.object(forInfoDictionaryKey: "ALTPairingFile") as? String,
|
||||||
@@ -234,26 +225,25 @@ private extension SettingsViewController
|
|||||||
return xcodeVersion
|
return xcodeVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var versionLabel: String = ""
|
var versionLabel: String = ""
|
||||||
|
|
||||||
if let installedApp = InstalledApp.fetchAltStore(in: DatabaseManager.shared.viewContext)
|
if let installedApp = InstalledApp.fetchAltStore(in: DatabaseManager.shared.viewContext)
|
||||||
{
|
{
|
||||||
#if BETA
|
let isStableBuild = (buildInfo.channel == .stable)
|
||||||
// Only show build version (and build revision) for BETA builds.
|
let revision = buildInfo.revision ?? ""
|
||||||
let bundleVersion: String? = Bundle.main.object(forInfoDictionaryKey: CURRENT_PROJECT_VERSION) as? String
|
|
||||||
let buildRevision: String? = Bundle.main.object(forInfoDictionaryKey: BUILD_REVISION) as? String
|
|
||||||
|
|
||||||
var localizedVersion = bundleVersion.map { version in
|
|
||||||
"\(installedApp.version) (\(version))" + (buildRevision.map { revision in " - \(revision)" } ?? "") // Ex: "0.6.0 (0600) - 1acdef3"
|
|
||||||
} ?? installedApp.localizedVersion
|
|
||||||
|
|
||||||
#else
|
|
||||||
var localizedVersion = installedApp.version
|
var localizedVersion = installedApp.version
|
||||||
#endif
|
// Only show build version (and build revision) for non stable builds.
|
||||||
|
if !isStableBuild {
|
||||||
|
localizedVersion += buildInfo.project_version.map{ version in
|
||||||
|
version.isEmpty ? "" : " (\(version))" + (revision.isEmpty ? "" : " - \(revision)")
|
||||||
|
} ?? installedApp.localizedVersion
|
||||||
|
}
|
||||||
|
|
||||||
versionLabel = NSLocalizedString(String(format: "Version %@", localizedVersion), comment: "SideStore Version")
|
versionLabel = NSLocalizedString(String(format: "Version %@", localizedVersion), comment: "SideStore Version")
|
||||||
}
|
}
|
||||||
else if let version = Bundle.main.object(forInfoDictionaryKey: MARKETING_VERSION_KEY) as? String
|
else if let version = buildInfo.marketing_version
|
||||||
{
|
{
|
||||||
var version = "SideStore \(version)"
|
var version = "SideStore \(version)"
|
||||||
|
|
||||||
@@ -268,10 +258,11 @@ private extension SettingsViewController
|
|||||||
versionLabel = NSLocalizedString(version, comment: "SideStore Version")
|
versionLabel = NSLocalizedString(version, comment: "SideStore Version")
|
||||||
}
|
}
|
||||||
|
|
||||||
// add xcode build version if in debug mode
|
// add xcode build version for local builds
|
||||||
#if DEBUG
|
if buildInfo.channel == .local
|
||||||
versionLabel += "\n\(getXcodeVersion())"
|
{
|
||||||
#endif
|
versionLabel += "\n\(getXcodeVersion())"
|
||||||
|
}
|
||||||
|
|
||||||
return versionLabel
|
return versionLabel
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,11 +13,11 @@
|
|||||||
<!--Sources-->
|
<!--Sources-->
|
||||||
<scene sceneID="QxB-Dd-1xC">
|
<scene sceneID="QxB-Dd-1xC">
|
||||||
<objects>
|
<objects>
|
||||||
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="7We-99-yEv" customClass="ForwardingNavigationController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
|
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="7We-99-yEv" customClass="ForwardingNavigationController" customModule="SideStore" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<tabBarItem key="tabBarItem" title="Sources" image="Sources" id="xPv-dc-X4v"/>
|
<tabBarItem key="tabBarItem" title="Sources" image="Sources" id="xPv-dc-X4v"/>
|
||||||
<toolbarItems/>
|
<toolbarItems/>
|
||||||
<simulatedTabBarMetrics key="simulatedBottomBarMetrics"/>
|
<simulatedTabBarMetrics key="simulatedBottomBarMetrics"/>
|
||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="xWh-1U-u0q" customClass="NavigationBar" customModule="AltStore" customModuleProvider="target">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="xWh-1U-u0q" customClass="NavigationBar" customModule="SideStore" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="59" width="393" height="96"/>
|
<rect key="frame" x="0.0" y="59" width="393" height="96"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
<!--All Apps-->
|
<!--All Apps-->
|
||||||
<scene sceneID="d8a-U8-CPc">
|
<scene sceneID="d8a-U8-CPc">
|
||||||
<objects>
|
<objects>
|
||||||
<collectionViewController storyboardIdentifier="browseViewController" id="Nhf-Gw-Ukx" customClass="BrowseViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
|
<collectionViewController storyboardIdentifier="browseViewController" id="Nhf-Gw-Ukx" customClass="BrowseViewController" customModule="SideStore" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="oBI-6P-Lm3">
|
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="oBI-6P-Lm3">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="393" height="842"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="842"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
@@ -59,9 +59,9 @@
|
|||||||
<!--Source Detail View Controller-->
|
<!--Source Detail View Controller-->
|
||||||
<scene sceneID="xbN-Mz-TtU">
|
<scene sceneID="xbN-Mz-TtU">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController storyboardIdentifier="sourceDetailViewController" id="7XE-Wv-lf9" customClass="SourceDetailViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
|
<viewController storyboardIdentifier="sourceDetailViewController" id="7XE-Wv-lf9" customClass="SourceDetailViewController" customModule="SideStore" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<view key="view" contentMode="scaleToFill" id="eIv-0H-ZIq">
|
<view key="view" contentMode="scaleToFill" id="eIv-0H-ZIq">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="842"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<viewLayoutGuide key="safeArea" id="GND-ro-Anp"/>
|
<viewLayoutGuide key="safeArea" id="GND-ro-Anp"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
<!--Source Detail Content View Controller-->
|
<!--Source Detail Content View Controller-->
|
||||||
<scene sceneID="8nl-ly-jhT">
|
<scene sceneID="8nl-ly-jhT">
|
||||||
<objects>
|
<objects>
|
||||||
<collectionViewController storyboardIdentifier="sourceDetailContentViewController" id="MSh-hM-32I" customClass="SourceDetailContentViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
|
<collectionViewController storyboardIdentifier="sourceDetailContentViewController" id="MSh-hM-32I" customClass="SourceDetailContentViewController" customModule="SideStore" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="fiF-YD-Ing">
|
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="fiF-YD-Ing">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
|
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||||
</collectionViewFlowLayout>
|
</collectionViewFlowLayout>
|
||||||
<cells>
|
<cells>
|
||||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AppCell" id="ioR-1o-Qe1" customClass="AppBannerCollectionViewCell" customModule="AltStore" customModuleProvider="target">
|
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AppCell" id="ioR-1o-Qe1" customClass="AppBannerCollectionViewCell" customModule="SideStore" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="128" height="128"/>
|
<rect key="frame" x="0.0" y="0.0" width="128" height="128"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<collectionViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" id="Bda-YQ-Gv5">
|
<collectionViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" id="Bda-YQ-Gv5">
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</collectionViewCellContentView>
|
</collectionViewCellContentView>
|
||||||
</collectionViewCell>
|
</collectionViewCell>
|
||||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AboutCell" id="Bnj-xm-pBT" customClass="TextViewCollectionViewCell" customModule="AltStore" customModuleProvider="target">
|
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AboutCell" id="Bnj-xm-pBT" customClass="TextViewCollectionViewCell" customModule="SideStore" customModuleProvider="target">
|
||||||
<rect key="frame" x="265" y="0.0" width="128" height="128"/>
|
<rect key="frame" x="265" y="0.0" width="128" height="128"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<collectionViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" id="lXN-gL-rhU">
|
<collectionViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" id="lXN-gL-rhU">
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
<!--All News-->
|
<!--All News-->
|
||||||
<scene sceneID="avV-5f-uNE">
|
<scene sceneID="avV-5f-uNE">
|
||||||
<objects>
|
<objects>
|
||||||
<collectionViewController storyboardIdentifier="newsViewController" id="MVH-oB-c8m" customClass="NewsViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
|
<collectionViewController storyboardIdentifier="newsViewController" id="MVH-oB-c8m" customClass="NewsViewController" customModule="SideStore" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" id="p9p-rr-fbF">
|
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" id="p9p-rr-fbF">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="393" height="842"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="842"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
<!--Sources-->
|
<!--Sources-->
|
||||||
<scene sceneID="w2v-ek-6dY">
|
<scene sceneID="w2v-ek-6dY">
|
||||||
<objects>
|
<objects>
|
||||||
<collectionViewController storyboardIdentifier="sourcesViewController" title="Sources" id="Wm7-1O-FkD" customClass="SourcesViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
|
<collectionViewController storyboardIdentifier="sourcesViewController" title="Sources" id="Wm7-1O-FkD" customClass="SourcesViewController" customModule="SideStore" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" alwaysBounceVertical="YES" dataMode="prototypes" id="VJr-nx-7Vh">
|
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" alwaysBounceVertical="YES" dataMode="prototypes" id="VJr-nx-7Vh">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
@@ -160,7 +160,7 @@
|
|||||||
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
|
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||||
</collectionViewFlowLayout>
|
</collectionViewFlowLayout>
|
||||||
<cells>
|
<cells>
|
||||||
<collectionViewCell opaque="NO" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" reuseIdentifier="Cell" id="1Rm-Gf-VDt" customClass="AppBannerCollectionViewCell" customModule="AltStore" customModuleProvider="target">
|
<collectionViewCell opaque="NO" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" reuseIdentifier="Cell" id="1Rm-Gf-VDt" customClass="AppBannerCollectionViewCell" customModule="SideStore" customModuleProvider="target">
|
||||||
<rect key="frame" x="9" y="0.0" width="375" height="80"/>
|
<rect key="frame" x="9" y="0.0" width="375" height="80"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
|
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
|
||||||
@@ -192,7 +192,7 @@
|
|||||||
<!--Add Source-->
|
<!--Add Source-->
|
||||||
<scene sceneID="oCv-by-94o">
|
<scene sceneID="oCv-by-94o">
|
||||||
<objects>
|
<objects>
|
||||||
<collectionViewController id="bbz-wy-kaK" customClass="AddSourceViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
|
<collectionViewController id="bbz-wy-kaK" customClass="AddSourceViewController" customModule="SideStore" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="lXl-N1-6cT">
|
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="lXl-N1-6cT">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="393" height="842"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="842"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
@@ -226,7 +226,6 @@
|
|||||||
</barButtonItem>
|
</barButtonItem>
|
||||||
</navigationItem>
|
</navigationItem>
|
||||||
<connections>
|
<connections>
|
||||||
<segue destination="qr8-ss-Ghz" kind="unwind" unwindAction="unwindFromAddSource:" id="nj3-eB-DML"/>
|
|
||||||
<segue destination="7XE-Wv-lf9" kind="show" identifier="showSourceDetails" destinationCreationSelector="makeSourceDetailViewController:sender:" id="LO9-iP-zZC"/>
|
<segue destination="7XE-Wv-lf9" kind="show" identifier="showSourceDetails" destinationCreationSelector="makeSourceDetailViewController:sender:" id="LO9-iP-zZC"/>
|
||||||
</connections>
|
</connections>
|
||||||
</collectionViewController>
|
</collectionViewController>
|
||||||
@@ -238,10 +237,10 @@
|
|||||||
<!--Forwarding Navigation Controller-->
|
<!--Forwarding Navigation Controller-->
|
||||||
<scene sceneID="NAl-mP-f8p">
|
<scene sceneID="NAl-mP-f8p">
|
||||||
<objects>
|
<objects>
|
||||||
<navigationController storyboardIdentifier="addSourceNavigationController" automaticallyAdjustsScrollViewInsets="NO" id="i15-Jk-F75" customClass="ForwardingNavigationController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
|
<navigationController storyboardIdentifier="addSourceNavigationController" automaticallyAdjustsScrollViewInsets="NO" id="i15-Jk-F75" customClass="ForwardingNavigationController" customModule="SideStore" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<toolbarItems/>
|
<toolbarItems/>
|
||||||
<navigationItem key="navigationItem" id="Opx-Pr-Tyy"/>
|
<navigationItem key="navigationItem" id="Opx-Pr-Tyy"/>
|
||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" largeTitles="YES" id="HLe-3g-P8I" customClass="NavigationBar" customModule="AltStore" customModuleProvider="target">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" largeTitles="YES" id="HLe-3g-P8I" customClass="NavigationBar" customModule="SideStore" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="393" height="108"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="108"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
<string>$(MARKETING_VERSION)</string>
|
<string>$(MARKETING_VERSION)</string>
|
||||||
<key>BuildRevision</key>
|
<key>BuildRevision</key>
|
||||||
<string>$(BUILD_REVISION)</string>
|
<string>$(BUILD_REVISION)</string>
|
||||||
|
<key>BuildChannel</key>
|
||||||
|
<string>$(BUILD_CHANNEL)</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
<string>$(MARKETING_VERSION)</string>
|
<string>$(MARKETING_VERSION)</string>
|
||||||
<key>BuildRevision</key>
|
<key>BuildRevision</key>
|
||||||
<string>$(BUILD_REVISION)</string>
|
<string>$(BUILD_REVISION)</string>
|
||||||
|
<key>BuildChannel</key>
|
||||||
|
<string>$(BUILD_CHANNEL)</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
<key>NSExtension</key>
|
<key>NSExtension</key>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
MARKETING_VERSION = 0.6.0
|
MARKETING_VERSION = 0.6.0
|
||||||
CURRENT_PROJECT_VERSION = 6000
|
CURRENT_PROJECT_VERSION = 6000
|
||||||
|
BUILD_CHANNEL = stable
|
||||||
|
|
||||||
// Vars to be overwritten by `CodeSigning.xcconfig` if exists
|
// Vars to be overwritten by `CodeSigning.xcconfig` if exists
|
||||||
DEVELOPMENT_TEAM = S32Z3HMYVQ
|
DEVELOPMENT_TEAM = S32Z3HMYVQ
|
||||||
|
|||||||
@@ -50,17 +50,55 @@ to force it to check for new binaries, run `bash ./SideStore/fetch-prebuilt.sh f
|
|||||||
## Building an IPA for distribution
|
## Building an IPA for distribution
|
||||||
|
|
||||||
Install cocoapods if required using: `brew install cocoapods`
|
Install cocoapods if required using: `brew install cocoapods`
|
||||||
|
|
||||||
Now perform Pod-Install using: `pod install` command to install the dependencies.
|
Now perform Pod-Install using: `pod install` command to install the dependencies.
|
||||||
|
|
||||||
You can then use the Makefile command: `make build fakesign ipa` in the root directory.
|
You can then use the Makefile command: `make build fakesign ipa` in the root directory.
|
||||||
|
By default the config for build is: `Release`
|
||||||
|
For debug builds: `export BUILD_CONFIG=Debug;make build fakesign ipa` in the root directory.
|
||||||
|
For alpha/beta builds: `export IS_ALPHA=1;` or `export IS_BETA=1;` before invoking the build command.
|
||||||
This will create SideStore.ipa.
|
This will create SideStore.ipa.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
# cocoapods
|
||||||
|
brew install cocoapods
|
||||||
|
# perform installation of the pods
|
||||||
|
pod install
|
||||||
|
|
||||||
|
# alpha release build
|
||||||
|
export IS_ALPHA=1;make build fakesign ipa
|
||||||
|
# alpha debug build
|
||||||
|
export IS_ALPHA=1;export BUILD_CONFIG=Debug;make build fakesign ipa
|
||||||
|
|
||||||
|
# beta release build
|
||||||
|
export IS_BETA=1;make build fakesign ipa
|
||||||
|
# beta debug build
|
||||||
|
export IS_BETA=1;export BUILD_CONFIG=Debug;make build fakesign ipa
|
||||||
|
|
||||||
|
# stable release build
|
||||||
|
make build fakesign ipa
|
||||||
|
# stable debug build
|
||||||
|
export BUILD_CONFIG=Debug;make build fakesign ipa
|
||||||
|
```
|
||||||
|
By default sidestore will build for its default bundleIdentifier `com.SideStore.SideStore` but if you need to set a custom bundleID for commandline builds, once can do so by exporting `BUNDLE_ID_SUFFIX` env var
|
||||||
|
```sh
|
||||||
|
# stable release build
|
||||||
|
export BUNDLE_ID_SUFFIX=XYZ0123456;make build fakesign ipa
|
||||||
|
# stable debug build
|
||||||
|
export BUNDLE_ID_SUFFIX=XYZ0123456;export BUILD_CONFIG=Debug;make build fakesign ipa
|
||||||
|
```
|
||||||
|
NOTE: When building from XCode, the `BUNDLE_ID_SUFFIX` is set by default with the value of `DEVELOPMENT_TEAM`
|
||||||
|
|
||||||
|
This can be customized by setting/removing the BUNDLE_ID_SUFFIX in overriding CodeSigning.xcconfig created from CodeSigning.xcconfig.sample
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
> **Warning**
|
> **Warning**
|
||||||
>
|
>
|
||||||
> The binary created will contain paths to Xcode's DerivedData, and if you built minimuxer on your machine, paths to $HOME/.cargo. This will include your username. If you want to keep your user's
|
> The binary created will contain paths to Xcode's DerivedData, and if you built minimuxer on your machine, paths to $HOME/.cargo. This will include your username. If you want to keep your user's
|
||||||
> username private, you might want to get GitHub Actions to build the IPA instead.
|
> username private, you might want to get GitHub Actions to build the IPA instead.
|
||||||
|
>
|
||||||
|
|
||||||
## Developing minimuxer alongside SideStore
|
## Developing minimuxer alongside SideStore
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ ORG_IDENTIFIER = com.myuniquename
|
|||||||
// we don't want to do this for release since those builds will most likely be installed via SideServer, which adds the team ID
|
// we don't want to do this for release since those builds will most likely be installed via SideServer, which adds the team ID
|
||||||
BUNDLE_ID_SUFFIX = .$(DEVELOPMENT_TEAM)
|
BUNDLE_ID_SUFFIX = .$(DEVELOPMENT_TEAM)
|
||||||
|
|
||||||
|
// Comment this out to use default 'stable' channel defined in Build.xcconfig
|
||||||
|
// For local xcode or commandline builds we can use local channel for local build specific logic
|
||||||
|
BUILD_CHANNEL = local
|
||||||
|
|
||||||
// Set to YES if you have a valid paid Apple Developer account
|
// Set to YES if you have a valid paid Apple Developer account
|
||||||
DEVELOPER_ACCOUNT_PAID = NO
|
DEVELOPER_ACCOUNT_PAID = NO
|
||||||
|
|
||||||
|
|||||||
2
Dependencies/Roxas
vendored
2
Dependencies/Roxas
vendored
Submodule Dependencies/Roxas updated: 03f6013972...0784711ed9
10
Makefile
10
Makefile
@@ -161,19 +161,24 @@ test:
|
|||||||
IS_ALPHA_TRUE := $(filter true TRUE 1, $(IS_ALPHA))
|
IS_ALPHA_TRUE := $(filter true TRUE 1, $(IS_ALPHA))
|
||||||
IS_BETA_TRUE := $(filter true TRUE 1, $(IS_BETA))
|
IS_BETA_TRUE := $(filter true TRUE 1, $(IS_BETA))
|
||||||
|
|
||||||
|
# set build types to embed into Info.plist for key: BuildChannel
|
||||||
|
BUILD_CHANNEL := stable
|
||||||
|
BUILD_CHANNEL := $(if $(IS_ALPHA_TRUE),alpha,$(BUILD_CHANNEL))
|
||||||
|
BUILD_CHANNEL := $(if $(IS_BETA_TRUE),beta,$(BUILD_CHANNEL))
|
||||||
|
|
||||||
# Fetch the latest commit ID for ALPHA or BETA builds
|
# Fetch the latest commit ID for ALPHA or BETA builds
|
||||||
COMMIT_ID := $(if $(or $(IS_ALPHA_TRUE),$(IS_BETA_TRUE)),$(shell git rev-parse --short HEAD),)
|
COMMIT_ID := $(if $(or $(IS_ALPHA_TRUE),$(IS_BETA_TRUE)),$(shell git rev-parse --short HEAD),)
|
||||||
|
|
||||||
# Print release type based on the value of IS_ALPHA or IS_BETA
|
# Print release type based on the value of IS_ALPHA or IS_BETA
|
||||||
print_release_type:
|
print_release_type:
|
||||||
@echo ""
|
@echo ""
|
||||||
@if [ "$(filter true TRUE 1,$(IS_ALPHA))" ]; then \
|
@if [ $(IS_ALPHA_TRUE) ]; then \
|
||||||
echo "'IS_ALPHA' is set to true. Fetched the latest commit ID from HEAD..."; \
|
echo "'IS_ALPHA' is set to true. Fetched the latest commit ID from HEAD..."; \
|
||||||
echo " Commit ID: $(COMMIT_ID)"; \
|
echo " Commit ID: $(COMMIT_ID)"; \
|
||||||
echo ""; \
|
echo ""; \
|
||||||
echo ">>>>>>>> This is now an ALPHA release for COMMIT_ID = '$(COMMIT_ID)' <<<<<<<<<"; \
|
echo ">>>>>>>> This is now an ALPHA release for COMMIT_ID = '$(COMMIT_ID)' <<<<<<<<<"; \
|
||||||
echo " Building with BUILD_REVISION = '$(COMMIT_ID)'"; \
|
echo " Building with BUILD_REVISION = '$(COMMIT_ID)'"; \
|
||||||
elif [ "$(filter true TRUE 1,$(IS_BETA))" ]; then \
|
elif [ $(IS_BETA_TRUE) ]; then \
|
||||||
echo "'IS_BETA' is set to true. Fetched the latest commit ID from HEAD..."; \
|
echo "'IS_BETA' is set to true. Fetched the latest commit ID from HEAD..."; \
|
||||||
echo " Commit ID: $(COMMIT_ID)"; \
|
echo " Commit ID: $(COMMIT_ID)"; \
|
||||||
echo ""; \
|
echo ""; \
|
||||||
@@ -215,6 +220,7 @@ build: print_release_type
|
|||||||
DEVELOPMENT_TEAM=XYZ0123456 \
|
DEVELOPMENT_TEAM=XYZ0123456 \
|
||||||
ORG_IDENTIFIER=com.SideStore \
|
ORG_IDENTIFIER=com.SideStore \
|
||||||
BUILD_REVISION=$(COMMIT_ID) \
|
BUILD_REVISION=$(COMMIT_ID) \
|
||||||
|
BUILD_CHANNEL=$(BUILD_CHANNEL)
|
||||||
BUNDLE_ID_SUFFIX=
|
BUNDLE_ID_SUFFIX=
|
||||||
# DWARF_DSYM_FOLDER_PATH="."
|
# DWARF_DSYM_FOLDER_PATH="."
|
||||||
|
|
||||||
|
|||||||
58
SideStore/Utils/buildinfo/BuildInfo.swift
Normal file
58
SideStore/Utils/buildinfo/BuildInfo.swift
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
//
|
||||||
|
// BuildInfo.swift
|
||||||
|
// AltStore
|
||||||
|
//
|
||||||
|
// Created by Magesh K on 21/01/25.
|
||||||
|
// Copyright © 2025 SideStore. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
public class BuildInfo{
|
||||||
|
private static let BUILD_REVISION_TAG = "BuildRevision" // commit ID for now (but could be any, set by build env vars
|
||||||
|
private static let BUILD_CHANNEL_TAG = "BuildChannel" // set by build env, ex CI will set it via env vars, for xcode builds this is empty
|
||||||
|
|
||||||
|
private static let MARKETING_VERSION_TAG = "CFBundleShortVersionString"
|
||||||
|
private static let CURRENT_PROJECT_VERSION_TAG = kCFBundleVersionKey as String
|
||||||
|
|
||||||
|
private static let XCODE_VERSION_TAG = "DTXcode"
|
||||||
|
private static let XCODE_REVISION_TAG = "DTXcodeBuild"
|
||||||
|
|
||||||
|
public enum Channel: String {
|
||||||
|
case unknown
|
||||||
|
case local // xcodebuilds can use this by setting BUILD_CHANNEL in CodeSigning.xcconfig
|
||||||
|
|
||||||
|
case alpha
|
||||||
|
case beta
|
||||||
|
case stable
|
||||||
|
}
|
||||||
|
|
||||||
|
public lazy var channel: Channel = {
|
||||||
|
let channel = Bundle.main.object(forInfoDictionaryKey: Self.BUILD_CHANNEL_TAG) as? String
|
||||||
|
return Channel(rawValue: channel ?? "") ?? .unknown
|
||||||
|
}()
|
||||||
|
|
||||||
|
public lazy var revision: String? = {
|
||||||
|
let revision = Bundle.main.object(forInfoDictionaryKey: Self.BUILD_REVISION_TAG) as? String
|
||||||
|
return revision
|
||||||
|
}()
|
||||||
|
|
||||||
|
public lazy var project_version: String? = {
|
||||||
|
let revision = Bundle.main.object(forInfoDictionaryKey: Self.CURRENT_PROJECT_VERSION_TAG) as? String
|
||||||
|
return revision
|
||||||
|
}()
|
||||||
|
|
||||||
|
public lazy var marketing_version: String? = {
|
||||||
|
let revision = Bundle.main.object(forInfoDictionaryKey: Self.MARKETING_VERSION_TAG) as? String
|
||||||
|
return revision
|
||||||
|
}()
|
||||||
|
|
||||||
|
public lazy var xcode: String? = {
|
||||||
|
let xcode = Bundle.main.object(forInfoDictionaryKey: Self.XCODE_VERSION_TAG) as? String
|
||||||
|
return xcode
|
||||||
|
}()
|
||||||
|
|
||||||
|
public lazy var xcode_revision: String? = {
|
||||||
|
let revision = Bundle.main.object(forInfoDictionaryKey: Self.XCODE_REVISION_TAG) as? String
|
||||||
|
return revision
|
||||||
|
}()
|
||||||
|
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ class ErrorProcessing {
|
|||||||
self.recur = recur
|
self.recur = recur
|
||||||
}
|
}
|
||||||
|
|
||||||
private func processError(_ error: NSError, getMoreErrors: (_ error: NSError)->String) -> String{
|
private func processError(_ error: NSError, ignoreTitle: Bool = false, getMoreErrors: (_ error: NSError)->String) -> String{
|
||||||
// if unique was requested and if this error is duplicate, ignore processing it
|
// if unique was requested and if this error is duplicate, ignore processing it
|
||||||
let serializedError = "\(error)"
|
let serializedError = "\(error)"
|
||||||
if unique && errors.contains(serializedError) {
|
if unique && errors.contains(serializedError) {
|
||||||
@@ -39,7 +39,7 @@ class ErrorProcessing {
|
|||||||
var desc = ""
|
var desc = ""
|
||||||
switch (info){
|
switch (info){
|
||||||
case .localizedDescription:
|
case .localizedDescription:
|
||||||
title = (error.localizedTitle.map{$0+"\n"} ?? "")
|
title = !ignoreTitle ? (error.localizedTitle.map{$0+"\n"} ?? "") : ""
|
||||||
desc = error.localizedDescription
|
desc = error.localizedDescription
|
||||||
case .fullError:
|
case .fullError:
|
||||||
desc = serializedError
|
desc = serializedError
|
||||||
@@ -54,13 +54,14 @@ class ErrorProcessing {
|
|||||||
return getDescriptionText(error: error)
|
return getDescriptionText(error: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
private lazy var recurseErrors = { error in
|
|
||||||
self.getDescriptionText(error: error) // recursively process underlying error(s) if any
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDescriptionText(error: NSError) -> String{
|
func getDescriptionText(error: NSError,_ depth: Int = 0) -> String{
|
||||||
|
// closure
|
||||||
|
let recurseErrors = { error in
|
||||||
|
self.getDescriptionText(error: error, depth+1) // recursively process underlying error(s) if any
|
||||||
|
}
|
||||||
|
|
||||||
var description = ""
|
var description = ""
|
||||||
|
|
||||||
// process current error only if recur was not requested
|
// process current error only if recur was not requested
|
||||||
let processMoreErrors = recur ? recurseErrors : {_ in ""}
|
let processMoreErrors = recur ? recurseErrors : {_ in ""}
|
||||||
|
|
||||||
@@ -74,7 +75,9 @@ class ErrorProcessing {
|
|||||||
let error = underlyingError as NSError
|
let error = underlyingError as NSError
|
||||||
description += processError(error, getMoreErrors: processMoreErrors)
|
description += processError(error, getMoreErrors: processMoreErrors)
|
||||||
} else {
|
} else {
|
||||||
description += processError(error, getMoreErrors: processMoreErrors)
|
// ignore the title for the base error since we wanted this to be description
|
||||||
|
let isBaseError = (depth == 0)
|
||||||
|
description += processError(error, ignoreTitle: isBaseError, getMoreErrors: processMoreErrors)
|
||||||
}
|
}
|
||||||
return description
|
return description
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user