From 73aab07d9b5af2aaf9debb8ea52e44172120f8cd Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Sun, 6 Oct 2024 20:01:09 +0200 Subject: [PATCH] Works --- src/core/collection/album.rs | 4 +- src/core/musichoard/base.rs | 5 +++ src/core/musichoard/database.rs | 58 ++++++++++++++++++++++++++--- src/tui/app/machine/fetch_state.rs | 59 ++++++++++++++++++++++++++++-- src/tui/lib/mod.rs | 16 +++++++- 5 files changed, 132 insertions(+), 10 deletions(-) diff --git a/src/core/collection/album.rs b/src/core/collection/album.rs index 27c171e..fdccb1f 100644 --- a/src/core/collection/album.rs +++ b/src/core/collection/album.rs @@ -258,7 +258,9 @@ impl Merge for AlbumInfo { fn merge_in_place(&mut self, other: Self) { self.musicbrainz = self.musicbrainz.take().or(other.musicbrainz); self.primary_type = self.primary_type.take().or(other.primary_type); - self.secondary_types.merge_in_place(other.secondary_types); + if self.secondary_types.is_empty() { + self.secondary_types = other.secondary_types; + } } } diff --git a/src/core/musichoard/base.rs b/src/core/musichoard/base.rs index 22f0d4d..71496e9 100644 --- a/src/core/musichoard/base.rs +++ b/src/core/musichoard/base.rs @@ -34,6 +34,7 @@ pub trait IMusicHoardBasePrivate { artist_id: &ArtistId, ) -> Result<&'a mut Artist, Error>; + fn get_album<'a>(artist: &'a mut Artist, album_id: &AlbumId) -> Option<&'a Album>; fn get_album_mut<'a>(artist: &'a mut Artist, album_id: &AlbumId) -> Option<&'a mut Album>; fn get_album_mut_or_err<'a>( artist: &'a mut Artist, @@ -79,6 +80,10 @@ impl IMusicHoardBasePrivate for MusicHoard }) } + fn get_album<'a>(artist: &'a mut Artist, album_id: &AlbumId) -> Option<&'a Album> { + artist.albums.iter().find(|a| &a.meta.id == album_id) + } + fn get_album_mut<'a>(artist: &'a mut Artist, album_id: &AlbumId) -> Option<&'a mut Album> { artist.albums.iter_mut().find(|a| &a.meta.id == album_id) } diff --git a/src/core/musichoard/database.rs b/src/core/musichoard/database.rs index 606c54d..9e95ab1 100644 --- a/src/core/musichoard/database.rs +++ b/src/core/musichoard/database.rs @@ -1,7 +1,11 @@ use std::mem; use crate::{ - collection::{album::AlbumInfo, artist::ArtistInfo, merge::Merge}, + collection::{ + album::{AlbumInfo, AlbumMeta}, + artist::ArtistInfo, + merge::Merge, + }, core::{ collection::{ album::{Album, AlbumId, AlbumSeq}, @@ -57,6 +61,17 @@ pub trait IMusicHoardDatabase { property: S, ) -> Result<(), Error>; + fn add_album>( + &mut self, + artist_id: ArtistIdRef, + album_meta: AlbumMeta, + ) -> Result<(), Error>; + fn remove_album, AlbumIdRef: AsRef>( + &mut self, + artist_id: ArtistIdRef, + album_id: AlbumIdRef, + ) -> Result<(), Error>; + fn set_album_seq, AlbumIdRef: AsRef>( &mut self, artist_id: ArtistIdRef, @@ -68,15 +83,15 @@ pub trait IMusicHoardDatabase { artist_id: ArtistIdRef, album_id: AlbumIdRef, ) -> Result<(), Error>; - fn merge_album_info, AlbumIdRef: AsRef>( + fn merge_album_info, AlbumIdRef: AsRef>( &mut self, - artist_id: Id, + artist_id: ArtistIdRef, album_id: AlbumIdRef, info: AlbumInfo, ) -> Result<(), Error>; - fn clear_album_info, AlbumIdRef: AsRef>( + fn clear_album_info, AlbumIdRef: AsRef>( &mut self, - artist_id: Id, + artist_id: ArtistIdRef, album_id: AlbumIdRef, ) -> Result<(), Error>; } @@ -194,6 +209,39 @@ impl IMusicHoardDatabase for MusicHoard>( + &mut self, + artist_id: ArtistIdRef, + album_meta: AlbumMeta, + ) -> Result<(), Error> { + let album = Album { + meta: album_meta, + tracks: vec![], + }; + self.update_artist(artist_id.as_ref(), |artist| { + if Self::get_album(artist, &album.meta.id).is_none() { + artist.albums.push(album); + artist.albums.sort_unstable(); + } + }) + } + + fn remove_album, AlbumIdRef: AsRef>( + &mut self, + artist_id: ArtistIdRef, + album_id: AlbumIdRef, + ) -> Result<(), Error> { + self.update_artist(artist_id.as_ref(), |artist| { + let index_opt = artist + .albums + .iter() + .position(|a| &a.meta.id == album_id.as_ref()); + if let Some(index) = index_opt { + artist.albums.remove(index); + } + }) + } + fn set_album_seq, AlbumIdRef: AsRef>( &mut self, artist_id: ArtistIdRef, diff --git a/src/tui/app/machine/fetch_state.rs b/src/tui/app/machine/fetch_state.rs index b08a96f..1015d44 100644 --- a/src/tui/app/machine/fetch_state.rs +++ b/src/tui/app/machine/fetch_state.rs @@ -13,10 +13,12 @@ use musichoard::collection::{ use crate::tui::{ app::{ machine::{match_state::MatchState, App, AppInner, AppMachine}, + selection::KeySelection, AppPublicState, AppState, Category, IAppEventFetch, IAppInteractFetch, }, lib::interface::musicbrainz::daemon::{ - Error as DaemonError, IMbJobSender, MbApiResult, MbParams, MbReturn, ResultSender, + EntityList, Error as DaemonError, IMbJobSender, MbApiResult, MbParams, MbReturn, + ResultSender, }, }; @@ -139,14 +141,19 @@ impl AppMachine { Ok(requests) } - pub fn app_fetch_next(inner: AppInner, mut fetch: FetchState) -> App { + pub fn app_fetch_next(mut inner: AppInner, mut fetch: FetchState) -> App { loop { let app: App = match fetch.try_recv() { Ok(fetch_result) => match fetch_result { Ok(MbReturn::Match(next_match)) => { AppMachine::match_state(inner, MatchState::new(next_match, fetch)).into() } - Ok(MbReturn::Fetch(_)) => continue, + Ok(MbReturn::Fetch(list)) => { + match Self::apply_fetch_results(&mut inner, list) { + Ok(()) => continue, + Err(err) => AppMachine::error_state(inner, err.to_string()).into(), + } + } Err(fetch_err) => { AppMachine::error_state(inner, format!("fetch failed: {fetch_err}")).into() } @@ -164,6 +171,52 @@ impl AppMachine { } } + fn apply_fetch_results( + inner: &mut AppInner, + list: EntityList, + ) -> Result<(), musichoard::Error> { + match list { + EntityList::Album(new_albums) => { + let coll = inner.music_hoard.get_collection(); + let artist_state = inner.selection.state_artist(coll).unwrap(); + + let artist = &coll[artist_state.index]; + let artist_id = &coll[artist_state.index].meta.id.clone(); + let old_albums = &artist.albums; + + let mut to_be_added = vec![]; + for new in new_albums.into_iter() { + let mut exists = false; + for old in old_albums.iter() { + if matches!(old.meta.info.musicbrainz, MbRefOption::Some(_)) { + if new.info.musicbrainz == old.meta.info.musicbrainz { + exists = true; + break; + } + } + } + + if !exists { + to_be_added.push(new); + } + } + + let previous = + KeySelection::get(inner.music_hoard.get_collection(), &inner.selection); + + for new in to_be_added.into_iter() { + inner.music_hoard.add_album(&artist_id, new)?; + } + + inner + .selection + .select_by_id(inner.music_hoard.get_collection(), previous); + + Ok(()) + } + } + } + pub fn app_lookup_artist( inner: AppInner, fetch: FetchState, diff --git a/src/tui/lib/mod.rs b/src/tui/lib/mod.rs index 59cfd41..7470a3a 100644 --- a/src/tui/lib/mod.rs +++ b/src/tui/lib/mod.rs @@ -3,7 +3,7 @@ pub mod interface; use musichoard::{ collection::{ - album::{AlbumId, AlbumInfo}, + album::{AlbumId, AlbumInfo, AlbumMeta}, artist::{ArtistId, ArtistInfo}, Collection, }, @@ -20,6 +20,12 @@ pub trait IMusicHoard { fn reload_database(&mut self) -> Result<(), musichoard::Error>; fn get_collection(&self) -> &Collection; + fn add_album( + &mut self, + artist_id: &ArtistId, + album_meta: AlbumMeta, + ) -> Result<(), musichoard::Error>; + fn merge_artist_info( &mut self, id: &ArtistId, @@ -47,6 +53,14 @@ impl IMusicHoard for MusicHoard::get_collection(self) } + fn add_album( + &mut self, + artist_id: &ArtistId, + album_meta: AlbumMeta, + ) -> Result<(), musichoard::Error> { + ::add_album(self, artist_id, album_meta) + } + fn merge_artist_info( &mut self, id: &ArtistId,