feat(slint): sidebar Playlists toolbar + folders + micro-collage refinements
PLAYLISTS header: smaller title, recursive search (hides title), create modal at 1:1 with Tauri (name/description/folder/public), sort menu, and a collapse chevron. Folders: accent-tinted icon, open/close chevron as the primary affordance (no more purposeless "..."), count shown on hover only. Playlists render a 2x2 micro-collage of track covers (opt-out) instead of the glyph, sourced from the existing playlist images (no extra fetch). cc
This commit is contained in:
4 files changed
+601
-102
No files matched your search
@@ -0,0 +1,69 @@
|
||||
// Sidebar playlist micro-collage. A tiny (20px) thumbnail of a
|
||||
// playlist's track covers shown in place of the generic list-music
|
||||
// glyph, mirroring Tauri's PlaylistCoverCollage:
|
||||
// - 0 covers -> parent renders the fallback glyph (nothing here)
|
||||
// - 1-3 covers -> a single cover (the first tile), full bleed
|
||||
// - 4+ covers -> a 2x2 grid, 1px gap, 3px radius
|
||||
//
|
||||
// The covers + decoded images live on the SidebarEntry (cover-count,
|
||||
// cover1..cover4). This component only lays them out.
|
||||
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { SidebarEntry } from "../state.slint";
|
||||
|
||||
export component SidebarPlaylistCollage inherits Rectangle {
|
||||
in property <SidebarEntry> entry;
|
||||
in property <length> size: 20px;
|
||||
|
||||
width: root.size;
|
||||
height: root.size;
|
||||
border-radius: 3px;
|
||||
clip: true;
|
||||
background: Theme.surface-elevated;
|
||||
|
||||
property <int> n: root.entry.cover-count;
|
||||
property <length> gap: 1px;
|
||||
|
||||
// 1-3 covers -> single full-bleed cover (Tauri: tiles.length < 4).
|
||||
if root.n >= 1 && root.n < 4: Image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
source: root.entry.cover1;
|
||||
image-fit: cover;
|
||||
}
|
||||
|
||||
// 4+ covers -> 2x2 grid (Tauri: tiles.slice(0, 4)).
|
||||
if root.n >= 4: VerticalLayout {
|
||||
spacing: root.gap;
|
||||
HorizontalLayout {
|
||||
spacing: root.gap;
|
||||
Image {
|
||||
source: root.entry.cover1;
|
||||
image-fit: cover;
|
||||
width: (root.size - root.gap) / 2;
|
||||
height: (root.size - root.gap) / 2;
|
||||
}
|
||||
Image {
|
||||
source: root.entry.cover2;
|
||||
image-fit: cover;
|
||||
width: (root.size - root.gap) / 2;
|
||||
height: (root.size - root.gap) / 2;
|
||||
}
|
||||
}
|
||||
HorizontalLayout {
|
||||
spacing: root.gap;
|
||||
Image {
|
||||
source: root.entry.cover3;
|
||||
image-fit: cover;
|
||||
width: (root.size - root.gap) / 2;
|
||||
height: (root.size - root.gap) / 2;
|
||||
}
|
||||
Image {
|
||||
source: root.entry.cover4;
|
||||
image-fit: cover;
|
||||
width: (root.size - root.gap) / 2;
|
||||
height: (root.size - root.gap) / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user