瀏覽代碼

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 2 月之前
父節點
當前提交
e85f4dd01d
共有 2 個文件被更改,包括 56 次插入17 次删除
  1. 2 0
      App for Indeed/Views/DashboardView.swift
  2. 54 17
      App for Indeed/Views/MyProfilePageView.swift

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

@@ -1185,6 +1185,7 @@ final class DashboardView: NSView, NSTextFieldDelegate {
         nonHomeHost.wantsLayer = true
         nonHomeHost.layer?.backgroundColor = Theme.mainHostBackground.cgColor
         nonHomeHost.isHidden = true
+        nonHomeHost.userInterfaceLayoutDirection = .leftToRight
 
         nonHomeGenericContainer.translatesAutoresizingMaskIntoConstraints = false
         savedJobsPageContainer.translatesAutoresizingMaskIntoConstraints = false
@@ -1338,6 +1339,7 @@ final class DashboardView: NSView, NSTextFieldDelegate {
         profilePageContainer.wantsLayer = true
         profilePageContainer.layer?.backgroundColor = Theme.mainHostBackground.cgColor
         profilePageContainer.isHidden = true
+        profilePageContainer.userInterfaceLayoutDirection = .leftToRight
 
         myProfilePageView.translatesAutoresizingMaskIntoConstraints = false
         profilePageContainer.addSubview(myProfilePageView)

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

@@ -45,6 +45,12 @@ final class MyProfilePageView: NSView {
 
     private var lastCompactLayout: Bool?
 
+    /// Force left-to-right geometry so profile fields span the full width even when the window uses RTL layout.
+    override var userInterfaceLayoutDirection: NSUserInterfaceLayoutDirection {
+        get { .leftToRight }
+        set { super.userInterfaceLayoutDirection = .leftToRight }
+    }
+
     override init(frame frameRect: NSRect) {
         super.init(frame: frameRect)
         setup()
@@ -63,8 +69,10 @@ final class MyProfilePageView: NSView {
     private func setup() {
         wantsLayer = true
         layer?.backgroundColor = ProfilePagePalette.pageBackground.cgColor
+        userInterfaceLayoutDirection = .leftToRight
 
         scrollView.translatesAutoresizingMaskIntoConstraints = false
+        scrollView.userInterfaceLayoutDirection = .leftToRight
         scrollView.hasVerticalScroller = true
         scrollView.hasHorizontalScroller = false
         scrollView.autohidesScrollers = true
@@ -72,6 +80,7 @@ final class MyProfilePageView: NSView {
         scrollView.borderType = .noBorder
         scrollView.scrollerStyle = .overlay
         scrollView.automaticallyAdjustsContentInsets = false
+        scrollView.contentView.userInterfaceLayoutDirection = .leftToRight
 
         documentView.translatesAutoresizingMaskIntoConstraints = false
         documentView.userInterfaceLayoutDirection = .leftToRight
@@ -90,9 +99,12 @@ final class MyProfilePageView: NSView {
         formStack.translatesAutoresizingMaskIntoConstraints = false
         formStack.orientation = .vertical
         formStack.alignment = .width
+        formStack.distribution = .fill
         formStack.spacing = 20
-        formStack.edgeInsets = NSEdgeInsets(top: 28, left: 28, bottom: 28, right: 28)
+        formStack.edgeInsets = NSEdgeInsets(top: 28, left: 22, bottom: 28, right: 22)
         formStack.userInterfaceLayoutDirection = .leftToRight
+        formStack.setContentHuggingPriority(.defaultLow, for: .horizontal)
+        formStack.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
 
         addSubview(scrollView)
         scrollView.documentView = documentView
@@ -105,13 +117,14 @@ final class MyProfilePageView: NSView {
             scrollView.topAnchor.constraint(equalTo: topAnchor),
             scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
 
-            documentView.leadingAnchor.constraint(equalTo: scrollView.contentView.leadingAnchor),
-            documentView.trailingAnchor.constraint(equalTo: scrollView.contentView.trailingAnchor),
+            // Pin left and right to the clip view’s geometric edges so the document spans the full visible
+            // width (leading/trailing + width alone can leave a narrow strip on the wrong side in edge cases).
+            documentView.leftAnchor.constraint(equalTo: scrollView.contentView.leftAnchor),
+            documentView.rightAnchor.constraint(equalTo: scrollView.contentView.rightAnchor),
             documentView.topAnchor.constraint(equalTo: scrollView.contentView.topAnchor),
-            documentView.widthAnchor.constraint(equalTo: scrollView.contentView.widthAnchor),
 
-            cardView.leadingAnchor.constraint(equalTo: documentView.leadingAnchor, constant: 24),
-            cardView.trailingAnchor.constraint(equalTo: documentView.trailingAnchor, constant: -24),
+            cardView.leadingAnchor.constraint(equalTo: documentView.leadingAnchor, constant: 20),
+            cardView.trailingAnchor.constraint(equalTo: documentView.trailingAnchor, constant: -20),
             cardView.topAnchor.constraint(equalTo: documentView.topAnchor, constant: 16),
             cardView.bottomAnchor.constraint(equalTo: documentView.bottomAnchor, constant: -24),
 
@@ -185,14 +198,26 @@ final class MyProfilePageView: NSView {
         row.addArrangedSubview(right)
     }
 
-    private func sectionHeading(_ text: String) -> NSTextField {
+    private func sectionHeading(_ text: String) -> NSView {
         let label = NSTextField(labelWithString: text)
         label.font = .systemFont(ofSize: 15, weight: .semibold)
         label.textColor = ProfilePagePalette.primaryText
         label.alignment = .left
+        label.baseWritingDirection = .leftToRight
         label.translatesAutoresizingMaskIntoConstraints = false
-        label.setContentHuggingPriority(.defaultLow, for: .horizontal)
-        return label
+        label.setContentHuggingPriority(.defaultHigh, for: .horizontal)
+
+        let spacer = NSView()
+        spacer.translatesAutoresizingMaskIntoConstraints = false
+        spacer.setContentHuggingPriority(.defaultLow, for: .horizontal)
+
+        let row = NSStackView(views: [label, spacer])
+        row.orientation = .horizontal
+        row.alignment = .centerY
+        row.spacing = 0
+        row.userInterfaceLayoutDirection = .leftToRight
+        row.translatesAutoresizingMaskIntoConstraints = false
+        return row
     }
 
     private func labeledGroup(title: String, field: NSTextField, placeholder: String) -> NSView {
@@ -200,7 +225,9 @@ final class MyProfilePageView: NSView {
         label.font = .systemFont(ofSize: 12, weight: .medium)
         label.textColor = ProfilePagePalette.secondaryText
         label.alignment = .left
+        label.baseWritingDirection = .leftToRight
         label.translatesAutoresizingMaskIntoConstraints = false
+        label.setContentHuggingPriority(.defaultHigh, for: .horizontal)
 
         styleSingleLineField(field, placeholder: placeholder)
         let wrap = roundedFieldChrome(containing: field, minHeight: 40)
@@ -208,12 +235,16 @@ final class MyProfilePageView: NSView {
         let stack = NSStackView(views: [label, wrap])
         stack.orientation = .vertical
         stack.spacing = 8
-        stack.alignment = .width
+        // Leading keeps the title at the left edge; width match keeps the field full width.
+        stack.alignment = .leading
         stack.translatesAutoresizingMaskIntoConstraints = false
         stack.userInterfaceLayoutDirection = .leftToRight
         stack.setContentHuggingPriority(.defaultLow, for: .horizontal)
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
         wrap.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
+        NSLayoutConstraint.activate([
+            wrap.widthAnchor.constraint(equalTo: stack.widthAnchor)
+        ])
         return stack
     }
 
@@ -236,6 +267,8 @@ final class MyProfilePageView: NSView {
         field.cell?.usesSingleLineMode = true
         field.cell?.wraps = false
         field.cell?.isScrollable = true
+        field.baseWritingDirection = .leftToRight
+        field.alignment = .left
     }
 
     private func roundedFieldChrome(containing field: NSTextField, minHeight: CGFloat) -> NSView {
@@ -251,8 +284,8 @@ final class MyProfilePageView: NSView {
         }
         wrap.addSubview(field)
         NSLayoutConstraint.activate([
-            field.leadingAnchor.constraint(equalTo: wrap.leadingAnchor, constant: 12),
-            field.trailingAnchor.constraint(equalTo: wrap.trailingAnchor, constant: -12),
+            field.leftAnchor.constraint(equalTo: wrap.leftAnchor, constant: 12),
+            field.rightAnchor.constraint(equalTo: wrap.rightAnchor, constant: -12),
             field.centerYAnchor.constraint(equalTo: wrap.centerYAnchor),
             wrap.heightAnchor.constraint(greaterThanOrEqualToConstant: minHeight)
         ])
@@ -281,6 +314,8 @@ final class MyProfilePageView: NSView {
         careerField.stringValue = ""
         careerField.setContentHuggingPriority(.defaultLow, for: .horizontal)
         careerField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
+        careerField.baseWritingDirection = .leftToRight
+        careerField.alignment = .left
         careerField.placeholderAttributedString = NSAttributedString(
             string: "Brief overview of your professional background and key achievements...",
             attributes: [
@@ -301,8 +336,8 @@ final class MyProfilePageView: NSView {
         }
         wrap.addSubview(careerField)
         NSLayoutConstraint.activate([
-            careerField.leadingAnchor.constraint(equalTo: wrap.leadingAnchor, constant: 12),
-            careerField.trailingAnchor.constraint(equalTo: wrap.trailingAnchor, constant: -12),
+            careerField.leftAnchor.constraint(equalTo: wrap.leftAnchor, constant: 12),
+            careerField.rightAnchor.constraint(equalTo: wrap.rightAnchor, constant: -12),
             careerField.topAnchor.constraint(equalTo: wrap.topAnchor, constant: 10),
             careerField.bottomAnchor.constraint(equalTo: wrap.bottomAnchor, constant: -10),
             wrap.heightAnchor.constraint(greaterThanOrEqualToConstant: 120)
@@ -323,6 +358,7 @@ final class MyProfilePageView: NSView {
         let title = NSTextField(labelWithString: "Profile Image (Optional)")
         title.font = .systemFont(ofSize: 12, weight: .medium)
         title.textColor = ProfilePagePalette.secondaryText
+        title.alignment = .left
         title.translatesAutoresizingMaskIntoConstraints = false
 
         let avatarHost = NSView()
@@ -360,6 +396,7 @@ final class MyProfilePageView: NSView {
         let hint = NSTextField(wrappingLabelWithString: "Recommended: Square image, max 2MB")
         hint.font = .systemFont(ofSize: 11, weight: .regular)
         hint.textColor = ProfilePagePalette.secondaryText
+        hint.alignment = .left
         hint.maximumNumberOfLines = 0
 
         let rightColumn = NSStackView(views: [uploadPhotoButton, hint])
@@ -373,6 +410,7 @@ final class MyProfilePageView: NSView {
         row.alignment = .centerY
         row.spacing = 16
         row.translatesAutoresizingMaskIntoConstraints = false
+        row.userInterfaceLayoutDirection = .leftToRight
 
         let stack = NSStackView(views: [title, row])
         stack.orientation = .vertical
@@ -381,7 +419,6 @@ final class MyProfilePageView: NSView {
         stack.translatesAutoresizingMaskIntoConstraints = false
         stack.userInterfaceLayoutDirection = .leftToRight
         row.setContentHuggingPriority(.defaultLow, for: .horizontal)
-        row.alignment = .leading
         return stack
     }
 
@@ -393,10 +430,10 @@ final class MyProfilePageView: NSView {
         host.addSubview(saveButton)
         NSLayoutConstraint.activate([
             saveButton.leadingAnchor.constraint(equalTo: host.leadingAnchor),
-            saveButton.trailingAnchor.constraint(equalTo: host.trailingAnchor),
             saveButton.topAnchor.constraint(equalTo: host.topAnchor),
             saveButton.bottomAnchor.constraint(equalTo: host.bottomAnchor),
-            saveButton.heightAnchor.constraint(equalToConstant: 48)
+            saveButton.heightAnchor.constraint(equalToConstant: 48),
+            saveButton.trailingAnchor.constraint(lessThanOrEqualTo: host.trailingAnchor)
         ])
         return host
     }