Add Google Calendar app - #675
Draft
nsluke wants to merge 4 commits into
Draft
Conversation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueComment |
Co-Authored-By: Claude Opus 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.
Your next event, at a glance — a recreation of Tidbyt's first-party Google Calendar app (13th most-installed on the platform). It was OAuth-only through their cloud, so it died with the shutdown, and nothing has replaced it: the catalog covers iCal feeds (
anycalendar,universalical,hellocal) and Home Assistant, but not Google directly.Screenshots
Three ways to authenticate
config["auth"]is present it's used directly as a bearer token — the tronbyt-server Connections contract. A Google provider on the server side would light this app up with no changes here.outlookcalendarandspotifyalready use. The app exchanges the refresh token and caches the access token forexpires_inminus a minute.Two API details worth knowing
Both came from the live discovery doc (revision 20260826), fetched keyless rather than recalled from memory:
timeMinis a lower bound on the event's end time, not its start. That's what makes the "NOW" state work from a single query — in-progress events come back naturally, no second request.maxAttendees=1returns only the requesting participant, which gives exactly the self-attendee needed to filter declined events while shrinking the payload.Also confirmed live: the token endpoint answers
401 {"error":"invalid_client"}(invalid_grantis 400), and the unauthenticated events endpoint returns 403PERMISSION_DENIED, not 401 — so the app treats both as auth failures and clears the cached token so the next cycle re-exchanges.Verification
20 states from a stub: soon, imminent, later today, now, back-to-back, all-day, tomorrow, next-all-day, clear-7-days, no items, long title, declined, nulls, 401, 500, non-JSON, token failure, token endpoint down, and the Connections path.
pixlet checkpasses under the repo's pinned v0.50.1. Default render 31 ms, no network.Adversarial review found nine issues, all reproduced and fixed. The two most interesting:
Also fixed: Google's non-meeting event types (
workingLocation,outOfOffice) were hijacking the card and hiding your real next event.Caveats
$tz.hash.starisn't available, so cache keys use a hand-rolled djb2 hash of the credentials. Collision risk is negligible, andoutlookcalendarkeys by the raw token for comparison.🤖 Generated with Claude Code
64x64 square panel support
The wide card shows exactly one event because 2:1 is all it fits — while
fetch_eventshad already pulled, filtered and cached a whole week of them with nowhere to put them. On square an event card becomes an agenda: the wide card's hero across the top (badge grown to the panel), a rule, then up to three "when | what" rows. Cards that aren't about an event (setup, offline, reconnect, all-clear) become a centred poster using the full 64px width rather than the 43px the icon leaves beside it on wide. The plumbing is one optionalrestargument:Nonemeans poster, a list means agenda.The wide layout is untouched. An additive
is_square()branch oncanvas.size()(h * 2 > w + 16, matching the convention in #655/#666 — shape, never size, so a 2x wide panel is never mistaken for a square one). Wide output was rendered before and after the port and compared byte for byte: 262 comparisons across configs at both 64x32 and 128x64, zero differences, with a deliberately broken copy used as a negative control to prove the comparison actually discriminates.pixlet checkgreen on the pinned v0.50.1. No manifest change — upstream has nosupports64x64field.