import AppKit @MainActor final class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { private var windowObservers: [NSObjectProtocol] = [] private var shouldCenterMainWindowOnShow = true private var centeringDeadline: Date? private weak var trackedMainWindow: NSWindow? func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { false } func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool { if !flag { showMainWindow() } return true } func applicationDidFinishLaunching(_ notification: Notification) { installWindowObservers() configureMainWindows() beginCenteringMainWindow() } func applicationDidBecomeActive(_ notification: Notification) { configureMainWindows() showMainWindowIfNeeded() RedditWebViewStore.shared.handleApplicationDidBecomeActive() } func windowShouldClose(_ sender: NSWindow) -> Bool { if isMainAppWindow(sender) { trackedMainWindow = sender shouldCenterMainWindowOnShow = true centeringDeadline = nil } sender.orderOut(nil) return false } func windowWillMiniaturize(_ sender: NSWindow) { guard isMainAppWindow(sender) else { return } RedditWebViewStore.shared.suspendMediaPlaybackForWindowMinimize() } func windowDidDeminiaturize(_ sender: NSWindow) { guard isMainAppWindow(sender) else { return } RedditWebViewStore.shared.resumeMediaPlaybackAfterWindowDeminiaturize() } func windowDidMove(_ sender: NSWindow) { guard isMainAppWindow(sender), isCenteringMainWindow else { return } AppWindow.centerOnScreen(sender) } func configureMainWindows() { for window in NSApp.windows where isMainAppWindow(window) { trackedMainWindow = window window.isReleasedWhenClosed = false window.isRestorable = false window.setFrameAutosaveName("") if window.delegate !== self { window.delegate = self } } } func centerMainWindow() { beginCenteringMainWindow() } private var isCenteringMainWindow: Bool { guard shouldCenterMainWindowOnShow else { return false } if let centeringDeadline { return Date() < centeringDeadline } return true } private func beginCenteringMainWindow() { shouldCenterMainWindowOnShow = true centeringDeadline = Date().addingTimeInterval(0.6) centerMainWindowIfNeeded() } private func finishCenteringMainWindow() { shouldCenterMainWindowOnShow = false centeringDeadline = nil } private func centerMainWindowIfNeeded() { guard isCenteringMainWindow else { return } guard let window = NSApp.windows.first(where: isMainAppWindow) else { return } let centerAction = { [weak self] in guard let self, self.isCenteringMainWindow else { return } AppWindow.centerOnScreen(window) } centerAction() DispatchQueue.main.async(execute: centerAction) DispatchQueue.main.asyncAfter(deadline: .now() + 0.15, execute: centerAction) DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) { [weak self] in centerAction() self?.finishCenteringMainWindow() } } private func installWindowObservers() { let center = NotificationCenter.default windowObservers = [ center.addObserver( forName: NSWindow.didBecomeKeyNotification, object: nil, queue: .main ) { [weak self] _ in Task { @MainActor in self?.configureMainWindows() } }, center.addObserver( forName: NSApplication.didUpdateNotification, object: nil, queue: .main ) { [weak self] _ in Task { @MainActor in self?.configureMainWindows() } }, ] } func showMainWindow() { configureMainWindows() guard let window = resolvedMainWindow() else { return } trackedMainWindow = window beginCenteringMainWindow() if window.isMiniaturized { window.deminiaturize(nil) } window.collectionBehavior.insert(.moveToActiveSpace) window.orderFrontRegardless() window.makeKeyAndOrderFront(nil) NSApp.activate(ignoringOtherApps: true) } private func showMainWindowIfNeeded() { guard !NSApp.windows.contains(where: { isMainAppWindow($0) && $0.isVisible && !$0.isMiniaturized }) else { return } showMainWindow() } private func resolvedMainWindow() -> NSWindow? { if let trackedMainWindow, NSApp.windows.contains(trackedMainWindow) { return trackedMainWindow } if let visible = NSApp.windows.first(where: { isMainAppWindow($0) && $0.isVisible }) { return visible } return NSApp.windows.first(where: isMainAppWindow) } private func isMainAppWindow(_ window: NSWindow) -> Bool { if window === trackedMainWindow { return true } guard !(window is NSPanel), window.level == .normal else { return false } if window.title == "Sign in to Reddit" { return false } return window.canBecomeKey || window.canBecomeMain } }