Retain ListState when reinitialising
All checks were successful
Cargo CI / Build and Test (pull_request) Successful in 1m5s
Cargo CI / Lint (pull_request) Successful in 44s

This commit is contained in:
Wojciech Kozlowski 2024-02-01 23:35:47 +01:00
parent 9ccaab563a
commit 272b41a6a0

View File

@ -62,7 +62,7 @@ impl Selection {
} }
pub fn select(&mut self, artists: &[Artist], selected: ActiveSelection) { pub fn select(&mut self, artists: &[Artist], selected: ActiveSelection) {
self.artist = ArtistSelection::reinitialise(artists, selected.artist); self.artist.reinitialise(artists, selected.artist);
} }
pub fn increment_category(&mut self) { pub fn increment_category(&mut self) {
@ -124,39 +124,44 @@ impl Selection {
impl ArtistSelection { impl ArtistSelection {
fn initialise(artists: &[Artist]) -> Self { fn initialise(artists: &[Artist]) -> Self {
Self::reinitialise(artists, None) let mut selection = ArtistSelection {
state: ListState::default(),
album: AlbumSelection::initialise(&[]),
};
selection.reinitialise(artists, None);
selection
} }
fn reinitialise(artists: &[Artist], active: Option<ActiveArtist>) -> Self { fn reinitialise(&mut self, artists: &[Artist], active: Option<ActiveArtist>) {
if let Some(active) = active { if let Some(active) = active {
let result = artists.binary_search_by(|a| a.get_sort_key().cmp(&active.artist_id)); let result = artists.binary_search_by(|a| a.get_sort_key().cmp(&active.artist_id));
match result { match result {
Ok(index) => Self::reinitialise_with_index(artists, index, active.album), Ok(index) => self.reinitialise_with_index(artists, index, active.album),
Err(index) => Self::reinitialise_with_index(artists, index, None), Err(index) => self.reinitialise_with_index(artists, index, None),
} }
} else { } else {
Self::reinitialise_with_index(artists, 0, None) self.reinitialise_with_index(artists, 0, None)
} }
} }
fn reinitialise_with_index( fn reinitialise_with_index(
&mut self,
artists: &[Artist], artists: &[Artist],
mut index: usize, mut index: usize,
mut active_album: Option<ActiveAlbum>, mut active_album: Option<ActiveAlbum>,
) -> Self { ) {
let mut state = ListState::default();
let album: AlbumSelection;
if artists.is_empty() { if artists.is_empty() {
album = AlbumSelection::initialise(&[]); self.state.select(None);
self.album.reinitialise(&[], None);
} else { } else {
if index >= artists.len() { if index >= artists.len() {
index = artists.len() - 1; index = artists.len() - 1;
active_album = None; active_album = None;
} }
state.select(Some(index)); self.state.select(Some(index));
album = AlbumSelection::reinitialise(&artists[index].albums, active_album); self.album
.reinitialise(&artists[index].albums, active_album);
} }
ArtistSelection { state, album }
} }
fn increment(&mut self, artists: &[Artist]) { fn increment(&mut self, artists: &[Artist]) {
@ -206,39 +211,43 @@ impl ArtistSelection {
impl AlbumSelection { impl AlbumSelection {
fn initialise(albums: &[Album]) -> Self { fn initialise(albums: &[Album]) -> Self {
Self::reinitialise(albums, None) let mut selection = AlbumSelection {
state: ListState::default(),
track: TrackSelection::initialise(&[]),
};
selection.reinitialise(albums, None);
selection
} }
fn reinitialise(albums: &[Album], album: Option<ActiveAlbum>) -> Self { fn reinitialise(&mut self, albums: &[Album], album: Option<ActiveAlbum>) {
if let Some(album) = album { if let Some(album) = album {
let result = albums.binary_search_by(|a| a.get_sort_key().cmp(&album.album_id)); let result = albums.binary_search_by(|a| a.get_sort_key().cmp(&album.album_id));
match result { match result {
Ok(index) => Self::reinitialise_with_index(albums, index, album.track), Ok(index) => self.reinitialise_with_index(albums, index, album.track),
Err(index) => Self::reinitialise_with_index(albums, index, None), Err(index) => self.reinitialise_with_index(albums, index, None),
} }
} else { } else {
Self::reinitialise_with_index(albums, 0, None) self.reinitialise_with_index(albums, 0, None)
} }
} }
fn reinitialise_with_index( fn reinitialise_with_index(
&mut self,
albums: &[Album], albums: &[Album],
mut index: usize, mut index: usize,
mut active_track: Option<ActiveTrack>, mut active_track: Option<ActiveTrack>,
) -> Self { ) {
let mut state = ListState::default();
let track: TrackSelection;
if albums.is_empty() { if albums.is_empty() {
track = TrackSelection::initialise(&[]); self.state.select(None);
self.track = TrackSelection::initialise(&[]);
} else { } else {
if index >= albums.len() { if index >= albums.len() {
index = albums.len() - 1; index = albums.len() - 1;
active_track = None; active_track = None;
} }
state.select(Some(index)); self.state.select(Some(index));
track = TrackSelection::reinitialise(&albums[index].tracks, active_track); self.track.reinitialise(&albums[index].tracks, active_track);
} }
AlbumSelection { state, track }
} }
fn increment(&mut self, albums: &[Album]) { fn increment(&mut self, albums: &[Album]) {
@ -276,29 +285,33 @@ impl AlbumSelection {
impl TrackSelection { impl TrackSelection {
fn initialise(tracks: &[Track]) -> Self { fn initialise(tracks: &[Track]) -> Self {
Self::reinitialise(tracks, None) let mut selection = TrackSelection {
state: ListState::default(),
};
selection.reinitialise(tracks, None);
selection
} }
fn reinitialise(tracks: &[Track], track: Option<ActiveTrack>) -> Self { fn reinitialise(&mut self, tracks: &[Track], track: Option<ActiveTrack>) {
if let Some(track) = track { if let Some(track) = track {
let result = tracks.binary_search_by(|t| t.get_sort_key().cmp(&track.track_id)); let result = tracks.binary_search_by(|t| t.get_sort_key().cmp(&track.track_id));
match result { match result {
Ok(index) | Err(index) => Self::reinitialise_with_index(tracks, index), Ok(index) | Err(index) => self.reinitialise_with_index(tracks, index),
} }
} else { } else {
Self::reinitialise_with_index(tracks, 0) self.reinitialise_with_index(tracks, 0)
} }
} }
fn reinitialise_with_index(tracks: &[Track], mut index: usize) -> Self { fn reinitialise_with_index(&mut self, tracks: &[Track], mut index: usize) {
let mut state = ListState::default(); if tracks.is_empty() {
if !tracks.is_empty() { self.state.select(None);
} else {
if index >= tracks.len() { if index >= tracks.len() {
index = tracks.len() - 1; index = tracks.len() - 1;
} }
state.select(Some(index)); self.state.select(Some(index));
} }
TrackSelection { state }
} }
fn increment(&mut self, tracks: &[Track]) { fn increment(&mut self, tracks: &[Track]) {
@ -415,20 +428,20 @@ mod tests {
// Re-initialise. // Re-initialise.
let previous = sel.clone(); let previous = sel.clone();
let active_track = ActiveTrack::get(tracks, &sel); let active_track = ActiveTrack::get(tracks, &sel);
sel = TrackSelection::reinitialise(tracks, active_track); sel.reinitialise(tracks, active_track);
assert_eq!(sel, previous); assert_eq!(sel, previous);
// Re-initialise out-of-bounds. // Re-initialise out-of-bounds.
let mut previous = sel.clone(); let mut previous = sel.clone();
previous.decrement(tracks); previous.decrement(tracks);
let active_track = ActiveTrack::get(tracks, &sel); let active_track = ActiveTrack::get(tracks, &sel);
sel = TrackSelection::reinitialise(&tracks[..(tracks.len() - 1)], active_track); sel.reinitialise(&tracks[..(tracks.len() - 1)], active_track);
assert_eq!(sel, previous); assert_eq!(sel, previous);
// Re-initialise empty. // Re-initialise empty.
let previous = TrackSelection::initialise(&[]); let previous = TrackSelection::initialise(&[]);
let active_track = ActiveTrack::get(tracks, &sel); let active_track = ActiveTrack::get(tracks, &sel);
sel = TrackSelection::reinitialise(&[], active_track); sel.reinitialise(&[], active_track);
assert_eq!(sel, previous); assert_eq!(sel, previous);
// Artifical test case to verify upper limit. // Artifical test case to verify upper limit.
@ -486,20 +499,20 @@ mod tests {
// Re-initialise. // Re-initialise.
let previous = sel.clone(); let previous = sel.clone();
let active_album = ActiveAlbum::get(albums, &sel); let active_album = ActiveAlbum::get(albums, &sel);
sel = AlbumSelection::reinitialise(albums, active_album); sel.reinitialise(albums, active_album);
assert_eq!(sel, previous); assert_eq!(sel, previous);
// Re-initialise out-of-bounds. // Re-initialise out-of-bounds.
let mut previous = sel.clone(); let mut previous = sel.clone();
previous.decrement(albums); previous.decrement(albums);
let active_album = ActiveAlbum::get(albums, &sel); let active_album = ActiveAlbum::get(albums, &sel);
sel = AlbumSelection::reinitialise(&albums[..(albums.len() - 1)], active_album); sel.reinitialise(&albums[..(albums.len() - 1)], active_album);
assert_eq!(sel, previous); assert_eq!(sel, previous);
// Re-initialise empty. // Re-initialise empty.
let previous = AlbumSelection::initialise(&[]); let previous = AlbumSelection::initialise(&[]);
let active_album = ActiveAlbum::get(albums, &sel); let active_album = ActiveAlbum::get(albums, &sel);
sel = AlbumSelection::reinitialise(&[], active_album); sel.reinitialise(&[], active_album);
assert_eq!(sel, previous); assert_eq!(sel, previous);
// Artifical test case to verify upper limit. // Artifical test case to verify upper limit.
@ -560,20 +573,20 @@ mod tests {
// Re-initialise. // Re-initialise.
let previous = sel.clone(); let previous = sel.clone();
let active_artist = ActiveArtist::get(artists, &sel); let active_artist = ActiveArtist::get(artists, &sel);
sel = ArtistSelection::reinitialise(artists, active_artist); sel.reinitialise(artists, active_artist);
assert_eq!(sel, previous); assert_eq!(sel, previous);
// Re-initialise out-of-bounds. // Re-initialise out-of-bounds.
let mut previous = sel.clone(); let mut previous = sel.clone();
previous.decrement(artists); previous.decrement(artists);
let active_artist = ActiveArtist::get(artists, &sel); let active_artist = ActiveArtist::get(artists, &sel);
sel = ArtistSelection::reinitialise(&artists[..(artists.len() - 1)], active_artist); sel.reinitialise(&artists[..(artists.len() - 1)], active_artist);
assert_eq!(sel, previous); assert_eq!(sel, previous);
// Re-initialise empty. // Re-initialise empty.
let previous = ArtistSelection::initialise(&[]); let previous = ArtistSelection::initialise(&[]);
let active_artist = ActiveArtist::get(artists, &sel); let active_artist = ActiveArtist::get(artists, &sel);
sel = ArtistSelection::reinitialise(&[], active_artist); sel.reinitialise(&[], active_artist);
assert_eq!(sel, previous); assert_eq!(sel, previous);
// Artifical test case to verify upper limit. // Artifical test case to verify upper limit.