Typing lessons like duolingo & musicmouse cleanup
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
* artwork agree - and so do the LED strips, which run the same primary colour.
|
||||
*/
|
||||
|
||||
import type { Album, AlbumKind } from "../api/types";
|
||||
import type { Album, AlbumKind, PlayerState } from "../api/types";
|
||||
import { GROUP_HUE } from "./theme";
|
||||
|
||||
export const isBook = (album: Album): boolean => album.kind === "book";
|
||||
@@ -14,8 +14,8 @@ export const isBook = (album: Album): boolean => album.kind === "book";
|
||||
/** Shape is how you tell the two apart without reading anything: albums are square,
|
||||
* audiobooks are taller than wide, everywhere they appear - grid, list, group preview,
|
||||
* player bar, now-playing. Nothing else may set an aspect ratio on a cover. */
|
||||
export const ALBUM_ASPECT = 1;
|
||||
export const BOOK_ASPECT = 0.82;
|
||||
const ALBUM_ASPECT = 1;
|
||||
const BOOK_ASPECT = 0.82;
|
||||
|
||||
export const aspectOfKind = (kind: AlbumKind): number =>
|
||||
kind === "book" ? BOOK_ASPECT : ALBUM_ASPECT;
|
||||
@@ -29,7 +29,7 @@ const colours = (album: Album): [string, string, string] => [
|
||||
];
|
||||
|
||||
/** Diagonal two-tone stripes, the mockup's stand-in for a music cover. */
|
||||
export function stripes(album: Album, width: number): string {
|
||||
function stripes(album: Album, width: number): string {
|
||||
const [primary, secondary] = colours(album);
|
||||
return (
|
||||
`repeating-linear-gradient(135deg, ${primary} 0px, ${primary} ${width}px, ` +
|
||||
@@ -82,3 +82,24 @@ export const albumLine = (album: Album): string => {
|
||||
? `${prefix}${album.title} · ${album.artist}`
|
||||
: `${prefix}${album.title}`;
|
||||
};
|
||||
|
||||
export interface NowPlayingText {
|
||||
title: string;
|
||||
subtitle: string;
|
||||
/** "Kapitel 3 von 8" or "Song 3 von 8" - only meaningful while an album is loaded. */
|
||||
progress: string;
|
||||
/** Changes whenever the track itself changes, so a progress bar can reset its drag
|
||||
* state instead of animating across two unrelated tracks. */
|
||||
resetKey: string;
|
||||
}
|
||||
|
||||
/** The title/subtitle/progress text shared by the player bar and the full-screen
|
||||
* now-playing view, so the two cannot drift apart on a copy change. */
|
||||
export function nowPlayingText(state: PlayerState, album: Album | null): NowPlayingText {
|
||||
return {
|
||||
title: state.track_title ?? "Wähl ein Album!",
|
||||
subtitle: album ? albumLine(album) : "Tippen oder klicken",
|
||||
progress: `${album && isBook(album) ? "Kapitel" : "Song"} ${state.track_index + 1} von ${state.track_count}`,
|
||||
resetKey: `${state.album_id ?? ""}:${state.track_index}`,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
/** The browse screen's shelf/row look, in one place: per-group colors and identity,
|
||||
* and the feature toggles that have gone back and forth while this design was under
|
||||
* review. Flip a toggle here rather than hunting through BrowseView.tsx/covers.ts.
|
||||
/** Per-group colors and identity, and the feature toggles that have gone back and
|
||||
* forth while this design was under review - flip one here rather than hunting
|
||||
* through the components that read it. Most toggles are about the browse screen's
|
||||
* shelf/row look, but some (`SHOW_GLASS_BLUR`, `SHOW_AMBIENCE`,
|
||||
* `SHOW_DECORATIVE_ANIMATIONS`) reach further: the play view, the player bar, the
|
||||
* room page and `App.tsx` all read this module too, wherever they share the same
|
||||
* "cut this on weak hardware" knob.
|
||||
*
|
||||
* `SHOW_ROW_TITLES` and `SHOW_ROW_ICONS` both `true` reproduces the original shelf
|
||||
* header - an icon badge plus label button above each row's tiles. */
|
||||
|
||||
import type { CSSProperties } from "react";
|
||||
|
||||
import type { Group } from "./search";
|
||||
|
||||
// ---------------------------------------------------------------- toggles --
|
||||
@@ -70,7 +76,7 @@ export const GROUP_LABEL: Record<Group, string> = {
|
||||
|
||||
/** A shelf/row's frosted background and border, tinted with its group's hue - or,
|
||||
* with `SHOW_ROW_TINT` off, `{}` so `.glass-panel`'s own neutral CSS shows through. */
|
||||
export function glassTint(hue: number): React.CSSProperties {
|
||||
export function glassTint(hue: number): CSSProperties {
|
||||
if (!SHOW_ROW_TINT) return {};
|
||||
return {
|
||||
background: `linear-gradient(160deg, oklch(55% 0.1 ${hue} / .32), oklch(30% 0.06 ${hue} / .14))`,
|
||||
@@ -81,7 +87,7 @@ export function glassTint(hue: number): React.CSSProperties {
|
||||
/** One list row's background, tinted with its group's hue and brighter/more opaque
|
||||
* while it's the currently-playing row - or, with `SHOW_ROW_TINT` off, the same
|
||||
* neutral highlight the row used before tinting existed. */
|
||||
export function rowTint(hue: number, highlighted: boolean): React.CSSProperties {
|
||||
export function rowTint(hue: number, highlighted: boolean): CSSProperties {
|
||||
if (!SHOW_ROW_TINT) {
|
||||
return { background: `oklch(97% 0.01 210 / ${highlighted ? ".22" : ".10"})` };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user