mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-12 08:13:26 +01:00
Prioritizes app refresh order
Tries to refresh apps that are about to expire first, and then always refreshes AltStore itself last, since refreshing AltStore means that the app will quit.
This commit is contained in:
@@ -63,7 +63,7 @@ extension AppDelegate
|
||||
{
|
||||
private func prepareForBackgroundFetch()
|
||||
{
|
||||
// Fetch every 6 hours.
|
||||
// "Fetch" every hour, but then refresh only those that need to be refreshed (so we don't drain the battery).
|
||||
UIApplication.shared.setMinimumBackgroundFetchInterval(60 * 60)
|
||||
|
||||
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (success, error) in
|
||||
@@ -72,49 +72,100 @@ extension AppDelegate
|
||||
|
||||
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)
|
||||
{
|
||||
let installedApps = InstalledApp.fetchAppsForBackgroundRefresh(in: DatabaseManager.shared.viewContext)
|
||||
guard !installedApps.isEmpty else { return completionHandler(.noData) }
|
||||
|
||||
print("Apps to refresh:", installedApps.map { $0.app.identifier })
|
||||
|
||||
ServerManager.shared.startDiscovering()
|
||||
|
||||
let content = UNMutableNotificationContent()
|
||||
content.title = NSLocalizedString("Refreshing apps...", comment: "")
|
||||
|
||||
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.01, repeats: false)
|
||||
|
||||
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
|
||||
UNUserNotificationCenter.current().add(request) { (error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
// Wait a few seconds so we have a chance to discover nearby AltServers.
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
|
||||
let installedApps = InstalledApp.all(in: DatabaseManager.shared.viewContext)
|
||||
|
||||
_ = AppManager.shared.refresh(installedApps, presentingViewController: nil) { (result) in
|
||||
func finish(_ result: Result<[String: Result<InstalledApp, Error>], Error>)
|
||||
{
|
||||
ServerManager.shared.stopDiscovering()
|
||||
|
||||
let content = UNMutableNotificationContent()
|
||||
var shouldPresentAlert = true
|
||||
|
||||
do
|
||||
{
|
||||
let results = try result.get()
|
||||
shouldPresentAlert = !results.isEmpty
|
||||
|
||||
for (_, result) in results
|
||||
{
|
||||
guard case let .failure(error) = result else { continue }
|
||||
throw error
|
||||
}
|
||||
|
||||
content.title = "Refreshed Apps!"
|
||||
content.body = "Successfully refreshed all apps."
|
||||
|
||||
completionHandler(.newData)
|
||||
content.title = NSLocalizedString("Refreshed all apps!", comment: "")
|
||||
}
|
||||
catch
|
||||
{
|
||||
print("Failed to refresh apps in background.", error)
|
||||
|
||||
content.title = "Failed to Refresh Apps"
|
||||
content.title = NSLocalizedString("Failed to Refresh Apps", comment: "")
|
||||
content.body = error.localizedDescription
|
||||
|
||||
completionHandler(.failed)
|
||||
shouldPresentAlert = true
|
||||
}
|
||||
|
||||
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.1, repeats: false)
|
||||
|
||||
let request = UNNotificationRequest(identifier: "RefreshedApps", content: content, trigger: trigger)
|
||||
UNUserNotificationCenter.current().add(request) { (error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
if shouldPresentAlert
|
||||
{
|
||||
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.01, repeats: false)
|
||||
|
||||
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
|
||||
UNUserNotificationCenter.current().add(request) { (error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch result
|
||||
{
|
||||
case .failure(ConnectionError.serverNotFound): completionHandler(.newData)
|
||||
case .failure: completionHandler(.failed)
|
||||
case .success: completionHandler(.newData)
|
||||
}
|
||||
}
|
||||
|
||||
let group = AppManager.shared.refresh(installedApps, presentingViewController: nil)
|
||||
group.beginInstallationHandler = { (installedApp) in
|
||||
guard installedApp.app.identifier == App.altstoreAppID else { return }
|
||||
|
||||
// We're starting to install AltStore, which means the app is about to quit.
|
||||
// So, we say we were successful even though we technically don't know 100% yet.
|
||||
// Also since AltServer has already received the app, it can finish installing even if we're no longer running in background.
|
||||
|
||||
if let error = group.error
|
||||
{
|
||||
finish(.failure(error))
|
||||
}
|
||||
else
|
||||
{
|
||||
var results = group.results
|
||||
results[installedApp.app.identifier] = .success(installedApp)
|
||||
|
||||
finish(.success(results))
|
||||
}
|
||||
}
|
||||
group.completionHandler = { (result) in
|
||||
finish(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user