import { html, useState, useEffect, useRef, useCallback, } from './vendor/htm-preact.js'; import { t } from './i18n.js'; import { Icon } from './icon.js'; import { CHUNK_SIZE, pipelinedDownload } from './file-utils.js'; /** * The Music app's persistent player bar (docs/musicbay.md §2.3, §7.2). * * Owned and rendered by group-page.js, *not* by music-app.js: it is the one * piece of this feature that lives outside the tab-switched area, so * playback survives navigating to Chat or Files, exactly the way the * video/preview modals are shell-owned rather than owned by whichever app * opened them. music-app.js never touches audio state directly — it only * calls `onPlayQueue(tracks, startIndex)`, threaded down from group-page.js, * to hand this component a new queue. * * No streaming, no MSE, no node-side transcode pool for the common case: a * track is a few megabytes, so it is downloaded and decrypted once through * the same chunk pipeline Files already uses (file-utils.js's * pipelinedDownload), then played from a blob URL — the deliberate * simplification recorded in musicbay.md §2.2. WMA and Musepack are the one * exception (`NEEDS_TRANSCODE_RE` below): neither decodes in a browser's *