summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/music-app.js73
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/style.css31
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