Эх сурвалжийг харах

Start local meeting recording from every in-app join path.

Centralize recording in beginZoomMeetingRecordingIfAppropriate after
opening URLs: meeting cards, search results, widgets, and new meeting
use the same Zoom join/start URL detection as the Join sheet. Skip
non-call Zoom pages and avoid starting when a recording is already
active.

Co-authored-by: Cursor <cursoragent@cursor.com>
huzaifahayat12 2 сар өмнө
parent
commit
dcbaba30e1

+ 39 - 22
zoom_app/ViewController.swift

@@ -1702,24 +1702,49 @@ 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.
     @MainActor
-    private func openWebURLPreferringInApp(_ url: URL) {
+    private func openWebURLPreferringInApp(_ url: URL, zoomMeetingDisplayName: String? = nil) {
         _ = openURLInDefaultBrowser(url)
+        beginZoomMeetingRecordingIfAppropriate(sourceURL: url, meetingDisplayName: zoomMeetingDisplayName)
+    }
+
+    /// True when `url` looks like joining or starting a Zoom call (not OAuth, API, or generic marketing pages).
+    private func isZoomMeetingJoinOrStartURL(_ url: URL) -> Bool {
+        guard let host = url.host?.lowercased(), host.contains("zoom.") else { return false }
+        if host.hasPrefix("api.") { return false }
+        let path = url.path.lowercased()
+        if path.hasPrefix("/oauth") || path.hasPrefix("/signin") { return false }
+        if path.contains("/j/") { return true }
+        if path.contains("/wc/join") { return true }
+        if path.contains("/join/") { return true }
+        if path.contains("/my/") { return true }
+        if path.contains("/w/") { return true }
+        if path.contains("videomeeting") { return true }
+        if path.contains("/start") && path.contains("meeting") { return true }
+        return false
     }
 
+    @MainActor
+    private func beginZoomMeetingRecordingIfAppropriate(sourceURL: URL, meetingDisplayName: String?) {
+        guard isZoomMeetingJoinOrStartURL(sourceURL) else { return }
+        guard MeetingRecordingManager.shared.isRecording == false else { return }
+        Task { @MainActor in
+            do {
+                try await MeetingRecordingManager.shared.startRecording(sourceURL: sourceURL, meetingDisplayName: meetingDisplayName)
+                self.updateAiCompanionRecordingUI()
+            } catch {
+                self.showSimpleAlert(title: "Recording could not start", message: error.localizedDescription)
+            }
+        }
+    }
+
+    @MainActor
     private func openZoomMeetingInDefaultBrowser(_ url: URL, meetingDisplayName: String? = nil) {
         let opened = openURLInDefaultBrowser(url)
         if opened {
             joinMeetingWindow?.performClose(nil)
-            // AI Companion mode requirement: automatically record every meeting we start/join.
-            Task { @MainActor in
-                do {
-                    try await MeetingRecordingManager.shared.startRecording(sourceURL: url, meetingDisplayName: meetingDisplayName)
-                    self.updateAiCompanionRecordingUI()
-                } catch {
-                    self.showSimpleAlert(title: "Recording could not start", message: error.localizedDescription)
-                }
-            }
+            beginZoomMeetingRecordingIfAppropriate(sourceURL: url, meetingDisplayName: meetingDisplayName)
         } else {
             showSimpleAlert(title: "Unable to open", message: "Your default browser could not be opened.")
         }
@@ -2289,7 +2314,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)
+            openWebURLPreferringInApp(url, zoomMeetingDisplayName: meeting.title)
         } else {
             let pasteboard = NSPasteboard.general
             pasteboard.clearContents()
@@ -7290,7 +7315,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)
+            self.openWebURLPreferringInApp(url, zoomMeetingDisplayName: nil)
         }
     }
 
@@ -7759,15 +7784,7 @@ class ViewController: NSViewController {
             showSimpleAlert(title: "Unable to open", message: "Could not start a new Zoom meeting right now.")
             return
         }
-        openWebURLPreferringInApp(url)
-        Task { @MainActor in
-            do {
-                try await MeetingRecordingManager.shared.startRecording(sourceURL: url, meetingDisplayName: "Instant meeting")
-                self.updateAiCompanionRecordingUI()
-            } catch {
-                self.showSimpleAlert(title: "Recording could not start", message: error.localizedDescription)
-            }
-        }
+        openWebURLPreferringInApp(url, zoomMeetingDisplayName: "Instant meeting")
     }
 
     func menuBarTriggerJoinMeeting() {
@@ -8085,7 +8102,7 @@ class ViewController: NSViewController {
             hoverBackground: hoverBackground,
             hoverBorder: hoverBorder,
             onTapURL: { [weak self] url in
-                self?.openWebURLPreferringInApp(url)
+                self?.openWebURLPreferringInApp(url, zoomMeetingDisplayName: meeting.title)
             }
         )
         card.wantsLayer = true