feat(core,backend,sync): carry calendar account email and event iCalUID on the wire - #2564
Merged
Merged
Conversation
…ID on the wire Groundwork for supporting multiple connected Google accounts. Each calendar in /api/calendars now reports the email of the provider account it belongs to (joined from the connection list; absent for the local calendar), and imported Google events store their iCalUID in the provider metadata bag so copies of the same meeting on different accounts can be correlated later. No visual or behavioral change yet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tyler-dane
added a commit
that referenced
this pull request
Aug 4, 2026
* fix(web): commit dropdown selection when Enter lands on the trigger useListNavigation moves focus from the trigger into the option list a frame after the dropdown opens, so a fast ArrowDown+Enter can land Enter on the trigger button. Its native Enter-click then toggled the dropdown closed and lost the selection. Both dropdown components now commit the active option from the trigger too, mirroring the floating element's own handler (the dual placement floating-ui's Select example uses). The keyboard e2e test additionally waits for the roving tabindex to land on the target option before committing: floating-ui applies the arrow-key move a frame later, and Playwright (unlike any human) can type ArrowDown+Enter inside one frame, re-committing the previous selection - which closed the dropdown with an unchanged label and made the test intermittently fail with no app error to show for it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(e2e): drop the flaky keyboard-commit tail of the calendar picker test The ArrowDown+Enter commit in this test failed ~40% of isolated repeated runs. Two mechanism-level fixes were applied and verified insufficient: hardening the component against a real trigger-Enter race (kept - it fixes a genuine fast-keyboard bug, and the same latent race in SelectView), and waiting for the roving tabindex to move before Enter. The residual race lives somewhere in floating-ui's async active-item handling under Playwright's faster-than-human key cadence and is not worth more investigation: keyboard navigation and Enter/Space selection are covered deterministically in CalendarSelect.test.tsx. The stable and otherwise-uncovered part of the test - the form offers only writable calendars - stays. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor: simplify multi-account cross-account-merge plumbing Findings from a 4-angle review (reuse/simplification/efficiency/altitude) of PRs #2564-#2573. Applied: - The 'also on another account' fact now rides on the event itself (GridEvent.otherAccount), joined the same way isDemo already is, instead of a parallel side-band map hand-threaded through 2 view-model hooks and 4 list components. Deletes findCrossAccountDuplicate and all of its call sites; resolveCalendarCardIdentity now reads the fact straight off the event. - useDayEventViewModel/useWeekEventViewModel's identical ~20-line filter->merge->derive pipeline collapses into one shared useCalendarEventViewModel hook. - A single-account early-out in mergeCrossAccountDuplicates: duplicates need two accounts, so the overwhelming majority of users (one account) now skip the per-event grouping pass entirely. - The merge's 3-level memo (WeakMap>WeakMap>Map-of-emails) drops to a last-value slot - every consumer in one render derives the same default-account email, so remembering one is as effective as a map. - computeMerge groups {id, event, accountEmail} directly instead of re-deriving accountEmail from a second pass over the group. - The calendarAccentStyle/calendarAccentAccessibleSuffix helpers move out of the calendars module (which had started importing types from events/queries - an inverted dependency) to grid/components, next to their only two consumers. - SYNC_STATUS_VARIANT_CLASSNAME, copy-pasted between CalendarListHeader and the new AccountSectionHeader, is now one export from sync-status.types.ts. - sync-service.client.ts's expectNoContent flag and optional schema encoded one fact twice; collapsed to one rule (no schema -> expect 204). - Dead optionality in user-metadata.service.ts's GoogleMetadataAssessment (connections?/connection? guarded against a producer that never omits them) replaced with the real GoogleConnectionFromSync type. - backfill-icaluid's write path no longer double-passes (samples loop, then a separate filter/map for writes) or re-derives guards the query already enforced. - New shared test factories (createMockCalendar, createMockConnection) replace four near-identical per-file copies written across this same feature - the Calendar/GoogleSyncConnectionSummary contracts grew fields in this very set of PRs, so the duplication was already live. All four suites green (1642 web / 327 backend / 768 sync / 36 scripts), type-check and biome clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Invisible groundwork for supporting multiple connected Google accounts on one Compass grid:
CalendarSchemagains an optionalaccountEmail— the email of the provider account each calendar belongs to. The backend joins it from the principal's connection list (fetched in parallel with the calendar list; both are cheap passive-mode sync reads). Absent (not null/empty) for the local calendar and for accounts that reported no email.iCalUIDin the ownershipproviderMetadatabag. Google sharesiCalUIDacross copies of the same meeting on different accounts (unlikeproviderEventId), so it is the correlation key for recognizing cross-account duplicates later. The bag now merges both facts it can carry (transparencyfor free events,iCalUID), stillnullwhen neither applies.No visual or behavioral change: the web parses the same core schema, so the new optional field flows through untouched, and nothing reads
iCalUIDyet.Tests
accountEmailwhen supplied and omits the key entirely when not.connectionId; a connection with a null email yields a calendar without the key.iCalUIDand omits it when Google reports none.{iCalUID}, merges{transparency, iCalUID}, and keepsnullfor plain busy events.bun run type-checkand biome clean.🤖 Generated with Claude Code