aboutsummaryrefslogtreecommitdiff
path: root/docs/specs/2026-07-02-timer-panel-spec.org
blob: ceb6e035cfd5ebcee634f03147902fd5bafb3fc0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#+TITLE: Timer GTK Panel
#+AUTHOR: Craig Jennings
#+DATE: 2026-07-02
#+TODO: TODO | DONE
#+TODO: DRAFT READY DOING | IMPLEMENTED SUPERSEDED CANCELLED

* IMPLEMENTED Timer GTK Panel
:PROPERTIES:
:ID:       25ed5321-f035-42b3-b115-69364d775f41
:END:
- 2026-07-04 Sat @ 12:36:56 -0500 — retrofitted by spec-sort; status set to DRAFT (evidence-based, human-confirmed)

* IMPLEMENTED Status
:PROPERTIES:
:ID:       1770af2e-b093-4024-a512-ae4324a2869f
:END:
- [2026-07-05 Sun] IMPLEMENTED — built and shipped to dotfiles in a no-approvals speedrun (4 commits 1f4f270..78d3cbb): wtimer watch/lap/save; a new timer/ package with a GTK-free PanelModel (62 tests) + the GTK instrument-console panel; bar integration (custom/timer opens the panel, the fuzzel creation flow retired, Hyprland float rule added). Code-complete; live GTK behavior awaits Craig's manual pass (filed under "Manual testing and validation" in todo.org) — a failing check promotes to a bug.
- [2026-07-05 Sun] DOING — Craig directed the build (no-approvals speedrun). Folded in the cj input from the sibling waybar-timer-module spec (GTK app styled like the panels; a queue/output-wall auto-sorted by fire time; stopwatch lap/stop + saveable runs; notify integration; 5/25-min configurable+deletable defaults; up to 10 timers; widget-gallery elements) — see Build scope below. Bypassed the READY spec-review step at Craig's direction; the four decisions were already resolved.
- [2026-07-04 Sat] DRAFT — all four decisions resolved by Craig (standalone; retire fuzzel once the panel lands; timer chips gain 10m/30m/2h; wtimer watch mode over polling). Decision-complete; ready for a spec-review to flip it READY before build.
- [2026-07-02 Thu] DRAFT — initial spec from Craig's roam capture "give the
  timer a gtk UI/UX like the network panel. spec this out."

* Metadata

| Field  | Value                                             |
|--------+---------------------------------------------------|
| Status | implemented                                       |
|--------+---------------------------------------------------|
| Owner  | Craig Jennings                                    |
|--------+---------------------------------------------------|
| Repo   | dotfiles                                          |
|--------+---------------------------------------------------|
| Kin    | net panel (architecture donor), wtimer (backing), |
|        | desktop-settings panel spec (sibling)             |
|--------+---------------------------------------------------|

* Problem

The timer's whole UI is a chain of three fuzzel prompts (type, value, label)
plus a fourth for cancel. That flow can't show what's already running while
you create, can't offer one-tap presets, gives no feedback on a typo until
the add silently fails, and pomodoro state (phase, cycle) is only visible in
a tooltip. The 2026-07-02 styling pass made the dialogs presentable, but the
shape is still four blind modals for what is really one small control
surface.

* Goals

1. One panel, opened from the bar's timer module, that shows everything
   running (live countdowns, pomodoro phase/cycle, paused state) and creates
   new items without leaving it.
2. One-tap presets for the common cases (tea, pomodoro, quick alarm) next to
   freeform entry, with inline validation before the add.
3. Per-item controls: pause/resume, cancel, promote to primary (the bar
   glyph slot).
4. wtimer stays the single owner of timer state and the notification path;
   the panel is a view over it, never a second engine.

* Design sketch

** Architecture — clone the net panel's proven stack

- GTK4 + gtk4-layer-shell dropdown anchored under the timer module, Blueprint
  .blp compiled to committed .ui (=make ui=; compiler is dev-only).
- Humble-object split: GTK-free PanelModel presenter, unit-tested to 100%,
  with thin widget bindings; one gated AT-SPI smoke via the
  run-panel-smoke.sh pattern.
- Backing: shell out to the existing wtimer CLI (=add=, =toggle=, =cancel=,
  =cycle=, =render=). =render= already emits a JSON payload. Live state comes
  from a new wtimer watch/subscribe mode (decision D), which the panel
  subscribes to for push updates instead of polling =render= on a timer.
  wtimer's 89-case suite keeps owning the logic; panel tests fake the CLI
  like every dotfiles suite fakes binaries.
- Dupre WIP palette CSS shared with the net panel (same factoring the
  desktop-settings spec calls for — one palette asset, three panels).

** Layout sketch

- Header row: running-item count + a Clear All button (maps to cancel-all).
- Item list: one row per item — type glyph, label, live countdown / clock
  time / phase+cycle for pomodoro, pause and cancel buttons, click-to-promote.
- Create strip: four type buttons (the wtimer glyphs), preset chips per type
  (timer 5m / 10m / 15m / 25m / 30m / 60m / 2h; alarm +30m / top-of-hour /
  07:00; pomodoro default cycle; stopwatch none — decision C), a freeform
  entry validated with wtimer's own parsers, an optional label field.
- Empty state: the create strip alone, centered.

** What happens to the fuzzel flow

Decision B (below) resolved this: the fuzzel chain retires once the panel
lands. The panel becomes the single creation surface, replacing both the
click-driven bar path and the keybind/fuzzel path. Until the panel ships the
fuzzel flow stays (it's styled and tested); phase 4 removes it after the
panel proves out.

* Build scope (consolidated 2026-07-05 — the four decisions plus Craig's cj input)

The panel is a new =timer/= dotfiles package mirroring =net/= and =audio/= (src-layout, GTK4 + gtk4-layer-shell, humble-object PanelModel, instrument-console faceplate aesthetic — machined plate, engraved section labels, status lamps, console keys). wtimer stays the state engine; the panel is a view over it.

Create + queue:
- A configure strip (top): pick timer / alarm / stopwatch / pomodoro, set the value (preset chips per decision C + a freeform entry validated by wtimer's parsers, optional label). A =+= adds the configured item to the queue.
- The queue is an output-wall-style list (the instrument-console output well), *auto-sorted by soonest fire time* (the item that notifies next is on top). One row per item: type glyph, label, live countdown / clock time / pomodoro phase+cycle, pause/resume, cancel, click-to-promote (bar glyph slot).
- Up to 10 timers; the two starting timer presets default to 5 min and 25 min, and the preset set is configurable and deletable.

Stopwatch:
- A running stopwatch row has a Lap button and a Stop button. Lap records the elapsed time at the press; unlimited laps; a lap can optionally be named (non-interruptive — naming never blocks further laps). On stop, the full run (splits + optional names) can be saved to review later. Save target: an org file (default =~/org/stopwatch-runs.org=, override via a config key) — one heading per run with a table of laps.

Live updates + notifications:
- A new =wtimer watch= subcommand emits state on every change (state-file watch → JSON lines on stdout); the panel subscribes for push updates instead of polling. The bar may adopt it later.
- Notifications for alarms and timers go through the =notify= script (wtimer already fires notify on completion; keep that path the single notification owner).

UI elements: draw from the panel widget gallery prototype (=docs/prototypes/2026-07-03-panel-widget-gallery-prototype.html= in the archsetup repo) for the console keys, lamps, output-well rows, and chips, matching the shipped net/bt/audio look.

Retire the old timer: the bar's =custom/timer= on-click drives =wtimer new= (the fuzzel chain). Rewire the bar module's on-click to open this panel, and retire the =wtimer new= fuzzel creation flow (decision B). Keep =wtimer render= as the bar indicator and the wtimer engine as the state source.

* Decisions (Craig)

** DONE Panel scope: standalone timer panel, or a page in the desktop-settings panel?
CLOSED: [2026-07-04 Sat]
Resolved (Craig, 2026-07-04): standalone, sharing the palette/css asset. Matches the net panel's one-domain-one-panel shape and keeps the timer dropdown small.

** DONE Fuzzel flow: keep as keyboard fast lane, or retire once the panel lands?
CLOSED: [2026-07-04 Sat]
Resolved (Craig, 2026-07-04): retire the fuzzel flow once the panel lands. The panel becomes the single creation surface; the keybind chain goes away rather than staying as a parallel path. (Implementation phase 4's "decide the fuzzel flow's future" is now decided — retire, don't keep.)

** DONE Presets: which chips per type?
CLOSED: [2026-07-04 Sat]
Resolved (Craig, 2026-07-04): timer chips are 5m / 10m / 15m / 25m / 30m / 60m / 2h (the strawman plus 10m, 30m, 2h). Alarm +30m / top-of-hour / 07:00, pomodoro default cycle only, stopwatch none — as the strawman.

** DONE Live updates: poll render (1s, like the bar) or a wtimer "watch" mode?
CLOSED: [2026-07-04 Sat]
Resolved (Craig, 2026-07-04): a wtimer watch/subscribe mode, not 1s polling. This grows wtimer with a new watch capability that the panel (and potentially the bar) subscribes to for live state, rather than reusing the poll cadence — cleaner at the cost of a wtimer addition. Fold the watch mode into the phase 1 CLI-backing seam.

* Implementation phases

1. PanelModel presenter + CLI-backing seam (TDD, GTK-free, 100% like the net
   PanelModel), plus the wtimer watch/subscribe mode (decision D) the presenter
   subscribes to for live state.
2. Blueprint UI: item list + create strip, wired to the presenter; palette
   css factored to the shared asset.
3. Bar integration: timer module left-click opens the panel (replacing the
   fuzzel menu binding there); the panel and bar both track state via the
   wtimer watch subscription.
4. AT-SPI smoke + manual-testing checklist; retire the fuzzel flow (decision B)
   after the panel proves out over a week of real use.