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>
This commit is contained in:
@@ -18,7 +18,7 @@ import {
|
||||
unitLabel,
|
||||
} from "../lib/covers";
|
||||
import { clock } from "../lib/format";
|
||||
import type { Category, Group, Results, SongHit } from "../lib/search";
|
||||
import type { Category, Group, Results, SearchIndex, SongHit } from "../lib/search";
|
||||
import { categoryMatches, groupOf } from "../lib/search";
|
||||
import {
|
||||
ANIMATE_VIEW_TRANSITIONS,
|
||||
@@ -37,7 +37,7 @@ import { Cover } from "./Cover";
|
||||
interface Props {
|
||||
results: Results;
|
||||
group: Group | null;
|
||||
albums: Album[];
|
||||
index: SearchIndex;
|
||||
mode: "albums" | "tracks";
|
||||
search: string;
|
||||
category: string | null;
|
||||
@@ -76,7 +76,7 @@ const GROUP_SECTION_LABEL: Record<Group, string> = {
|
||||
export function BrowseView({
|
||||
results,
|
||||
group,
|
||||
albums,
|
||||
index,
|
||||
mode,
|
||||
search,
|
||||
category,
|
||||
@@ -114,14 +114,14 @@ export function BrowseView({
|
||||
GROUPS.map((shelfGroup) => ({
|
||||
group: shelfGroup,
|
||||
categories: categoryMatches({
|
||||
albums,
|
||||
index,
|
||||
search: "",
|
||||
mode: "albums",
|
||||
category: null,
|
||||
group: shelfGroup,
|
||||
}),
|
||||
})),
|
||||
[albums],
|
||||
[index],
|
||||
);
|
||||
|
||||
// Keep the selection on screen as the arrow keys walk past the fold.
|
||||
|
||||
Reference in New Issue
Block a user