ソースを参照

Set default window to 1120×750 with a fixed minimum size.

Centralize launch sizing in AppWindowConfiguration, add chrome margins, and remove the chat min-height constraint so layout no longer fights the window frame.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 3 週間 前
コミット
4ad3b03ce3
共有4 個のファイルを変更した65 個の追加24 個の削除を含む
  1. 46 16
      App for Indeed/AppDelegate.swift
  2. 2 2
      App for Indeed/Base.lproj/Main.storyboard
  3. 13 1
      App for Indeed/ViewController.swift
  4. 4 5
      App for Indeed/Views/DashboardView.swift

+ 46 - 16
App for Indeed/AppDelegate.swift

@@ -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
-

+ 2 - 2
App for Indeed/Base.lproj/Main.storyboard

@@ -686,7 +686,7 @@
686 686
                     <window key="window" title="App for Indeed" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="YES" animationBehavior="default" id="IQv-IB-iLA">
687 687
                         <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="YES"/>
688 688
                         <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
689
-                        <rect key="contentRect" x="196" y="240" width="480" height="270"/>
689
+                        <rect key="contentRect" x="196" y="240" width="1120" height="750"/>
690 690
                         <rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
691 691
                         <connections>
692 692
                             <outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/>
@@ -705,7 +705,7 @@
705 705
             <objects>
706 706
                 <viewController id="XfG-lQ-9wD" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
707 707
                     <view key="view" id="m2S-Jp-Qdl">
708
-                        <rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
708
+                        <rect key="frame" x="0.0" y="0.0" width="1120" height="750"/>
709 709
                         <autoresizingMask key="autoresizingMask"/>
710 710
                     </view>
711 711
                 </viewController>

+ 13 - 1
App for Indeed/ViewController.swift

@@ -7,5 +7,17 @@
7 7
 
8 8
 import Cocoa
9 9
 
10
-final class ViewController: DashboardViewController {}
10
+final class ViewController: DashboardViewController {
11
+    private var didApplyDefaultWindowFrame = false
12
+
13
+    override func viewDidAppear() {
14
+        super.viewDidAppear()
15
+        guard !didApplyDefaultWindowFrame, let window = view.window else { return }
16
+        didApplyDefaultWindowFrame = true
17
+        // Layout can grow the window after launch; re-apply once content is on screen.
18
+        view.layoutSubtreeIfNeeded()
19
+        AppWindowConfiguration.apply(to: window)
20
+        window.center()
21
+    }
22
+}
11 23
 

+ 4 - 5
App for Indeed/Views/DashboardView.swift

@@ -365,10 +365,10 @@ final class DashboardView: NSView, NSTextFieldDelegate {
365 365
         panelsRow.addSubview(mainHost)
366 366
 
367 367
         NSLayoutConstraint.activate([
368
-            chromeContainer.leadingAnchor.constraint(equalTo: leadingAnchor),
369
-            chromeContainer.trailingAnchor.constraint(equalTo: trailingAnchor),
370
-            chromeContainer.topAnchor.constraint(equalTo: topAnchor),
371
-            chromeContainer.bottomAnchor.constraint(equalTo: bottomAnchor),
368
+            chromeContainer.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 12),
369
+            chromeContainer.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -12),
370
+            chromeContainer.topAnchor.constraint(equalTo: topAnchor, constant: 10),
371
+            chromeContainer.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -12),
372 372
 
373 373
             panelsRow.leadingAnchor.constraint(equalTo: chromeContainer.leadingAnchor, constant: 12),
374 374
             panelsRow.trailingAnchor.constraint(equalTo: chromeContainer.trailingAnchor, constant: -20),
@@ -531,7 +531,6 @@ final class DashboardView: NSView, NSTextFieldDelegate {
531 531
         chatScrollView.documentView = chatDocumentView
532 532
         chatScrollView.setContentHuggingPriority(.defaultLow, for: .vertical)
533 533
         chatScrollView.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
534
-        chatScrollView.heightAnchor.constraint(greaterThanOrEqualToConstant: 420).isActive = true
535 534
         // Match Saved Jobs: pin document width to the clip view so cards and bubbles track window width instead of sticking to a narrow intrinsic width.
536 535
         NSLayoutConstraint.activate([
537 536
             chatDocumentView.topAnchor.constraint(equalTo: chatScrollView.contentView.topAnchor),