mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
Supports removing inactive apps from My Apps
This commit is contained in:
@@ -22,6 +22,8 @@ extension UserDefaults
|
||||
|
||||
@NSManaged var legacySideloadedApps: [String]?
|
||||
|
||||
@NSManaged var isLegacyDeactivationSupported: Bool
|
||||
|
||||
var activeAppsLimit: Int? {
|
||||
get {
|
||||
return self._activeAppsLimit?.intValue
|
||||
@@ -41,6 +43,9 @@ extension UserDefaults
|
||||
|
||||
func registerDefaults()
|
||||
{
|
||||
self.register(defaults: [#keyPath(UserDefaults.isBackgroundRefreshEnabled): true])
|
||||
self.register(defaults: [
|
||||
#keyPath(UserDefaults.isBackgroundRefreshEnabled): true,
|
||||
#keyPath(UserDefaults.isLegacyDeactivationSupported): false
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,6 +344,48 @@ extension AppManager
|
||||
self.run([deactivateAppOperation], context: context, requiresSerialQueue: true)
|
||||
}
|
||||
|
||||
func remove(_ installedApp: InstalledApp, completionHandler: @escaping (Result<Void, Error>) -> Void)
|
||||
{
|
||||
let authenticationContext = AuthenticatedOperationContext()
|
||||
let appContext = InstallAppOperationContext(bundleIdentifier: installedApp.bundleIdentifier, authenticatedContext: authenticationContext)
|
||||
appContext.installedApp = installedApp
|
||||
|
||||
let removeAppOperation = RSTAsyncBlockOperation { (operation) in
|
||||
DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in
|
||||
let installedApp = context.object(with: installedApp.objectID) as! InstalledApp
|
||||
context.delete(installedApp)
|
||||
|
||||
do { try context.save() }
|
||||
catch { appContext.error = error }
|
||||
|
||||
operation.finish()
|
||||
}
|
||||
}
|
||||
|
||||
let removeAppBackupOperation = RemoveAppBackupOperation(context: appContext)
|
||||
removeAppBackupOperation.resultHandler = { (result) in
|
||||
switch result
|
||||
{
|
||||
case .success: break
|
||||
case .failure(let error): print("Failed to remove app backup.", error)
|
||||
}
|
||||
|
||||
// Throw the error from removeAppOperation,
|
||||
// since that's the error we really care about.
|
||||
if let error = appContext.error
|
||||
{
|
||||
completionHandler(.failure(error))
|
||||
}
|
||||
else
|
||||
{
|
||||
completionHandler(.success(()))
|
||||
}
|
||||
}
|
||||
removeAppBackupOperation.addDependency(removeAppOperation)
|
||||
|
||||
self.run([removeAppOperation, removeAppBackupOperation], context: authenticationContext)
|
||||
}
|
||||
|
||||
func installationProgress(for app: AppProtocol) -> Progress?
|
||||
{
|
||||
let progress = self.installationProgress[app.bundleIdentifier]
|
||||
|
||||
@@ -960,15 +960,31 @@ private extension MyAppsViewController
|
||||
|
||||
func remove(_ installedApp: InstalledApp)
|
||||
{
|
||||
let alertController = UIAlertController(title: nil, message: NSLocalizedString("Removing a sideloaded app only removes it from AltStore. You must also delete it from the home screen to fully uninstall the app.", comment: ""), preferredStyle: .actionSheet)
|
||||
let title = String(format: NSLocalizedString("Remove “%@” from AltStore?", comment: ""), installedApp.name)
|
||||
let message: String
|
||||
|
||||
if UserDefaults.standard.isLegacyDeactivationSupported
|
||||
{
|
||||
message = NSLocalizedString("You must also delete it from the home screen to fully uninstall the app.", comment: "")
|
||||
}
|
||||
else
|
||||
{
|
||||
message = NSLocalizedString("This will also erase all backup data for this app.", comment: "")
|
||||
}
|
||||
|
||||
let alertController = UIAlertController(title: title, message: message, preferredStyle: .actionSheet)
|
||||
alertController.addAction(.cancel)
|
||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Remove", comment: ""), style: .destructive, handler: { (action) in
|
||||
DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in
|
||||
let installedApp = context.object(with: installedApp.objectID) as! InstalledApp
|
||||
context.delete(installedApp)
|
||||
|
||||
do { try context.save() }
|
||||
catch { print("Failed to remove sideloaded app.", error) }
|
||||
AppManager.shared.remove(installedApp) { (result) in
|
||||
switch result
|
||||
{
|
||||
case .success: break
|
||||
case .failure(let error):
|
||||
DispatchQueue.main.async {
|
||||
let toastView = ToastView(error: error)
|
||||
toastView.show(in: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
@@ -1161,39 +1177,43 @@ extension MyAppsViewController
|
||||
self.remove(installedApp)
|
||||
}
|
||||
|
||||
if installedApp.bundleIdentifier == StoreApp.altstoreAppID
|
||||
guard installedApp.bundleIdentifier != StoreApp.altstoreAppID else {
|
||||
return [refreshAction]
|
||||
}
|
||||
|
||||
if installedApp.isActive
|
||||
{
|
||||
actions = [refreshAction]
|
||||
actions.append(refreshAction)
|
||||
actions.append(deactivateAction)
|
||||
}
|
||||
else
|
||||
{
|
||||
if installedApp.isActive
|
||||
{
|
||||
if UserDefaults.standard.activeAppsLimit != nil
|
||||
{
|
||||
actions = [refreshAction, deactivateAction]
|
||||
}
|
||||
else
|
||||
{
|
||||
actions = [refreshAction]
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
actions.append(activateAction)
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
actions.append(removeAction)
|
||||
#else
|
||||
if (UserDefaults.standard.legacySideloadedApps ?? []).contains(installedApp.bundleIdentifier)
|
||||
{
|
||||
// Only display option for legacy sideloaded apps.
|
||||
actions.append(removeAction)
|
||||
}
|
||||
#endif
|
||||
actions.append(activateAction)
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
if installedApp.bundleIdentifier != StoreApp.altstoreAppID
|
||||
{
|
||||
actions.append(removeAction)
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (UserDefaults.standard.legacySideloadedApps ?? []).contains(installedApp.bundleIdentifier)
|
||||
{
|
||||
// Legacy sideloaded app, so can't detect if it's deleted.
|
||||
actions.append(removeAction)
|
||||
}
|
||||
else if !UserDefaults.standard.isLegacyDeactivationSupported && !installedApp.isActive
|
||||
{
|
||||
// Inactive apps are actually deleted, so we need another way
|
||||
// for user to remove them from AltStore.
|
||||
actions.append(removeAction)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return actions
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user