Skip to content

firmware: idle screen when usage data goes stale#64

Merged
HermannBjorgvin merged 1 commit into
HermannBjorgvin:mainfrom
nathanjohnpayne:status-dot
Jun 5, 2026
Merged

firmware: idle screen when usage data goes stale#64
HermannBjorgvin merged 1 commit into
HermannBjorgvin:mainfrom
nathanjohnpayne:status-dot

Conversation

@nathanjohnpayne

@nathanjohnpayne nathanjohnpayne commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Shows a calm idle screen when the device is connected over BLE but isn't receiving usage data — so it never leaves hours-old numbers on screen as if they were live.

The usage view resolves to three states:

  • live — usage panels, when data is flowing
  • idle — connected but no usage update in ~90s (token expired, daemon down, host asleep); shows a shrunk, animated sleeping creature (reused claudepix expression sleep art), with a status line that alternates "Listening…" / "No data…" (alive + explicit)
  • pairing — the existing hint when BLE is disconnected (from Collapse UX to single Usage view + hold-to-pair + brightness #49)

Also makes the bottom status line consistent — it now animates present-participle gerunds throughout, with the disconnected screen using "Waiting…" (replacing the static "Disconnected…").

A small splash_mini_create() / splash_mini_tick() API renders any claudepix animation shrunk into a parent, keeping the art data in the splash module. No new persistent on-screen elements. (See the thread for the design discussion — this evolved from an earlier status-dot approach.)

🤖 Generated with Claude Code

@nathanjohnpayne

nathanjohnpayne commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

Nifty indicator to show the data is live!
image

@HermannBjorgvin

Copy link
Copy Markdown
Owner

#49 merged the other day I don't know where your branch base is at but it changed the UX a bit by removing the BT screen and adding a pairing instruction screen which displays automatically when BLE is disconnected.

So your grey dot is redundant I would think.

On the amber dot I think the right solution is to maybe resolve #63 by introducing an idle state or screen or something to indicate that the token is expired, I am assuming that was what you were thinking with the amber dot? Please correct me if not.

That leaves the green dot indicator which I think would also be redundant if we nail the idle indicator display.

I appreciate the design and that you kept it in the brand design styleguide but in my opinion the better design would be eliminating the need for it at all and sticking to having fewer elements on the screen and less info for the user to take in unless strictly necessary.

WDYT? We could pivot to a "😴 Zzz" indicator screen similar to the new BLE pairing instruction screen when not receiving data from the daemon? Also open to other ideas.

@nathanjohnpayne

Copy link
Copy Markdown
Contributor Author

Reworked this per your steer—dropped the dot entirely and replaced it with a full-screen idle state, in the spirit of your 😴 Zzz idea:

image

What's baked in:

  • Dot's gone. Grey was redundant with the pairing screen, and green stops earning its place once idle has a clear treatment—agreed on all of it.
  • An animated "Listening…" status line at the bottom so the screen reads as alive (waiting), not frozen.

Two notes on behavior:

It reuses the freshness timer, so it's mostly a presentation swap—net result is what you wanted: zero persistent elements, one screen that appears only when something's actually off.

One small thing I noticed while in there (didn't touch it — it's your #49 work): the bottom status line on the disconnected screen reads ✳ Disconnected…. Everywhere else, that line animates a present-participle gerund ("Pondering…" and now "Listening…" on the idle screen), so "Disconnected…" clangs a little—a static state sitting beneath an animated spinner. If you ever want it to match, something like "Listening…" or "Waiting…" would slot right in (and could cover both the bonded + unbonded cases, dropping the has_bonds split). Totally your call—just flagging it.

Threshold is ~90s of no data before it flips (daemon sends ~every 60s); happy to tune that or the copy. I'll get the updated diff up on the branch.

@nathanjohnpayne nathanjohnpayne changed the title firmware: online status dot next to the battery firmware: idle screen when usage data goes stale Jun 5, 2026
@HermannBjorgvin

Copy link
Copy Markdown
Owner

If you ever want it to match, something like "Listening…" or "Waiting…" would slot right in (and could cover both the bonded + unbonded cases, dropping the has_bonds split). Totally your call—just flagging it.

I think that'd possibly work better, continues the same UX of utilizing the animated spinner for the status

Threshold is ~90s of no data before it flips (daemon sends ~every 60s); happy to tune that or the copy. I'll get the updated diff up on the branch.

Just an idea on the Daemon you could send a health status message more frequently if you feel like the 60s polling window is too long.

And also maybe a nitpick that I wouldn't have given on a PR pre-gpt but now that everything is a prompt away I don't need to feel as guilty about it: what about instead of showing "Zzz waiting for usage data" we indeed do as you suggest and use the animation spinner on the bottom for conveying that info and instead in the middle of the screen show the "sleeping" splash animation shrunk down so it's not 480x480px but some tasteful size that fits in between the header and footer elements?

Let me know what you think! Thanks for the effort BTW

@nathanjohnpayne

Copy link
Copy Markdown
Contributor Author

Love all three — let's do it.

The "Disconnected…" gerund: agreed, I'll swap it to a present participle so it matches the animated-spinner pattern. One nuance — since the idle screen now uses "Listening…", I'd make the disconnected one "Waiting…" so the two read distinctly (one waiting for a connection, the other for data)—but happy to use whatever you prefer. I will fold the one-liner into this PR with my recommendation.

Daemon heartbeat: good call—a lighter, more-frequent ping would make the idle flip snappier than the ~90s window, and could even tell "daemon alive, token just expired" apart from "daemon's gone." I'd keep it out of this PR (it's a daemon-side / #63 change), and ~90s is fine for v1, but it's an easy follow-up if the lag feels long in the field.

Sleeping creature: yes — this is the better screen. Bonus: there's already an expression sleep creature in the claudepix set (24 frames), so we reuse the existing art instead of drawing anything (which you probably knew :-) ). Plan: render it shrunk (~140px), centered between the header and the status line, animated on its own frame timing; drop the "Zzz / Waiting for usage data" text and let the bottom spinner carry it ("Listening…", or "Sleeping…" to match the creature — open to taste). I'll get a preview up.

Thanks for the thoughtful review—better screen than where I started.

@HermannBjorgvin

Copy link
Copy Markdown
Owner

Appreciate taking the feedback! No wonder Disney Plus feels nicer to browse thank Netflix 😄

When the host is connected over BLE but no usage update has landed recently
(~90s — token expired, daemon down, host asleep), show a calm idle screen
instead of leaving hours-old numbers on screen as if they were live: a shrunk,
animated "expression sleep" creature (reused claudepix art) centered between
the header and the status line.

The usage view resolves to three sub-screens via a data-freshness timer: live
panels, this idle screen, or the existing pairing hint. The bottom status line
animates present-participle gerunds: the idle screen alternates "Listening…" /
"No data…" (alive + explicit), the disconnected screen uses "Waiting…"
(replacing the static "Disconnected…").

splash_mini_create()/splash_mini_tick() render any claudepix animation shrunk
into an arbitrary parent, keeping the art data in the splash module.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@nathanjohnpayne

nathanjohnpayne commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

Pushed the final version — I think this covers everything:
image
image

  • Sleeping creature in the middle — reused the existing claudepix expression sleep art, shrunk to ~160px between the header and the status line. No new art drawn.
  • The status line carries the words, as you suggested — and it alternates "Listening…" / "No data…" every 4s, so it reads as alive and makes the "no data" part explicit (I'd worried "Listening…" alone was a touch ambiguous).
  • "Disconnected…" → "Waiting…" for gerund consistency (drops the has_bonds split).

On the daemon heartbeat idea—left it out of this PR since it's daemon-side (#63 territory); making that fix now in the other PR.

It's a single clean commit (idle screen + a small splash_mini_create() helper). Ready for another look whenever.

@HermannBjorgvin

Copy link
Copy Markdown
Owner

I agree with your call on the PR scope. The changes you made look great!

Good call on "listening/no data" alternating.

Will merge your changes, appreciate the help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants