diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-08-24 17:39:41 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-08-24 17:39:41 +0200 |
| commit | 8c780b9928db8145b7fe18ecd137384ccfe25d8f (patch) | |
| tree | 5cfc06eec0fdf9bb7fe0a14f45e3ef803bb86a20 /packages/meshbay-hub/src/meshbay_hub/static/icon.js | |
| parent | 941d1a135dd7b03834576855e8e9fdaa24c4e406 (diff) | |
| download | meshbay-8c780b9928db8145b7fe18ecd137384ccfe25d8f.tar.gz | |
feat(hub): Music app client — album grid, flat list, persistent player
Implements the client half of docs/musicbay.md against MNP 0.8:
- music-app.js: album grid (grouped by artist -> album, from index-time
artist/album fields) or flat folder view, per-group localStorage
toggle like Videos. MusicBrainz (music_meta_req) is only looked up
when a track has no embedded cover at all — well-tagged files never
trigger a network call, unlike Videos where TMDB is unconditional.
Reuses video-app.js's MediaThumb/LazyTile (now exported) rather than
duplicating the chunk-path thumbnail decode + virtualization.
- music-player.js: the persistent player bar — queue, shuffle (Fisher-
Yates, keeps the current track in place when toggled), repeat (off/
all/one), volume (localStorage), prev/next, a one-track prefetch
cache. No MSE, no node-side streaming: a track is downloaded and
decrypted once via file-utils.js's pipelinedDownload, same chunk
pipeline Files already uses, then played from a blob URL.
- group-page.js: owns musicQueue/musicbrainzConfig state and renders
MusicPlayerBar outside the tab-switched area — deliberately, so
playback survives navigating to Chat/Files, the same reasoning the
video/preview modals are shell-owned rather than app-owned.
- apps.js: registers "music". transport.js: fetchMusicMeta (keyed by
path, same reordering-hazard fix as fetchMediaMeta),
setMusicbrainzConfig/setMusicbrainzEnabled (signed ops, mirroring
TMDB's), and the three new ack handlers. group-settings.js: a
MusicBrainz settings section (contact string, per-group toggle) —
the existing Applications checklist already picks up "music" for
free, per apps.md's own claim.
- icon.js: music/pause/skip-next/skip-prev/shuffle/repeat/volume,
drawn in the same stroked style as the existing set.
- i18n: group.tab_music, the music.* and settings_node.musicbrainz_*
keys, translated (not just copied) across all ten locales, Polish
carrying full one/few/many/other plural forms for music.n_tracks.
- webapp.py's _ASSETS, test_hook_ordering.py's STATIC_FILES and
test_transport_contracts.py's SPLIT_FILES gain the two new files.
Full suite (common + hub + node): 1116 passed, no regressions.
`npm run sync-ui` in meshbay-client confirmed both files copied.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBi7ALLGfwcjBXt57yNMcy
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/icon.js')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/icon.js | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/icon.js b/packages/meshbay-hub/src/meshbay_hub/static/icon.js index 84a5195..0ecbd70 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/icon.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/icon.js @@ -71,6 +71,17 @@ const ICON_PATHS = { 'M2 21h.01'], video: ['M3.5 6.5a1.5 1.5 0 0 1 1.5-1.5h14a1.5 1.5 0 0 1 1.5 1.5v11a1.5 1.5 0 0 1-1.5 1.5h-14a1.5 1.5 0 0 1-1.5-1.5z', 'M10 9.5v5l4.5-2.5z'], + music: ['M9 18V5l12-2v13', + 'M4 18a2 2 0 1 0 4 0 2 2 0 1 0 -4 0', + 'M16 16a2 2 0 1 0 4 0 2 2 0 1 0 -4 0'], + pause: ['M7 5.5v13', 'M17 5.5v13'], + 'skip-next': ['M5 4l10 8-10 8z', 'M19 5v14'], + 'skip-prev': ['M19 4L9 12l10 8z', 'M5 5v14'], + shuffle: ['M16 3h5v5', 'M4 20L21 3', 'M21 16v5h-5', 'M15 15l6 6', 'M4 4l5 5'], + repeat: ['M17 1l4 4-4 4', 'M3 11V9a4 4 0 0 1 4-4h14', + 'M7 23l-4-4 4-4', 'M21 13v2a4 4 0 0 1-4 4H3'], + volume: ['M11 5L6 9H2v6h4l5 4z', 'M15.54 8.46a5 5 0 0 1 0 7.07', + 'M19.07 4.93a10 10 0 0 1 0 14.14'], }; // The M of the wordmark is a picture; the rest is text. Resolved from this |