diff --git a/Builds.xcodeproj/project.pbxproj b/Builds.xcodeproj/project.pbxproj index 73999a4..548801b 100644 --- a/Builds.xcodeproj/project.pbxproj +++ b/Builds.xcodeproj/project.pbxproj @@ -77,6 +77,7 @@ D8A1224A2BD131C5002BDF42 /* BuildsPreviewHostWidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D8A122392BD131C4002BDF42 /* BuildsPreviewHostWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; D8A122502BD131E0002BDF42 /* BuildsCore in Frameworks */ = {isa = PBXBuildFile; productRef = D8A1224F2BD131E0002BDF42 /* BuildsCore */; }; D8A269B12BAA3B6800A0E19A /* ProgressSpinner.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8A269B02BAA3B6800A0E19A /* ProgressSpinner.swift */; }; + D8A4658C2BD1D0FF00CA2849 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8A4658B2BD1D0FF00CA2849 /* AppDelegate.swift */; }; D8ADD98F2B9E9E2700D314F1 /* DetailsPopover.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8ADD98E2B9E9E2700D314F1 /* DetailsPopover.swift */; }; D8ADD9912B9E9E5600D314F1 /* AnnotationList.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8ADD9902B9E9E5600D314F1 /* AnnotationList.swift */; }; D8ADD9932B9EA06800D314F1 /* WorkflowJobsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8ADD9922B9EA06800D314F1 /* WorkflowJobsList.swift */; }; @@ -241,6 +242,7 @@ D8A122452BD131C5002BDF42 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; D8A122472BD131C5002BDF42 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D8A269B02BAA3B6800A0E19A /* ProgressSpinner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressSpinner.swift; sourceTree = ""; }; + D8A4658B2BD1D0FF00CA2849 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; D8ADD98E2B9E9E2700D314F1 /* DetailsPopover.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailsPopover.swift; sourceTree = ""; }; D8ADD9902B9E9E5600D314F1 /* AnnotationList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnnotationList.swift; sourceTree = ""; }; D8ADD9922B9EA06800D314F1 /* WorkflowJobsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkflowJobsList.swift; sourceTree = ""; }; @@ -499,6 +501,7 @@ isa = PBXGroup; children = ( D8D413F228045535001BA6C0 /* Action.swift */, + D8A4658B2BD1D0FF00CA2849 /* AppDelegate.swift */, D8D413EE280454AA001BA6C0 /* ApplicationModel.swift */, D850F4DA2BAA709800CE1796 /* Confirmable.swift */, D850F4DC2BAA75F900CE1796 /* ConfirmableAction.swift */, @@ -972,6 +975,7 @@ D850F4DB2BAA709800CE1796 /* Confirmable.swift in Sources */, D866F250280350BC00FC6EBB /* PhoneSettingsView.swift in Sources */, D854FD852BB615D500DD31DD /* WorkflowCommands.swift in Sources */, + D8A4658C2BD1D0FF00CA2849 /* AppDelegate.swift in Sources */, D8CA0EF22B94110A00DAE758 /* TimeInterval.swift in Sources */, D8B49EE82BB76D4D0076E273 /* StatusButton.swift in Sources */, D86B1D302B9EA78000CA4E21 /* PopoverButton.swift in Sources */, @@ -1051,6 +1055,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = QS82QFHKWB; ENABLE_HARDENED_RUNTIME = YES; GCC_C_LANGUAGE_STANDARD = gnu17; @@ -1093,6 +1098,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "3rd Party Mac Developer Application"; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = QS82QFHKWB; "DEVELOPMENT_TEAM[sdk=macosx*]" = QS82QFHKWB; diff --git a/Builds.xcodeproj/xcshareddata/xcschemes/Builds.xcscheme b/Builds.xcodeproj/xcshareddata/xcschemes/Builds.xcscheme index 5e1c3ec..ef925e1 100644 --- a/Builds.xcodeproj/xcshareddata/xcschemes/Builds.xcscheme +++ b/Builds.xcodeproj/xcshareddata/xcschemes/Builds.xcscheme @@ -1,6 +1,6 @@ + BGTaskSchedulerPermittedIdentifiers + + uk.co.jbmorley.builds.tasks.refresh + CFBundleURLTypes @@ -36,6 +40,7 @@ UIBackgroundModes + fetch remote-notification diff --git a/Builds/Models/AppDelegate.swift b/Builds/Models/AppDelegate.swift new file mode 100644 index 0000000..6f59b2e --- /dev/null +++ b/Builds/Models/AppDelegate.swift @@ -0,0 +1,74 @@ +// Copyright (c) 2022-2024 Jason Morley +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import BackgroundTasks +import SwiftUI + +#if os(iOS) + +class AppDelegate: NSObject, UIApplicationDelegate { + + let applicationModel = ApplicationModel() + + @MainActor func application(_ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { + + // Background refresh handler. + BGTaskScheduler.shared.register(forTaskWithIdentifier: "uk.co.jbmorley.builds.tasks.refresh", using: nil) { task in + Task { + await self.applicationModel.refresh() + task.setTaskCompleted(success: true) + } + } + + NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, + object: nil, + queue: nil) { _ in + DispatchQueue.main.async { [weak self] in + self?.scheduleBackgroundRefresh() + } + } + + return true + } + + func scheduleBackgroundRefresh() { + let request = BGAppRefreshTaskRequest(identifier: "uk.co.jbmorley.builds.tasks.refresh") + request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) + do { + print("Scheduling background refresh...") + try BGTaskScheduler.shared.submit(request) + print("Success!") + } catch { + print("Could not schedule app refresh: \(error)") + } + } + +} + +#else + +@MainActor class AppDelegate: NSObject, NSApplicationDelegate { + + let applicationModel = ApplicationModel() + +} + +#endif