// Track-row "more" context menu — flat, ported 1:1 from the Tauri // TrackMenu component. Items that have no Slint wiring yet emit a // media-action with an action string the runtime currently ignores // (no-op until backend wiring lands). import { ContextMenu } from "ContextMenu.slint"; import { ContextMenuItem } from "ContextMenuItem.slint"; export component TrackContextMenu inherits PopupWindow { in property track-id; // Per-source applicability (the surrounding row sets these from the track's // source). `qobuz-actions` = the Qobuz-backed block (radio, share, // make-offline, go-to album/artist, track info) — on for Qobuz + offline, // off for local / Plex / ephemeral. `favorite-action` / `mixtape-action` // gate the favorite and Add-to-Mixtape entries independently of the block // (library surfaces show them on rows the Qobuz block is dead for — spec // §3.1/§3.2); they default to the block so Qobuz surfaces are unchanged. // `playlist-action` = Add to playlist — on for Qobuz + offline + local + // Plex (local playlists store each source's own ref), off for ephemeral. // `remove-from-playlist-action` = the playlist-detail per-row removal // (every row source — the arm splits by id namespace); the surface // gates it on ownership (spec §3.1). // `track-info-action` lets a surface HIDE the Track Info entry while // its target feature is missing there (spec §3.3) — defaults on so // other surfaces are untouched. // `go-album-action` / `go-artist-action` — the Go to album / Go to // artist pair, gated independently of the block so library surfaces // can show them on local/plex/qobuz_download rows too (owner // improvement over Tauri, which omits both on local rows; the Rust // arms route by row source). Default to the block so Qobuz surfaces // are unchanged. // The transient actions (play / next / queue) always show. in property qobuz-actions: true; in property favorite-action: root.qobuz-actions; in property mixtape-action: root.qobuz-actions; in property playlist-action: true; in property remove-from-playlist-action: false; in property track-info-action: true; in property go-album-action: root.qobuz-actions; in property go-artist-action: root.qobuz-actions; // The row's offline-cache status (TrackItem.cache-status): when cached // (3) the single "Make available offline" entry swaps for the // Refresh / Remove pair — Tauri's ready-state submenu, rendered flat // (cosmetic-flat per spec §3.5). in property cache-status: 0; callback media-action(string, string, string); width: 224px; // 3 transient + optional favorite/mixtape/add-to-playlist/remove + // optional go-to pair + the Qobuz block (3 fixed + 1-or-2 offline // entries + optional track info). height: (3 + (root.favorite-action ? 1 : 0) + (root.mixtape-action ? 1 : 0) + (root.playlist-action ? 1 : 0) + (root.remove-from-playlist-action ? 1 : 0) + (root.go-album-action ? 1 : 0) + (root.go-artist-action ? 1 : 0) + (root.qobuz-actions ? 3 + (root.cache-status == 3 ? 2 : 1) + (root.track-info-action ? 1 : 0) : 0)) * 30px; ContextMenu { ContextMenuItem { icon: @image-url("../assets/icons/play.svg"); label: @tr("Play now"); clicked => { root.media-action("track", root.track-id, "play"); } } ContextMenuItem { icon: @image-url("../assets/icons/list-plus.svg"); label: @tr("Play next"); clicked => { root.media-action("track", root.track-id, "play-next"); } } ContextMenuItem { icon: @image-url("../assets/icons/list-end.svg"); label: @tr("Add to queue"); clicked => { root.media-action("track", root.track-id, "queue"); } } if root.qobuz-actions: ContextMenuItem { icon: @image-url("../assets/icons/radio.svg"); label: @tr("Create radio"); clicked => { root.media-action("track", root.track-id, "create-radio"); } } if root.favorite-action: ContextMenuItem { icon: @image-url("../assets/icons/heart.svg"); label: @tr("Add to library"); clicked => { root.media-action("track", root.track-id, "favorite"); } } if root.mixtape-action: ContextMenuItem { icon: @image-url("../assets/icons/cassette-tape.svg"); label: @tr("Add to mixtape"); clicked => { root.media-action("track", root.track-id, "add-to-mixtape"); } } if root.playlist-action: ContextMenuItem { icon: @image-url("../assets/icons/list-music.svg"); label: @tr("Add to playlist"); clicked => { root.media-action("track", root.track-id, "add-to-playlist"); } } // Remove from playlist (danger) — playlist detail only, after Add // to playlist (Tauri group order, spec §1.3 #8). if root.remove-from-playlist-action: ContextMenuItem { icon: @image-url("../assets/icons/trash-2.svg"); label: @tr("Remove from playlist"); danger: true; clicked => { root.media-action("track", root.track-id, "remove-from-playlist"); } } if root.qobuz-actions: ContextMenuItem { icon: @image-url("../assets/icons/link.svg"); label: @tr("Share Qobuz link"); clicked => { root.media-action("track", root.track-id, "share-qobuz"); } } if root.qobuz-actions: ContextMenuItem { icon: @image-url("../assets/icons/link.svg"); label: @tr("Share Song.link"); clicked => { root.media-action("track", root.track-id, "share-songlink"); } } // Offline-cache block — cached-state-aware (Tauri's ready-state // submenu, flat per spec §3.5): not cached -> Make available // offline; cached -> Refresh + Remove (icons 1:1 with Tauri's // RefreshCw / Trash2). if root.qobuz-actions && root.cache-status != 3: ContextMenuItem { icon: @image-url("../assets/icons/cloud-download.svg"); label: @tr("Make available offline"); clicked => { root.media-action("track", root.track-id, "download"); } } if root.qobuz-actions && root.cache-status == 3: ContextMenuItem { icon: @image-url("../assets/icons/refresh-cw.svg"); label: @tr("Refresh offline copy"); clicked => { root.media-action("track", root.track-id, "recache"); } } if root.qobuz-actions && root.cache-status == 3: ContextMenuItem { icon: @image-url("../assets/icons/trash-2.svg"); label: @tr("Remove offline copy"); danger: true; clicked => { root.media-action("track", root.track-id, "uncache"); } } if root.go-album-action: ContextMenuItem { icon: @image-url("../assets/icons/disc-3.svg"); label: @tr("Go to album"); clicked => { root.media-action("track", root.track-id, "go-to-album"); } } if root.go-artist-action: ContextMenuItem { icon: @image-url("../assets/icons/user.svg"); label: @tr("Go to artist"); clicked => { root.media-action("track", root.track-id, "go-to-artist"); } } if root.qobuz-actions && root.track-info-action: ContextMenuItem { icon: @image-url("../assets/icons/info.svg"); label: @tr("Track info"); clicked => { root.media-action("track", root.track-id, "track-info"); } } } }