diff --git a/Brand/iOCNotes.plist b/Brand/iOCNotes.plist index 9af1843a..3321d8c6 100644 --- a/Brand/iOCNotes.plist +++ b/Brand/iOCNotes.plist @@ -97,10 +97,23 @@ UILaunchStoryboardName Launch Screen - UIMainStoryboardFile - Main_iPhone - UIMainStoryboardFile~ipad - Main_iPhone + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + SceneDelegate + + + + UIRequiredDeviceCapabilities armv7 diff --git a/Source/AppDelegate.swift b/Source/AppDelegate.swift index 03d622ab..43d8467f 100644 --- a/Source/AppDelegate.swift +++ b/Source/AppDelegate.swift @@ -15,7 +15,6 @@ import SwiftUI class AppDelegate: UIResponder, UIApplicationDelegate { var store = Store.shared - var window: UIWindow? var notesTableViewController: NotesTableViewController? /// @@ -53,8 +52,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } } - window?.tintColor = .ph_iconColor - if #available(iOS 15, *) { let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() @@ -90,26 +87,20 @@ class AppDelegate: UIResponder, UIApplicationDelegate { UITextField.appearance().textColor = .ph_textColor UITextView.appearance().tintColor = .ph_selectedTextColor - - let contentView = ContentView() - .environment(Store.shared) - let window = UIWindow(frame: UIScreen.main.bounds) - window.rootViewController = UIHostingController(rootView: contentView) - self.window = window - window.makeKeyAndVisible() - return true } - func applicationDidEnterBackground(_ application: UIApplication) { + /// + /// Scene lifecycle is adopted via ``SceneDelegate``; these handlers hold the shared behaviour it forwards. + /// + func handleDidEnterBackground() { notesTableViewController?.disableFetchedResultsController() updateFrcDelegateNeeded = true scheduleAppSync() } - func applicationWillResignActive(_ application: UIApplication) { - + func handleWillResignActive() { if !KeychainHelper.server.isEmpty, let server = URL(string: KeychainHelper.server), let scheme = server.scheme, let host = server.host, @@ -119,7 +110,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } } - func applicationDidBecomeActive(_ application: UIApplication) { + func handleDidBecomeActive() { store.synchronize() updateFrcDelegateIfNeeded() } @@ -169,7 +160,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { operationQueue.addOperation(operation) } - func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { + @discardableResult + func handleOpen(url: URL) -> Bool { if let scheme = url.scheme, scheme == "nextcloudnotes" { let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) if let queryItems = urlComponents?.queryItems, diff --git a/Source/SceneDelegate.swift b/Source/SceneDelegate.swift index f026fd5c..22faf1a0 100644 --- a/Source/SceneDelegate.swift +++ b/Source/SceneDelegate.swift @@ -9,48 +9,48 @@ import UIKit import SwiftUI +@objc(SceneDelegate) class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { - // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. - // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. - // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). guard let windowScene = (scene as? UIWindowScene) else { return } - + windowScene.title = "NextcloudNotes" - } - func sceneDidDisconnect(_ scene: UIScene) { - // Called as the scene is being released by the system. - // This occurs shortly after the scene enters the background, or when its session is discarded. - // Release any resources associated with this scene that can be re-created the next time the scene connects. - // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). + let contentView = ContentView() + .environment(Store.shared) + + let window = UIWindow(windowScene: windowScene) + window.tintColor = .ph_iconColor + window.rootViewController = UIHostingController(rootView: contentView) + self.window = window + window.makeKeyAndVisible() + + for context in connectionOptions.urlContexts { + _ = AppDelegate.shared.handleOpen(url: context.url) + } } func sceneDidBecomeActive(_ scene: UIScene) { - // Called when the scene has moved from an inactive state to an active state. - // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + AppDelegate.shared.handleDidBecomeActive() } func sceneWillResignActive(_ scene: UIScene) { - // Called when the scene will move from an active state to an inactive state. - // This may occur due to temporary interruptions (ex. an incoming phone call). - } - - func sceneWillEnterForeground(_ scene: UIScene) { - // Called as the scene transitions from the background to the foreground. - // Use this method to undo the changes made on entering the background. + AppDelegate.shared.handleWillResignActive() } func sceneDidEnterBackground(_ scene: UIScene) { - // Called as the scene transitions from the foreground to the background. - // Use this method to save data, release shared resources, and store enough scene-specific state information - // to restore the scene back to its current state. + AppDelegate.shared.handleDidEnterBackground() + } + func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { + for context in URLContexts { + _ = AppDelegate.shared.handleOpen(url: context.url) + } } - + } diff --git a/iOCNotes.xcodeproj/project.pbxproj b/iOCNotes.xcodeproj/project.pbxproj index 5db3ee2d..c1108ffd 100644 --- a/iOCNotes.xcodeproj/project.pbxproj +++ b/iOCNotes.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ D00CDFBF194E65B3007505E9 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D00CDFC1194E65B4007505E9 /* Localizable.strings */; }; D01067E22213BB5E0047E090 /* NoteProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01067E12213BB5E0047E090 /* NoteProtocol.swift */; }; D01067E42213BDF30047E090 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01067E32213BDF20047E090 /* AppDelegate.swift */; }; + D004DB7F23948F3D0080A7D1 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D004DB7E23948F3D0080A7D1 /* SceneDelegate.swift */; }; D01067E62213C17D0047E090 /* NotesTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01067E52213C17D0047E090 /* NotesTableViewController.swift */; }; D017D4241D3B03BE00B21443 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D017D4231D3B03BE00B21443 /* WebKit.framework */; }; D02256C71891FD7C0038232A /* defaults.plist in Resources */ = {isa = PBXBuildFile; fileRef = D02256C61891FD7C0038232A /* defaults.plist */; }; @@ -703,6 +704,7 @@ D0E60F5C277FADD5009CF78F /* AttributedStringKey.swift in Sources */, BD653F88231C43FA00D59A88 /* Constants.swift in Sources */, D01067E42213BDF30047E090 /* AppDelegate.swift in Sources */, + D004DB7F23948F3D0080A7D1 /* SceneDelegate.swift in Sources */, F3F734512C6FA550007C8C0B /* Notes.xcdatamodeld in Sources */, F7F0812B299D0B53006A2041 /* NCViewerNextcloudText.swift in Sources */, D0E38B0324930C410075B7F0 /* Throttler.swift in Sources */,