Sort albums by month if two releases of the same artist happen in the same year #155
@ -41,8 +41,8 @@ impl Artist {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_sort_key(&self) -> &ArtistId {
|
||||
self.sort.as_ref().unwrap_or(&self.id)
|
||||
pub fn get_sort_key(&self) -> (&ArtistId,) {
|
||||
(self.sort.as_ref().unwrap_or(&self.id),)
|
||||
}
|
||||
|
||||
pub fn set_sort_key<SORT: Into<ArtistId>>(&mut self, sort: SORT) {
|
||||
@ -114,7 +114,7 @@ impl PartialOrd for Artist {
|
||||
|
||||
impl Ord for Artist {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.get_sort_key().cmp(other.get_sort_key())
|
||||
self.get_sort_key().cmp(&other.get_sort_key())
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,7 +260,7 @@ mod tests {
|
||||
|
||||
assert_eq!(artist.id, artist_id);
|
||||
assert_eq!(artist.sort, None);
|
||||
assert_eq!(artist.get_sort_key(), &artist_id);
|
||||
assert_eq!(artist.get_sort_key(), (&artist_id,));
|
||||
assert!(artist < Artist::new(sort_id_1.clone()));
|
||||
assert!(artist < Artist::new(sort_id_2.clone()));
|
||||
|
||||
@ -268,7 +268,7 @@ mod tests {
|
||||
|
||||
assert_eq!(artist.id, artist_id);
|
||||
assert_eq!(artist.sort.as_ref(), Some(&sort_id_1));
|
||||
assert_eq!(artist.get_sort_key(), &sort_id_1);
|
||||
assert_eq!(artist.get_sort_key(), (&sort_id_1,));
|
||||
assert!(artist > Artist::new(artist_id.clone()));
|
||||
assert!(artist < Artist::new(sort_id_2.clone()));
|
||||
|
||||
@ -276,7 +276,7 @@ mod tests {
|
||||
|
||||
assert_eq!(artist.id, artist_id);
|
||||
assert_eq!(artist.sort.as_ref(), Some(&sort_id_2));
|
||||
assert_eq!(artist.get_sort_key(), &sort_id_2);
|
||||
assert_eq!(artist.get_sort_key(), (&sort_id_2,));
|
||||
assert!(artist > Artist::new(artist_id.clone()));
|
||||
assert!(artist > Artist::new(sort_id_1.clone()));
|
||||
|
||||
@ -284,7 +284,7 @@ mod tests {
|
||||
|
||||
assert_eq!(artist.id, artist_id);
|
||||
assert_eq!(artist.sort, None);
|
||||
assert_eq!(artist.get_sort_key(), &artist_id);
|
||||
assert_eq!(artist.get_sort_key(), (&artist_id,));
|
||||
assert!(artist < Artist::new(sort_id_1.clone()));
|
||||
assert!(artist < Artist::new(sort_id_2.clone()));
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::tui::{
|
||||
app::{
|
||||
machine::{App, AppInner, AppMachine},
|
||||
selection::IdSelection,
|
||||
selection::KeySelection,
|
||||
AppPublic, AppState, IAppInteractReload,
|
||||
},
|
||||
lib::IMusicHoard,
|
||||
@ -36,7 +36,7 @@ impl<MH: IMusicHoard> IAppInteractReload for AppMachine<MH, AppReload> {
|
||||
type APP = App<MH>;
|
||||
|
||||
fn reload_library(mut self) -> Self::APP {
|
||||
let previous = IdSelection::get(
|
||||
let previous = KeySelection::get(
|
||||
self.inner.music_hoard.get_collection(),
|
||||
&self.inner.selection,
|
||||
);
|
||||
@ -45,7 +45,7 @@ impl<MH: IMusicHoard> IAppInteractReload for AppMachine<MH, AppReload> {
|
||||
}
|
||||
|
||||
fn reload_database(mut self) -> Self::APP {
|
||||
let previous = IdSelection::get(
|
||||
let previous = KeySelection::get(
|
||||
self.inner.music_hoard.get_collection(),
|
||||
&self.inner.selection,
|
||||
);
|
||||
@ -63,11 +63,11 @@ impl<MH: IMusicHoard> IAppInteractReload for AppMachine<MH, AppReload> {
|
||||
}
|
||||
|
||||
trait IAppInteractReloadPrivate<MH: IMusicHoard> {
|
||||
fn refresh(self, previous: IdSelection, result: Result<(), musichoard::Error>) -> App<MH>;
|
||||
fn refresh(self, previous: KeySelection, result: Result<(), musichoard::Error>) -> App<MH>;
|
||||
}
|
||||
|
||||
impl<MH: IMusicHoard> IAppInteractReloadPrivate<MH> for AppMachine<MH, AppReload> {
|
||||
fn refresh(mut self, previous: IdSelection, result: Result<(), musichoard::Error>) -> App<MH> {
|
||||
fn refresh(mut self, previous: KeySelection, result: Result<(), musichoard::Error>) -> App<MH> {
|
||||
match result {
|
||||
Ok(()) => {
|
||||
self.inner
|
||||
|
@ -6,7 +6,7 @@ use musichoard::collection::{
|
||||
};
|
||||
|
||||
use crate::tui::app::selection::{
|
||||
track::{IdSelectTrack, TrackSelection},
|
||||
track::{KeySelectTrack, TrackSelection},
|
||||
Delta, SelectionState, WidgetState,
|
||||
};
|
||||
|
||||
@ -26,7 +26,7 @@ impl AlbumSelection {
|
||||
selection
|
||||
}
|
||||
|
||||
pub fn reinitialise(&mut self, albums: &[Album], album: Option<IdSelectAlbum>) {
|
||||
pub fn reinitialise(&mut self, albums: &[Album], album: Option<KeySelectAlbum>) {
|
||||
if let Some(album) = album {
|
||||
let result = albums.binary_search_by(|a| a.get_sort_key().cmp(&album.get_sort_key()));
|
||||
match result {
|
||||
@ -42,7 +42,7 @@ impl AlbumSelection {
|
||||
&mut self,
|
||||
albums: &[Album],
|
||||
index: usize,
|
||||
active_track: Option<IdSelectTrack>,
|
||||
active_track: Option<KeySelectTrack>,
|
||||
) {
|
||||
if albums.is_empty() {
|
||||
self.state.list.select(None);
|
||||
@ -160,19 +160,19 @@ impl AlbumSelection {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IdSelectAlbum {
|
||||
pub struct KeySelectAlbum {
|
||||
key: (AlbumDate, AlbumSeq, AlbumId),
|
||||
track: Option<IdSelectTrack>,
|
||||
track: Option<KeySelectTrack>,
|
||||
}
|
||||
|
||||
impl IdSelectAlbum {
|
||||
impl KeySelectAlbum {
|
||||
pub fn get(albums: &[Album], selection: &AlbumSelection) -> Option<Self> {
|
||||
selection.state.list.selected().map(|index| {
|
||||
let album = &albums[index];
|
||||
let key = album.get_sort_key();
|
||||
IdSelectAlbum {
|
||||
KeySelectAlbum {
|
||||
key: (key.0.to_owned(), key.1.to_owned(), key.2.to_owned()),
|
||||
track: IdSelectTrack::get(&album.tracks, &selection.track),
|
||||
track: KeySelectTrack::get(&album.tracks, &selection.track),
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -335,20 +335,20 @@ mod tests {
|
||||
|
||||
// Re-initialise.
|
||||
let expected = sel.clone();
|
||||
let active_album = IdSelectAlbum::get(albums, &sel);
|
||||
let active_album = KeySelectAlbum::get(albums, &sel);
|
||||
sel.reinitialise(albums, active_album);
|
||||
assert_eq!(sel, expected);
|
||||
|
||||
// Re-initialise out-of-bounds.
|
||||
let mut expected = sel.clone();
|
||||
expected.decrement(albums, Delta::Line);
|
||||
let active_album = IdSelectAlbum::get(albums, &sel);
|
||||
let active_album = KeySelectAlbum::get(albums, &sel);
|
||||
sel.reinitialise(&albums[..(albums.len() - 1)], active_album);
|
||||
assert_eq!(sel, expected);
|
||||
|
||||
// Re-initialise empty.
|
||||
let expected = AlbumSelection::initialise(&[]);
|
||||
let active_album = IdSelectAlbum::get(albums, &sel);
|
||||
let active_album = KeySelectAlbum::get(albums, &sel);
|
||||
sel.reinitialise(&[], active_album);
|
||||
assert_eq!(sel, expected);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use musichoard::collection::{
|
||||
};
|
||||
|
||||
use crate::tui::app::selection::{
|
||||
album::{AlbumSelection, IdSelectAlbum},
|
||||
album::{AlbumSelection, KeySelectAlbum},
|
||||
Delta, SelectionState, WidgetState,
|
||||
};
|
||||
|
||||
@ -27,9 +27,9 @@ impl ArtistSelection {
|
||||
selection
|
||||
}
|
||||
|
||||
pub fn reinitialise(&mut self, artists: &[Artist], active: Option<IdSelectArtist>) {
|
||||
pub fn reinitialise(&mut self, artists: &[Artist], active: Option<KeySelectArtist>) {
|
||||
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.get_sort_key()));
|
||||
match result {
|
||||
Ok(index) => self.reinitialise_with_index(artists, index, active.album),
|
||||
Err(index) => self.reinitialise_with_index(artists, index, None),
|
||||
@ -43,7 +43,7 @@ impl ArtistSelection {
|
||||
&mut self,
|
||||
artists: &[Artist],
|
||||
index: usize,
|
||||
active_album: Option<IdSelectAlbum>,
|
||||
active_album: Option<KeySelectAlbum>,
|
||||
) {
|
||||
if artists.is_empty() {
|
||||
self.state.list.select(None);
|
||||
@ -193,21 +193,26 @@ impl ArtistSelection {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IdSelectArtist {
|
||||
artist_id: ArtistId,
|
||||
album: Option<IdSelectAlbum>,
|
||||
pub struct KeySelectArtist {
|
||||
key: (ArtistId,),
|
||||
album: Option<KeySelectAlbum>,
|
||||
}
|
||||
|
||||
impl IdSelectArtist {
|
||||
impl KeySelectArtist {
|
||||
pub fn get(artists: &[Artist], selection: &ArtistSelection) -> Option<Self> {
|
||||
selection.state.list.selected().map(|index| {
|
||||
let artist = &artists[index];
|
||||
IdSelectArtist {
|
||||
artist_id: artist.get_sort_key().clone(),
|
||||
album: IdSelectAlbum::get(&artist.albums, &selection.album),
|
||||
let key = artist.get_sort_key();
|
||||
KeySelectArtist {
|
||||
key: (key.0.to_owned(),),
|
||||
album: KeySelectAlbum::get(&artist.albums, &selection.album),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_sort_key(&self) -> (&ArtistId,) {
|
||||
(&self.key.0,)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -385,20 +390,20 @@ mod tests {
|
||||
|
||||
// Re-initialise.
|
||||
let expected = sel.clone();
|
||||
let active_artist = IdSelectArtist::get(artists, &sel);
|
||||
let active_artist = KeySelectArtist::get(artists, &sel);
|
||||
sel.reinitialise(artists, active_artist);
|
||||
assert_eq!(sel, expected);
|
||||
|
||||
// Re-initialise out-of-bounds.
|
||||
let mut expected = sel.clone();
|
||||
expected.decrement(artists, Delta::Line);
|
||||
let active_artist = IdSelectArtist::get(artists, &sel);
|
||||
let active_artist = KeySelectArtist::get(artists, &sel);
|
||||
sel.reinitialise(&artists[..(artists.len() - 1)], active_artist);
|
||||
assert_eq!(sel, expected);
|
||||
|
||||
// Re-initialise empty.
|
||||
let expected = ArtistSelection::initialise(&[]);
|
||||
let active_artist = IdSelectArtist::get(artists, &sel);
|
||||
let active_artist = KeySelectArtist::get(artists, &sel);
|
||||
sel.reinitialise(&[], active_artist);
|
||||
assert_eq!(sel, expected);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ mod track;
|
||||
use musichoard::collection::{album::Album, artist::Artist, track::Track, Collection};
|
||||
use ratatui::widgets::ListState;
|
||||
|
||||
use artist::{ArtistSelection, IdSelectArtist};
|
||||
use artist::{ArtistSelection, KeySelectArtist};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Category {
|
||||
@ -64,7 +64,7 @@ impl Selection {
|
||||
self.artist.album.track.state.list = selected.track;
|
||||
}
|
||||
|
||||
pub fn select_by_id(&mut self, artists: &[Artist], selected: IdSelection) {
|
||||
pub fn select_by_id(&mut self, artists: &[Artist], selected: KeySelection) {
|
||||
self.artist.reinitialise(artists, selected.artist);
|
||||
}
|
||||
|
||||
@ -229,14 +229,14 @@ impl ListSelection {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IdSelection {
|
||||
artist: Option<IdSelectArtist>,
|
||||
pub struct KeySelection {
|
||||
artist: Option<KeySelectArtist>,
|
||||
}
|
||||
|
||||
impl IdSelection {
|
||||
impl KeySelection {
|
||||
pub fn get(collection: &Collection, selection: &Selection) -> Self {
|
||||
IdSelection {
|
||||
artist: IdSelectArtist::get(collection, &selection.artist),
|
||||
KeySelection {
|
||||
artist: KeySelectArtist::get(collection, &selection.artist),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ impl TrackSelection {
|
||||
selection
|
||||
}
|
||||
|
||||
pub fn reinitialise(&mut self, tracks: &[Track], track: Option<IdSelectTrack>) {
|
||||
pub fn reinitialise(&mut self, tracks: &[Track], track: Option<KeySelectTrack>) {
|
||||
if let Some(track) = track {
|
||||
let result = tracks.binary_search_by(|t| t.get_sort_key().cmp(&track.get_sort_key()));
|
||||
match result {
|
||||
@ -100,16 +100,16 @@ impl TrackSelection {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IdSelectTrack {
|
||||
pub struct KeySelectTrack {
|
||||
key: (TrackNum, TrackId),
|
||||
}
|
||||
|
||||
impl IdSelectTrack {
|
||||
impl KeySelectTrack {
|
||||
pub fn get(tracks: &[Track], selection: &TrackSelection) -> Option<Self> {
|
||||
selection.state.list.selected().map(|index| {
|
||||
let track = &tracks[index];
|
||||
let key = track.get_sort_key();
|
||||
IdSelectTrack {
|
||||
KeySelectTrack {
|
||||
key: (key.0.to_owned(), key.1.to_owned()),
|
||||
}
|
||||
})
|
||||
@ -215,20 +215,20 @@ mod tests {
|
||||
|
||||
// Re-initialise.
|
||||
let expected = sel.clone();
|
||||
let active_track = IdSelectTrack::get(tracks, &sel);
|
||||
let active_track = KeySelectTrack::get(tracks, &sel);
|
||||
sel.reinitialise(tracks, active_track);
|
||||
assert_eq!(sel, expected);
|
||||
|
||||
// Re-initialise out-of-bounds.
|
||||
let mut expected = sel.clone();
|
||||
expected.decrement(tracks, Delta::Line);
|
||||
let active_track = IdSelectTrack::get(tracks, &sel);
|
||||
let active_track = KeySelectTrack::get(tracks, &sel);
|
||||
sel.reinitialise(&tracks[..(tracks.len() - 1)], active_track);
|
||||
assert_eq!(sel, expected);
|
||||
|
||||
// Re-initialise empty.
|
||||
let expected = TrackSelection::initialise(&[]);
|
||||
let active_track = IdSelectTrack::get(tracks, &sel);
|
||||
let active_track = KeySelectTrack::get(tracks, &sel);
|
||||
sel.reinitialise(&[], active_track);
|
||||
assert_eq!(sel, expected);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user