feat(slint): extend scroll-position restore to all views
Wire the per-history-entry scroll memory (added for Local Library) into every top-level view: Home/Discover, Album, Local Album, Artist, Musician, Label, Label Releases, Location, Favorites, Mix, Playlist, Playlist Manager, Offline Manager, Search, Settings. Each view's primary scroll container reports its viewport-y and restores it on back/forward via NavState.restore-scope (scope_for in main.rs maps each entry to a stable id; tab views carry the tab, e.g. "fav:albums"). The container restores once per arm, only after content lays out, then clears the scope. A `changed sr-armed` trigger covers views that persist across sub-tab navigation (Home's Discover tabs, Favorites' shared list, Playlist A->B->A) where no fresh mount occurs. ScrollView-based views (Offline Manager, Settings) use visible-height for the overflow check; ListView/Flickable views use height. Favorites' shared albums/artists/playlists/labels Flickable matches the active tab's scope dynamically. cc
This commit is contained in:
17 files changed
+243
-21
No files matched your search
@@ -664,20 +664,31 @@ fn navigate_search(
|
||||
|
||||
/// Apply a history entry — set the view and re-load entity pages.
|
||||
/// Stable scroll-restore id for an entry's primary list container, matching
|
||||
/// the `scope` strings the Slint scroll containers compare against. Returns
|
||||
/// `""` for views without a wired scroll memory (no container will match, so
|
||||
/// nothing restores). Keep in sync with the `restore-scope` checks in the
|
||||
/// `.slint` views.
|
||||
fn scope_for(entry: &nav::NavEntry) -> &'static str {
|
||||
/// the `restore-scope` strings the Slint scroll containers compare against.
|
||||
/// Returns `""` for views without a wired scroll memory (no container will
|
||||
/// match, so nothing restores). Tab/sub-page views carry the tab in the id so
|
||||
/// each tab keeps its own position. Keep in sync with the `.slint` views.
|
||||
fn scope_for(entry: &nav::NavEntry) -> String {
|
||||
match entry {
|
||||
nav::NavEntry::LocalLibrary { tab } => match tab.as_str() {
|
||||
"albums" => "ll:albums",
|
||||
"tracks" => "ll:tracks",
|
||||
"folders" => "ll:folders",
|
||||
"artists" => "ll:artists",
|
||||
_ => "",
|
||||
},
|
||||
_ => "",
|
||||
// HomeView is one persistent Flickable shared by the Discover tabs;
|
||||
// a single scope is enough (each tab entry stores its own scroll).
|
||||
nav::NavEntry::Home | nav::NavEntry::Discover { .. } => "home".into(),
|
||||
nav::NavEntry::Favorites { tab } => format!("fav:{tab}"),
|
||||
nav::NavEntry::LocalLibrary { tab } => format!("ll:{tab}"),
|
||||
nav::NavEntry::DiscoverBrowse { .. } => "discover-browse".into(),
|
||||
nav::NavEntry::Mix { .. } => "mix".into(),
|
||||
nav::NavEntry::Playlist(_) => "playlist".into(),
|
||||
nav::NavEntry::PlaylistManager => "playlist-manager".into(),
|
||||
nav::NavEntry::OfflineManager => "offline-manager".into(),
|
||||
nav::NavEntry::Album(_) => "album".into(),
|
||||
nav::NavEntry::LocalAlbum(_) => "local-album".into(),
|
||||
nav::NavEntry::Artist(_) => "artist".into(),
|
||||
nav::NavEntry::Settings => "settings".into(),
|
||||
nav::NavEntry::Search(_) => "search".into(),
|
||||
nav::NavEntry::Musician { .. } => "musician".into(),
|
||||
nav::NavEntry::Label { .. } => "label".into(),
|
||||
nav::NavEntry::LabelReleases { .. } => "label-releases".into(),
|
||||
nav::NavEntry::Location { .. } => "location".into(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -136,6 +136,18 @@ export component AlbumPageView inherits Rectangle {
|
||||
interactive: !DragState.active;
|
||||
viewport-width: self.width;
|
||||
viewport-height: page.preferred-height;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "album" && self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
|
||||
// Artwork-tinted gradient behind the header; scrolls with content.
|
||||
Rectangle {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { LocalAlbumState, LocalAlbumActions, LocalAlbumVersion, NowPlayingState } from "../state.slint";
|
||||
import { LocalAlbumState, LocalAlbumActions, LocalAlbumVersion, NowPlayingState, NavState } from "../state.slint";
|
||||
import { NavButtons } from "../shell/NavButtons.slint";
|
||||
import { CircleAction } from "../primitives/CircleAction.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
@@ -320,6 +320,18 @@ export component LocalAlbumView inherits Rectangle {
|
||||
padding-top: 12px;
|
||||
tracks-list := ListView {
|
||||
vertical-scrollbar-policy: ScrollBarPolicy.always-off;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "local-album" && self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
for track[i] in LocalAlbumState.tracks: TrackRow {
|
||||
track: track;
|
||||
index: i;
|
||||
|
||||
@@ -130,6 +130,18 @@ export component ArtistPageView inherits Rectangle {
|
||||
interactive: !DragState.active;
|
||||
viewport-width: self.width;
|
||||
viewport-height: page.preferred-height;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "artist" && self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
|
||||
// Artwork-tinted gradient behind the header; scrolls with content.
|
||||
Rectangle {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { DiscoverBrowseState, DiscoverBrowseActions, GenreFilterState, GenreFilterActions } from "../state.slint";
|
||||
import { DiscoverBrowseState, DiscoverBrowseActions, GenreFilterState, GenreFilterActions, NavState } from "../state.slint";
|
||||
import { AlbumCollectionView } from "AlbumCollectionView.slint";
|
||||
import { GenreFilterPopup } from "GenreFilterPopup.slint";
|
||||
import { LoadingSpinner } from "../primitives/LoadingSpinner.slint";
|
||||
@@ -248,12 +248,24 @@ export component DiscoverBrowseView inherits Rectangle {
|
||||
vertical-stretch: 1;
|
||||
viewport-width: self.width;
|
||||
viewport-height: page.preferred-height;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "discover-browse" && self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
|
||||
// Infinite scroll — when the viewport nears the bottom of the
|
||||
// content (within 600px), pull the next page. Guarded by
|
||||
// has-more + the loading flags AND an empty search query, so a
|
||||
// client-side search filter does not keep paging in the catalog.
|
||||
changed viewport-y => {
|
||||
NavState.report-scroll(self.viewport-y);
|
||||
if (-self.viewport-y + self.height >= self.viewport-height - 600px
|
||||
&& DiscoverBrowseState.has-more
|
||||
&& !DiscoverBrowseState.loading-more
|
||||
|
||||
@@ -254,6 +254,18 @@ export component HomeView inherits Rectangle {
|
||||
height: 100%;
|
||||
viewport-width: self.width;
|
||||
viewport-height: home-content.preferred-height;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "home" && self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
|
||||
home-content := VerticalLayout {
|
||||
padding: 32px;
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
GenreFilterState,
|
||||
GenreFilterActions,
|
||||
AlphaJump,
|
||||
NavState,
|
||||
} from "../state.slint";
|
||||
import { AlbumCollectionView } from "../discover/AlbumCollectionView.slint";
|
||||
import { PlaylistCard } from "../discover/PlaylistCard.slint";
|
||||
@@ -963,6 +964,18 @@ export component FavoritesView inherits Rectangle {
|
||||
track-list := ListView {
|
||||
vertical-stretch: 1;
|
||||
vertical-scrollbar-policy: ScrollBarPolicy.always-off;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "fav:tracks" && self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
for track[i] in FavoritesState.tracks-visible: VerticalLayout {
|
||||
spacing: 0px;
|
||||
// Group header rows when grouping by album / artist.
|
||||
@@ -1050,6 +1063,21 @@ export component FavoritesView inherits Rectangle {
|
||||
interactive: !DragState.active;
|
||||
viewport-width: self.width;
|
||||
viewport-height: other-page.preferred-height;
|
||||
// Scroll-position restore on back/forward. One Flickable serves the
|
||||
// albums/artists/playlists/labels tabs, so match the active tab's
|
||||
// scope dynamically (see nav::scope_for → "fav:<tab>").
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "fav:" + FavoritesState.active-tab
|
||||
&& self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
|
||||
other-page := VerticalLayout {
|
||||
width: parent.width;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { LabelState, LabelActions, TrackItem, DragState } from "../state.slint";
|
||||
import { LabelState, LabelActions, TrackItem, DragState, NavState } from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { TrackRow } from "../primitives/TrackRow.slint";
|
||||
import { CircleAction } from "../primitives/CircleAction.slint";
|
||||
@@ -52,6 +52,18 @@ export component LabelPageView inherits Rectangle {
|
||||
interactive: !DragState.active;
|
||||
viewport-width: self.width;
|
||||
viewport-height: page.preferred-height;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "label" && self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
|
||||
page := VerticalLayout {
|
||||
width: parent.width;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { LabelState, LabelActions } from "../state.slint";
|
||||
import { LabelState, LabelActions, NavState } from "../state.slint";
|
||||
import { AlbumCollectionView } from "../discover/AlbumCollectionView.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { QbzSelect } from "../primitives/QbzSelect.slint";
|
||||
@@ -32,6 +32,18 @@ export component LabelReleasesView inherits Rectangle {
|
||||
flick := Flickable {
|
||||
viewport-width: self.width;
|
||||
viewport-height: page.preferred-height;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "label-releases" && self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
|
||||
page := VerticalLayout {
|
||||
width: parent.width;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { LocationViewState, LocationViewActions, LocationArtistItem } from "../state.slint";
|
||||
import { LocationViewState, LocationViewActions, LocationArtistItem, NavState } from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { LoadingSpinner } from "../primitives/LoadingSpinner.slint";
|
||||
import { ListScrollbar } from "../primitives/ListScrollbar.slint";
|
||||
@@ -87,6 +87,18 @@ export component ArtistsByLocationView inherits Rectangle {
|
||||
flick := Flickable {
|
||||
viewport-width: self.width;
|
||||
viewport-height: page.preferred-height;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "location" && self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
|
||||
page := VerticalLayout {
|
||||
width: parent.width;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { MixState, DragState } from "../state.slint";
|
||||
import { MixState, DragState, NavState } from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { TrackRow } from "../primitives/TrackRow.slint";
|
||||
import { LoadingSpinner } from "../primitives/LoadingSpinner.slint";
|
||||
@@ -71,6 +71,18 @@ export component MixView inherits Rectangle {
|
||||
interactive: !DragState.active;
|
||||
viewport-width: self.width;
|
||||
viewport-height: page.preferred-height;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "mix" && self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
|
||||
page := VerticalLayout {
|
||||
width: parent.width;
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
MusicianState,
|
||||
MusicianActions,
|
||||
MusicianAppearanceItem,
|
||||
NavState,
|
||||
} from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { LoadingSpinner } from "../primitives/LoadingSpinner.slint";
|
||||
@@ -93,6 +94,18 @@ export component MusicianPageView inherits Rectangle {
|
||||
flick := Flickable {
|
||||
viewport-width: self.width;
|
||||
viewport-height: page.preferred-height;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "musician" && self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
|
||||
page := VerticalLayout {
|
||||
width: parent.width;
|
||||
|
||||
@@ -13,6 +13,7 @@ import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { OfflineManagerState, OfflineManagerActions, OfflineRow, OfflineArtist } from "../state.slint";
|
||||
import { NavState } from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { QbzSelect } from "../primitives/QbzSelect.slint";
|
||||
import { LoadingSpinner } from "../primitives/LoadingSpinner.slint";
|
||||
@@ -394,6 +395,18 @@ export component OfflineManagerView inherits Rectangle {
|
||||
}
|
||||
}
|
||||
if !OfflineManagerState.loading && OfflineManagerState.rows.length > 0: ScrollView {
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "offline-manager" && self.viewport-height > self.visible-height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
VerticalLayout {
|
||||
spacing: 2px;
|
||||
for row in OfflineManagerState.rows: Rectangle {
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
PmFolderItem,
|
||||
PmPlaylistItem,
|
||||
PmTreeRow,
|
||||
NavState,
|
||||
} from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { LoadingSpinner } from "../primitives/LoadingSpinner.slint";
|
||||
@@ -1233,6 +1234,18 @@ export component PlaylistManagerView inherits Rectangle {
|
||||
vertical-stretch: 1;
|
||||
viewport-width: self.width;
|
||||
viewport-height: page.preferred-height;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "playlist-manager" && self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
|
||||
page := VerticalLayout {
|
||||
width: parent.width;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { PlaylistState, PlaylistActions, DragState } from "../state.slint";
|
||||
import { PlaylistState, PlaylistActions, DragState, NavState } from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { TrackRow } from "../primitives/TrackRow.slint";
|
||||
import { ExpandableSearch } from "../primitives/ExpandableSearch.slint";
|
||||
@@ -625,6 +625,18 @@ export component PlaylistView inherits Rectangle {
|
||||
track-list := ListView {
|
||||
vertical-stretch: 1;
|
||||
vertical-scrollbar-policy: ScrollBarPolicy.always-off;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "playlist" && self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
for track[i] in PlaylistState.tracks: TrackRow {
|
||||
track: track;
|
||||
index: i;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
// per-type tabs show the full loaded set as a card grid or row list with
|
||||
// a load-more button.
|
||||
|
||||
import { SearchState, SearchActions, TrackItem, SearchPlaylistItem, AlbumCardItem, SlimItem, DragState } from "../state.slint";
|
||||
import { SearchState, SearchActions, TrackItem, SearchPlaylistItem, AlbumCardItem, SlimItem, DragState, NavState } from "../state.slint";
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
@@ -436,6 +436,18 @@ export component SearchResultsView inherits Rectangle {
|
||||
vertical-stretch: 1;
|
||||
viewport-width: self.width;
|
||||
viewport-height: body.preferred-height;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "search" && self.viewport-height > self.height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
|
||||
body := VerticalLayout {
|
||||
padding-left: 32px;
|
||||
|
||||
@@ -165,6 +165,18 @@ export component SettingsView inherits Rectangle {
|
||||
ScrollView {
|
||||
horizontal-stretch: 1;
|
||||
horizontal-scrollbar-policy: ScrollBarPolicy.always-off;
|
||||
// Scroll-position restore on back/forward (see nav::scope_for).
|
||||
property <string> sr-armed: NavState.restore-scope;
|
||||
function sr-restore() {
|
||||
if (NavState.restore-scope == "settings" && self.viewport-height > self.visible-height) {
|
||||
self.viewport-y = NavState.scroll-restore;
|
||||
NavState.restore-scope = "";
|
||||
}
|
||||
}
|
||||
init => { self.sr-restore(); }
|
||||
changed sr-armed => { self.sr-restore(); }
|
||||
changed viewport-height => { self.sr-restore(); }
|
||||
changed viewport-y => { NavState.report-scroll(self.viewport-y); }
|
||||
VerticalLayout {
|
||||
padding-left: 20px;
|
||||
padding-right: 40px;
|
||||
|
||||
Reference in new issue
Block a user