AlbumCard and PlaylistCard are now 200x246 (was 220x266), with the larger texts -2px and the smaller ones -1px. All album/playlist carousels and grids follow (card-width/height 200/246) so nothing reflows: Carousel, PlaylistCarousel, AlbumCollectionView/AlbumGrid, ReleaseGrid, Spotlight, HomeSkeleton, DiscoverBrowseView, SearchResultsView, FavoritesView. Artist / radio cards are untouched. cc
74 lines
2.7 KiB
Plaintext
74 lines
2.7 KiB
Plaintext
// Wrapping grid of AlbumCards for the artist page's release sections
|
|
// (Discography, EPs & Singles, Live Albums, Compilations, Others).
|
|
//
|
|
// The Tauri artist view lays these as grids — never as horizontally
|
|
// paginated carousels — so a long discography wraps into rows and the
|
|
// whole shape stays scannable. Pattern mirrors `discover/GridSection`:
|
|
// absolute positioning inside a Rectangle whose height comes from the
|
|
// row count, computed once per resize.
|
|
|
|
import { Theme } from "../foundation/semantic-colors.slint";
|
|
import { Typography } from "../foundation/typography.slint";
|
|
import { DiscoverSection } from "../state.slint";
|
|
import { AlbumCard } from "../discover/AlbumCard.slint";
|
|
|
|
export component ReleaseGrid inherits VerticalLayout {
|
|
in property <DiscoverSection> section;
|
|
callback album-clicked(string);
|
|
callback media-action(string, string, string);
|
|
|
|
property <length> card-width: 200px;
|
|
property <length> card-height: 246px;
|
|
property <length> gap: 24px;
|
|
property <int> count: root.section.albums.length;
|
|
|
|
spacing: 12px;
|
|
|
|
// --- Header: title + count -------------------------------------------
|
|
HorizontalLayout {
|
|
Text {
|
|
text: root.section.title;
|
|
color: Theme.text-primary;
|
|
font-size: Typography.heading;
|
|
font-weight: Typography.semibold;
|
|
vertical-alignment: center;
|
|
horizontal-stretch: 1;
|
|
}
|
|
if root.count > 0: Text {
|
|
text: " " + root.count;
|
|
color: Theme.text-muted;
|
|
font-size: Typography.body;
|
|
font-weight: Typography.regular;
|
|
vertical-alignment: center;
|
|
}
|
|
}
|
|
|
|
// --- Grid: absolute-positioned cards inside a sized Rectangle --------
|
|
grid := Rectangle {
|
|
// Columns recomputed per resize so the grid flows from 5 wide
|
|
// at large viewports down to 2 on narrow ones.
|
|
property <int> columns: Math.max(
|
|
1,
|
|
Math.floor((self.width + root.gap) / (root.card-width + root.gap)));
|
|
property <int> rows: Math.ceil(root.count / self.columns);
|
|
|
|
height: self.rows > 0
|
|
? self.rows * root.card-height + Math.max(0, self.rows - 1) * root.gap
|
|
: 0px;
|
|
|
|
for album[i] in root.section.albums: AlbumCard {
|
|
x: Math.mod(i, grid.columns) * (root.card-width + root.gap);
|
|
y: Math.floor(i / grid.columns) * (root.card-height + root.gap);
|
|
width: root.card-width;
|
|
height: root.card-height;
|
|
album: album;
|
|
clicked(id) => {
|
|
root.album-clicked(id);
|
|
}
|
|
media-action(kind, id, action) => {
|
|
root.media-action(kind, id, action);
|
|
}
|
|
}
|
|
}
|
|
}
|