|
|
@@ -7,10 +7,41 @@
|
|
7
|
7
|
|
|
8
|
8
|
import Cocoa
|
|
9
|
9
|
|
|
|
10
|
+enum AppWindowConfiguration {
|
|
|
11
|
+ static let defaultContentSize = NSSize(width: 1120, height: 750)
|
|
|
12
|
+ static let minimumContentSize = NSSize(width: 1120, height: 750)
|
|
|
13
|
+
|
|
|
14
|
+ @MainActor
|
|
|
15
|
+ static func apply(to window: NSWindow) {
|
|
|
16
|
+ window.minSize = minimumContentSize
|
|
|
17
|
+ window.isRestorable = false
|
|
|
18
|
+ window.title = "App for Indeed"
|
|
|
19
|
+ window.styleMask.insert(.fullSizeContentView)
|
|
|
20
|
+ window.titlebarAppearsTransparent = true
|
|
|
21
|
+ window.titleVisibility = .hidden
|
|
|
22
|
+ window.isMovableByWindowBackground = true
|
|
|
23
|
+
|
|
|
24
|
+ let targetContent = NSRect(origin: .zero, size: defaultContentSize)
|
|
|
25
|
+ let targetFrame = window.frameRect(forContentRect: targetContent)
|
|
|
26
|
+ var frame = targetFrame
|
|
|
27
|
+ let current = window.frame
|
|
|
28
|
+ frame.origin.x = current.midX - frame.width / 2
|
|
|
29
|
+ frame.origin.y = current.midY - frame.height / 2
|
|
|
30
|
+ window.setFrame(frame, display: false, animate: false)
|
|
|
31
|
+ window.setContentSize(defaultContentSize)
|
|
|
32
|
+ }
|
|
|
33
|
+
|
|
|
34
|
+ @MainActor
|
|
|
35
|
+ static func mainWindow(in app: NSApplication = .shared) -> NSWindow? {
|
|
|
36
|
+ app.mainWindow
|
|
|
37
|
+ ?? app.keyWindow
|
|
|
38
|
+ ?? app.windows.first(where: { $0.isVisible && $0.canBecomeKey })
|
|
|
39
|
+ }
|
|
|
40
|
+}
|
|
|
41
|
+
|
|
10
|
42
|
@main
|
|
11
|
43
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
|
12
|
44
|
|
|
13
|
|
- private let minimumWindowSize = NSSize(width: 1120, height: 700)
|
|
14
|
45
|
/// Avoids hammering StoreKit when `didBecomeActive` fires in quick succession (e.g. after system sheets).
|
|
15
|
46
|
private var lastSubscriptionRefreshAt: Date?
|
|
16
|
47
|
|
|
|
@@ -45,23 +76,23 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|
45
|
76
|
NotificationCenter.default.post(name: .subscriptionStatusDidChange, object: nil)
|
|
46
|
77
|
}
|
|
47
|
78
|
NSApp.activate(ignoringOtherApps: true)
|
|
|
79
|
+ applyDefaultWindowSize()
|
|
|
80
|
+ }
|
|
|
81
|
+
|
|
|
82
|
+ @MainActor
|
|
|
83
|
+ private func applyDefaultWindowSize() {
|
|
48
|
84
|
DispatchQueue.main.async { [weak self] in
|
|
49
|
|
- guard
|
|
50
|
|
- let self,
|
|
51
|
|
- let window = NSApp.windows.first
|
|
52
|
|
- else { return }
|
|
53
|
|
-
|
|
54
|
|
- window.minSize = self.minimumWindowSize
|
|
55
|
|
- window.setContentSize(self.minimumWindowSize)
|
|
56
|
|
- // Prevents "className=(null)" restoration warnings; layout is applied each launch.
|
|
57
|
|
- window.isRestorable = false
|
|
58
|
|
- window.title = "App for Indeed"
|
|
59
|
|
- window.styleMask.insert(.fullSizeContentView)
|
|
60
|
|
- window.titlebarAppearsTransparent = true
|
|
61
|
|
- window.titleVisibility = .hidden
|
|
62
|
|
- window.isMovableByWindowBackground = true
|
|
|
85
|
+ guard let self, let window = AppWindowConfiguration.mainWindow() else { return }
|
|
|
86
|
+ AppWindowConfiguration.apply(to: window)
|
|
63
|
87
|
window.center()
|
|
64
|
88
|
window.makeKeyAndOrderFront(nil)
|
|
|
89
|
+
|
|
|
90
|
+ // Layout can run after the first pass; enforce default size once more.
|
|
|
91
|
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { [weak self] in
|
|
|
92
|
+ guard self != nil, let window = AppWindowConfiguration.mainWindow() else { return }
|
|
|
93
|
+ AppWindowConfiguration.apply(to: window)
|
|
|
94
|
+ window.center()
|
|
|
95
|
+ }
|
|
65
|
96
|
}
|
|
66
|
97
|
}
|
|
67
|
98
|
|
|
|
@@ -76,4 +107,3 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|
76
|
107
|
|
|
77
|
108
|
|
|
78
|
109
|
}
|
|
79
|
|
-
|