diff options
Diffstat (limited to 'packages/meshbay-hub')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/music-app.js | 73 | ||||
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/style.css | 31 |
2 files changed, 71 insertions, 33 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/music-app.js b/packages/meshbay-hub/src/meshbay_hub/static/music-app.js index 7e16b53..cb14fb4 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/music-app.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/music-app.js @@ -3,7 +3,6 @@ import { } from './vendor/htm-preact.js'; import { t } from './i18n.js'; import { Icon } from './icon.js'; -import { formatSize } from './file-utils.js'; import { MediaThumb, LazyTile } from './video-app.js'; import { formatTime } from './music-player.js'; @@ -279,17 +278,21 @@ function AlbumGrid({ artists, transportRef, gekRef, musicbrainzEnabled, onPlayQu // -- Mode B: flat, folder-based, no MusicBrainz ------------------------------ -function FlatTrackRow({ track, onPlay }) { +// A track is not a folder — it was rendered with the same boxy thumbnail +// slot as one anyway (borrowed wholesale from Videos' flat list), which +// meant a big album unfolded into a wall of identical little squares, one +// per row, carrying no information (no embedded-art-in-a-list-row concept +// exists here, unlike Videos' per-episode thumbnail). Reuses the plain +// numbered-row style Mode A's own tracklist already uses instead +// (music-track-row) — track number, title, duration, no icon box. +function FlatTrackRow({ track, index, onPlay }) { + const num = track.track_no || (index != null ? index + 1 : null); return html` - <div class="music-flat-row" onClick=${onPlay}> - <div class="music-flat-thumb video-thumb-empty"><${Icon} name="music" /></div> - <div class="video-flat-info"> - <div class="video-flat-title">${track.display_title || track.name}</div> - <div class="video-flat-sub"> - ${formatTime(track.duration || 0)} ${' - '}${formatSize(track.size)} - </div> - </div> - </div> + <button class="music-track-row music-flat-track" onClick=${onPlay}> + <span class="music-track-no">${num || ''}</span> + <span class="music-track-title">${track.display_title || track.name}</span> + <span class="music-track-duration">${formatTime(track.duration || 0)}</span> + </button> `; } @@ -305,9 +308,14 @@ function FlatAlbumFolder({ album, onPlayQueue }) { </div> <${Icon} name="chevron" cls=${open ? 'video-flat-chevron open' : 'video-flat-chevron'} /> </div> - ${open && album.tracks.map((tr, i) => html` - <${FlatTrackRow} key=${tr.id} track=${tr} onPlay=${() => onPlayQueue(album.tracks, i)} /> - `)} + ${open && html` + <div class="music-flat-children"> + ${album.tracks.map((tr, i) => html` + <${FlatTrackRow} key=${tr.id} track=${tr} index=${i} + onPlay=${() => onPlayQueue(album.tracks, i)} /> + `)} + </div> + `} </div> `; } @@ -329,22 +337,27 @@ function FlatArtistFolder({ artist, onPlayQueue }) { </div> <${Icon} name="chevron" cls=${open ? 'video-flat-chevron open' : 'video-flat-chevron'} /> </div> - ${/* A real artist folder with no album layer at all is common here -- a - pile of loose singles, not one release (musicbay.md section 2.1's - "flat per-artist folder" case). Nesting them one more level behind - their own always-empty "Unknown album" row was exactly the - friction reported live: an extra, pointless expand before - reaching a track that's playable (with full previous/next across - the whole pile -- onPlayQueue already gets every track sharing - this bucket) at all. A real, named album still gets its own - foldable row. */ - open && artist.albums.map((album) => (album.isUnknown - ? album.tracks.map((tr, i) => html` - <${FlatTrackRow} key=${tr.id} track=${tr} - onPlay=${() => onPlayQueue(album.tracks, i)} /> - `) - : html`<${FlatAlbumFolder} key=${album.album} album=${album} onPlayQueue=${onPlayQueue} />` - ))} + ${open && html` + <div class="music-flat-children"> + ${/* A real artist folder with no album layer at all is common here + -- a pile of loose singles, not one release (musicbay.md + section 2.1's "flat per-artist folder" case). Nesting them + one more level behind their own always-empty "Unknown album" + row was exactly the friction reported live: an extra, + pointless expand before reaching a track that's playable + (with full previous/next across the whole pile -- + onPlayQueue already gets every track sharing this bucket) at + all. A real, named album still gets its own foldable row, + one indent level deeper than its loose siblings would be. */ + artist.albums.map((album) => (album.isUnknown + ? album.tracks.map((tr, i) => html` + <${FlatTrackRow} key=${tr.id} track=${tr} index=${i} + onPlay=${() => onPlayQueue(album.tracks, i)} /> + `) + : html`<${FlatAlbumFolder} key=${album.album} album=${album} onPlayQueue=${onPlayQueue} />` + ))} + </div> + `} </div> `; } diff --git a/packages/meshbay-hub/src/meshbay_hub/static/style.css b/packages/meshbay-hub/src/meshbay_hub/static/style.css index 42cfcf9..38c38c8 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/style.css +++ b/packages/meshbay-hub/src/meshbay_hub/static/style.css @@ -2690,9 +2690,13 @@ a.transfer-name { Reuses .video-overlay/.video-top-bar/.video-title/.video-close, .tb-btn/ .tb-search, .video-flat-list/.video-flat-row/.video-flat-info/ .video-flat-title/.video-flat-sub/.video-flat-folder/.video-flat-chevron - and .video-thumb-empty as-is — only what's genuinely different from - Videos (album art is square, not 2:3; there is a persistent player bar; - grouping is artist -> album, not movie/show) gets its own rule below. */ + and .video-thumb-empty as-is for a *folder* row (artist/album headers) — + that part of Videos' flat list genuinely fits. A *track* row does not: + it reuses .music-track-row (Mode A's own tracklist style) instead, and + the tree gets its own .music-flat-children for indent/nesting, which + Videos' single-level flat list never needed. Also genuinely different + from Videos: album art is square, not 2:3; there is a persistent player + bar; grouping is artist -> album, not movie/show. */ .music-artist-section { margin-bottom: 22px; } .music-artist-heading { @@ -2846,6 +2850,27 @@ a.transfer-name { border-radius: 4px; border: 1px solid var(--border); } +/* A folder's expanded contents — artist -> album -> track. Videos' own flat + list never needed this (one level, folders of episodes, no further + nesting) so there was nothing to reuse: every depth used to sit flush + left, indistinguishable from its parent except by which chevron happened + to be open. The rule line gives the eye a rail to follow down the tree; + it nests for free (each level wraps its own children in one more of + these), so an artist with a real album inside it reads as two visible + steps in, not one. */ +.music-flat-children { + margin-left: 12px; + padding-left: 12px; + border-left: 2px solid var(--border); + display: flex; + flex-direction: column; + gap: 2px; +} +/* A touch tighter vertically than Mode A's tracklist rows + (.music-track-row, reused as the base) — this one already sits behind + up to two levels of indent, so it gives a little of its own padding + back rather than compounding with the rail. */ +.music-flat-track { padding: 5px 8px; } /* ── Persistent player bar (docs/musicbay.md §2.3) ──────────────────────── `position: sticky`, not `fixed` — deliberately: CLAUDE.md's own history |