feat(slint): playlist detail view

First piece of the playlist module: a detail view at the AlbumView /
MixView level, reusing the shared TrackRow (show-artwork + show-album +
context menu, so Add to playlist / Go to album / etc. work in it).

  - PlaylistState + crate::playlist controller (get_playlist -> header
    metadata + TrackItem rows; cached track list backs play-all /
    per-track play; artwork jobs resolve row covers + the header cover).
  - PlaylistView.slint: cover + "Playlist" label + name + description +
    "owner - N tracks - duration" info line + circular actions (Play
    all, Shuffle, Favorite) over a column-headed track list.
  - ContentView.playlist + NavEntry::Playlist (back/forward history) +
    navigate_playlist; the Favorites > Playlists card now opens it.
  - media-action: playlist play-all / shuffle / favorite (add/remove
    favorite) + per-track play-from-here.

cc
This commit is contained in:
vicrodh committed 2026-05-22 03:02:09 -06:00
1 parent 75d8571be3
commit 1be78193e2
8 files changed
+607 -5

No files matched your search

+18
View File
@@ -22,6 +22,7 @@ import { LabelReleasesView } from "../label/LabelReleasesView.slint";
import { ArtistsByLocationView } from "../location/ArtistsByLocationView.slint";
import { FavoritesView } from "../favorites/FavoritesView.slint";
import { MixView } from "../mix/MixView.slint";
import { PlaylistView } from "../playlist/PlaylistView.slint";
import { SettingsView } from "../settings/SettingsView.slint";
import { SearchResultsView } from "../search/SearchResultsView.slint";
@@ -147,6 +148,23 @@ export component AppShell inherits Rectangle {
root.media-action(kind, id, action);
}
}
if NavState.view == ContentView.playlist: PlaylistView {
play-track(id) => {
root.media-action("playlist-track", id, "play");
}
play-all => {
root.media-action("playlist", "", "play-all");
}
shuffle => {
root.media-action("playlist", "", "shuffle");
}
toggle-favorite => {
root.media-action("playlist", "", "favorite");
}
media-action(kind, id, action) => {
root.media-action(kind, id, action);
}
}
if NavState.view == ContentView.settings: SettingsView {
settings-bool(k, v) => {
root.settings-bool(k, v);