feat(web): match track kebab to Android + add it to full-screen Now Playing
test-web / test (push) Failing after 32s

Bring the web TrackMenu to parity with Android's canonical TrackActionsSheet
so the kebab reads the same on both clients:
- Reorder to Android's groups: queue → like/add-to-playlist/start-radio →
  go-to-album/artist → hide.
- Drop the duplicate "Flag this track…" item — it opened the very same
  FlagPopover as "Hide" (Android folds flag into a single Hide).
- Align icons (ListVideo / ListMusic / ListPlus / Disc3 / User).
- Admin-only "Remove from library" stays as a web superset (Android has no
  surface for it), past its own divider.

Mount the kebab on the full-screen /now-playing route with hideQueueActions,
mirroring Android's NowPlayingScreen — Start radio / Add to playlist / Hide
were previously unreachable there (only like + volume + queue existed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-14 21:46:54 -04:00
parent 773275e916
commit b3d6785543
2 changed files with 29 additions and 25 deletions
+19 -25
View File
@@ -1,15 +1,14 @@
<script lang="ts">
import {
MoreVertical,
ListPlus,
Plus,
Radio,
ListVideo,
ListMusic,
Heart,
HeartOff,
ListMusic,
Album,
ListPlus,
Radio,
Disc3,
Flag,
User,
EyeOff,
Eye,
Trash2
@@ -125,11 +124,6 @@
goto(`/artists/${track.artist_id}`);
}
function onFlag() {
menuOpen = false;
flagOpen = true;
}
function onRemoveOpen() {
menuOpen = false;
removeOpen = true;
@@ -167,46 +161,46 @@
onclick={(e) => e.stopPropagation()}
onkeydown={(e) => { e.stopPropagation(); if (e.key === 'Escape') menuOpen = false; }}
>
<!-- Item set + order mirror Android's canonical TrackActionsSheet so
the kebab reads the same on both clients: queue group → like /
add-to-playlist / start-radio group → navigation group → hide.
"Start radio" is shown even under hideQueueActions (reseeding a
station from the current track is meaningful where play-next /
add-to-queue are not). The admin-only "Remove from library" is a
web superset Android has no surface for — kept past the divider. -->
{#if !hideQueueActions}
<TrackMenuItem icon={ListPlus} label="Play next" onclick={onPlayNext} />
<TrackMenuItem icon={Plus} label="Add to queue" onclick={onAddToQueue} />
<TrackMenuItem icon={ListVideo} label="Play next" onclick={onPlayNext} />
<TrackMenuItem icon={ListMusic} label="Add to queue" onclick={onAddToQueue} />
<TrackMenuDivider />
{/if}
<!-- Start radio is always offered, even on the now-playing surfaces
(hideQueueActions) — reseeding the queue as a radio station from
the current track is meaningful where "play next" / "add to queue"
are not. Mirrors TrackRow's inline 📻 button via playRadio(). -->
<TrackMenuItem icon={Radio} label="Start radio" onclick={onStartRadio} />
<TrackMenuDivider />
<TrackMenuItem
icon={liked ? HeartOff : Heart}
label={liked ? 'Unlike' : 'Like'}
onclick={onToggleLike}
/>
<TrackMenuItem
icon={ListMusic}
icon={ListPlus}
label="Add to playlist…"
onclick={() => { addOpen = true; menuOpen = false; }}
/>
<TrackMenuItem icon={Radio} label="Start radio" onclick={onStartRadio} />
<TrackMenuDivider />
<TrackMenuItem icon={Album} label="Go to album" onclick={onGoToAlbum} />
<TrackMenuItem icon={Disc3} label="Go to artist" onclick={onGoToArtist} />
<TrackMenuItem icon={Disc3} label="Go to album" onclick={onGoToAlbum} />
<TrackMenuItem icon={User} label="Go to artist" onclick={onGoToArtist} />
<TrackMenuDivider />
<TrackMenuItem icon={Flag} label="Flag this track…" onclick={onFlag} />
<TrackMenuItem
icon={hidden ? Eye : EyeOff}
label={hidden ? 'Unhide' : 'Hide'}
onclick={onToggleHide}
/>
{#if isAdmin}
<TrackMenuDivider />
<TrackMenuItem
icon={Trash2}
label="Remove from library"
+10
View File
@@ -16,6 +16,7 @@
import { FALLBACK_COVER, coverUrl } from '$lib/media/covers';
import { useSmoothPosition } from '$lib/player/smoothPosition.svelte';
import LikeButton from '$lib/components/LikeButton.svelte';
import TrackMenu from '$lib/components/TrackMenu.svelte';
import QueueList from '$lib/components/QueueList.svelte';
import { pageTitle } from '$lib/branding';
@@ -78,6 +79,15 @@
<ArrowLeft size={22} strokeWidth={1.5} />
</button>
<div class="ml-2 text-xs uppercase tracking-wide text-text-secondary">Now playing</div>
<!-- Full-screen Now Playing carries the same kebab as Android's
NowPlayingScreen (hideQueueActions — the menu's track IS the one
playing), so Start radio / Add to playlist / Hide etc. are reachable
here, not just from the mini-player bar. -->
{#if current}
<div class="ml-auto">
<TrackMenu track={current} hideQueueActions />
</div>
{/if}
</header>
{#if !current}