Add a "cannot-have-an-mbid" entry to possible matches #208
@ -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<MatchOption<Album>> =
|
||||
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<MatchOption<Album>> =
|
||||
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<MatchOption<Artist>> = matches.into_iter().map(Into::into).collect();
|
||||
matches.push(MatchOption::CannotHaveMbid);
|
||||
let expected = Some(AppMatchesInfo::Artist(AppArtistMatches {
|
||||
matching: artist.clone(),
|
||||
list: matches.clone(),
|
||||
|
@ -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<AppMatches> {
|
||||
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));
|
||||
}
|
||||
(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<AppMatchesInfo>) {
|
||||
fn matches_flow(mut matches_info_vec: Vec<AppMatchesInfo>) {
|
||||
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));
|
||||
|
@ -129,16 +129,28 @@ pub struct AppPublicInner<'app> {
|
||||
pub selection: &'app mut Selection,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum MatchOption<T> {
|
||||
Match(Match<T>),
|
||||
CannotHaveMbid,
|
||||
}
|
||||
|
||||
impl<T> From<Match<T>> for MatchOption<T> {
|
||||
fn from(value: Match<T>) -> Self {
|
||||
MatchOption::Match(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct AppArtistMatches {
|
||||
pub matching: Artist,
|
||||
pub list: Vec<Match<Artist>>,
|
||||
pub list: Vec<MatchOption<Artist>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct AppAlbumMatches {
|
||||
pub matching: Album,
|
||||
pub list: Vec<Match<Album>>,
|
||||
pub list: Vec<MatchOption<Album>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
@ -148,11 +160,13 @@ pub enum AppMatchesInfo {
|
||||
}
|
||||
|
||||
impl AppMatchesInfo {
|
||||
pub fn artist(matching: Artist, list: Vec<Match<Artist>>) -> Self {
|
||||
pub fn artist<M: Into<MatchOption<Artist>>>(matching: Artist, list: Vec<M>) -> Self {
|
||||
let list: Vec<MatchOption<Artist>> = list.into_iter().map(Into::into).collect();
|
||||
AppMatchesInfo::Artist(AppArtistMatches { matching, list })
|
||||
}
|
||||
|
||||
pub fn album(matching: Album, list: Vec<Match<Album>>) -> Self {
|
||||
pub fn album<M: Into<MatchOption<Album>>>(matching: Album, list: Vec<M>) -> Self {
|
||||
let list: Vec<MatchOption<Album>> = list.into_iter().map(Into::into).collect();
|
||||
AppMatchesInfo::Album(AppAlbumMatches { matching, list })
|
||||
}
|
||||
}
|
||||
|
@ -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,8 +124,9 @@ impl UiDisplay {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_artist_match(match_artist: &Match<Artist>) -> String {
|
||||
format!(
|
||||
pub fn display_artist_match(match_option: &MatchOption<Artist>) -> String {
|
||||
match match_option {
|
||||
MatchOption::Match(match_artist) => format!(
|
||||
"{}{} ({}%)",
|
||||
&match_artist.item.id.name,
|
||||
&match_artist
|
||||
@ -134,11 +135,14 @@ impl UiDisplay {
|
||||
.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<Album>) -> String {
|
||||
format!(
|
||||
pub fn display_album_match(match_option: &MatchOption<Album>) -> String {
|
||||
match match_option {
|
||||
MatchOption::Match(match_album) => format!(
|
||||
"{:010} | {} [{}] ({}%)",
|
||||
UiDisplay::display_album_date(&match_album.item.date),
|
||||
&match_album.item.id.title,
|
||||
@ -147,7 +151,13 @@ impl UiDisplay {
|
||||
&match_album.item.secondary_types
|
||||
),
|
||||
match_album.score,
|
||||
)
|
||||
),
|
||||
MatchOption::CannotHaveMbid => Self::display_cannot_have_mbid().to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn display_cannot_have_mbid() -> &'static str {
|
||||
"-- Cannot have a MusicBrainz Identifier --"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<Artist>], state: &'b mut WidgetState) -> Self {
|
||||
fn artists(
|
||||
matching: &Artist,
|
||||
matches: &[MatchOption<Artist>],
|
||||
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<Album>], state: &'b mut WidgetState) -> Self {
|
||||
fn albums(
|
||||
matching: &Album,
|
||||
matches: &[MatchOption<Album>],
|
||||
state: &'b mut WidgetState,
|
||||
) -> Self {
|
||||
let matching = UiDisplay::display_album_matching(matching);
|
||||
|
||||
let list = List::new(
|
||||
|
@ -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<Match<Artist>>) -> AppMatchesInfo {
|
||||
let mut list: Vec<MatchOption<Artist>> = list.into_iter().map(Into::into).collect();
|
||||
list.push(MatchOption::CannotHaveMbid);
|
||||
AppMatchesInfo::artist(matching, list)
|
||||
}
|
||||
|
||||
fn album_matches(matching: Album, list: Vec<Match<Album>>) -> AppMatchesInfo {
|
||||
let mut list: Vec<MatchOption<Album>> = list.into_iter().map(Into::into).collect();
|
||||
list.push(MatchOption::CannotHaveMbid);
|
||||
AppMatchesInfo::album(matching, list)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user