func unregister(_ id: UUID) { // Call cleanup callback if set onWindowClose?(id) windows.removeValue(forKey: id) // If this was the active window, switch to another if activeWindowId == id { activeWindowId = windows.keys.first } print("🪟 [WindowRegistry] Unregistered window: \(id)")}
The onWindowClose callback handles resource cleanup:
windowRegistry.onWindowClose = { [weak self] windowId in self?.splitManager.cleanupSplitState(for: windowId) self?.webViewCoordinator?.removeAllWebViews(for: windowId) // Clean up ephemeral profile if incognito window if let windowState = self?.windowRegistry.windows[windowId], windowState.isIncognito, let profileId = windowState.profileId { Task { await self?.profileManager.removeEphemeralProfile(for: windowId) } }}
The onActiveWindowChange callback synchronizes systems:
windowRegistry.onActiveWindowChange = { [weak self] window in // Update global current tab to match active window's tab if let currentTabId = window.currentTabId, let tab = self?.tabManager.allTabs().first(where: { $0.id == currentTabId }) { self?.tabManager.updateActiveTabState(tab) } // Update split view context self?.splitManager.setActiveWindow(window.id)}
@Observableclass BrowserWindowState: Identifiable { let id: UUID var currentTabId: UUID? var isIncognito: Bool = false var profileId: UUID? // Ephemeral tabs for incognito windows (not persisted) var ephemeralTabs: [Tab] = [] // Split view state var isSplit: Bool = false var leftTabId: UUID? var rightTabId: UUID? var activeSide: SplitSide = .left // Window-specific UI state var sidebarWidth: CGFloat = 280 var isFullscreen: Bool = false weak var tabManager: TabManager? weak var browserManager: BrowserManager?}
Key properties:
currentTabId: The active tab for this window
ephemeralTabs: Incognito tabs that are NOT persisted to disk
profileId: Profile for this window (persistent or ephemeral)
Window state is NOT persisted across app launches. Each launch creates fresh BrowserWindowState instances. Only tab state (via TabManager) is persisted.Rationale: Window positions, sizes, and split states are session-specific and should reset on relaunch.
func openIncognitoWindow() { let windowState = BrowserWindowState() windowState.isIncognito = true // Create ephemeral profile for this window let ephemeralProfile = profileManager.createEphemeralProfile(for: windowState.id) windowState.profileId = ephemeralProfile.id windowRegistry.register(windowState) // Open NSWindow with this state openNewWindow(with: windowState)}
windowRegistry.onWindowClose = { [weak self] windowId in guard let windowState = self?.windowRegistry.windows[windowId] else { return } if windowState.isIncognito { // Clean up ephemeral tabs (not persisted, just release references) windowState.ephemeralTabs.removeAll() // Destroy ephemeral profile and its data store Task { await self?.profileManager.removeEphemeralProfile(for: windowId) } }}