Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@

Local-API integrations for the BUSY Bar — a 72×16 LED status display on USB or LAN.

## Display design

The **Signal** display style pairs dark backgrounds with bright time readouts,
consistent status cards, and native animation. Urgent calendar screens retain
the event title; CI status headings stay fixed while details scroll. Nyan has
a softer rainbow trail and a seamless star loop. See the
[design and device captures](docs/display-design.md) for the before/after
comparison and unchanged priority/handoff behavior.

## Requirements

- **BUSY Bar** on USB (default address `10.0.4.20`) or LAN
Expand Down
Binary file modified assets/nyan/frames/frame_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_12.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_13.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_14.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_15.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_17.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_18.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_19.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_20.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_21.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_22.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_23.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/frames/frame_9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/nyan/nyan_72x16.anim
Binary file not shown.
84 changes: 84 additions & 0 deletions docs/display-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Signal display design

Signal gives the calendar, CI status, and idle animation a shared visual style:
dark navy backgrounds, bright numerals, thin progress tracks, and native motion.
Cyan signals activity, amber approaching or waiting, coral urgency or failure,
and mint an active event or healthy CI. Text labels keep each state identifiable
without relying on color alone.

![Signal screens captured from a BUSY Bar](images/signal-overview.png)

These are native **72×16 framebuffer captures**, enlarged with nearest-neighbor
scaling. They use fixed demonstration events and runs, not live calendar content.
The screenshots show the start of scrolling titles; the full text remains in
the device payload. LED brightness and diffusion can look different in person.

## Calendar flow

The familiar sequence stays intact: upcoming → approaching → warning → imminent
→ start animation → in progress. The redesign makes that sequence easier to read:

- The large start time and countdown retain their existing size and positions.
- Warning and imminent screens reserve a 16-pixel lane for the animated calendar
icon and a **52-pixel title lane**. The title remains visible through the final
minute, with `IN <1m` below it.
- A bright endpoint makes the progress track easier to locate. Upcoming tracks
drain toward the start; active-event tracks now drain against the event's
duration, alongside the existing `ENDS` countdown.
- The existing full-screen start animation still provides the transition into
an active event.

![Calendar before and after](images/signal-calendar.png)

## CI flow

Failure, waiting, and healthy cards share a fixed heading and a bold lower row.
`CI FAIL`, `CI WAIT`, and `CI OK` stay visible while repository, ref, and workflow
details scroll. The healthy state uses the compact, static `ALL CLEAR` label.
Firmware 1.2.3 adds a small status icon beside the heading; the words remain
readable when icons are disabled or unavailable over an older/cloud route.

Running builds retain their large ETA. Moving the native spinner to the
lower-right corner gives the title its full width, while a separate text budget
keeps ETA labels clear of the spinner. The progress track uses a cyan-to-mint
gradient with a bright endpoint.

Quota screens label the left value `GQL LEFT` or `REST LEFT`, and the right
value `RESET`, with a thin separator. Their percentages and reset countdowns
keep the existing meaning.

![CI before and after](images/signal-ci.png)

## Idle animation

Nyan keeps its recognizable silhouette and 12 fps motion, with a navy backdrop,
a rainbow that fades toward the tail, and a star pattern that repeats seamlessly
over the 24-frame loop. The device plays the uploaded animation as before.

![Nyan source-frame animation preview](images/signal-nyan.gif)

The GIF is an enlarged preview generated from the committed source frames,
not a recording of the physical display. The encoded `.anim` was also uploaded
under a separate preview application and successfully drawn by the device.

## Behavior and validation

This is a presentation change. Event selection, escalation thresholds,
integration priorities, CI rotation and dwell times, poll intervals, frame
timeouts, quiet hours, and manual-session precedence retain their existing
contracts. New shapes use the same cleanup and expiring-frame paths. Motion
runs on the device; no host animation loop, service, dependency, or new
configuration is introduced.

Validation on firmware **1.2.3 / API 27.5.0** included native captures of five
calendar states, running/failure/waiting/healthy CI, both quota labels, and an
encoded Nyan asset draw. The final-minute `<` glyph, `ALL CLEAR`, and `REST LEFT`
were checked on the native framebuffer. Temporary preview frames used their
own application name, priority below manual sessions, a five-second timeout,
and application-scoped cleanup. Production jobs were not restarted for these
previews.

The automated suite passes **445 tests**, covering existing selection and
handoff behavior plus title retention, track bounds, spinner separation, CI log
context, and deterministic animation generation. All 24 PNG frames and the
encoded animation were independently regenerated and matched byte for byte.
Binary file added docs/images/signal-calendar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/signal-ci.png
Binary file added docs/images/signal-nyan.gif
Binary file added docs/images/signal-overview.png
10 changes: 5 additions & 5 deletions integrations/calendar_countdown/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

This integration polls your macOS calendar for upcoming events and displays a live countdown on the busybar device: a full-panel gradient background that itself signals urgency, an uppercase title row, a horizontal drain track, and large numerals (start time, or countdown) floating directly on the background — no card surfaces, for an airy, high-contrast look.

- **Color Horizon background** — the whole panel is a top-to-bottom gradient whose colors shift with urgency: deep violet when the event is far off, warm orange approaching `notice_minutes`, red approaching `warn_minutes`, and teal while the event is in progress. Urgency reads at a glance before you even look at the countdown.
- **Signal background** — the whole panel is a top-to-bottom gradient whose colors shift with urgency: deep navy when the event is far off, warm orange approaching `notice_minutes`, red approaching `warn_minutes`, and teal while the event is in progress. Urgency reads at a glance before you even look at the countdown.
- **Title row** — the event title, uppercased, in a small font flush across the top. Long titles scroll; short ones sit static.
- **Drain track** — a thin horizontal line spanning the full width, edge to edge, below the title. It fills proportionally to time remaining within `progress_window_minutes` (default 60) and shrinks toward empty as the start time arrives. An in-progress event shows it full-width and steady instead (no drain — the relevant countdown is now "time until it ends").
- **Drain track** — a thin horizontal line spanning the full width, edge to edge, below the title. It fills proportionally to time remaining within `progress_window_minutes` (default 60) and shrinks toward empty as the start time arrives. During an active event, the track drains against the event duration. A bright endpoint makes the remaining fraction easy to locate.
- **Time / Ends** — a large local `HH:MM` start time for an upcoming event, or a bold "ENDS" label once the event has begun. No card behind either — both float directly on the gradient background.
- **Countdown** — a large minutes-granular countdown, same size as the time/ends numeral (they always change together): `"54m"` under an hour, `"1h05m"` at/above an hour, falling back to hour-only (`"9h"`) whenever the combined form would run too wide for the space available — which font-width measurement shows can happen even for some single-digit-hour values, not just at 10+ hours. Counts to the event start while upcoming, or to its end once in progress; re-rendered each poll rather than ticking natively on-device, so it updates on the same cadence as the rest of the display (`poll_seconds`).
- **Four states** — `normal`, `notice` (within `notice_minutes` of start), `warning` (within `warn_minutes` of start), and `in_progress`, each with its own background gradient, title color, drain-track gradient, divider color, and digit color. See the design spec (`docs/superpowers/specs/2026-08-03-calendar-ci-integrations-design.md`) for the full palette table and row-budget diagram.
- **Four states** — `normal`, `notice` (within `notice_minutes` of start), `warning` (within `warn_minutes` of start), and `in_progress`, each with its own background gradient, title color, drain-track gradient, divider color, and digit color. See the [current design and device captures](../../docs/display-design.md) for the visual flow.

The integration looks ahead 12 hours by default and draws at the ambient tier (`busybar.display.PRIORITY_AMBIENT`, priority 20) on the display. If an active BUSY session exists on the device, the calendar event display is suppressed in favor of the busy state (priority 90). If the `ci_status` integration is also running with `show_running` and/or `show_quota` enabled, the calendar and the overlay rotation (running badge, GraphQL/REST quota frames) trade the screen back and forth for as long as a CI run is active — see `ci_status`'s README ("Display Priority Tiers" / alternation rhythm) for the measured numbers; the panel still goes fully dark for a few seconds in most cycles because the firmware never restores an occluded element on its own (see "Display Priority Tiers" below), but at the tuned 10s ambient poll the calendar now recovers the screen in roughly 3 of every 4 overlay dwell gaps rather than effectively never.

Expand Down Expand Up @@ -196,8 +196,8 @@ This integration uses device stock animations to accent the calendar escalation

When `escalation_icons` is true (default), animated calendar icons accompany the text-based countdown:

- **Warn stage** (within `warn_minutes` of start, e.g., 5 minutes): a `calendar_event_16x16` icon animates at the top-left corner. The event title is shown to the right of the icon, in the reduced space between the icon and the countdown numeral; the large countdown numeral remains at its usual position. The start-time text (`HH:MM`) is dropped to make room. Palette is red, priority is `PRIORITY_AMBIENT_URGENT` (65).
- **Imminent stage** (within `imminent_minutes` of start, e.g., 1 minute): the animated icon switches to `calendar_reminder_16x16` (calendar + bell). The event title is dropped to give the icon and countdown full prominence. Palette remains red, priority unchanged (65).
- **Warn stage** (within `warn_minutes` of start, e.g., 5 minutes): a `calendar_event_16x16` icon animates at the top-left corner. The event title is shown to the right of the icon, across a reserved 52-pixel title lane above the countdown; the large countdown numeral remains at its usual position. The start-time text (`HH:MM`) is dropped to make room. Palette is red, priority is `PRIORITY_AMBIENT_URGENT` (65).
- **Imminent stage** (within `imminent_minutes` of start, e.g., 1 minute): the animated icon switches to `calendar_reminder_16x16` (calendar + bell). The title stays visible; the lower row reads `IN <1m` during the final positive fraction of a minute. Palette remains red, priority unchanged (65).

Setting `escalation_icons = false` reverts both stages to text-only display: title, start-time (`HH:MM`), and countdown numeral, with no icons.

Expand Down
Loading
Loading