AppDelegate.swift 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import AppKit
  2. @MainActor
  3. final class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
  4. private var windowObservers: [NSObjectProtocol] = []
  5. func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
  6. false
  7. }
  8. func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
  9. if !flag {
  10. showMainWindow()
  11. }
  12. return true
  13. }
  14. func applicationDidFinishLaunching(_ notification: Notification) {
  15. installWindowObservers()
  16. configureMainWindows()
  17. }
  18. func applicationDidBecomeActive(_ notification: Notification) {
  19. configureMainWindows()
  20. showMainWindowIfNeeded()
  21. }
  22. func windowShouldClose(_ sender: NSWindow) -> Bool {
  23. sender.orderOut(nil)
  24. return false
  25. }
  26. func windowWillMiniaturize(_ sender: NSWindow) {
  27. guard isMainAppWindow(sender) else { return }
  28. RedditWebViewStore.shared.suspendMediaPlaybackForWindowMinimize()
  29. }
  30. func windowDidDeminiaturize(_ sender: NSWindow) {
  31. guard isMainAppWindow(sender) else { return }
  32. RedditWebViewStore.shared.resumeMediaPlaybackAfterWindowDeminiaturize()
  33. }
  34. func configureMainWindows() {
  35. for window in NSApp.windows where isMainAppWindow(window) {
  36. window.isReleasedWhenClosed = false
  37. if window.delegate !== self {
  38. window.delegate = self
  39. }
  40. }
  41. }
  42. private func installWindowObservers() {
  43. let center = NotificationCenter.default
  44. windowObservers = [
  45. center.addObserver(
  46. forName: NSWindow.didBecomeKeyNotification,
  47. object: nil,
  48. queue: .main
  49. ) { [weak self] _ in
  50. Task { @MainActor in
  51. self?.configureMainWindows()
  52. }
  53. },
  54. center.addObserver(
  55. forName: NSApplication.didUpdateNotification,
  56. object: nil,
  57. queue: .main
  58. ) { [weak self] _ in
  59. Task { @MainActor in
  60. self?.configureMainWindows()
  61. }
  62. },
  63. ]
  64. }
  65. private func showMainWindowIfNeeded() {
  66. guard !NSApp.windows.contains(where: { isMainAppWindow($0) && $0.isVisible }) else { return }
  67. showMainWindow()
  68. }
  69. private func showMainWindow() {
  70. guard let window = NSApp.windows.first(where: isMainAppWindow) else { return }
  71. window.makeKeyAndOrderFront(nil)
  72. NSApp.activate(ignoringOtherApps: true)
  73. }
  74. private func isMainAppWindow(_ window: NSWindow) -> Bool {
  75. guard window.canBecomeMain, !(window is NSPanel) else { return false }
  76. if window.title == "Sign in to Reddit" { return false }
  77. return window.level == .normal
  78. }
  79. }