feat(slint): MB relationships section in the network sidebar
Wires the third MB-driven section: Members & Former, Member Of, and
Collaborators, mirroring Tauri's RELATIONSHIPS block.
Controller (`crates/qbz-slint/src/artist.rs`):
- load_mb_relationships(runtime, mbid) — calls QbzCore's
musicbrainz_get_artist_relationships, then maps each section
independently with group_relations.
- group_relations dedupes by mbid combining roles, preserves first-
seen order, and computes the per-row role + tooltip:
* role = first attribute, or the section default ("Band Member"
/ "Band" / "Collaborator") when MB has no attributes.
* tooltip = roles joined with ", " plus the period in parens
("Vocalist, Guitarist (1965 - 1969)"); falls back to just the
period or to the name.
- format_period mirrors Tauri's `{begin || '?'} - {end || 'present'}`
when at least one of the two is set, otherwise empty.
main.rs:
- The MB enrichment task now chains: resolve + metadata first, then
relationships with the resolved mbid. Both loading flags flip
together so the sidebar shows a single "Loading…" line per section
while the calls run.
ArtistPageView.slint:
- RELATIONSHIPS section, gated by mb-available + (loading || has-
data). Three sub-groups, each with a secondary label
("Members & Former" / "Member Of" / "Collaborators"), shown only
when their list is non-empty.
- Members and Collaborators use the User icon, Member Of uses the
Music icon (matches Tauri's Lucide imports).
- Each row reuses SidebarLink, emits NetworkSidebarActions.musician-
clicked(name, role) — logged-only until MusicianPage lands.
cc
This commit is contained in:
3 files changed
+286
-4
No files matched your search
@@ -887,6 +887,100 @@ export component ArtistPageView inherits Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Relationships (MB) --------------------------
|
||||
// Section is gated by mb-available so a
|
||||
// disabled MB or unmatched artist hides it.
|
||||
if NetworkSidebarState.mb-available
|
||||
&& (NetworkSidebarState.relationships-loading
|
||||
|| NetworkSidebarState.relationships.has-data):
|
||||
VerticalLayout {
|
||||
padding-left: 14px;
|
||||
padding-right: 14px;
|
||||
padding-top: 12px;
|
||||
padding-bottom: 6px;
|
||||
spacing: 6px;
|
||||
|
||||
Text {
|
||||
text: @tr("RELATIONSHIPS");
|
||||
color: Theme.text-muted;
|
||||
font-size: 11px;
|
||||
font-weight: Typography.semibold;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
if NetworkSidebarState.relationships-loading: Text {
|
||||
text: @tr("Loading…");
|
||||
color: Theme.text-muted;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
if !NetworkSidebarState.relationships-loading
|
||||
&& NetworkSidebarState.relationships.members.length > 0:
|
||||
VerticalLayout {
|
||||
spacing: 2px;
|
||||
padding-top: 2px;
|
||||
Text {
|
||||
text: @tr("Members & Former");
|
||||
color: Theme.text-muted;
|
||||
font-size: 11px;
|
||||
}
|
||||
for member in NetworkSidebarState.relationships.members:
|
||||
SidebarLink {
|
||||
label: member.name;
|
||||
icon: @image-url("../assets/icons/user.svg");
|
||||
tooltip: member.tooltip;
|
||||
clicked => {
|
||||
NetworkSidebarActions.musician-clicked(
|
||||
member.name, member.role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !NetworkSidebarState.relationships-loading
|
||||
&& NetworkSidebarState.relationships.groups.length > 0:
|
||||
VerticalLayout {
|
||||
spacing: 2px;
|
||||
padding-top: 2px;
|
||||
Text {
|
||||
text: @tr("Member Of");
|
||||
color: Theme.text-muted;
|
||||
font-size: 11px;
|
||||
}
|
||||
for group in NetworkSidebarState.relationships.groups:
|
||||
SidebarLink {
|
||||
label: group.name;
|
||||
icon: @image-url("../assets/icons/music.svg");
|
||||
tooltip: group.tooltip;
|
||||
clicked => {
|
||||
NetworkSidebarActions.musician-clicked(
|
||||
group.name, group.role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !NetworkSidebarState.relationships-loading
|
||||
&& NetworkSidebarState.relationships.collaborators.length > 0:
|
||||
VerticalLayout {
|
||||
spacing: 2px;
|
||||
padding-top: 2px;
|
||||
Text {
|
||||
text: @tr("Collaborators");
|
||||
color: Theme.text-muted;
|
||||
font-size: 11px;
|
||||
}
|
||||
for collab in NetworkSidebarState.relationships.collaborators:
|
||||
SidebarLink {
|
||||
label: collab.name;
|
||||
icon: @image-url("../assets/icons/user.svg");
|
||||
tooltip: collab.tooltip;
|
||||
clicked => {
|
||||
NetworkSidebarActions.musician-clicked(
|
||||
collab.name, collab.role);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user