Skip to content

feat(meet): open attached Google Doc notes when joining#919

Open
AlexeyMK wants to merge 5 commits intoleits:masterfrom
AlexeyMK:feat/open-meeting-notes-on-join
Open

feat(meet): open attached Google Doc notes when joining#919
AlexeyMK wants to merge 5 commits intoleits:masterfrom
AlexeyMK:feat/open-meeting-notes-on-join

Conversation

@AlexeyMK
Copy link
Copy Markdown

@AlexeyMK AlexeyMK commented Apr 22, 2026

🇺🇦 Слава Україні! 👋

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

  • MBEvent gains meetingNotesDocLink: URL?
  • GCEventStore populates it from attachments[] (first application/vnd.google-apps.document)
  • openMeeting() opens it after the Meet link when the pref is on
  • New toggle in Preferences > Services, default off

Scope note: Google Calendar provider only. EKEvent has no public attachments API, so EventKit events leave the field nil. Happy to add a description-regex fallback in a follow-up if wanted.

Checklist

Steps to Test or Reproduce

  1. Connect a Google account in MeetingBar
  2. Create a calendar event with a Meet link, click "Take meeting notes" in GCal to attach a Doc
  3. Preferences > Services > enable "Open attached Google Doc notes when joining"
  4. Join the event from MeetingBar — both the Meet link and the Doc should open
  5. Toggle off → only Meet opens (no behavior change)
  6. Event with no attachment → only Meet opens

Summary by CodeRabbit

  • New Features

    • Automatically open attached Google Docs when joining Google Meet meetings (when enabled).
  • Chores / Preferences

    • New preference (off by default) to enable/disable opening attached Google Doc notes; visible in Preferences and only active for the Google Calendar provider.
  • Localization

    • Added strings for the new preference and its help text.
  • Tests

    • Added tests validating parsing and handling of Google Doc attachments.

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.
@dosubot dosubot Bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Apr 22, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2026

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5855388e-65b2-4e00-9a9c-79be600fad1d

📥 Commits

Reviewing files that changed from the base of the PR and between f27095d and 0b51a63.

📒 Files selected for processing (2)
  • MeetingBar/UI/Views/Preferences/LinksTab.swift
  • MeetingBarTests/GCEventStoreTests.swift
🚧 Files skipped from review as they are similar to previous changes (2)
  • MeetingBar/UI/Views/Preferences/LinksTab.swift
  • MeetingBarTests/GCEventStoreTests.swift

Walkthrough

Extracts 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

Cohort / File(s) Summary
Event parsing
MeetingBar/Core/EventStores/GCEventStore.swift
Scan an event's attachments for mimeType == "application/vnd.google-apps.document", convert its fileUrl to URL?, and pass it as meetingNotesDocLink when constructing MBEvent.
Event model & runtime behavior
MeetingBar/Core/Models/MBEvent.swift
Add meetingNotesDocLink: URL? to MBEvent and update openMeeting() to also open the notes URL when the detected service is Google Meet and the new preference is enabled.
Preferences & UI
MeetingBar/Extensions/DefaultsKeys.swift, MeetingBar/UI/Views/Preferences/LinksTab.swift
Add openGoogleMeetingNotesOnJoin Defaults key and a toggle in LinksTab bound to it; toggle is disabled unless eventStoreProvider == .googleCalendar.
Localization
MeetingBar/Resources/Localization/en.lproj/Localizable.strings
Add preferences_services_meet_open_notes_on_join and preferences_services_meet_open_notes_on_join_help English strings.
Tests
MeetingBarTests/GCEventStoreTests.swift
Add tests for GCParser.event(from:calendar:) verifying meetingNotesDocLink is set for Google Docs attachments and nil for non-document or missing attachments.
Minor test import fix
MeetingBarTests/TimelineLogicTests.swift
Change SwiftUI import from SwiftUICore to SwiftUI.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

lgtm

Suggested reviewers

  • leits
  • mskopp

Poem

🐰 I sniffed a doc behind the meet,
tucked notes that made my heart skip a beat.
Flip the toggle, hop on through—
the doc pops open, fresh and new. 📓🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main feature: enabling auto-opening of attached Google Docs when joining Google Meet meetings.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@dosubot dosubot Bot added the feature New feature or request label Apr 22, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between c4971f1 and 41143da.

📒 Files selected for processing (5)
  • MeetingBar/Core/EventStores/GCEventStore.swift
  • MeetingBar/Core/Models/MBEvent.swift
  • MeetingBar/Extensions/DefaultsKeys.swift
  • MeetingBar/Resources /Localization /en.lproj/Localizable.strings
  • MeetingBar/UI/Views/Preferences/LinksTab.swift

Comment thread MeetingBar/Core/EventStores/GCEventStore.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)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should of course generalize this eventually to notion / other methods

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 22, 2026

Codecov Report

❌ Patch coverage is 38.18182% with 34 lines in your changes missing coverage. Please review.
✅ Project coverage is 36.28%. Comparing base (3d81a85) to head (0b51a63).
⚠️ Report is 11 commits behind head on master.

Files with missing lines Patch % Lines
MeetingBarTests/GCEventStoreTests.swift 57.14% 15 Missing ⚠️
MeetingBar/Core/EventStores/GCEventStore.swift 0.00% 8 Missing ⚠️
MeetingBar/UI/Views/Preferences/LinksTab.swift 0.00% 7 Missing ⚠️
MeetingBar/Core/Models/MBEvent.swift 20.00% 4 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

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
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 41143da and e697097.

📒 Files selected for processing (3)
  • MeetingBar/Core/EventStores/GCEventStore.swift
  • MeetingBar/Resources /Localization /en.lproj/Localizable.strings
  • MeetingBar/UI/Views/Preferences/LinksTab.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • MeetingBar/Resources /Localization /en.lproj/Localizable.strings

Comment thread MeetingBar/UI/Views/Preferences/LinksTab.swift Outdated
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.
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:S This PR changes 10-29 lines, ignoring generated files. labels Apr 22, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between e697097 and 967f469.

📒 Files selected for processing (1)
  • MeetingBarTests/GCEventStoreTests.swift

Comment thread MeetingBarTests/GCEventStoreTests.swift Outdated
AlexeyMK and others added 2 commits April 22, 2026 16:36
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants