Commit Graph

10 Commits

Author SHA1 Message Date
cc3db44c4e Add a ?pi=1 profile, and stop re-deriving search keys per keystroke
Two separate costs, both measured on musicdolphin (Pi 4, 1920x1080 kiosk), where the
app was burning ~70% of a core with nothing happening on screen.

Per-frame work. The ambient canvas repaints a full-screen gradient plus a particle
field every frame, and `usePlaybackClock` pushes a React setState per animation frame
into both PlayView and PlayerBar for the whole length of a track. `?pi=1` (lib/
lowPower.ts) makes those cheaper rather than switching them off: the canvas paints a
quarter of the pixels at 30fps with a bubble cap, and the clock renders ten times a
second - a progress bar advances one pixel every few hundred ms and its label has
one-second resolution, so nothing on screen can tell. Only the effects with no cheap
version actually go: the backdrop-filter glass blur and the decorative CSS loops.
Also drops a redundant full-canvas clearRect that the opaque gradient always covered.

Search. normalize() runs a Unicode NFD decomposition, and albumMatches/songMatches
called it on every album title and every track title on every keystroke - 4969 of them
for a track search, whose answer cannot change until the library does. buildSearchIndex
does it once per library payload; a keystroke is now String.includes over strings that
already exist. On the real library that is 33ms -> 3.4ms for an eight-letter track
query on a laptop, and this runs on a Pi. The same index partitions albums by shelf and
pre-sorts each shelf's categories, which App and BrowseView were deriving separately
from the same data.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 13:15:23 +02:00
b8f9f6d537 Give the tab rail its own glass bar and reserve space for it
The three tab buttons now share one frosted glass pill instead of each
floating separately, and BrowseView/RoomView reserve TAB_RAIL_CLEARANCE
of right-side padding so a full-width row or grid never renders under
it - verified against the real library, where dense rows (e.g. Conni's
82 audiobooks) previously butted right up against the rail.

Also gitignore the real (non-.example) tippen-curriculum.yml and
tippen-progress.json, matching config.yml's own privacy treatment,
since the curriculum now contains real reward paths into a personal
library.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 00:16:42 +02:00
57ead93497 Apply lock state to category-tile cover previews too
Verified the whole reward-lock feature against a real library with an
actual browser (Playwright + headless Chromium): the album-grid cards
already showed the question-mark placeholder for a locked album, but
its 2x2 preview thumbnail in the category-tile view (the screen before
drilling into an artist/category) still rendered the real cover art,
since that Cover call never received the locked prop.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 21:37:57 +02:00
7f5e2733c2 Merge the typing game into the music player as a tab, with lock/unlock UI
Moves tippen from a standalone app into web/ as a third tab (audio player /
smarthome / typing), replacing the old single room-toggle corner button with a
vertical icon tab rail. Curriculum and progress now come from the backend
(musicmouse/tippen/*) instead of a build-time YAML import and localStorage.

Adds reward-driven lock rendering: Cover/BrowseView/AlbumModal show a question
mark for locked albums/tracks with a hint on what unlocks them, and
ResultSheet gets a new unlock-animation block alongside the existing
lesson-unlock and aquarium-creature celebrations.

CSS from the two apps is merged carefully: identical rules (bubble/card/
key-cap/view-enter/backdrop-enter and their keyframes) are shared as-is,
while rules that bake in each app's own hue are kept separate under a
`tp-` prefix and scoped to the typing tab's own .tp-stage wrapper, so
neither app's look bleeds into the other's.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 21:25:42 +02:00
a5210fead2 Typing lessons like duolingo & musicmouse cleanup 2026-09-12 18:58:02 +02:00
7e5fd5ab75 Animations 2026-09-11 13:56:02 +02:00
fbf03a9847 UI cleanup, visual and keyboard navigation 2026-09-11 13:32:07 +02:00
ba7f082f48 Rework navigation for a consistent music/room toggle and back button
- Replace the "Mein Zimmer"/"Musik" text pills and the help button with
  two fixed circular corner buttons: a music/room toggle (top-right)
  and a single "back one level" button (top-left) used everywhere -
  search, categories, and the play view.
- Split `view` (browse/play) from a new `page` (music/room) in UiState
  so toggling to the room and back leaves the music side - search,
  selection, even the full-screen play view - exactly as it was.
- Back peels one step at a time (search, then track-search mode, then
  group+category together, since a root shelf tile sets both at once
  and undoing that jump should be one step too).
- Album cards: click the cover to open the track list, click the title
  to start playing immediately (matching what Enter already did from
  the keyboard). Audiobook cards drop the artist line and clamp the
  title to a fixed height so covers stay aligned across a row.
- Root shelf group headings ("Musik", "Hörbücher", "Podcasts") are now
  the link into that group's full category grid, replacing the
  separate search-icon button.
- "Taste zuweisen" is now an icon-only round button, moved to the
  bottom-right so it doesn't sit under the new toggle.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-11 11:12:39 +02:00
8aed3b022b updates 2026-08-27 23:46:19 +02:00
edb6e5e027 Web frontend 2026-08-27 12:32:20 +02:00