Clock: show it at once and render it cheaply; Guide is KEY_GUIDE
The remote's hauppauge.rem names the Guide button KEY_GUIDE, not lircd's KEY_EPG, so the remote never toggled the clock. The overlay is now hidden by opacity rather than display: none, so it is already laid out and painted when Pos1 or Guide shows it. The drop-shadow filter on the whole watch is gone (it re-rendered and re-blurred the dial on every second-hand tick), the hands sit on their own layers, and the bubbles and countdown cards only exist while the clock is on screen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -111,7 +111,7 @@ general:
|
|||||||
# lircd itself is set up on the Pi). Omit the whole section to run without a remote.
|
# lircd itself is set up on the Pi). Omit the whole section to run without a remote.
|
||||||
# Play/pause/stop/previous/forward/rewind/volume/mute map to normal music control;
|
# Play/pause/stop/previous/forward/rewind/volume/mute map to normal music control;
|
||||||
# number keys 0-9 play whatever the "remote:" section below assigns them; Guide
|
# number keys 0-9 play whatever the "remote:" section below assigns them; Guide
|
||||||
# (KEY_EPG) shows the kiosk's clock. Run with --log-level DEBUG to see the name of a
|
# (KEY_GUIDE) shows the kiosk's clock. Run with --log-level DEBUG to see the name of a
|
||||||
# button that does nothing.
|
# button that does nothing.
|
||||||
lirc:
|
lirc:
|
||||||
host: "musicmouse-pi.local"
|
host: "musicmouse-pi.local"
|
||||||
|
|||||||
@@ -47,8 +47,10 @@ _TRANSPORT: dict[str, Callable[[], IntentEvent]] = {
|
|||||||
"KEY_FORWARD": lambda: NextTrackRequested(source="lirc"),
|
"KEY_FORWARD": lambda: NextTrackRequested(source="lirc"),
|
||||||
# Does nothing unless general.screen is configured - see ScreenService.
|
# Does nothing unless general.screen is configured - see ScreenService.
|
||||||
"KEY_POWER": lambda: ToggleScreenRequested(source="lirc"),
|
"KEY_POWER": lambda: ToggleScreenRequested(source="lirc"),
|
||||||
# "Guide": what time is it. Shows the kiosk's clock overlay.
|
# "Guide": what time is it. Shows the kiosk's clock overlay. KEY_GUIDE is what
|
||||||
"KEY_EPG": lambda: ToggleClockRequested(source="lirc"),
|
# irserver's hauppauge.rem calls it (the ansible repo); lircd's own Hauppauge
|
||||||
|
# config says KEY_EPG.
|
||||||
|
"KEY_GUIDE": lambda: ToggleClockRequested(source="lirc"),
|
||||||
}
|
}
|
||||||
|
|
||||||
#: Acted on every repeat, for a continuous ramp while held - same feel as the rotary
|
#: Acted on every repeat, for a continuous ramp while held - same feel as the rotary
|
||||||
|
|||||||
@@ -328,8 +328,8 @@ async def test_the_guide_key_asks_for_the_clock(
|
|||||||
task = await _run_service(sim, _lirc_config(port))
|
task = await _run_service(sim, _lirc_config(port))
|
||||||
try:
|
try:
|
||||||
await station.wait_connected()
|
await station.wait_connected()
|
||||||
await station.send("b7c0000000000000 00 key_epg hauppauge")
|
await station.send("b7c0000000000000 00 key_guide hauppauge")
|
||||||
await station.send("b7c0000000000000 00 key_epg hauppauge") # still held
|
await station.send("b7c0000000000000 00 key_guide hauppauge") # still held
|
||||||
await sim.bus.drain()
|
await sim.bus.drain()
|
||||||
finally:
|
finally:
|
||||||
task.cancel()
|
task.cancel()
|
||||||
|
|||||||
@@ -4,9 +4,11 @@
|
|||||||
* minus the mascot swimming through the scene (too distracting for a clock you read
|
* minus the mascot swimming through the scene (too distracting for a clock you read
|
||||||
* at a glance).
|
* at a glance).
|
||||||
*
|
*
|
||||||
* Mounted for as long as the app is, and only hidden: Pos1 and the remote's Guide key
|
* Mounted for as long as the app is, and only hidden (by opacity, see clock.css): Pos1
|
||||||
* have to show it at once, not after a first render. The second ticker only runs while
|
* and the remote's Guide key have to show it at once, not after a first render and
|
||||||
* it is on screen. Any click closes it. */
|
* paint. What moves - the second ticker, the bubbles, a ringing countdown card - only
|
||||||
|
* exists while it is on screen, so a hidden clock costs nothing per frame. Any click
|
||||||
|
* closes it. */
|
||||||
|
|
||||||
import { memo } from "react";
|
import { memo } from "react";
|
||||||
|
|
||||||
@@ -53,9 +55,10 @@ export function ClockOverlay({ visible, clock, onClose }: Props) {
|
|||||||
hidden={!visible}
|
hidden={!visible}
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
role="dialog"
|
role="dialog"
|
||||||
|
aria-hidden={!visible}
|
||||||
aria-label="Uhr"
|
aria-label="Uhr"
|
||||||
>
|
>
|
||||||
{SHOW_DECORATIVE_ANIMATIONS && (
|
{visible && SHOW_DECORATIVE_ANIMATIONS && (
|
||||||
<Drift field={BUBBLES} bubbleColor={(alpha) => `oklch(90% 0.02 var(--hue) / ${alpha})`} />
|
<Drift field={BUBBLES} bubbleColor={(alpha) => `oklch(90% 0.02 var(--hue) / ${alpha})`} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -79,7 +82,7 @@ export function ClockOverlay({ visible, clock, onClose }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{countdowns.length > 0 && (
|
{visible && countdowns.length > 0 && (
|
||||||
<div className="clock-countdowns">
|
<div className="clock-countdowns">
|
||||||
{countdowns.map((countdown) => (
|
{countdowns.map((countdown) => (
|
||||||
<CountdownCard key={countdown.kind} countdown={countdown} />
|
<CountdownCard key={countdown.kind} countdown={countdown} />
|
||||||
|
|||||||
@@ -21,11 +21,17 @@
|
|||||||
);
|
);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
will-change: opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* `display: flex` above would otherwise beat the `hidden` attribute. */
|
/* Hidden by opacity, not `display: none`: the watch stays styled, laid out and
|
||||||
|
rasterized, so Pos1 or the remote's Guide key shows it in the next frame instead of
|
||||||
|
after the Pi has painted every gradient of the dial from scratch. `display: flex`
|
||||||
|
above would otherwise beat the `hidden` attribute anyway. */
|
||||||
.clock-overlay[hidden] {
|
.clock-overlay[hidden] {
|
||||||
display: none;
|
display: flex;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Upright screens: the countdowns go under the watch instead of beside it. */
|
/* Upright screens: the countdowns go under the watch instead of beside it. */
|
||||||
@@ -62,7 +68,6 @@
|
|||||||
flex: none;
|
flex: none;
|
||||||
width: 78vmin;
|
width: 78vmin;
|
||||||
height: 96vmin;
|
height: 96vmin;
|
||||||
filter: drop-shadow(0 3vmin 5vmin oklch(15% 0.05 210 / 0.5));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.clock-strap {
|
.clock-strap {
|
||||||
@@ -72,6 +77,7 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: 0.55vmin solid var(--clock-ink);
|
border: 0.55vmin solid var(--clock-ink);
|
||||||
--strap: oklch(70% 0.16 340);
|
--strap: oklch(70% 0.16 340);
|
||||||
|
box-shadow: 0 3vmin 5vmin oklch(15% 0.05 210 / 0.35);
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
90deg,
|
90deg,
|
||||||
var(--strap) 0%,
|
var(--strap) 0%,
|
||||||
@@ -144,6 +150,10 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border: 0.6vmin solid var(--clock-ink);
|
border: 0.6vmin solid var(--clock-ink);
|
||||||
|
/* The watch's shadow. It used to be a drop-shadow filter on the whole watch, which
|
||||||
|
made the Pi re-render and re-blur the entire dial on every tick of the second
|
||||||
|
hand. */
|
||||||
|
box-shadow: 0 3vmin 5vmin oklch(15% 0.05 210 / 0.5);
|
||||||
background:
|
background:
|
||||||
radial-gradient(
|
radial-gradient(
|
||||||
circle closest-side,
|
circle closest-side,
|
||||||
@@ -347,6 +357,9 @@
|
|||||||
left: 50%;
|
left: 50%;
|
||||||
bottom: 50%;
|
bottom: 50%;
|
||||||
transform-origin: 50% 100%;
|
transform-origin: 50% 100%;
|
||||||
|
/* Each hand on its own layer: turning it moves a finished picture on the GPU,
|
||||||
|
and the dial underneath is never repainted. */
|
||||||
|
will-change: transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
.clock-hand-hour,
|
.clock-hand-hour,
|
||||||
|
|||||||
Reference in New Issue
Block a user