Move the album description and the artist biography out of the metadata column to span the full content width below the header block, so the text is no longer cramped into the narrow column beside the artwork. cc
745 lines
28 KiB
Plaintext
745 lines
28 KiB
Plaintext
// Album detail page.
|
|
//
|
|
// Mirrors the Svelte AlbumDetailView: back button, an album header
|
|
// (artwork + title / artist / info line / action buttons), a divider,
|
|
// and the track list with a column header. Data comes from the
|
|
// AlbumState global; the action buttons are visual for now.
|
|
|
|
import { Theme } from "../foundation/semantic-colors.slint";
|
|
import { Typography } from "../foundation/typography.slint";
|
|
import { Radius } from "../foundation/radius.slint";
|
|
import { Spacing } from "../foundation/spacing.slint";
|
|
import { AlbumState, AlbumTrackItem, AlbumActions, NavState, ContentView } from "../state.slint";
|
|
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
|
import { ContextMenu } from "../primitives/ContextMenu.slint";
|
|
import { ContextMenuItem } from "../primitives/ContextMenuItem.slint";
|
|
import { QualityBadgeFull } from "../primitives/QualityBadgeFull.slint";
|
|
import { NavButtons } from "../shell/NavButtons.slint";
|
|
|
|
component CircleAction inherits Rectangle {
|
|
in property <image> icon;
|
|
in property <bool> primary: false;
|
|
in property <length> diameter: 40px;
|
|
callback clicked();
|
|
|
|
width: root.diameter;
|
|
height: root.diameter;
|
|
border-radius: root.diameter / 2;
|
|
// Ghost circle — translucent fill with a faint ring, never a solid
|
|
// accent fill (mirrors the Tauri transport controls).
|
|
background: ta.has-hover ? Theme.surface-hover : transparent;
|
|
border-width: 1px;
|
|
border-color: ta.has-hover ? Theme.text-disabled : Theme.border-subtle;
|
|
|
|
QbzIcon {
|
|
source: root.icon;
|
|
width: root.primary ? 19px : 17px;
|
|
height: root.primary ? 19px : 17px;
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
tint: ta.has-hover ? Theme.text-primary : Theme.text-secondary;
|
|
}
|
|
|
|
ta := TouchArea {
|
|
mouse-cursor: pointer;
|
|
clicked => {
|
|
root.clicked();
|
|
}
|
|
}
|
|
}
|
|
|
|
component TrackRow inherits Rectangle {
|
|
in property <AlbumTrackItem> track;
|
|
in property <int> index;
|
|
// kind ("track"), track id, action ("play" | "queue" | "favorite").
|
|
callback media-action(string, string, string);
|
|
|
|
height: 56px;
|
|
border-radius: 8px;
|
|
background: ta.has-hover
|
|
? Theme.surface-hover
|
|
: (Math.mod(root.index, 2) == 1 ? Theme.surface-card : transparent);
|
|
|
|
// Row hover/background detector — declared before the content so the
|
|
// more-button keeps its own clicks.
|
|
ta := TouchArea {
|
|
mouse-cursor: default;
|
|
}
|
|
|
|
HorizontalLayout {
|
|
padding-left: 12px;
|
|
padding-right: 12px;
|
|
spacing: 16px;
|
|
|
|
Text {
|
|
text: root.track.number;
|
|
width: 32px;
|
|
color: Theme.text-muted;
|
|
font-size: Typography.body;
|
|
vertical-alignment: center;
|
|
}
|
|
|
|
VerticalLayout {
|
|
alignment: center;
|
|
horizontal-stretch: 1;
|
|
spacing: 2px;
|
|
|
|
// alignment: start packs the title and the explicit badge at
|
|
// their natural sizes, so the badge sits right after the name
|
|
// instead of being stretched out to a column position.
|
|
HorizontalLayout {
|
|
alignment: start;
|
|
spacing: 6px;
|
|
Text {
|
|
text: root.track.title;
|
|
color: Theme.text-primary;
|
|
font-size: Typography.body;
|
|
font-weight: Typography.medium;
|
|
vertical-alignment: center;
|
|
overflow: elide;
|
|
}
|
|
if root.track.explicit: VerticalLayout {
|
|
alignment: center;
|
|
Rectangle {
|
|
width: 16px;
|
|
height: 16px;
|
|
border-radius: 3px;
|
|
background: Theme.surface-elevated;
|
|
Text {
|
|
text: "E";
|
|
color: Theme.text-muted;
|
|
font-size: 9px;
|
|
font-weight: Typography.semibold;
|
|
horizontal-alignment: center;
|
|
vertical-alignment: center;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Text {
|
|
text: root.track.artist;
|
|
visible: root.track.artist != "";
|
|
color: Theme.text-muted;
|
|
font-size: Typography.link;
|
|
overflow: elide;
|
|
}
|
|
}
|
|
|
|
Text {
|
|
text: root.track.duration;
|
|
width: 80px;
|
|
color: Theme.text-muted;
|
|
font-size: Typography.body;
|
|
horizontal-alignment: center;
|
|
vertical-alignment: center;
|
|
}
|
|
Text {
|
|
text: root.track.quality-tier == "hires"
|
|
? "Hi-Res"
|
|
: (root.track.quality-tier == "cd" ? "CD" : "");
|
|
width: 80px;
|
|
color: Theme.text-muted;
|
|
font-size: Typography.legal;
|
|
horizontal-alignment: center;
|
|
vertical-alignment: center;
|
|
}
|
|
|
|
// Favorite column (visual).
|
|
Rectangle {
|
|
width: 28px;
|
|
QbzIcon {
|
|
source: @image-url("../assets/icons/heart.svg");
|
|
width: 16px;
|
|
height: 16px;
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
tint: Theme.text-muted;
|
|
}
|
|
}
|
|
// Offline-cache column (visual).
|
|
Rectangle {
|
|
width: 28px;
|
|
QbzIcon {
|
|
source: @image-url("../assets/icons/cloud-download.svg");
|
|
width: 16px;
|
|
height: 16px;
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
tint: Theme.text-muted;
|
|
}
|
|
}
|
|
|
|
// Context-menu button — always visible in the muted column color,
|
|
// a 32px square hit area that brightens on hover.
|
|
VerticalLayout {
|
|
alignment: center;
|
|
Rectangle {
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: Radius.sm;
|
|
background: more-ta.has-hover ? Theme.surface-elevated : transparent;
|
|
QbzIcon {
|
|
source: @image-url("../assets/icons/ellipsis.svg");
|
|
width: 16px;
|
|
height: 16px;
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
tint: more-ta.has-hover ? Theme.text-primary : Theme.text-muted;
|
|
}
|
|
more-ta := TouchArea {
|
|
mouse-cursor: pointer;
|
|
clicked => {
|
|
track-menu.show();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
track-menu := PopupWindow {
|
|
x: parent.width - 208px;
|
|
y: 46px;
|
|
width: 196px;
|
|
height: 109px;
|
|
ContextMenu {
|
|
ContextMenuItem {
|
|
icon: @image-url("../assets/icons/play.svg");
|
|
label: @tr("Play");
|
|
clicked => {
|
|
root.media-action("track", root.track.id, "play");
|
|
}
|
|
}
|
|
ContextMenuItem {
|
|
icon: @image-url("../assets/icons/list-plus.svg");
|
|
label: @tr("Add to queue");
|
|
clicked => {
|
|
root.media-action("track", root.track.id, "queue");
|
|
}
|
|
}
|
|
ContextMenuItem {
|
|
icon: @image-url("../assets/icons/heart.svg");
|
|
label: @tr("Add to favorites");
|
|
clicked => {
|
|
root.media-action("track", root.track.id, "favorite");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// One label/award entry in the album sidebar — a round gradient avatar
|
|
// and a name.
|
|
component SidebarCard inherits Rectangle {
|
|
in property <image> icon;
|
|
in property <string> name;
|
|
in property <brush> avatar-bg;
|
|
callback clicked();
|
|
|
|
height: 56px;
|
|
border-radius: Radius.sm;
|
|
background: ta.has-hover ? Theme.surface-hover : transparent;
|
|
|
|
HorizontalLayout {
|
|
padding: 8px;
|
|
spacing: 10px;
|
|
VerticalLayout {
|
|
alignment: center;
|
|
Rectangle {
|
|
width: 36px;
|
|
height: 36px;
|
|
border-radius: 18px;
|
|
background: root.avatar-bg;
|
|
QbzIcon {
|
|
source: root.icon;
|
|
width: 18px;
|
|
height: 18px;
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
tint: #ffffff;
|
|
}
|
|
}
|
|
}
|
|
VerticalLayout {
|
|
alignment: center;
|
|
horizontal-stretch: 1;
|
|
Text {
|
|
text: root.name;
|
|
color: Theme.text-secondary;
|
|
font-size: Typography.link;
|
|
font-weight: Typography.medium;
|
|
wrap: word-wrap;
|
|
}
|
|
}
|
|
}
|
|
|
|
ta := TouchArea {
|
|
mouse-cursor: pointer;
|
|
clicked => {
|
|
root.clicked();
|
|
}
|
|
}
|
|
}
|
|
|
|
component SidebarHeading inherits Text {
|
|
color: Theme.text-muted;
|
|
font-size: 10px;
|
|
font-weight: Typography.semibold;
|
|
letter-spacing: 1px;
|
|
}
|
|
|
|
export component AlbumPageView inherits Rectangle {
|
|
callback open-artist(string);
|
|
callback media-action(string, string, string);
|
|
|
|
// Whether the full-description modal is open.
|
|
property <bool> show-description: false;
|
|
|
|
background: Theme.surface-main;
|
|
|
|
Flickable {
|
|
viewport-width: self.width;
|
|
viewport-height: page.preferred-height;
|
|
|
|
// Artwork-tinted gradient behind the header; scrolls with content.
|
|
Rectangle {
|
|
x: 0;
|
|
y: 0;
|
|
width: parent.width;
|
|
height: 340px;
|
|
background: @linear-gradient(180deg,
|
|
AlbumState.header-color 0%,
|
|
AlbumState.header-color 16%,
|
|
transparent 100%);
|
|
}
|
|
|
|
page := VerticalLayout {
|
|
width: parent.width;
|
|
padding-left: 24px;
|
|
padding-right: 24px;
|
|
padding-top: 14px;
|
|
padding-bottom: 100px;
|
|
spacing: 0px;
|
|
alignment: start;
|
|
|
|
// --- History navigation ------------------------------------------
|
|
HorizontalLayout {
|
|
alignment: start;
|
|
NavButtons { }
|
|
}
|
|
|
|
Rectangle { height: 22px; }
|
|
|
|
// --- Album header ------------------------------------------------
|
|
HorizontalLayout {
|
|
spacing: 32px;
|
|
|
|
Rectangle {
|
|
width: 224px;
|
|
height: 224px;
|
|
border-radius: 12px;
|
|
background: Theme.surface-elevated;
|
|
drop-shadow-blur: 32px;
|
|
drop-shadow-color: #00000080;
|
|
drop-shadow-offset-y: 8px;
|
|
clip: true;
|
|
Image {
|
|
width: 100%;
|
|
height: 100%;
|
|
source: AlbumState.artwork;
|
|
image-fit: cover;
|
|
}
|
|
}
|
|
|
|
VerticalLayout {
|
|
alignment: start;
|
|
padding-top: 4px;
|
|
spacing: 0px;
|
|
horizontal-stretch: 1;
|
|
|
|
Text {
|
|
text: AlbumState.title;
|
|
color: Theme.text-primary;
|
|
font-size: Typography.title;
|
|
font-weight: Typography.bold;
|
|
overflow: elide;
|
|
}
|
|
Rectangle { height: 4px; }
|
|
HorizontalLayout {
|
|
alignment: start;
|
|
artist-area := TouchArea {
|
|
width: artist-text.preferred-width;
|
|
height: artist-text.preferred-height;
|
|
mouse-cursor: pointer;
|
|
clicked => {
|
|
root.open-artist(AlbumState.artist-id);
|
|
}
|
|
artist-text := Text {
|
|
text: AlbumState.artist;
|
|
color: artist-area.has-hover
|
|
? Theme.accent-hover
|
|
: Theme.accent;
|
|
font-size: Typography.heading;
|
|
font-weight: Typography.medium;
|
|
}
|
|
}
|
|
}
|
|
Rectangle { height: 10px; }
|
|
Text {
|
|
text: AlbumState.info-line;
|
|
color: Theme.text-muted;
|
|
font-size: Typography.body;
|
|
overflow: elide;
|
|
}
|
|
|
|
Rectangle { height: 20px; }
|
|
HorizontalLayout {
|
|
alignment: start;
|
|
spacing: 12px;
|
|
CircleAction {
|
|
icon: @image-url("../assets/icons/play-fill.svg");
|
|
primary: true;
|
|
diameter: 44px;
|
|
clicked => {
|
|
root.media-action("album", AlbumState.id, "play");
|
|
}
|
|
}
|
|
VerticalLayout {
|
|
alignment: center;
|
|
CircleAction { icon: @image-url("../assets/icons/shuffle.svg"); }
|
|
}
|
|
VerticalLayout {
|
|
alignment: center;
|
|
CircleAction {
|
|
icon: @image-url("../assets/icons/heart.svg");
|
|
clicked => {
|
|
root.media-action("album", AlbumState.id, "favorite");
|
|
}
|
|
}
|
|
}
|
|
VerticalLayout {
|
|
alignment: center;
|
|
CircleAction { icon: @image-url("../assets/icons/radio.svg"); }
|
|
}
|
|
VerticalLayout {
|
|
alignment: center;
|
|
CircleAction { icon: @image-url("../assets/icons/user.svg"); }
|
|
}
|
|
VerticalLayout {
|
|
alignment: center;
|
|
CircleAction { icon: @image-url("../assets/icons/book-open.svg"); }
|
|
}
|
|
VerticalLayout {
|
|
alignment: center;
|
|
CircleAction { icon: @image-url("../assets/icons/cassette-tape.svg"); }
|
|
}
|
|
VerticalLayout {
|
|
alignment: center;
|
|
CircleAction { icon: @image-url("../assets/icons/square-check-big.svg"); }
|
|
}
|
|
VerticalLayout {
|
|
alignment: center;
|
|
CircleAction { icon: @image-url("../assets/icons/ellipsis.svg"); }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Editorial description — full content width, pre-truncated so
|
|
// it wraps cleanly, with a Read more link to the full modal.
|
|
if AlbumState.description != "": Rectangle { height: 18px; }
|
|
if AlbumState.description != "": Text {
|
|
text: AlbumState.description-short;
|
|
color: Theme.text-secondary;
|
|
font-size: Typography.body;
|
|
wrap: word-wrap;
|
|
}
|
|
if AlbumState.description != AlbumState.description-short: Rectangle { height: 4px; }
|
|
if AlbumState.description != AlbumState.description-short: read-more := TouchArea {
|
|
width: read-more-row.preferred-width;
|
|
height: 22px;
|
|
mouse-cursor: pointer;
|
|
clicked => {
|
|
root.show-description = true;
|
|
}
|
|
read-more-row := HorizontalLayout {
|
|
Text {
|
|
text: @tr("Read more");
|
|
color: read-more.has-hover ? Theme.accent-hover : Theme.accent;
|
|
font-size: Typography.legal;
|
|
vertical-alignment: center;
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle { height: 20px; }
|
|
Rectangle {
|
|
height: 1px;
|
|
background: Theme.border-subtle;
|
|
}
|
|
Rectangle { height: 8px; }
|
|
|
|
// --- Track list + label/awards sidebar --------------------------
|
|
// No `alignment: start` here: it would defeat the track list's
|
|
// horizontal-stretch and leave the sidebar floating mid-row
|
|
// with dead space to its right. The track list stretches and
|
|
// the 254px sidebar is pushed flush to the right edge; when a
|
|
// main right sidebar opens, the whole content region narrows
|
|
// and the sidebar rides along with it.
|
|
HorizontalLayout {
|
|
spacing: 32px;
|
|
|
|
VerticalLayout {
|
|
horizontal-stretch: 1;
|
|
spacing: 0px;
|
|
alignment: start;
|
|
|
|
if AlbumState.loading && AlbumState.tracks.length == 0: Text {
|
|
text: @tr("Loading album...");
|
|
color: Theme.text-muted;
|
|
font-size: Typography.body;
|
|
}
|
|
|
|
// Toolbar — album quality badge and track search.
|
|
HorizontalLayout {
|
|
height: 52px;
|
|
spacing: 16px;
|
|
VerticalLayout {
|
|
alignment: center;
|
|
QualityBadgeFull {
|
|
tier: AlbumState.quality-tier;
|
|
detail: AlbumState.quality-detail;
|
|
}
|
|
}
|
|
Rectangle { horizontal-stretch: 1; }
|
|
VerticalLayout {
|
|
alignment: center;
|
|
Rectangle {
|
|
width: 280px;
|
|
height: 34px;
|
|
border-radius: 6px;
|
|
border-width: 1px;
|
|
border-color: Theme.border-subtle;
|
|
background: Theme.surface-elevated;
|
|
HorizontalLayout {
|
|
padding-left: 10px;
|
|
padding-right: 10px;
|
|
spacing: 7px;
|
|
VerticalLayout {
|
|
alignment: center;
|
|
QbzIcon {
|
|
source: @image-url("../assets/icons/search.svg");
|
|
width: 14px;
|
|
height: 14px;
|
|
tint: Theme.text-muted;
|
|
}
|
|
}
|
|
// Functional client-side filter.
|
|
Rectangle {
|
|
horizontal-stretch: 1;
|
|
track-search := TextInput {
|
|
width: 100%;
|
|
height: 100%;
|
|
color: Theme.text-primary;
|
|
font-size: 13px;
|
|
vertical-alignment: center;
|
|
single-line: true;
|
|
edited => {
|
|
AlbumActions.search(self.text);
|
|
}
|
|
}
|
|
Text {
|
|
visible: track-search.text == "";
|
|
text: @tr("Search tracks...");
|
|
color: Theme.text-muted;
|
|
font-size: 13px;
|
|
vertical-alignment: center;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Column header.
|
|
HorizontalLayout {
|
|
height: 40px;
|
|
padding-left: 12px;
|
|
padding-right: 12px;
|
|
spacing: 16px;
|
|
Text {
|
|
text: "#";
|
|
width: 32px;
|
|
color: Theme.text-muted;
|
|
font-size: Typography.legal;
|
|
letter-spacing: 0.5px;
|
|
vertical-alignment: center;
|
|
}
|
|
Text {
|
|
text: @tr("TITLE");
|
|
horizontal-stretch: 1;
|
|
color: Theme.text-muted;
|
|
font-size: Typography.legal;
|
|
letter-spacing: 0.5px;
|
|
vertical-alignment: center;
|
|
}
|
|
Text {
|
|
text: @tr("DURATION");
|
|
width: 80px;
|
|
color: Theme.text-muted;
|
|
font-size: Typography.legal;
|
|
letter-spacing: 0.5px;
|
|
horizontal-alignment: center;
|
|
vertical-alignment: center;
|
|
}
|
|
Text {
|
|
text: @tr("QUALITY");
|
|
width: 80px;
|
|
color: Theme.text-muted;
|
|
font-size: Typography.legal;
|
|
letter-spacing: 0.5px;
|
|
horizontal-alignment: center;
|
|
vertical-alignment: center;
|
|
}
|
|
// Favorite / offline-cache column headers.
|
|
Rectangle {
|
|
width: 28px;
|
|
QbzIcon {
|
|
source: @image-url("../assets/icons/heart.svg");
|
|
width: 14px;
|
|
height: 14px;
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
tint: Theme.text-muted;
|
|
}
|
|
}
|
|
Rectangle {
|
|
width: 28px;
|
|
QbzIcon {
|
|
source: @image-url("../assets/icons/cloud-download.svg");
|
|
width: 14px;
|
|
height: 14px;
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
tint: Theme.text-muted;
|
|
}
|
|
}
|
|
// Aligns with the per-row more-button slot.
|
|
Rectangle { width: 32px; }
|
|
}
|
|
|
|
for track[index] in AlbumState.tracks: TrackRow {
|
|
track: track;
|
|
index: index;
|
|
media-action(kind, id, action) => {
|
|
root.media-action(kind, id, action);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Label / awards sidebar.
|
|
if AlbumState.label != "" || AlbumState.awards.length > 0: VerticalLayout {
|
|
width: 254px;
|
|
spacing: 24px;
|
|
alignment: start;
|
|
|
|
if AlbumState.label != "": VerticalLayout {
|
|
spacing: 8px;
|
|
SidebarHeading { text: @tr("LABEL"); }
|
|
SidebarCard {
|
|
icon: @image-url("../assets/icons/disc.svg");
|
|
name: AlbumState.label;
|
|
avatar-bg: @linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
|
}
|
|
}
|
|
|
|
if AlbumState.awards.length > 0: VerticalLayout {
|
|
spacing: 8px;
|
|
SidebarHeading { text: @tr("AWARDS"); }
|
|
for award in AlbumState.awards: SidebarCard {
|
|
icon: @image-url("../assets/laurels.svg");
|
|
name: award;
|
|
avatar-bg: @linear-gradient(135deg, #b45309 0%, #eab308 100%);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- Full-description modal --------------------------------------------
|
|
if root.show-description: Rectangle {
|
|
background: #000000bf;
|
|
|
|
// Scrim — a click anywhere outside the panel dismisses.
|
|
TouchArea {
|
|
mouse-cursor: default;
|
|
clicked => {
|
|
root.show-description = false;
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
width: Math.min(root.width - 80px, 560px);
|
|
height: Math.min(root.height - 120px, 460px);
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
border-radius: Radius.md;
|
|
background: Theme.surface-card;
|
|
border-width: 1px;
|
|
border-color: Theme.border-subtle;
|
|
drop-shadow-blur: 32px;
|
|
drop-shadow-color: Theme.card-shadow;
|
|
|
|
// Swallow clicks so they do not reach the scrim.
|
|
TouchArea { }
|
|
|
|
VerticalLayout {
|
|
padding: 24px;
|
|
spacing: 14px;
|
|
|
|
HorizontalLayout {
|
|
Text {
|
|
text: @tr("About this album");
|
|
color: Theme.text-primary;
|
|
font-size: Typography.heading;
|
|
font-weight: Typography.semibold;
|
|
horizontal-stretch: 1;
|
|
vertical-alignment: center;
|
|
}
|
|
close-x := TouchArea {
|
|
width: 28px;
|
|
height: 28px;
|
|
mouse-cursor: pointer;
|
|
clicked => {
|
|
root.show-description = false;
|
|
}
|
|
QbzIcon {
|
|
source: @image-url("../assets/icons/x.svg");
|
|
width: 18px;
|
|
height: 18px;
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
tint: close-x.has-hover ? Theme.text-primary : Theme.text-muted;
|
|
}
|
|
}
|
|
}
|
|
|
|
// vertical-stretch bounds the Flickable to the leftover
|
|
// panel height so a long description actually scrolls.
|
|
Flickable {
|
|
vertical-stretch: 1;
|
|
viewport-width: self.width;
|
|
viewport-height: desc-text.preferred-height;
|
|
desc-text := Text {
|
|
width: parent.width;
|
|
text: AlbumState.description;
|
|
color: Theme.text-secondary;
|
|
font-size: Typography.body;
|
|
wrap: word-wrap;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|