瀏覽代碼

Update Settings layout with legal links and scrolling.

Add Privacy Policy, Support, and Terms actions, split App vs Help & Legal sections, and make Settings content scroll without stretching the page.

Made-with: Cursor
huzaifahayat12 1 周之前
父節點
當前提交
30b76659e2
共有 1 個文件被更改,包括 71 次插入23 次删除
  1. 71 23
      meetings_app/ViewController.swift

+ 71 - 23
meetings_app/ViewController.swift

@@ -30,6 +30,8 @@ private enum SettingsAction: Int {
30 30
     case moreApps = 3
31 31
     case shareApp = 4
32 32
     case upgrade = 5
33
+    case privacyPolicy = 6
34
+    case termsOfServices = 7
33 35
 }
34 36
 
35 37
 private enum PremiumPlan: Int {
@@ -865,10 +867,11 @@ private extension ViewController {
865 867
         case .rateUs:
866 868
             openRateUsDestination()
867 869
         case .support:
868
-            if let supportURL = Bundle.main.object(forInfoDictionaryKey: "SupportURL") as? String,
869
-               let url = URL(string: supportURL) {
870
-                openInAppBrowser(with: url, policy: inAppBrowserDefaultPolicy)
871
-            }
870
+            openSettingsLink(infoKey: "SupportURL")
871
+        case .privacyPolicy:
872
+            openSettingsLink(infoKey: "PrivacyPolicyURL")
873
+        case .termsOfServices:
874
+            openSettingsLink(infoKey: "TermsOfServiceURL")
872 875
         case .moreApps:
873 876
             if let moreAppsURL = Bundle.main.object(forInfoDictionaryKey: "MoreAppsURL") as? String,
874 877
                let url = URL(string: moreAppsURL) {
@@ -881,6 +884,13 @@ private extension ViewController {
881 884
         }
882 885
     }
883 886
 
887
+    private func openSettingsLink(infoKey: String) {
888
+        let defaultURL = (Bundle.main.object(forInfoDictionaryKey: "AppLaunchPlaceholderURL") as? String) ?? "https://example.com/app-link-coming-soon"
889
+        let urlString = (Bundle.main.object(forInfoDictionaryKey: infoKey) as? String) ?? defaultURL
890
+        guard let url = URL(string: urlString) else { return }
891
+        openInAppBrowser(with: url, policy: inAppBrowserDefaultPolicy)
892
+    }
893
+
884 894
     private func showSimpleAlert(title: String, message: String) {
885 895
         let alert = NSAlert()
886 896
         alert.messageText = title
@@ -1512,10 +1522,28 @@ private extension ViewController {
1512 1522
         let panel = NSView()
1513 1523
         panel.translatesAutoresizingMaskIntoConstraints = false
1514 1524
 
1525
+        let scroll = NSScrollView()
1526
+        scroll.translatesAutoresizingMaskIntoConstraints = false
1527
+        scroll.drawsBackground = false
1528
+        scroll.hasHorizontalScroller = false
1529
+        scroll.hasVerticalScroller = true
1530
+        scroll.autohidesScrollers = true
1531
+        scroll.borderType = .noBorder
1532
+        scroll.scrollerStyle = .overlay
1533
+        scroll.automaticallyAdjustsContentInsets = false
1534
+        let clip = TopAlignedClipView()
1535
+        clip.drawsBackground = false
1536
+        scroll.contentView = clip
1537
+        panel.addSubview(scroll)
1538
+
1539
+        let content = NSView()
1540
+        content.translatesAutoresizingMaskIntoConstraints = false
1541
+        scroll.documentView = content
1542
+
1515 1543
         let card = roundedContainer(cornerRadius: 16, color: palette.sectionCard)
1516 1544
         card.translatesAutoresizingMaskIntoConstraints = false
1517 1545
         styleSurface(card, borderColor: palette.inputBorder, borderWidth: 1, shadow: true)
1518
-        panel.addSubview(card)
1546
+        content.addSubview(card)
1519 1547
 
1520 1548
         let stack = NSStackView()
1521 1549
         stack.translatesAutoresizingMaskIntoConstraints = false
@@ -1552,12 +1580,22 @@ private extension ViewController {
1552 1580
             stack.addArrangedSubview(rateButton)
1553 1581
             rateButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
1554 1582
         }
1555
-        let supportButton = makeSettingsActionButton(icon: "💬", title: "Support", action: .support)
1556
-        stack.addArrangedSubview(supportButton)
1557
-        supportButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
1558 1583
         let shareButton = makeSettingsActionButton(icon: "⤴︎", title: "Share App", action: .shareApp)
1559 1584
         stack.addArrangedSubview(shareButton)
1560 1585
         shareButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
1586
+        stack.setCustomSpacing(24, after: shareButton)
1587
+
1588
+        let legalTitle = textLabel("Help & Legal", font: typography.joinWithURLTitle, color: palette.textPrimary)
1589
+        stack.addArrangedSubview(legalTitle)
1590
+        let privacyButton = makeSettingsActionButton(icon: "🔒", title: "Privacy Policy", action: .privacyPolicy)
1591
+        stack.addArrangedSubview(privacyButton)
1592
+        privacyButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
1593
+        let supportButton = makeSettingsActionButton(icon: "💬", title: "Support", action: .support)
1594
+        stack.addArrangedSubview(supportButton)
1595
+        supportButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
1596
+        let termsButton = makeSettingsActionButton(icon: "📄", title: "Terms of Services", action: .termsOfServices)
1597
+        stack.addArrangedSubview(termsButton)
1598
+        termsButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
1561 1599
         if storeKitCoordinator.hasPremiumAccess && !storeKitCoordinator.hasLifetimeAccess {
1562 1600
             let upgradeButton = makeSettingsActionButton(icon: "⬆︎", title: "Upgrade", action: .upgrade)
1563 1601
             stack.addArrangedSubview(upgradeButton)
@@ -1565,13 +1603,24 @@ private extension ViewController {
1565 1603
         }
1566 1604
 
1567 1605
         NSLayoutConstraint.activate([
1568
-            card.centerXAnchor.constraint(equalTo: panel.centerXAnchor),
1569
-            card.topAnchor.constraint(equalTo: panel.topAnchor, constant: 36),
1570
-            card.bottomAnchor.constraint(lessThanOrEqualTo: panel.bottomAnchor, constant: -36),
1606
+            scroll.leadingAnchor.constraint(equalTo: panel.leadingAnchor),
1607
+            scroll.trailingAnchor.constraint(equalTo: panel.trailingAnchor),
1608
+            scroll.topAnchor.constraint(equalTo: panel.topAnchor),
1609
+            scroll.bottomAnchor.constraint(equalTo: panel.bottomAnchor),
1610
+
1611
+            content.leadingAnchor.constraint(equalTo: scroll.contentView.leadingAnchor),
1612
+            content.trailingAnchor.constraint(equalTo: scroll.contentView.trailingAnchor),
1613
+            content.topAnchor.constraint(equalTo: scroll.contentView.topAnchor),
1614
+            content.bottomAnchor.constraint(greaterThanOrEqualTo: scroll.contentView.bottomAnchor),
1615
+            content.widthAnchor.constraint(equalTo: scroll.contentView.widthAnchor),
1616
+
1617
+            card.centerXAnchor.constraint(equalTo: content.centerXAnchor),
1618
+            card.topAnchor.constraint(equalTo: content.topAnchor, constant: 36),
1619
+            content.bottomAnchor.constraint(greaterThanOrEqualTo: card.bottomAnchor, constant: 36),
1571 1620
             card.widthAnchor.constraint(lessThanOrEqualToConstant: 620),
1572 1621
             card.widthAnchor.constraint(greaterThanOrEqualToConstant: 460),
1573
-            card.leadingAnchor.constraint(greaterThanOrEqualTo: panel.leadingAnchor, constant: 30),
1574
-            card.trailingAnchor.constraint(lessThanOrEqualTo: panel.trailingAnchor, constant: -30),
1622
+            card.leadingAnchor.constraint(greaterThanOrEqualTo: content.leadingAnchor, constant: 30),
1623
+            card.trailingAnchor.constraint(lessThanOrEqualTo: content.trailingAnchor, constant: -30),
1575 1624
 
1576 1625
             stack.leadingAnchor.constraint(equalTo: card.leadingAnchor, constant: 28),
1577 1626
             stack.trailingAnchor.constraint(equalTo: card.trailingAnchor, constant: -28),
@@ -1684,8 +1733,6 @@ private extension ViewController {
1684 1733
             scheduleConnectClicked()
1685 1734
         } else {
1686 1735
             performGoogleSignOut()
1687
-            pageCache[.settings] = nil
1688
-            showSidebarPage(.settings)
1689 1736
         }
1690 1737
     }
1691 1738
 
@@ -4526,7 +4573,9 @@ private final class SettingsMenuViewController: NSViewController {
4526 4573
         if showRateUsInSettings {
4527 4574
             stack.addArrangedSubview(settingsActionRow(icon: "★", title: "Rate Us", action: .rateUs))
4528 4575
         }
4576
+        stack.addArrangedSubview(settingsActionRow(icon: "🔒", title: "Privacy Policy", action: .privacyPolicy))
4529 4577
         stack.addArrangedSubview(settingsActionRow(icon: "💬", title: "Support", action: .support))
4578
+        stack.addArrangedSubview(settingsActionRow(icon: "📄", title: "Terms of Services", action: .termsOfServices))
4530 4579
         stack.addArrangedSubview(settingsActionRow(icon: "⤴︎", title: "Share App", action: .shareApp))
4531 4580
         if showUpgradeInSettings {
4532 4581
             stack.addArrangedSubview(settingsActionRow(icon: "⬆︎", title: "Upgrade", action: .upgrade))
@@ -6252,16 +6301,15 @@ private extension ViewController {
6252 6301
     private func performGoogleSignOut() {
6253 6302
         do {
6254 6303
             try googleOAuth.signOut()
6304
+            applyGoogleProfile(nil)
6305
+            updateGoogleAuthButtonTitle()
6306
+            pageCache[.joinMeetings] = nil
6255 6307
             pageCache[.photo] = nil
6308
+            pageCache[.video] = nil
6256 6309
             pageCache[.settings] = nil
6257
-            if selectedSidebarPage == .photo {
6258
-                showSidebarPage(.photo)
6259
-            } else if selectedSidebarPage == .settings {
6260
-                showSidebarPage(.settings)
6261
-            } else {
6262
-                Task { [weak self] in
6263
-                    await self?.loadSchedule()
6264
-                }
6310
+            showSidebarPage(selectedSidebarPage)
6311
+            Task { [weak self] in
6312
+                await self?.loadSchedule()
6265 6313
             }
6266 6314
         } catch {
6267 6315
             showSimpleError("Couldn’t logout Google account.", error: error)