[Feature]: Import external backup, Restore n-1 backup if current backup is corrupted by importing wrong directory

This commit is contained in:
Magesh K
2025-01-07 18:24:25 +05:30
parent 4e71e5d879
commit 5db45565f3
4 changed files with 248 additions and 14 deletions

View File

@@ -1357,6 +1357,50 @@ private extension MyAppsViewController
self.present(alertController, animated: true, completion: nil)
}
func importBackup(for installedApp: InstalledApp){
ImportExport.importBackup(presentingViewController: self, for: installedApp) { result in
var toast: ToastView
switch(result){
case .failure(let error):
toast = ToastView(error: error, opensLog: false)
break
case .success:
toast = ToastView(text: "Import Backup successful for \(installedApp.name)",
detailText: "Use 'Restore Backup' option to restore data from this imported backup")
}
DispatchQueue.main.async {
toast.show(in: self)
}
}
}
private func getPreviousBackupURL(_ installedApp: InstalledApp) -> URL
{
let backupURL = FileManager.default.backupDirectoryURL(for: installedApp)!
let backupBakURL = ImportExport.getPreviousBackupURL(backupURL)
return backupBakURL
}
func restorePreviousBackup(for installedApp: InstalledApp){
let backupURL = FileManager.default.backupDirectoryURL(for: installedApp)!
let backupBakURL = ImportExport.getPreviousBackupURL(backupURL)
// backupBakURL is expected to exist at this point, this needs to be ensured by caller logic
// or invoke this action only when backupBakURL exists
// delete the current backup
if(FileManager.default.fileExists(atPath: backupURL.path)){
try! FileManager.default.removeItem(at: backupURL)
}
// restore the previously saved backup as current backup
// (don't delete the N-1 backup yet so copy instead of move)
try! FileManager.default.copyItem(at: backupBakURL, to: backupURL)
//perform restore of data from the backup
restore(installedApp)
}
func restore(_ installedApp: InstalledApp)
{
guard minimuxerStatus else { return }
@@ -1810,9 +1854,17 @@ extension MyAppsViewController
self.exportBackup(for: installedApp)
}
let restoreBackupAction = UIAction(title: NSLocalizedString("Restore Backup", comment: ""), image: UIImage(systemName: "arrow.down.doc")) { (action) in
let importBackupAction = UIAction(title: NSLocalizedString("Import Backup", comment: ""), image: UIImage(systemName: "arrow.down.doc")) { (action) in
self.importBackup(for: installedApp)
}
let restoreBackupAction = UIAction(title: NSLocalizedString("Restore Backup", comment: "Restores the last or current backup of this app"), image: UIImage(systemName: "arrow.down.doc")) { (action) in
self.restore(installedApp)
}
let restorePreviousBackupAction = UIAction(title: NSLocalizedString("Restore Previous Backup", comment: "Restores the backup saved before the current backup was created."), image: UIImage(systemName: "arrow.down.doc")) { (action) in
self.restorePreviousBackup(for: installedApp)
}
let chooseIconAction = UIAction(title: NSLocalizedString("Photos", comment: ""), image: UIImage(systemName: "photo")) { (action) in
self.chooseIcon(for: installedApp)
@@ -1878,11 +1930,11 @@ extension MyAppsViewController
var outError: NSError? = nil
self.coordinator.coordinate(readingItemAt: backupDirectoryURL, options: [.withoutChanges], error: &outError) { (backupDirectoryURL) in
#if DEBUG
backupExists = true
#else
// #if DEBUG
// backupExists = true
// #else
backupExists = FileManager.default.fileExists(atPath: backupDirectoryURL.path)
#endif
// #endif
}
if backupExists
@@ -1903,16 +1955,23 @@ extension MyAppsViewController
if installedApp.isActive
{
actions.append(deactivateAction)
// import backup into shared backups dir is allowed
actions.append(importBackupAction)
}
#if DEBUG
if installedApp.bundleIdentifier != StoreApp.altstoreAppID
{
actions.append(removeAction)
// have an option to restore the n-1 backup
if FileManager.default.fileExists(atPath: getPreviousBackupURL(installedApp).path){
actions.append(restorePreviousBackupAction)
}
#else
// #if DEBUG
// if installedApp.bundleIdentifier != StoreApp.altstoreAppID
// {
// actions.append(removeAction)
// }
//
// #else
if (UserDefaults.standard.legacySideloadedApps ?? []).contains(installedApp.bundleIdentifier)
{
@@ -1926,9 +1985,29 @@ extension MyAppsViewController
actions.append(removeAction)
}
#endif
// #endif
}
// Change the order of entries to make changes to how the context menu is displayed
let orderedActions = [
openMenu,
refreshAction,
activateAction,
jitAction,
changeIconMenu,
backupAction,
exportBackupAction,
importBackupAction,
restoreBackupAction,
restorePreviousBackupAction,
deactivateAction,
removeAction,
]
// remove non-selected actions from the all-actions ordered list
// this way the declaration of the action in the above code doesn't determine the context menu order
actions = orderedActions.filter{ action in actions.contains(action)}
var title: String?
if let storeApp = installedApp.storeApp, storeApp.isPledgeRequired, !storeApp.isPledged