feat(slint): in-page search for the artist view
Mirrors Tauri's `.page-search` substring filter — Popular Tracks
(title + artist) and every release-section album (title) hide on
each keystroke when they don't match, restore when the query is
cleared.
UI:
- Search row added between the artist header and Popular Tracks,
always visible while artist data is present. Search icon +
inline TextInput, surface-card background with a thin border
that highlights on focus. Placeholder "Search this page…".
State:
- New ArtistActions global with `callback search(string)`, re-
exported through app.slint so main.rs can wire it.
Controller (artist.rs):
- Thread-local FULL_TOP_TRACKS and FULL_RELEASE_SECTIONS cache the
rendered models on the UI thread (same pattern as
AlbumPageView's FULL_TRACKS), populated in apply_artist so the
filter never round-trips to the backend.
- filter_artist(window, query): trim+lowercase the query, then
rebuild ArtistState.top_tracks and ArtistState.release_sections.
Sections whose albums all filter out are dropped from the visible
list, matching Tauri's behavior.
main.rs:
- ArtistActions::on_search wired to artist::filter_artist (same
shape as the existing AlbumActions::on_search wiring).
cc
This commit is contained in:
5 files changed
+145
-2
No files matched your search
@@ -10,6 +10,7 @@ import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import {
|
||||
ArtistState,
|
||||
ArtistActions,
|
||||
AlbumTrackItem,
|
||||
NavState,
|
||||
ContentView,
|
||||
@@ -467,7 +468,64 @@ export component ArtistPageView inherits Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle { height: 36px; }
|
||||
Rectangle { height: 24px; }
|
||||
|
||||
// --- In-page search ---------------------------------------------
|
||||
// Single client-side substring filter — applied to Popular
|
||||
// Tracks (title + artist) and to every release-section
|
||||
// album title. Same pattern as Tauri's `.page-search` plus
|
||||
// the AlbumActions.search wiring AlbumPageView uses for
|
||||
// its track list.
|
||||
if !ArtistState.loading || ArtistState.top-tracks.length > 0:
|
||||
Rectangle {
|
||||
height: 36px;
|
||||
border-radius: Radius.sm;
|
||||
background: Theme.surface-card;
|
||||
border-width: 1px;
|
||||
border-color: artist-search.has-focus
|
||||
? Theme.border-subtle
|
||||
: transparent;
|
||||
HorizontalLayout {
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
spacing: 8px;
|
||||
VerticalLayout {
|
||||
alignment: center;
|
||||
horizontal-stretch: 0;
|
||||
QbzIcon {
|
||||
source: @image-url("../assets/icons/search.svg");
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
tint: Theme.text-muted;
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
horizontal-stretch: 1;
|
||||
artist-search := TextInput {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: Theme.text-primary;
|
||||
font-size: Typography.body;
|
||||
vertical-alignment: center;
|
||||
single-line: true;
|
||||
edited => {
|
||||
ArtistActions.search(self.text);
|
||||
}
|
||||
}
|
||||
Text {
|
||||
visible: artist-search.text == "";
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text: @tr("Search this page…");
|
||||
color: Theme.text-muted;
|
||||
font-size: Typography.body;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle { height: 12px; }
|
||||
|
||||
if ArtistState.loading && ArtistState.top-tracks.length == 0: Rectangle {
|
||||
height: 280px;
|
||||
|
||||
Reference in new issue
Block a user