diff --git a/src/tui/app/machine/fetch_state.rs b/src/tui/app/machine/fetch_state.rs index 2993958..9bdad65 100644 --- a/src/tui/app/machine/fetch_state.rs +++ b/src/tui/app/machine/fetch_state.rs @@ -158,7 +158,7 @@ impl AppMachine { ) -> Result<(), FetchError> { let requests = match artist.meta.info.musicbrainz { MbRefOption::Some(ref arid) => { - Self::fetch_albums_requests(&artist.meta.id, &arid, &artist.albums) + Self::fetch_albums_requests(&artist.meta.id, arid, &artist.albums) } MbRefOption::CannotHaveMbid => VecDeque::new(), MbRefOption::None => Self::fetch_artist_request(&artist.meta), diff --git a/src/tui/app/machine/match_state.rs b/src/tui/app/machine/match_state.rs index 6cdf8d3..810e51a 100644 --- a/src/tui/app/machine/match_state.rs +++ b/src/tui/app/machine/match_state.rs @@ -1,8 +1,8 @@ use std::cmp; use musichoard::collection::{ - album::AlbumMeta, - artist::{ArtistId, ArtistMeta}, + album::{AlbumInfo, AlbumMeta}, + artist::{ArtistInfo, ArtistMeta}, musicbrainz::{MbRefOption, Mbid}, }; @@ -12,60 +12,70 @@ use crate::tui::{ AlbumMatches, AppPublicState, AppState, ArtistMatches, IAppInteractMatch, ListOption, MatchOption, MatchStateInfo, MatchStatePublic, WidgetState, }, - lib::{ - interface::musicbrainz::api::{Lookup, Match}, - IMusicHoard, - }, + lib::interface::musicbrainz::api::{Lookup, Match}, }; -macro_rules! item_option_artist_set { +trait GetInfoMeta { + type InfoType; +} +impl GetInfoMeta for ArtistMeta { + type InfoType = ArtistInfo; +} +impl GetInfoMeta for AlbumMeta { + type InfoType = AlbumInfo; +} + +trait GetInfo { + type InfoType; + fn into_info(self, info: Self::InfoType) -> InfoOption; +} + +enum InfoOption { + Info(T), + NeedInput, +} + +macro_rules! impl_match_option_artist_into_info { ($holder:ident) => { - impl MatchOption<$holder> { - fn set( - self, - music_hoard: &mut dyn IMusicHoard, - meta: &ArtistMeta, - ) -> Result<(), musichoard::Error> { - let mut info = meta.info.clone(); + impl GetInfo for MatchOption<$holder> { + type InfoType = ArtistInfo; + + fn into_info(self, mut info: Self::InfoType) -> InfoOption { match self { - MatchOption::Some(m) => info.musicbrainz = m.item.info.musicbrainz, + MatchOption::Some(option) => info.musicbrainz = option.item.info.musicbrainz, MatchOption::CannotHaveMbid => info.musicbrainz = MbRefOption::CannotHaveMbid, - MatchOption::ManualInputMbid => panic!(), + MatchOption::ManualInputMbid => return InfoOption::NeedInput, } - music_hoard.set_artist_info(&meta.id, info) + InfoOption::Info(info) } } }; } -item_option_artist_set!(Lookup); -item_option_artist_set!(Match); +impl_match_option_artist_into_info!(Match); +impl_match_option_artist_into_info!(Lookup); -macro_rules! item_option_album_set { +macro_rules! impl_match_option_album_into_info { ($holder:ident) => { - impl MatchOption<$holder> { - fn set( - self, - music_hoard: &mut dyn IMusicHoard, - artist: &ArtistId, - meta: &AlbumMeta, - ) -> Result<(), musichoard::Error> { - let mut info = meta.info.clone(); + impl GetInfo for MatchOption<$holder> { + type InfoType = AlbumInfo; + + fn into_info(self, mut info: Self::InfoType) -> InfoOption { match self { - MatchOption::Some(m) => info = m.item.info, + MatchOption::Some(option) => info = option.item.info, MatchOption::CannotHaveMbid => info.musicbrainz = MbRefOption::CannotHaveMbid, - MatchOption::ManualInputMbid => panic!(), + MatchOption::ManualInputMbid => return InfoOption::NeedInput, } - music_hoard.set_album_info(artist, &meta.id, info) + InfoOption::Info(info) } } }; } -item_option_album_set!(Lookup); -item_option_album_set!(Match); +impl_match_option_album_into_info!(Match); +impl_match_option_album_into_info!(Lookup); -impl ListOption { +impl ListOption { fn len(&self) -> usize { match self { ListOption::Lookup(list) => list.len(), @@ -86,40 +96,24 @@ impl ListOption { ListOption::Search(list) => list.push(MatchOption::ManualInputMbid), } } - - fn is_manual_input_mbid(&self, index: usize) -> bool { - match self { - ListOption::Lookup(list) => list.get(index) == Some(&MatchOption::ManualInputMbid), - ListOption::Search(list) => list.get(index) == Some(&MatchOption::ManualInputMbid), - } - } } -impl ListOption { - fn set( - self, - music_hoard: &mut dyn IMusicHoard, - meta: &ArtistMeta, - index: usize, - ) -> Result<(), musichoard::Error> { - match self { - ListOption::Lookup(mut list) => list.swap_remove(index).set(music_hoard, meta), - ListOption::Search(mut list) => list.swap_remove(index).set(music_hoard, meta), - } - } +trait ExtractInfo { + type InfoType; + fn extract_info(&mut self, index: usize, info: Self::InfoType) -> InfoOption; } -impl ListOption { - fn set( - self, - music_hoard: &mut dyn IMusicHoard, - artist: &ArtistId, - meta: &AlbumMeta, - index: usize, - ) -> Result<(), musichoard::Error> { +impl ExtractInfo for ListOption +where + MatchOption>: GetInfo, + MatchOption>: GetInfo, +{ + type InfoType = T::InfoType; + + fn extract_info(&mut self, index: usize, info: Self::InfoType) -> InfoOption { match self { - ListOption::Lookup(mut list) => list.swap_remove(index).set(music_hoard, artist, meta), - ListOption::Search(mut list) => list.swap_remove(index).set(music_hoard, artist, meta), + ListOption::Lookup(ref mut list) => list.swap_remove(index).into_info(info), + ListOption::Search(ref mut list) => list.swap_remove(index).into_info(info), } } } @@ -136,14 +130,6 @@ impl ArtistMatches { fn push_manual_input_mbid(&mut self) { self.list.push_manual_input_mbid(); } - - fn is_manual_input_mbid(&self, index: usize) -> bool { - self.list.is_manual_input_mbid(index) - } - - fn set(self, music_hoard: &mut dyn IMusicHoard, index: usize) -> Result<(), musichoard::Error> { - self.list.set(music_hoard, &self.matching, index) - } } impl AlbumMatches { @@ -158,15 +144,6 @@ impl AlbumMatches { fn push_manual_input_mbid(&mut self) { self.list.push_manual_input_mbid(); } - - fn is_manual_input_mbid(&self, index: usize) -> bool { - self.list.is_manual_input_mbid(index) - } - - fn set(self, music_hoard: &mut dyn IMusicHoard, index: usize) -> Result<(), musichoard::Error> { - self.list - .set(music_hoard, &self.artist, &self.matching, index) - } } impl MatchStateInfo { @@ -190,20 +167,6 @@ impl MatchStateInfo { Self::Album(a) => a.push_manual_input_mbid(), } } - - fn is_manual_input_mbid(&self, index: usize) -> bool { - match self { - Self::Artist(a) => a.is_manual_input_mbid(index), - Self::Album(a) => a.is_manual_input_mbid(index), - } - } - - fn set(self, music_hoard: &mut dyn IMusicHoard, index: usize) -> Result<(), musichoard::Error> { - match self { - Self::Artist(a) => a.set(music_hoard, index), - Self::Album(a) => a.set(music_hoard, index), - } - } } pub struct MatchState { @@ -256,6 +219,11 @@ impl AppMachine { } } } + + fn get_input(mut self) -> App { + self.input.replace(Input::default()); + self.into() + } } impl From> for App { @@ -303,23 +271,27 @@ impl IAppInteractMatch for AppMachine { if let Some(index) = self.state.state.list.selected() { // selected() implies current exists - if self - .state - .current - .as_ref() - .unwrap() - .is_manual_input_mbid(index) - { - self.input.replace(Input::default()); - return self.into(); - } + let mh = &mut self.inner.music_hoard; + let result = match self.state.current.as_mut().unwrap() { + MatchStateInfo::Artist(ref mut matches) => { + let info: ArtistInfo = matches.matching.info.clone(); + match matches.list.extract_info(index, info) { + InfoOption::Info(info) => mh.set_artist_info(&matches.matching.id, info), + InfoOption::NeedInput => return self.get_input(), + } + } + MatchStateInfo::Album(matches) => { + let info: AlbumInfo = matches.matching.info.clone(); + match matches.list.extract_info(index, info) { + InfoOption::Info(info) => { + mh.set_album_info(&matches.artist, &matches.matching.id, info) + } + InfoOption::NeedInput => return self.get_input(), + } + } + }; - if let Err(err) = self - .state - .current - .unwrap() - .set(&mut *self.inner.music_hoard, index) - { + if let Err(err) = result { return AppMachine::error_state(self.inner, err.to_string()).into(); } }