From 0796b6800164f49b9de3662d6b50d14341b8dca9 Mon Sep 17 00:00:00 2001 From: Brandon-T Date: Thu, 7 Dec 2023 13:56:36 -0500 Subject: [PATCH] Fix #8517: Update logic for multi-window on iPhone (#8531) --- App/iOS/Delegates/SceneDelegate.swift | 131 +++++++++++------------- Sources/Brave/Migration/Migration.swift | 18 ++-- 2 files changed, 72 insertions(+), 77 deletions(-) diff --git a/App/iOS/Delegates/SceneDelegate.swift b/App/iOS/Delegates/SceneDelegate.swift index 6db6e29cba2..7ec96982598 100644 --- a/App/iOS/Delegates/SceneDelegate.swift +++ b/App/iOS/Delegates/SceneDelegate.swift @@ -439,89 +439,42 @@ extension SceneDelegate { let isPrivate: Bool let urlToOpen: URL? - if let userActivity = userActivity { - // Restore the scene with the WindowID from the User-Activity - let windowInfo = BrowserState.getWindowInfo(from: userActivity) - windowId = UUID(uuidString: windowInfo.windowId ?? "") ?? UUID() - isPrivate = windowInfo.isPrivate - urlToOpen = windowInfo.openURL - privateBrowsingManager.isPrivateBrowsing = isPrivate - - // Create a new session window - SessionWindow.createWindow(isPrivate: isPrivate, isSelected: true, uuid: windowId) - - scene.userActivity = BrowserState.userActivity(for: windowId.uuidString, isPrivate: isPrivate) - BrowserState.setWindowInfo(for: scene.session, windowId: windowId.uuidString, isPrivate: isPrivate) + if UIApplication.shared.supportsMultipleScenes { + let windowInfo: BrowserState.SessionState + if let userActivity = userActivity { + windowInfo = BrowserState.getWindowInfo(from: userActivity) + } else { + windowInfo = BrowserState.getWindowInfo(from: scene.session) + } - Logger.module.info("[SCENE] - USER ACTIVITY RESTORED") - } else { - let windowInfo = BrowserState.getWindowInfo(from: scene.session) - if let sceneWindowId = windowInfo.windowId, - let windowUUID = UUID(uuidString: sceneWindowId) { - - // Restore the scene from the Session's User-Info WindowID + if let existingWindowId = windowInfo.windowId, + let windowUUID = UUID(uuidString: existingWindowId) { + // Restore the scene from the User-Info WindowID windowId = windowUUID isPrivate = windowInfo.isPrivate privateBrowsingManager.isPrivateBrowsing = windowInfo.isPrivate urlToOpen = windowInfo.openURL - scene.userActivity = BrowserState.userActivity(for: windowId.uuidString, isPrivate: isPrivate) - BrowserState.setWindowInfo(for: scene.session, windowId: windowId.uuidString, isPrivate: isPrivate) - - Logger.module.info("[SCENE] - SCENE SESSION RESTORED") - } else if UIApplication.shared.supportsMultipleScenes { - if let activeWindowId = SessionWindow.getActiveWindow(context: DataController.swiftUIContext)?.windowId { - let activeSession = UIApplication.shared.openSessions - .compactMap({ BrowserState.getWindowInfo(from: $0) }) - .first(where: { $0.windowId == activeWindowId.uuidString }) - - if activeSession != nil { - // An existing window is already active on screen - // So create a new window - windowId = UUID() - SessionWindow.createWindow(isPrivate: false, isSelected: true, uuid: windowId) - Logger.module.info("[SCENE] - CREATED NEW WINDOW") - } else { - // Restore the active window since none is active on screen - windowId = activeWindowId - Logger.module.info("[SCENE] - RESTORING ACTIVE WINDOW ID") - } - } else { - // Should be impossible to get here. There must always be an active window. - // However, if for some reason there is none, then we should create one. - windowId = UUID() - SessionWindow.createWindow(isPrivate: false, isSelected: true, uuid: windowId) - Logger.module.info("[SCENE] - WE HIT THE IMPOSSIBLE! - CREATING A NEW WINDOW ON MULTI-SCENE DEVICE!") - } - - isPrivate = false - privateBrowsingManager.isPrivateBrowsing = false - urlToOpen = nil - - scene.userActivity = BrowserState.userActivity(for: windowId.uuidString, isPrivate: false) - BrowserState.setWindowInfo(for: scene.session, windowId: windowId.uuidString, isPrivate: false) + // Create a new session window if it does not already exist + SessionWindow.createWindow(isPrivate: isPrivate, isSelected: true, uuid: windowId) + Logger.module.info("[SCENE] - SESSION RESTORED") } else { - // iPhones don't have a userActivity or session user info - if let activeWindowId = SessionWindow.getActiveWindow(context: DataController.swiftUIContext)?.windowId { - // Restore the active window since none is active on screen - windowId = activeWindowId - Logger.module.info("[SCENE] - RESTORING ACTIVE WINDOW ID") - } else { - // Should be impossible to get here. There must always be an active window. - // However, if for some reason there is none, then we should create one. - windowId = UUID() - SessionWindow.createWindow(isPrivate: false, isSelected: true, uuid: windowId) - Logger.module.info("[SCENE] - WE HIT THE IMPOSSIBLE! - CREATING A NEW WINDOW!") - } - + // Try to restore active window + windowId = restoreOrCreateWindow().windowId isPrivate = false privateBrowsingManager.isPrivateBrowsing = false urlToOpen = nil - - scene.userActivity = BrowserState.userActivity(for: windowId.uuidString, isPrivate: false) - BrowserState.setWindowInfo(for: scene.session, windowId: windowId.uuidString, isPrivate: false) } + } else { + // iPhones don't care about user-activity or session info since it will always have one window anyway + windowId = restoreOrCreateWindow().windowId + isPrivate = false + privateBrowsingManager.isPrivateBrowsing = false + urlToOpen = nil } + + scene.userActivity = BrowserState.userActivity(for: windowId.uuidString, isPrivate: false) + BrowserState.setWindowInfo(for: scene.session, windowId: windowId.uuidString, isPrivate: false) // Create a browser instance let browserViewController = BrowserViewController( @@ -574,6 +527,42 @@ extension SceneDelegate { return browserViewController } + + private func restoreOrCreateWindow() -> (windowId: UUID, isPrivate: Bool, urlToOpen: URL?) { + // Find active windows/sessions + let activeWindow = SessionWindow.getActiveWindow(context: DataController.swiftUIContext) + let activeSession = UIApplication.shared.openSessions + .compactMap({ BrowserState.getWindowInfo(from: $0) }) + .first(where: { $0.windowId == activeWindow?.windowId.uuidString }) + + if activeSession != nil { + if !UIApplication.shared.supportsMultipleScenes { + // iPhones should not create new windows + return (activeWindow!.windowId, false, nil) + } + + // An existing window is already active on screen + // So create a new window + let windowId = UUID() + SessionWindow.createWindow(isPrivate: false, isSelected: true, uuid: windowId) + Logger.module.info("[SCENE] - CREATED NEW WINDOW") + return (windowId, false, nil) + } + + // Restore the active window if possible + let windowId: UUID + if !UIApplication.shared.supportsMultipleScenes { + // iPhones don't have multi-window so we can restore the active window OR first window found + windowId = activeWindow?.windowId ?? SessionWindow.all().first?.windowId ?? UUID() + } else { + windowId = activeWindow?.windowId ?? UUID() + } + + // Create a new session window if it does not already exist + SessionWindow.createWindow(isPrivate: false, isSelected: true, uuid: windowId) + Logger.module.info("[SCENE] - RESTORING ACTIVE WINDOW OR CREATING A NEW WINDOW") + return (windowId, false, nil) + } } extension SceneDelegate: UIViewControllerRestoration { diff --git a/Sources/Brave/Migration/Migration.swift b/Sources/Brave/Migration/Migration.swift index c88d2191183..6cb3d0f24eb 100644 --- a/Sources/Brave/Migration/Migration.swift +++ b/Sources/Brave/Migration/Migration.swift @@ -55,10 +55,16 @@ public class Migration { public static func migrateLostTabsActiveWindow() { if UIApplication.shared.supportsMultipleScenes { return } - if Preferences.Migration.lostTabsWindowIDMigrationOne.value { return } + if Preferences.Migration.lostTabsWindowIDMigration.value { return } - let sessionWindows = SessionWindow.all() - guard let activeWindow = sessionWindows.first(where: { $0.isSelected }) else { + var sessionWindows = SessionWindow.all() + var activeWindow = sessionWindows.first(where: { $0.isSelected }) + if activeWindow == nil { + activeWindow = sessionWindows.removeFirst() + } + + guard let activeWindow = activeWindow else { + Preferences.Migration.lostTabsWindowIDMigration.value = true return } @@ -93,7 +99,7 @@ public class Migration { } } - Preferences.Migration.lostTabsWindowIDMigrationOne.value = true + Preferences.Migration.lostTabsWindowIDMigration.value = true } public static func postCoreDataInitMigrations() { @@ -158,8 +164,8 @@ fileprivate extension Preferences { key: "migration.ad-block-and-tracking-protection-shield-level-completed", default: false ) - static let lostTabsWindowIDMigrationOne = Option( - key: "migration.lost-tabs-window-id-one", + static let lostTabsWindowIDMigration = Option( + key: "migration.lost-tabs-window-id-two", default: !UIApplication.shared.supportsMultipleScenes ) }