Calendar in search
v0.9.7Narrow which calendars search reads, add Directions and Join buttons to event rows, and see a shared event once instead of twice.
- Settings → Drawer → Calendar → Calendars to search
- Settings → Drawer → Calendar → Event actions
Choosing which calendars to search
Drawer search reads every calendar your calendar app has marked visible. Settings → Drawer → Calendar → “Calendars to search” narrows that — useful when a calendar should stay visible in the calendar app but not surface when you’re typing in the drawer. The summary line reads “All calendars,” “No calendars,” or a count like “5 of 8 calendars.”
The picker only lists calendars currently marked visible, and starts with everything ticked — unticking a calendar excludes it from search while leaving it alone everywhere else. A calendar you hide in the calendar app itself stays hidden from search either way, regardless of what’s ticked here. Above five calendars, a “Select all”/“Select none” button appears.
Under the hood
The setting stores which calendars to exclude, not which to include — an empty exclusion set means search everything, so a calendar added to an account later is searched immediately without needing its own entry. The picker inverts this for display, since a ticked box meaning “search this” is what a checkbox is expected to mean. Renaming a calendar loses its exclusion, so a renamed calendar starts being searched again.
Directions and Join on event rows
A calendar row in search or on the drawer’s home surface can carry up to two action buttons: “Directions,” when the event’s location looks like a place, and “Join,” when it carries a known video-meeting link. Settings → Drawer → Calendar → “Event actions” is a multi-choice dialog for the two; Directions is ticked by default, Join is not.
A location that’s nothing but a meeting-service placeholder — the generic text some calendar apps write into the location field for a Teams meeting, for instance — is never treated as a place, so Directions doesn’t open a map on it. Join checks both the location and the description for a recognized meeting link, location first, and only counts a link as a match against a known list of meeting services rather than any web address.
Under the hood
Matching a meeting link checks the host itself — matching it exactly or as a subdomain — rather than searching for the service’s name anywhere in the URL, which is what stops a link like zoom.us.attacker.example or a query string mentioning zoom.us from being treated as a real Zoom link.
One row per event across calendars
An invitation that lands on two calendars in the same account — your own and a shared family calendar, say — is one event, but showed up as two rows before. It now shows once, keeping the copy on your main calendar when there is one, or otherwise the copy on a calendar you own over one only shared with you.
Under the hood
key(event) = (invite_id, start_time) # start_time keeps recurring instances distinct
sort events by:
start_time ascending
is_main_calendar descending # a copy on your main calendar wins
calendar_access_level descending # else, owned beats read-only
calendar_id ascending # tiebreak only, for stability
seen = {}
for event in sorted events:
if event.invite_id is empty:
keep event # no invite id, never merged with anything
elif key(event) in seen:
drop event # duplicate: another calendar's copy
else:
seen.add(key(event))
keep event
An event with no invite id — a local, unsynced event — is never merged with anything else, even another local event, since treating two blank ids as equal would risk hiding two genuinely different events. A dropped duplicate doesn’t cost a result slot, so a search capped at a fixed number of rows still returns that many distinct events.
Limits
A duplicate that reaches two calendars through some route other than a shared invite — without a shared invite id — still shows twice. Closing that gap would mean matching by title and start time instead, which was tried and rejected: it also catches distinct events that happen to share both, like a recurring meeting name repeated across two projects, and hiding a real event is worse than showing one twice.