瀏覽代碼

Gate all Zoom join/start opens behind recording consent.

Settings language popups stay aligned with consent choices; fix AI Companion copy in the consent message.

Co-authored-by: Cursor <cursoragent@cursor.com>
huzaifahayat12 2 月之前
父節點
當前提交
2984a2969e
共有 1 個文件被更改,包括 51 次插入26 次删除
  1. 51 26
      zoom_app/ViewController.swift

+ 51 - 26
zoom_app/ViewController.swift

@@ -1736,10 +1736,7 @@ class ViewController: NSViewController {
         }
         guard let url = zoomURL else { return }
 
-        let consentChoice = requestMeetingRecordingConsent(title: "Join Meeting")
-        if consentChoice == .dismissed { return }
-        let shouldRecord = (consentChoice == .allowAndContinue)
-        openZoomMeetingInDefaultBrowser(url, meetingDisplayName: meetingName, recordLocally: shouldRecord)
+        openWebURLPreferringInApp(url, zoomMeetingDisplayName: meetingName, recordingConsentWindowTitle: "Join Meeting")
     }
 
     private enum MeetingRecordingConsentChoice {
@@ -1751,7 +1748,7 @@ class ViewController: NSViewController {
     private func requestMeetingRecordingConsent(title: String) -> MeetingRecordingConsentChoice {
         let alert = NSAlert()
         alert.messageText = "Record this meeting locally?"
-        alert.informativeText = "With your consent, the app will record meeting audio on this Mac and show it in Ai Companion after the meeting."
+        alert.informativeText = "With your consent, the app will record meeting audio on this Mac and show it in AI Companion after the meeting."
         alert.addButton(withTitle: "Allow and Continue")
         alert.addButton(withTitle: "Continue Without Recording")
         alert.window.title = title
@@ -1873,6 +1870,7 @@ class ViewController: NSViewController {
                 secondary = nil
             }
             TranscriptionLanguagePreferences.updatePreferredLanguages(primary: primary, secondary: secondary)
+            syncSettingsSpeechLanguagePopupsFromStoredPreferences()
         }
 
         switch response {
@@ -1906,6 +1904,25 @@ class ViewController: NSViewController {
             meetingConsentSecondaryLanguagePopup?.selectItem(at: 0)
         }
         TranscriptionLanguagePreferences.updatePreferredLanguages(primary: primary, secondary: secondary)
+        syncSettingsSpeechLanguagePopupsFromStoredPreferences()
+    }
+
+    /// Keeps Settings language menus aligned when preferences change from the pre-join consent sheet.
+    private func syncSettingsSpeechLanguagePopupsFromStoredPreferences() {
+        let options = TranscriptionLanguagePreferences.supportedSpeechLocaleOptions()
+        if let primaryPopup = settingsPagePrimaryLanguagePopup {
+            let id = TranscriptionLanguagePreferences.selectedPrimaryIdentifier()
+                ?? options.first?.identifier
+                ?? Locale.current.identifier
+            selectTranscriptionLanguage(identifier: id, in: primaryPopup)
+        }
+        if let secondaryPopup = settingsPageSecondaryLanguagePopup {
+            if let selected = TranscriptionLanguagePreferences.selectedSecondaryIdentifier() {
+                selectTranscriptionLanguage(identifier: selected, in: secondaryPopup)
+            } else {
+                secondaryPopup.selectItem(at: 0)
+            }
+        }
     }
 
     private func selectTranscriptionLanguage(identifier: String, in popup: NSPopUpButton) {
@@ -1948,11 +1965,32 @@ class ViewController: NSViewController {
     }
 
     /// Opens non-sign-in web content in the system default browser.
-    /// For Zoom meeting join/start links, also begins local audio recording (when not already recording), same as the Join flow.
+    /// For Zoom meeting join/start links, asks for recording consent first, persists transcription languages from that sheet,
+    /// then optionally begins local audio recording (when the user allows and recording is not already active).
     @MainActor
-    private func openWebURLPreferringInApp(_ url: URL, zoomMeetingDisplayName: String? = nil) {
-        _ = openURLInDefaultBrowser(url)
-        beginZoomMeetingRecordingIfAppropriate(sourceURL: url, meetingDisplayName: zoomMeetingDisplayName)
+    private func openWebURLPreferringInApp(
+        _ url: URL,
+        zoomMeetingDisplayName: String? = nil,
+        recordingConsentWindowTitle: String = "Meeting"
+    ) {
+        let shouldRecordLocally: Bool
+        if isZoomMeetingJoinOrStartURL(url) {
+            let consentChoice = requestMeetingRecordingConsent(title: recordingConsentWindowTitle)
+            if consentChoice == .dismissed { return }
+            shouldRecordLocally = (consentChoice == .allowAndContinue)
+        } else {
+            shouldRecordLocally = false
+        }
+
+        let opened = openURLInDefaultBrowser(url)
+        if opened {
+            joinMeetingWindow?.performClose(nil)
+            if shouldRecordLocally {
+                beginZoomMeetingRecordingIfAppropriate(sourceURL: url, meetingDisplayName: zoomMeetingDisplayName)
+            }
+        } else {
+            showSimpleAlert(title: "Unable to open", message: "Your default browser could not be opened.")
+        }
     }
 
     /// True when `url` looks like joining or starting a Zoom call (not OAuth, API, or generic marketing pages).
@@ -1985,19 +2023,6 @@ class ViewController: NSViewController {
         }
     }
 
-    @MainActor
-    private func openZoomMeetingInDefaultBrowser(_ url: URL, meetingDisplayName: String? = nil, recordLocally: Bool = true) {
-        let opened = openURLInDefaultBrowser(url)
-        if opened {
-            joinMeetingWindow?.performClose(nil)
-            if recordLocally {
-                beginZoomMeetingRecordingIfAppropriate(sourceURL: url, meetingDisplayName: meetingDisplayName)
-            }
-        } else {
-            showSimpleAlert(title: "Unable to open", message: "Your default browser could not be opened.")
-        }
-    }
-
     @discardableResult
     private func openURLInDefaultBrowser(_ url: URL) -> Bool {
         NSWorkspace.shared.open(url)
@@ -2562,7 +2587,7 @@ class ViewController: NSViewController {
     @objc private func meetingSearchResultTapped(_ sender: NSButton) {
         guard let meeting = globalSearchResults[safe: sender.tag] else { return }
         if let url = meeting.webURL {
-            openWebURLPreferringInApp(url, zoomMeetingDisplayName: meeting.title)
+            openWebURLPreferringInApp(url, zoomMeetingDisplayName: meeting.title, recordingConsentWindowTitle: "Join Meeting")
         } else {
             let pasteboard = NSPasteboard.general
             pasteboard.clearContents()
@@ -8236,7 +8261,7 @@ class ViewController: NSViewController {
             guard let self else { return }
             guard let link = notification.userInfo?["link"] as? String,
                   let url = URL(string: link.trimmingCharacters(in: .whitespacesAndNewlines)) else { return }
-            self.openWebURLPreferringInApp(url, zoomMeetingDisplayName: nil)
+            self.openWebURLPreferringInApp(url, zoomMeetingDisplayName: nil, recordingConsentWindowTitle: "Join Meeting")
         }
     }
 
@@ -8705,7 +8730,7 @@ class ViewController: NSViewController {
             showSimpleAlert(title: "Unable to open", message: "Could not start a new Zoom meeting right now.")
             return
         }
-        openWebURLPreferringInApp(url, zoomMeetingDisplayName: "Instant meeting")
+        openWebURLPreferringInApp(url, zoomMeetingDisplayName: "Instant meeting", recordingConsentWindowTitle: "New Meeting")
     }
 
     func menuBarTriggerJoinMeeting() {
@@ -9023,7 +9048,7 @@ class ViewController: NSViewController {
             hoverBackground: hoverBackground,
             hoverBorder: hoverBorder,
             onTapURL: { [weak self] url in
-                self?.openWebURLPreferringInApp(url, zoomMeetingDisplayName: meeting.title)
+                self?.openWebURLPreferringInApp(url, zoomMeetingDisplayName: meeting.title, recordingConsentWindowTitle: "Join Meeting")
             }
         )
         card.wantsLayer = true