feat(meet): open attached Google Doc notes when joining#919
feat(meet): open attached Google Doc notes when joining#919AlexeyMK wants to merge 5 commits intoleits:masterfrom
Conversation
Adds an opt-in preference that, when enabled, opens the Google Calendar "meeting notes" Doc attachment alongside the Meet link on join. - Parse `attachments[]` from Google Calendar API events - New Defaults key `openGoogleMeetingNotesOnJoin` (default: false) - Toggle in Preferences > Services > Google Meet Scope: Google Calendar provider only. EventKit doesn't expose event attachments via public API; a notes-regex fallback could be added in a follow-up if there's demand.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
WalkthroughExtracts the first Google Docs attachment URL from Google Calendar event attachments, stores it on MBEvent, adds a Defaults key and a Preferences toggle to enable opening that doc when joining Google Meet, and opens the notes URL on join when enabled. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant PreferencesUI as LinksTab UI
participant GCParser
participant MBEvent
participant Browser
User->>PreferencesUI: enable "Open attached Google Doc notes"
PreferencesUI->>PreferencesUI: save Defaults
User->>MBEvent: Join meeting
MBEvent->>GCParser: ensure parsed event / meetingNotesDocLink
GCParser-->>MBEvent: MBEvent(..., meetingNotesDocLink)
MBEvent->>Browser: open meeting URL
alt Defaults.openGoogleMeetingNotesOnJoin && meetingNotesDocLink exists && service == meet
MBEvent->>Browser: open meetingNotesDocLink
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
MeetingBar/UI/Views/Preferences/LinksTab.swift (1)
60-62: Consider toggle placement and enablement.The toggle sits between the Meet browser picker and the Zoom picker, which visually groups it with "Open links in" controls rather than the Meet service specifically. Since it only applies to Google Meet (and, per the PR, only to the Google Calendar provider), consider either:
- Disabling/greying it out when
eventStoreProvider != .gcalendar, and/or- Adding a short helper caption clarifying the GCal-only scope so EventKit users aren't confused when it silently does nothing.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@MeetingBar/UI/Views/Preferences/LinksTab.swift` around lines 60 - 62, The Toggle labeled "preferences_services_meet_open_notes_on_join" (bound to openGoogleMeetingNotesOnJoin) is visually grouped with the "Open links in" pickers but only applies to Google Calendar; update the Toggle in LinksTab.swift so it is disabled unless eventStoreProvider == .gcalendar (use .disabled(eventStoreProvider != .gcalendar)) and add a short helper caption (e.g., a small Text or .help view) immediately under or beside the Toggle clarifying "Applies to Google Calendar/Google Meet only" so EventKit users aren’t confused when it has no effect.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@MeetingBar/Core/EventStores/GCEventStore.swift`:
- Around line 408-416: The attachment filtering currently accepts any attachment
whose fileUrl contains "docs.google.com", which can match non-Docs previews;
update the logic that sets meetingNotesDocLink: only accept attachments whose
mimeType is "application/vnd.google-apps.document" OR whose fileUrl starts with
"https://docs.google.com/document/" (drop the broad contains check), and
optionally further verify the attachment "title" has the event-notes pattern
(e.g., endsWith(" - Notes") or matches the event title + " - Notes") to target
the GCal auto-created notes doc; update references in the same block where
attachments, docAttachment, mimeType, fileUrl, and title are used.
---
Nitpick comments:
In `@MeetingBar/UI/Views/Preferences/LinksTab.swift`:
- Around line 60-62: The Toggle labeled
"preferences_services_meet_open_notes_on_join" (bound to
openGoogleMeetingNotesOnJoin) is visually grouped with the "Open links in"
pickers but only applies to Google Calendar; update the Toggle in LinksTab.swift
so it is disabled unless eventStoreProvider == .gcalendar (use
.disabled(eventStoreProvider != .gcalendar)) and add a short helper caption
(e.g., a small Text or .help view) immediately under or beside the Toggle
clarifying "Applies to Google Calendar/Google Meet only" so EventKit users
aren’t confused when it has no effect.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 1f519466-8456-413b-a94f-f2b4f3314f2d
📒 Files selected for processing (5)
MeetingBar/Core/EventStores/GCEventStore.swiftMeetingBar/Core/Models/MBEvent.swiftMeetingBar/Extensions/DefaultsKeys.swiftMeetingBar/Resources /Localization /en.lproj/Localizable.stringsMeetingBar/UI/Views/Preferences/LinksTab.swift
| if let attachments = item["attachments"] as? [[String: Any]] { | ||
| if let docAttachment = attachments.first(where: { | ||
| ($0["mimeType"] as? String) == "application/vnd.google-apps.document" | ||
| || (($0["fileUrl"] as? String)?.contains("docs.google.com") ?? false) |
There was a problem hiding this comment.
we should of course generalize this eventually to notion / other methods
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #919 +/- ##
==========================================
+ Coverage 36.24% 36.28% +0.03%
==========================================
Files 48 49 +1
Lines 5129 5184 +55
Branches 1743 1750 +7
==========================================
+ Hits 1859 1881 +22
- Misses 3213 3247 +34
+ Partials 57 56 -1 ☔ View full report in Codecov by Sentry. |
Addresses review feedback: - Match attachments by mimeType only (drop broad URL substring fallback) - Disable the preference toggle when not using the Google Calendar provider, with a help tooltip explaining the requirement
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@MeetingBar/UI/Views/Preferences/LinksTab.swift`:
- Around line 61-64: The Toggle currently binds directly to
openGoogleMeetingNotesOnJoin and becomes visually checked when disabled; change
the Toggle to use a computed Binding that returns false when eventStoreProvider
!= .googleCalendar but still writes through to openGoogleMeetingNotesOnJoin on
set. Concretely, replace the Toggle's isOn: $openGoogleMeetingNotesOnJoin with a
Binding(get: { eventStoreProvider == .googleCalendar ?
openGoogleMeetingNotesOnJoin : false }, set: { openGoogleMeetingNotesOnJoin = $0
}), keeping the .disabled(eventStoreProvider != .googleCalendar) and .help as-is
so the stored preference is preserved but the UI shows off when unsupported.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: a768b426-febd-4337-8860-eb233aca9ef1
📒 Files selected for processing (3)
MeetingBar/Core/EventStores/GCEventStore.swiftMeetingBar/Resources /Localization /en.lproj/Localizable.stringsMeetingBar/UI/Views/Preferences/LinksTab.swift
🚧 Files skipped from review as they are similar to previous changes (1)
- MeetingBar/Resources /Localization /en.lproj/Localizable.strings
Adds unit tests verifying that the Google Calendar event parser extracts the attached Google Doc URL into meetingNotesDocLink, ignores non-document attachments, and leaves the field nil when no attachments are present.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
MeetingBarTests/GCEventStoreTests.swift (1)
21-36: Add a mixed-attachments case for the “first Google Doc” behavior.The current positive case only proves a single document attachment is parsed. A mixed list would guard against an implementation that incorrectly checks only
attachments[0]instead of scanning for the first Google Docs attachment.🧪 Suggested coverage
+ func testParsesFirstGoogleDocAttachmentWhenMixedWithOtherAttachments() throws { + var item = baseItem() + item["attachments"] = [ + [ + "fileUrl": "https://drive.google.com/file/d/pdf/view", + "title": "Agenda.pdf", + "mimeType": "application/pdf", + "fileId": "pdf" + ], + [ + "fileUrl": "https://docs.google.com/document/d/abc123/edit", + "title": "Standup - Notes", + "mimeType": "application/vnd.google-apps.document", + "fileId": "abc123" + ] + ] + + let event = try XCTUnwrap(GCEventStore.GCParser.event(from: item, calendar: calendar)) + + XCTAssertEqual(event.meetingNotesDocLink?.absoluteString, + "https://docs.google.com/document/d/abc123/edit") + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@MeetingBarTests/GCEventStoreTests.swift` around lines 21 - 36, The test testParsesGoogleDocAttachmentAsMeetingNotes only covers a single Google Doc attachment, so add a new mixed-attachments case (or extend this test) where attachments contains non-Google items first and a Google Doc later to ensure GCEventStore.GCParser.event(from:calendar:) scans the list and returns the first Google Docs attachment; construct attachments with at least one non-Google mimeType (e.g., "application/pdf") followed by a Google Docs entry with fileUrl "https://docs.google.com/document/d/abc123/edit" and assert event?.meetingNotesDocLink?.absoluteString equals that URL.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@MeetingBarTests/GCEventStoreTests.swift`:
- Around line 49-57: The tests call GCEventStore.GCParser.event(...) and then
assert event?.meetingNotesDocLink is nil, which hides failures when the parser
returns nil; update each test (e.g., testNoAttachmentsLeavesMeetingNotesNil and
the other test that calls GCEventStore.GCParser.event(from:calendar:)) to first
unwrap the parsed event using XCTAssertNotNil or a guard let/XCTUnwrap on the
result of GCEventStore.GCParser.event(from: item, calendar: calendar), then
assert that the unwrapped event.meetingNotesDocLink is nil.
---
Nitpick comments:
In `@MeetingBarTests/GCEventStoreTests.swift`:
- Around line 21-36: The test testParsesGoogleDocAttachmentAsMeetingNotes only
covers a single Google Doc attachment, so add a new mixed-attachments case (or
extend this test) where attachments contains non-Google items first and a Google
Doc later to ensure GCEventStore.GCParser.event(from:calendar:) scans the list
and returns the first Google Docs attachment; construct attachments with at
least one non-Google mimeType (e.g., "application/pdf") followed by a Google
Docs entry with fileUrl "https://docs.google.com/document/d/abc123/edit" and
assert event?.meetingNotesDocLink?.absoluteString equals that URL.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 35d808be-9a2c-491c-9f47-1032656be7f7
📒 Files selected for processing (1)
MeetingBarTests/GCEventStoreTests.swift
Xcode 26.4+ rejects direct imports of SwiftUICore as it is now an implementation detail of SwiftUI. Unrelated to the feature but needed to build the test target on current Xcode.
… tests Use a gated Binding so the toggle visually shows off when the event store provider is not Google Calendar (while preserving the stored preference for when the user switches back). Use XCTUnwrap in nil-asserting tests so a parser regression that returns nil is caught rather than silently passing.
🇺🇦 Слава Україні! 👋
If available, auto-open the 1:1 / meeting notes doc when also auto-opening a meeting.
Status
READY
Description
Opt-in preference: when joining a Google Meet, also open the event's attached Google Doc (the GCal "Take meeting notes" doc).
GCal's "Take meeting notes" creates a Doc and attaches it to the event. Opening it alongside the Meet tab saves a click on every meeting.
How
MBEventgainsmeetingNotesDocLink: URL?GCEventStorepopulates it fromattachments[](firstapplication/vnd.google-apps.document)openMeeting()opens it after the Meet link when the pref is onScope note: Google Calendar provider only.
EKEventhas no public attachments API, so EventKit events leave the fieldnil. Happy to add a description-regex fallback in a follow-up if wanted.Checklist
Steps to Test or Reproduce
Summary by CodeRabbit
New Features
Chores / Preferences
Localization
Tests