diff --git a/Wikipedia/Code/AppDelegate.swift b/Wikipedia/Code/AppDelegate.swift index 42066f55656..4f1df68033d 100644 --- a/Wikipedia/Code/AppDelegate.swift +++ b/Wikipedia/Code/AppDelegate.swift @@ -43,10 +43,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func applicationWillTerminate(_ application: UIApplication) { updateDynamicIconShortcutItems() } - - func application(_ application: UIApplication, willContinueUserActivityWithType userActivityType: String) -> Bool { - return true - } // MARK: UISceneSession Lifecycle diff --git a/Wikipedia/Code/NavigationStateController.swift b/Wikipedia/Code/NavigationStateController.swift index d7113c9a9df..a7152646fe9 100644 --- a/Wikipedia/Code/NavigationStateController.swift +++ b/Wikipedia/Code/NavigationStateController.swift @@ -25,12 +25,14 @@ final class NavigationStateController: NSObject { } guard let articleViewController = visibleArticleViewController(for: selectedNavigationController) else { + moc.navigationState = nil return } let info = Info(articleKey: articleViewController.articleURL.wmf_databaseKey) guard let stateToPersist = NavigationState.ViewController(kind: .article, presentation: .push, info: info) else { + moc.navigationState = nil return } diff --git a/Wikipedia/Code/SceneDelegate.swift b/Wikipedia/Code/SceneDelegate.swift index e8105ecf589..ed711c846a5 100644 --- a/Wikipedia/Code/SceneDelegate.swift +++ b/Wikipedia/Code/SceneDelegate.swift @@ -33,6 +33,18 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { return } + // scene(_ scene: UIScene, continue userActivity: NSUserActivity) and + // scene(_ scene: UIScene, openURLContexts URLContexts: Set) + // windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) + // are not called upon terminated state, so we need to handle them explicitly here. + if let userActivity = connectionOptions.userActivities.first { + processUserActivity(userActivity) + } else if !connectionOptions.urlContexts.isEmpty { + openURLContexts(connectionOptions.urlContexts) + } else if let shortcutItem = connectionOptions.shortcutItem { + processShortcutItem(shortcutItem) + } + UNUserNotificationCenter.current().delegate = appViewController appViewController.launchApp(in: window, waitToResumeApp: appNeedsResume) } @@ -63,10 +75,20 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) { - appViewController?.processShortcutItem(shortcutItem, completion: completionHandler) + processShortcutItem(shortcutItem, completionHandler: completionHandler) + } + + private func processShortcutItem(_ shortcutItem: UIApplicationShortcutItem, completionHandler: ((Bool) -> Void)? = nil) { + appViewController?.processShortcutItem(shortcutItem) { handled in + completionHandler?(handled) + } } func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { + processUserActivity(userActivity) + } + + private func processUserActivity(_ userActivity: NSUserActivity) { guard let appViewController else { return } @@ -99,7 +121,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { - + openURLContexts(URLContexts) + } + + private func openURLContexts(_ URLContexts: Set) { guard let appViewController else { return } diff --git a/Wikipedia/Code/WMFAppViewController.m b/Wikipedia/Code/WMFAppViewController.m index a725b6e54c0..62c95a241b5 100644 --- a/Wikipedia/Code/WMFAppViewController.m +++ b/Wikipedia/Code/WMFAppViewController.m @@ -384,9 +384,7 @@ - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { #pragma mark - Notifications - (void)appWillEnterForegroundWithNotification:(NSNotification *)note { - // Don't access anything that can't be accessed in the background without starting a background task. For example, don't use anything in the shared app container like all of the Core Data persistent stores - self.unprocessedUserActivity = nil; - self.unprocessedShortcutItem = nil; + } // When the user launches from a terminated state, resume might not finish before didBecomeActive, so these tasks are held until both items complete diff --git a/docs/url_schemes.md b/docs/url_schemes.md index 33f0ca76769..a236867e130 100644 --- a/docs/url_schemes.md +++ b/docs/url_schemes.md @@ -6,9 +6,9 @@ The URL scheme is `wikipedia://`. The following URLs are currently handled: | ------------------ | ---------------------------------------- | ---------------------------------------- | | Article | wikipedia://[site]/wiki/[page_id] | wikipedia://en.wikipedia.org/wiki/Red | | | https://[[site]/wiki/[page_id] | https://en.wikipedia.org/wiki/Red | -| Content | wikipedia://content | | +| Content | wikipedia://content | wikipedia://content/on-this-day/wikipedia.org/en/2024/08/15 | | Explore | wikipedia://explore | | | History | wikipedia://history | | -| Places | wikipedia://places[?WMFArticleURL=] | | +| Places | wikipedia://places[?WMFArticleURL=] | wikipedia://places/?WMFArticleURL=https://en.wikipedia.org/wiki/Dallas + | | Saved pages | wikipedia://saved | | -| Search | wikipedia://[site]/w/index.php?search=[query] | wikipedia://en.wikipedia.org/w/index.php?search=dog |