Просмотр исходного кода

Fix profile editor label alignment and LTR layout

MyProfilePageView: use leading alignment and width constraints in
labeledGroup so field titles stay on the left; wrap Personal
Information in a horizontal stack with a flexible spacer.

DashboardView: force left-to-right on nonHomeHost and
profilePageContainer so nested controls align consistently.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 недель назад: 3
Родитель
Сommit
e85f4dd01d

+ 2 - 0
App for Indeed/Views/DashboardView.swift

@@ -1185,6 +1185,7 @@ final class DashboardView: NSView, NSTextFieldDelegate {
1185 1185
         nonHomeHost.wantsLayer = true
1186 1186
         nonHomeHost.layer?.backgroundColor = Theme.mainHostBackground.cgColor
1187 1187
         nonHomeHost.isHidden = true
1188
+        nonHomeHost.userInterfaceLayoutDirection = .leftToRight
1188 1189
 
1189 1190
         nonHomeGenericContainer.translatesAutoresizingMaskIntoConstraints = false
1190 1191
         savedJobsPageContainer.translatesAutoresizingMaskIntoConstraints = false
@@ -1338,6 +1339,7 @@ final class DashboardView: NSView, NSTextFieldDelegate {
1338 1339
         profilePageContainer.wantsLayer = true
1339 1340
         profilePageContainer.layer?.backgroundColor = Theme.mainHostBackground.cgColor
1340 1341
         profilePageContainer.isHidden = true
1342
+        profilePageContainer.userInterfaceLayoutDirection = .leftToRight
1341 1343
 
1342 1344
         myProfilePageView.translatesAutoresizingMaskIntoConstraints = false
1343 1345
         profilePageContainer.addSubview(myProfilePageView)

+ 54 - 17
App for Indeed/Views/MyProfilePageView.swift

@@ -45,6 +45,12 @@ final class MyProfilePageView: NSView {
45 45
 
46 46
     private var lastCompactLayout: Bool?
47 47
 
48
+    /// Force left-to-right geometry so profile fields span the full width even when the window uses RTL layout.
49
+    override var userInterfaceLayoutDirection: NSUserInterfaceLayoutDirection {
50
+        get { .leftToRight }
51
+        set { super.userInterfaceLayoutDirection = .leftToRight }
52
+    }
53
+
48 54
     override init(frame frameRect: NSRect) {
49 55
         super.init(frame: frameRect)
50 56
         setup()
@@ -63,8 +69,10 @@ final class MyProfilePageView: NSView {
63 69
     private func setup() {
64 70
         wantsLayer = true
65 71
         layer?.backgroundColor = ProfilePagePalette.pageBackground.cgColor
72
+        userInterfaceLayoutDirection = .leftToRight
66 73
 
67 74
         scrollView.translatesAutoresizingMaskIntoConstraints = false
75
+        scrollView.userInterfaceLayoutDirection = .leftToRight
68 76
         scrollView.hasVerticalScroller = true
69 77
         scrollView.hasHorizontalScroller = false
70 78
         scrollView.autohidesScrollers = true
@@ -72,6 +80,7 @@ final class MyProfilePageView: NSView {
72 80
         scrollView.borderType = .noBorder
73 81
         scrollView.scrollerStyle = .overlay
74 82
         scrollView.automaticallyAdjustsContentInsets = false
83
+        scrollView.contentView.userInterfaceLayoutDirection = .leftToRight
75 84
 
76 85
         documentView.translatesAutoresizingMaskIntoConstraints = false
77 86
         documentView.userInterfaceLayoutDirection = .leftToRight
@@ -90,9 +99,12 @@ final class MyProfilePageView: NSView {
90 99
         formStack.translatesAutoresizingMaskIntoConstraints = false
91 100
         formStack.orientation = .vertical
92 101
         formStack.alignment = .width
102
+        formStack.distribution = .fill
93 103
         formStack.spacing = 20
94
-        formStack.edgeInsets = NSEdgeInsets(top: 28, left: 28, bottom: 28, right: 28)
104
+        formStack.edgeInsets = NSEdgeInsets(top: 28, left: 22, bottom: 28, right: 22)
95 105
         formStack.userInterfaceLayoutDirection = .leftToRight
106
+        formStack.setContentHuggingPriority(.defaultLow, for: .horizontal)
107
+        formStack.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
96 108
 
97 109
         addSubview(scrollView)
98 110
         scrollView.documentView = documentView
@@ -105,13 +117,14 @@ final class MyProfilePageView: NSView {
105 117
             scrollView.topAnchor.constraint(equalTo: topAnchor),
106 118
             scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
107 119
 
108
-            documentView.leadingAnchor.constraint(equalTo: scrollView.contentView.leadingAnchor),
109
-            documentView.trailingAnchor.constraint(equalTo: scrollView.contentView.trailingAnchor),
120
+            // Pin left and right to the clip view’s geometric edges so the document spans the full visible
121
+            // width (leading/trailing + width alone can leave a narrow strip on the wrong side in edge cases).
122
+            documentView.leftAnchor.constraint(equalTo: scrollView.contentView.leftAnchor),
123
+            documentView.rightAnchor.constraint(equalTo: scrollView.contentView.rightAnchor),
110 124
             documentView.topAnchor.constraint(equalTo: scrollView.contentView.topAnchor),
111
-            documentView.widthAnchor.constraint(equalTo: scrollView.contentView.widthAnchor),
112 125
 
113
-            cardView.leadingAnchor.constraint(equalTo: documentView.leadingAnchor, constant: 24),
114
-            cardView.trailingAnchor.constraint(equalTo: documentView.trailingAnchor, constant: -24),
126
+            cardView.leadingAnchor.constraint(equalTo: documentView.leadingAnchor, constant: 20),
127
+            cardView.trailingAnchor.constraint(equalTo: documentView.trailingAnchor, constant: -20),
115 128
             cardView.topAnchor.constraint(equalTo: documentView.topAnchor, constant: 16),
116 129
             cardView.bottomAnchor.constraint(equalTo: documentView.bottomAnchor, constant: -24),
117 130
 
@@ -185,14 +198,26 @@ final class MyProfilePageView: NSView {
185 198
         row.addArrangedSubview(right)
186 199
     }
187 200
 
188
-    private func sectionHeading(_ text: String) -> NSTextField {
201
+    private func sectionHeading(_ text: String) -> NSView {
189 202
         let label = NSTextField(labelWithString: text)
190 203
         label.font = .systemFont(ofSize: 15, weight: .semibold)
191 204
         label.textColor = ProfilePagePalette.primaryText
192 205
         label.alignment = .left
206
+        label.baseWritingDirection = .leftToRight
193 207
         label.translatesAutoresizingMaskIntoConstraints = false
194
-        label.setContentHuggingPriority(.defaultLow, for: .horizontal)
195
-        return label
208
+        label.setContentHuggingPriority(.defaultHigh, for: .horizontal)
209
+
210
+        let spacer = NSView()
211
+        spacer.translatesAutoresizingMaskIntoConstraints = false
212
+        spacer.setContentHuggingPriority(.defaultLow, for: .horizontal)
213
+
214
+        let row = NSStackView(views: [label, spacer])
215
+        row.orientation = .horizontal
216
+        row.alignment = .centerY
217
+        row.spacing = 0
218
+        row.userInterfaceLayoutDirection = .leftToRight
219
+        row.translatesAutoresizingMaskIntoConstraints = false
220
+        return row
196 221
     }
197 222
 
198 223
     private func labeledGroup(title: String, field: NSTextField, placeholder: String) -> NSView {
@@ -200,7 +225,9 @@ final class MyProfilePageView: NSView {
200 225
         label.font = .systemFont(ofSize: 12, weight: .medium)
201 226
         label.textColor = ProfilePagePalette.secondaryText
202 227
         label.alignment = .left
228
+        label.baseWritingDirection = .leftToRight
203 229
         label.translatesAutoresizingMaskIntoConstraints = false
230
+        label.setContentHuggingPriority(.defaultHigh, for: .horizontal)
204 231
 
205 232
         styleSingleLineField(field, placeholder: placeholder)
206 233
         let wrap = roundedFieldChrome(containing: field, minHeight: 40)
@@ -208,12 +235,16 @@ final class MyProfilePageView: NSView {
208 235
         let stack = NSStackView(views: [label, wrap])
209 236
         stack.orientation = .vertical
210 237
         stack.spacing = 8
211
-        stack.alignment = .width
238
+        // Leading keeps the title at the left edge; width match keeps the field full width.
239
+        stack.alignment = .leading
212 240
         stack.translatesAutoresizingMaskIntoConstraints = false
213 241
         stack.userInterfaceLayoutDirection = .leftToRight
214 242
         stack.setContentHuggingPriority(.defaultLow, for: .horizontal)
215 243
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
216 244
         wrap.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
245
+        NSLayoutConstraint.activate([
246
+            wrap.widthAnchor.constraint(equalTo: stack.widthAnchor)
247
+        ])
217 248
         return stack
218 249
     }
219 250
 
@@ -236,6 +267,8 @@ final class MyProfilePageView: NSView {
236 267
         field.cell?.usesSingleLineMode = true
237 268
         field.cell?.wraps = false
238 269
         field.cell?.isScrollable = true
270
+        field.baseWritingDirection = .leftToRight
271
+        field.alignment = .left
239 272
     }
240 273
 
241 274
     private func roundedFieldChrome(containing field: NSTextField, minHeight: CGFloat) -> NSView {
@@ -251,8 +284,8 @@ final class MyProfilePageView: NSView {
251 284
         }
252 285
         wrap.addSubview(field)
253 286
         NSLayoutConstraint.activate([
254
-            field.leadingAnchor.constraint(equalTo: wrap.leadingAnchor, constant: 12),
255
-            field.trailingAnchor.constraint(equalTo: wrap.trailingAnchor, constant: -12),
287
+            field.leftAnchor.constraint(equalTo: wrap.leftAnchor, constant: 12),
288
+            field.rightAnchor.constraint(equalTo: wrap.rightAnchor, constant: -12),
256 289
             field.centerYAnchor.constraint(equalTo: wrap.centerYAnchor),
257 290
             wrap.heightAnchor.constraint(greaterThanOrEqualToConstant: minHeight)
258 291
         ])
@@ -281,6 +314,8 @@ final class MyProfilePageView: NSView {
281 314
         careerField.stringValue = ""
282 315
         careerField.setContentHuggingPriority(.defaultLow, for: .horizontal)
283 316
         careerField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
317
+        careerField.baseWritingDirection = .leftToRight
318
+        careerField.alignment = .left
284 319
         careerField.placeholderAttributedString = NSAttributedString(
285 320
             string: "Brief overview of your professional background and key achievements...",
286 321
             attributes: [
@@ -301,8 +336,8 @@ final class MyProfilePageView: NSView {
301 336
         }
302 337
         wrap.addSubview(careerField)
303 338
         NSLayoutConstraint.activate([
304
-            careerField.leadingAnchor.constraint(equalTo: wrap.leadingAnchor, constant: 12),
305
-            careerField.trailingAnchor.constraint(equalTo: wrap.trailingAnchor, constant: -12),
339
+            careerField.leftAnchor.constraint(equalTo: wrap.leftAnchor, constant: 12),
340
+            careerField.rightAnchor.constraint(equalTo: wrap.rightAnchor, constant: -12),
306 341
             careerField.topAnchor.constraint(equalTo: wrap.topAnchor, constant: 10),
307 342
             careerField.bottomAnchor.constraint(equalTo: wrap.bottomAnchor, constant: -10),
308 343
             wrap.heightAnchor.constraint(greaterThanOrEqualToConstant: 120)
@@ -323,6 +358,7 @@ final class MyProfilePageView: NSView {
323 358
         let title = NSTextField(labelWithString: "Profile Image (Optional)")
324 359
         title.font = .systemFont(ofSize: 12, weight: .medium)
325 360
         title.textColor = ProfilePagePalette.secondaryText
361
+        title.alignment = .left
326 362
         title.translatesAutoresizingMaskIntoConstraints = false
327 363
 
328 364
         let avatarHost = NSView()
@@ -360,6 +396,7 @@ final class MyProfilePageView: NSView {
360 396
         let hint = NSTextField(wrappingLabelWithString: "Recommended: Square image, max 2MB")
361 397
         hint.font = .systemFont(ofSize: 11, weight: .regular)
362 398
         hint.textColor = ProfilePagePalette.secondaryText
399
+        hint.alignment = .left
363 400
         hint.maximumNumberOfLines = 0
364 401
 
365 402
         let rightColumn = NSStackView(views: [uploadPhotoButton, hint])
@@ -373,6 +410,7 @@ final class MyProfilePageView: NSView {
373 410
         row.alignment = .centerY
374 411
         row.spacing = 16
375 412
         row.translatesAutoresizingMaskIntoConstraints = false
413
+        row.userInterfaceLayoutDirection = .leftToRight
376 414
 
377 415
         let stack = NSStackView(views: [title, row])
378 416
         stack.orientation = .vertical
@@ -381,7 +419,6 @@ final class MyProfilePageView: NSView {
381 419
         stack.translatesAutoresizingMaskIntoConstraints = false
382 420
         stack.userInterfaceLayoutDirection = .leftToRight
383 421
         row.setContentHuggingPriority(.defaultLow, for: .horizontal)
384
-        row.alignment = .leading
385 422
         return stack
386 423
     }
387 424
 
@@ -393,10 +430,10 @@ final class MyProfilePageView: NSView {
393 430
         host.addSubview(saveButton)
394 431
         NSLayoutConstraint.activate([
395 432
             saveButton.leadingAnchor.constraint(equalTo: host.leadingAnchor),
396
-            saveButton.trailingAnchor.constraint(equalTo: host.trailingAnchor),
397 433
             saveButton.topAnchor.constraint(equalTo: host.topAnchor),
398 434
             saveButton.bottomAnchor.constraint(equalTo: host.bottomAnchor),
399
-            saveButton.heightAnchor.constraint(equalToConstant: 48)
435
+            saveButton.heightAnchor.constraint(equalToConstant: 48),
436
+            saveButton.trailingAnchor.constraint(lessThanOrEqualTo: host.trailingAnchor)
400 437
         ])
401 438
         return host
402 439
     }