diff --git a/src/tui/app/machine/browse.rs b/src/tui/app/machine/browse.rs index 6157aa9..951d430 100644 --- a/src/tui/app/machine/browse.rs +++ b/src/tui/app/machine/browse.rs @@ -140,7 +140,7 @@ mod tests { app::{ machine::tests::{inner, inner_with_mb, music_hoard}, AppAlbumMatches, AppArtistMatches, AppMatchesInfo, Category, IAppAccess, IAppInteract, - IAppInteractMatches, + IAppInteractMatches, MatchOption, }, lib::interface::musicbrainz::{self, Match, MockIMusicBrainz}, testmod::COLLECTION, @@ -263,6 +263,9 @@ mod tests { let public_matches = public.state.unwrap_matches(); + let mut matches_1: Vec> = + matches_1.into_iter().map(Into::into).collect(); + matches_1.push(MatchOption::CannotHaveMbid); let expected = Some(AppMatchesInfo::Album(AppAlbumMatches { matching: album_1.clone(), list: matches_1.clone(), @@ -276,6 +279,9 @@ mod tests { let public_matches = public.state.unwrap_matches(); + let mut matches_4: Vec> = + matches_4.into_iter().map(Into::into).collect(); + matches_4.push(MatchOption::CannotHaveMbid); let expected = Some(AppMatchesInfo::Album(AppAlbumMatches { matching: album_4.clone(), list: matches_4.clone(), @@ -324,6 +330,8 @@ mod tests { let public_matches = public.state.unwrap_matches(); + let mut matches: Vec> = matches.into_iter().map(Into::into).collect(); + matches.push(MatchOption::CannotHaveMbid); let expected = Some(AppMatchesInfo::Artist(AppArtistMatches { matching: artist.clone(), list: matches.clone(), diff --git a/src/tui/app/machine/matches.rs b/src/tui/app/machine/matches.rs index 56f32d6..adeaea8 100644 --- a/src/tui/app/machine/matches.rs +++ b/src/tui/app/machine/matches.rs @@ -3,43 +3,43 @@ use std::{cmp, sync::mpsc}; use crate::tui::app::{ machine::{App, AppInner, AppMachine}, AppAlbumMatches, AppArtistMatches, AppMatchesInfo, AppPublic, AppPublicMatches, AppState, - IAppInteractMatches, WidgetState, + IAppInteractMatches, MatchOption, WidgetState, }; impl AppArtistMatches { - fn is_empty(&self) -> bool { - self.list.is_empty() - } - fn len(&self) -> usize { self.list.len() } + + fn push_cannot_have_mbid(&mut self) { + self.list.push(MatchOption::CannotHaveMbid) + } } impl AppAlbumMatches { - fn is_empty(&self) -> bool { - self.list.is_empty() - } - fn len(&self) -> usize { self.list.len() } + + fn push_cannot_have_mbid(&mut self) { + self.list.push(MatchOption::CannotHaveMbid) + } } impl AppMatchesInfo { - fn is_empty(&self) -> bool { - match self { - Self::Artist(a) => a.is_empty(), - Self::Album(a) => a.is_empty(), - } - } - fn len(&self) -> usize { match self { Self::Artist(a) => a.len(), Self::Album(a) => a.len(), } } + + fn push_cannot_have_mbid(&mut self) { + match self { + Self::Artist(a) => a.push_cannot_have_mbid(), + Self::Album(a) => a.push_cannot_have_mbid(), + } + } } pub struct AppMatches { @@ -107,13 +107,7 @@ impl IAppInteractMatches for AppMachine { fn select(mut self) -> Self::APP { self.state.next_matches_info(); match self.state.current { - Some(ref matches_info) => { - self.state.state = WidgetState::default(); - if !matches_info.is_empty() { - self.state.state.list.select(Some(0)); - } - self.into() - } + Some(_) => self.into(), None => AppMachine::browse(self.inner).into(), } } @@ -135,11 +129,10 @@ impl IAppInteractMatchesPrivate for AppMatches { fn next_matches_info(&mut self) { // FIXME: try_recv might not be appropriate for asynchronous version. (self.current, self.state) = match self.matches_rx.try_recv() { - Ok(next_match) => { + Ok(mut next_match) => { + next_match.push_cannot_have_mbid(); let mut state = WidgetState::default(); - if !next_match.is_empty() { - state.list.select(Some(0)); - } + state.list.select(Some(0)); (Some(next_match), state) } Err(_) => (None, WidgetState::default()), @@ -232,6 +225,12 @@ mod tests { rx } + fn push_cannot_have_mbid(matches_info_vec: &mut [AppMatchesInfo]) { + for matches_info in matches_info_vec.iter_mut() { + matches_info.push_cannot_have_mbid(); + } + } + #[test] fn create_empty() { let matches = AppMachine::matches(inner(music_hoard(vec![])), receiver(vec![])); @@ -251,11 +250,12 @@ mod tests { #[test] fn create_nonempty() { - let matches_info_vec = album_matches_info_vec(); + let mut matches_info_vec = album_matches_info_vec(); let matches = AppMachine::matches( inner(music_hoard(vec![])), receiver(matches_info_vec.clone()), ); + push_cannot_have_mbid(&mut matches_info_vec); let mut widget_state = WidgetState::default(); widget_state.list.select(Some(0)); @@ -271,11 +271,12 @@ mod tests { assert_eq!(public_matches.state, &widget_state); } - fn matches_flow(matches_info_vec: Vec) { + fn matches_flow(mut matches_info_vec: Vec) { let matches = AppMachine::matches( inner(music_hoard(vec![])), receiver(matches_info_vec.clone()), ); + push_cannot_have_mbid(&mut matches_info_vec); let mut widget_state = WidgetState::default(); widget_state.list.select(Some(0)); @@ -293,10 +294,16 @@ mod tests { assert_eq!(matches.state.current.as_ref(), Some(&matches_info_vec[0])); assert_eq!(matches.state.state.list.selected(), Some(1)); + // Next is CannotHaveMBID let matches = matches.next_match().unwrap_matches(); assert_eq!(matches.state.current.as_ref(), Some(&matches_info_vec[0])); - assert_eq!(matches.state.state.list.selected(), Some(1)); + assert_eq!(matches.state.state.list.selected(), Some(2)); + + let matches = matches.next_match().unwrap_matches(); + + assert_eq!(matches.state.current.as_ref(), Some(&matches_info_vec[0])); + assert_eq!(matches.state.state.list.selected(), Some(2)); let matches = matches.select().unwrap_matches(); @@ -319,11 +326,12 @@ mod tests { #[test] fn matches_abort() { - let matches_info_vec = album_matches_info_vec(); + let mut matches_info_vec = album_matches_info_vec(); let matches = AppMachine::matches( inner(music_hoard(vec![])), receiver(matches_info_vec.clone()), ); + push_cannot_have_mbid(&mut matches_info_vec); let mut widget_state = WidgetState::default(); widget_state.list.select(Some(0)); diff --git a/src/tui/app/mod.rs b/src/tui/app/mod.rs index 6b4d4a3..3279b17 100644 --- a/src/tui/app/mod.rs +++ b/src/tui/app/mod.rs @@ -129,16 +129,28 @@ pub struct AppPublicInner<'app> { pub selection: &'app mut Selection, } +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum MatchOption { + Match(Match), + CannotHaveMbid, +} + +impl From> for MatchOption { + fn from(value: Match) -> Self { + MatchOption::Match(value) + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct AppArtistMatches { pub matching: Artist, - pub list: Vec>, + pub list: Vec>, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct AppAlbumMatches { pub matching: Album, - pub list: Vec>, + pub list: Vec>, } #[derive(Clone, Debug, PartialEq, Eq)] @@ -148,11 +160,13 @@ pub enum AppMatchesInfo { } impl AppMatchesInfo { - pub fn artist(matching: Artist, list: Vec>) -> Self { + pub fn artist>>(matching: Artist, list: Vec) -> Self { + let list: Vec> = list.into_iter().map(Into::into).collect(); AppMatchesInfo::Artist(AppArtistMatches { matching, list }) } - pub fn album(matching: Album, list: Vec>) -> Self { + pub fn album>>(matching: Album, list: Vec) -> Self { + let list: Vec> = list.into_iter().map(Into::into).collect(); AppMatchesInfo::Album(AppAlbumMatches { matching, list }) } } diff --git a/src/tui/ui/display.rs b/src/tui/ui/display.rs index eb5b847..78f0927 100644 --- a/src/tui/ui/display.rs +++ b/src/tui/ui/display.rs @@ -4,7 +4,7 @@ use musichoard::collection::{ track::{TrackFormat, TrackQuality}, }; -use crate::tui::{app::AppMatchesInfo, lib::interface::musicbrainz::Match}; +use crate::tui::app::{AppMatchesInfo, MatchOption}; pub struct UiDisplay; @@ -124,30 +124,40 @@ impl UiDisplay { } } - pub fn display_artist_match(match_artist: &Match) -> String { - format!( - "{}{} ({}%)", - &match_artist.item.id.name, - &match_artist - .disambiguation - .as_ref() - .map(|d| format!(" ({d})")) - .unwrap_or_default(), - match_artist.score, - ) + pub fn display_artist_match(match_option: &MatchOption) -> String { + match match_option { + MatchOption::Match(match_artist) => format!( + "{}{} ({}%)", + &match_artist.item.id.name, + &match_artist + .disambiguation + .as_ref() + .map(|d| format!(" ({d})")) + .unwrap_or_default(), + match_artist.score, + ), + MatchOption::CannotHaveMbid => Self::display_cannot_have_mbid().to_string(), + } } - pub fn display_album_match(match_album: &Match) -> String { - format!( - "{:010} | {} [{}] ({}%)", - UiDisplay::display_album_date(&match_album.item.date), - &match_album.item.id.title, - UiDisplay::display_type( - &match_album.item.primary_type, - &match_album.item.secondary_types + pub fn display_album_match(match_option: &MatchOption) -> String { + match match_option { + MatchOption::Match(match_album) => format!( + "{:010} | {} [{}] ({}%)", + UiDisplay::display_album_date(&match_album.item.date), + &match_album.item.id.title, + UiDisplay::display_type( + &match_album.item.primary_type, + &match_album.item.secondary_types + ), + match_album.score, ), - match_album.score, - ) + MatchOption::CannotHaveMbid => Self::display_cannot_have_mbid().to_string(), + } + } + + fn display_cannot_have_mbid() -> &'static str { + "-- Cannot have a MusicBrainz Identifier --" } } diff --git a/src/tui/ui/matches.rs b/src/tui/ui/matches.rs index 41603b0..91bd158 100644 --- a/src/tui/ui/matches.rs +++ b/src/tui/ui/matches.rs @@ -2,8 +2,7 @@ use musichoard::collection::{album::Album, artist::Artist}; use ratatui::widgets::{List, ListItem}; use crate::tui::{ - app::{AppMatchesInfo, WidgetState}, - lib::interface::musicbrainz::Match, + app::{AppMatchesInfo, MatchOption, WidgetState}, ui::display::UiDisplay, }; @@ -32,7 +31,11 @@ impl<'a, 'b> MatchesState<'a, 'b> { } } - fn artists(matching: &Artist, matches: &[Match], state: &'b mut WidgetState) -> Self { + fn artists( + matching: &Artist, + matches: &[MatchOption], + state: &'b mut WidgetState, + ) -> Self { let matching = UiDisplay::display_artist_matching(matching); let list = List::new( @@ -50,7 +53,11 @@ impl<'a, 'b> MatchesState<'a, 'b> { } } - fn albums(matching: &Album, matches: &[Match], state: &'b mut WidgetState) -> Self { + fn albums( + matching: &Album, + matches: &[MatchOption], + state: &'b mut WidgetState, + ) -> Self { let matching = UiDisplay::display_album_matching(matching); let list = List::new( diff --git a/src/tui/ui/mod.rs b/src/tui/ui/mod.rs index 7231d8d..8e5fa70 100644 --- a/src/tui/ui/mod.rs +++ b/src/tui/ui/mod.rs @@ -182,7 +182,7 @@ mod tests { }; use crate::tui::{ - app::{AppPublic, AppPublicInner, AppPublicMatches, Delta}, + app::{AppPublic, AppPublicInner, AppPublicMatches, Delta, MatchOption}, lib::interface::musicbrainz::Match, testmod::COLLECTION, tests::terminal, @@ -225,10 +225,14 @@ mod tests { } fn artist_matches(matching: Artist, list: Vec>) -> AppMatchesInfo { + let mut list: Vec> = list.into_iter().map(Into::into).collect(); + list.push(MatchOption::CannotHaveMbid); AppMatchesInfo::artist(matching, list) } fn album_matches(matching: Album, list: Vec>) -> AppMatchesInfo { + let mut list: Vec> = list.into_iter().map(Into::into).collect(); + list.push(MatchOption::CannotHaveMbid); AppMatchesInfo::album(matching, list) }