calendar: graceful fallback when start-takeover animation is undrawable - #19
Merged
Conversation
…on is undrawable
The v1.6 start-takeover draws a full-panel stock AnimationElement
(shared/<start_animation>.anim) for the first start_window_seconds after
an event begins. If start_animation names an animation absent from the
device (an operator typo -- the default meeting_72x16 is valid), the live
device rejects the draw with DrawResult.ERROR every poll. Since the
takeover is the ONLY thing on screen, state never commits and run_once
re-clears + re-fails each poll, leaving the panel DARK for the whole
window instead of showing anything.
run_once now falls back to the normal in-progress ("ENDS") layout for that
poll when a just_started takeover draw returns ERROR, so a mistyped
start_animation degrades to a live countdown rather than a blank screen,
and logs the misconfiguration. Only ERROR triggers the fallback: REJECTED
(a higher-priority app owns the screen -- the lower-priority in-progress
draw would be rejected too) and UNREACHABLE (device down -- handled by the
loop's backoff) do not. Per-poll, not latched, so it self-heals the moment
the config is fixed or the animation appears, no restart needed.
Adds four FakeClient tests (ERROR falls back; REJECTED/UNREACHABLE do not;
fallback is per-poll not latched) and corrects the README, which had
described the mistyped-name case as leaving the panel dark.
Co-Authored-By: Claude Opus 4.8 <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
Makes the
calendar_countdownv1.6 start-takeover robust against a mistypedstart_animationconfig value (feature landed in #18).The takeover draws a full-panel stock
AnimationElement(shared/<start_animation>.anim) for the firststart_window_secondsafter an event begins. Ifstart_animationnames an animation that isn't on the device (operator typo — the defaultmeeting_72x16is valid), the live device rejects the draw withDrawResult.ERRORevery poll. Because the takeover is the only thing on screen,state["last_shape"]never commits,run_oncere-clears + re-fails each poll, and the panel stays DARK for the whole window (~60 s) instead of showing anything.Change
run_oncenow falls back to the normal in-progress (ENDS) layout for that poll when ajust_startedtakeover draw returnsERROR— so a typo degrades to a live countdown rather than a blank panel, and logs the misconfiguration.ERRORtriggers the fallback, deliberately:REJECTED→ a strictly-higher-priority app owns the screen; the in-progress layout draws at a lower priority (PRIORITY_AMBIENTvs the takeover'sPRIORITY_AMBIENT_URGENT) and would be rejected too — a pointless second draw.UNREACHABLE→ device down; the loop's own backoff (main()) handles it.clear()before the fallback draw: the failed takeover landed nothing and the shape-tracker clear already fired for any real id-set change (last_shapeis never the takeover shape, since a takeoverERRORnever commits it).Tests & docs
FakeClienttests intests/test_calendar_loop.py:ERRORfalls back to the in-progress layout and commits its shape;REJECTEDandUNREACHABLEdo not fall back; the fallback is per-poll (not latched). Full suite green: 363 passed.BusyBarClientonly; no new deps.🤖 Generated with Claude Code