Compare commits
3 Commits
898d2e1469
...
b01af5ff18
Author | SHA1 | Date | |
---|---|---|---|
b01af5ff18 | |||
b51fa34935 | |||
46d38d9274 |
@ -72,7 +72,7 @@ fn main() {
|
|||||||
println!("Release groups in this response: {count}");
|
println!("Release groups in this response: {count}");
|
||||||
|
|
||||||
match response.page.next_page_offset(count) {
|
match response.page.next_page_offset(count) {
|
||||||
NextPage::Offset(next_offset) => paging.with_offset(next_offset),
|
NextPage::Offset(next_offset) => paging.set_offset(next_offset),
|
||||||
NextPage::Complete => break,
|
NextPage::Complete => break,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
src/external/musicbrainz/api/mod.rs
vendored
17
src/external/musicbrainz/api/mod.rs
vendored
@ -61,7 +61,7 @@ impl<Http> MusicBrainzClient<Http> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct PageSettings {
|
pub struct PageSettings {
|
||||||
limit: Option<usize>,
|
limit: Option<usize>,
|
||||||
offset: Option<usize>,
|
offset: Option<usize>,
|
||||||
@ -79,7 +79,12 @@ impl PageSettings {
|
|||||||
Self::with_limit(MB_MAX_PAGE_LIMIT)
|
Self::with_limit(MB_MAX_PAGE_LIMIT)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_offset(&mut self, offset: usize) {
|
pub fn with_offset(mut self, offset: usize) -> Self {
|
||||||
|
self.offset = Some(offset);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_offset(&mut self, offset: usize) {
|
||||||
self.offset = Some(offset);
|
self.offset = Some(offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,6 +96,10 @@ pub enum NextPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NextPage {
|
impl NextPage {
|
||||||
|
pub fn new() -> NextPage {
|
||||||
|
NextPage::Offset(0)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn next_page_offset(offset: usize, total_count: usize, page_count: usize) -> NextPage {
|
pub fn next_page_offset(offset: usize, total_count: usize, page_count: usize) -> NextPage {
|
||||||
let next_offset = offset + page_count;
|
let next_offset = offset + page_count;
|
||||||
if next_offset < total_count {
|
if next_offset < total_count {
|
||||||
@ -387,14 +396,14 @@ mod tests {
|
|||||||
assert_eq!(ApiDisplay::format_page_settings(&paging), "&limit=100");
|
assert_eq!(ApiDisplay::format_page_settings(&paging), "&limit=100");
|
||||||
|
|
||||||
let mut paging = PageSettings::with_limit(45);
|
let mut paging = PageSettings::with_limit(45);
|
||||||
paging.with_offset(145);
|
paging.set_offset(145);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ApiDisplay::format_page_settings(&paging),
|
ApiDisplay::format_page_settings(&paging),
|
||||||
"&limit=45&offset=145"
|
"&limit=45&offset=145"
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut paging = PageSettings::default();
|
let mut paging = PageSettings::default();
|
||||||
paging.with_offset(26);
|
paging.set_offset(26);
|
||||||
assert_eq!(ApiDisplay::format_page_settings(&paging), "&offset=26");
|
assert_eq!(ApiDisplay::format_page_settings(&paging), "&offset=26");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ use crate::tui::{
|
|||||||
AppPublicState, AppState, Category, IAppEventFetch, IAppInteractFetch,
|
AppPublicState, AppState, Category, IAppEventFetch, IAppInteractFetch,
|
||||||
},
|
},
|
||||||
lib::interface::musicbrainz::daemon::{
|
lib::interface::musicbrainz::daemon::{
|
||||||
Error as DaemonError, IMbJobSender, MbApiResult, MbParams, ResultSender,
|
Error as DaemonError, IMbJobSender, MbApiResult, MbParams, MbReturn, ResultSender,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -116,9 +116,7 @@ impl AppMachine<FetchState> {
|
|||||||
pub fn app_fetch_next(inner: AppInner, mut fetch: FetchState) -> App {
|
pub fn app_fetch_next(inner: AppInner, mut fetch: FetchState) -> App {
|
||||||
match fetch.try_recv() {
|
match fetch.try_recv() {
|
||||||
Ok(fetch_result) => match fetch_result {
|
Ok(fetch_result) => match fetch_result {
|
||||||
Ok(next_match) => {
|
Ok(retval) => Self::handle_mb_api_return(inner, fetch, retval),
|
||||||
AppMachine::match_state(inner, MatchState::new(next_match, fetch)).into()
|
|
||||||
}
|
|
||||||
Err(fetch_err) => {
|
Err(fetch_err) => {
|
||||||
AppMachine::error_state(inner, format!("fetch failed: {fetch_err}")).into()
|
AppMachine::error_state(inner, format!("fetch failed: {fetch_err}")).into()
|
||||||
}
|
}
|
||||||
@ -130,6 +128,15 @@ impl AppMachine<FetchState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_mb_api_return(inner: AppInner, fetch: FetchState, retval: MbReturn) -> App {
|
||||||
|
match retval {
|
||||||
|
MbReturn::Match(next_match) => {
|
||||||
|
AppMachine::match_state(inner, MatchState::new(next_match, fetch)).into()
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn app_lookup_artist(
|
pub fn app_lookup_artist(
|
||||||
inner: AppInner,
|
inner: AppInner,
|
||||||
fetch: FetchState,
|
fetch: FetchState,
|
||||||
@ -288,7 +295,7 @@ mod tests {
|
|||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::{
|
app::{
|
||||||
machine::tests::{inner, music_hoard},
|
machine::tests::{inner, music_hoard},
|
||||||
Delta, IApp, IAppAccess, IAppInteractBrowse, MatchOption, MatchStateInfo,
|
Delta, EntityMatches, IApp, IAppAccess, IAppInteractBrowse, MatchOption,
|
||||||
},
|
},
|
||||||
lib::interface::musicbrainz::{self, api::Entity, daemon::MockIMbJobSender},
|
lib::interface::musicbrainz::{self, api::Entity, daemon::MockIMbJobSender},
|
||||||
testmod::COLLECTION,
|
testmod::COLLECTION,
|
||||||
@ -311,13 +318,13 @@ mod tests {
|
|||||||
let artist = COLLECTION[3].meta.clone();
|
let artist = COLLECTION[3].meta.clone();
|
||||||
|
|
||||||
let matches: Vec<Entity<ArtistMeta>> = vec![];
|
let matches: Vec<Entity<ArtistMeta>> = vec![];
|
||||||
let fetch_result = MatchStateInfo::artist_search(artist.clone(), matches);
|
let fetch_result = MbReturn::Match(EntityMatches::artist_search(artist.clone(), matches));
|
||||||
fetch_tx.send(Ok(fetch_result.clone())).unwrap();
|
fetch_tx.send(Ok(fetch_result.clone())).unwrap();
|
||||||
|
|
||||||
assert_eq!(fetch.try_recv(), Err(TryRecvError::Empty));
|
assert_eq!(fetch.try_recv(), Err(TryRecvError::Empty));
|
||||||
|
|
||||||
let lookup = Entity::new(artist.clone());
|
let lookup = Entity::new(artist.clone());
|
||||||
let lookup_result = MatchStateInfo::artist_lookup(artist.clone(), lookup);
|
let lookup_result = MbReturn::Match(EntityMatches::artist_lookup(artist.clone(), lookup));
|
||||||
lookup_tx.send(Ok(lookup_result.clone())).unwrap();
|
lookup_tx.send(Ok(lookup_result.clone())).unwrap();
|
||||||
|
|
||||||
assert_eq!(fetch.try_recv(), Ok(Ok(lookup_result)));
|
assert_eq!(fetch.try_recv(), Ok(Ok(lookup_result)));
|
||||||
@ -603,8 +610,8 @@ mod tests {
|
|||||||
let artist = COLLECTION[3].meta.clone();
|
let artist = COLLECTION[3].meta.clone();
|
||||||
let artist_match = Entity::with_score(COLLECTION[2].meta.clone(), 80);
|
let artist_match = Entity::with_score(COLLECTION[2].meta.clone(), 80);
|
||||||
let artist_match_info =
|
let artist_match_info =
|
||||||
MatchStateInfo::artist_search(artist.clone(), vec![artist_match.clone()]);
|
EntityMatches::artist_search(artist.clone(), vec![artist_match.clone()]);
|
||||||
let fetch_result = Ok(artist_match_info);
|
let fetch_result = Ok(MbReturn::Match(artist_match_info));
|
||||||
tx.send(fetch_result).unwrap();
|
tx.send(fetch_result).unwrap();
|
||||||
|
|
||||||
let inner = inner(music_hoard(COLLECTION.clone()));
|
let inner = inner(music_hoard(COLLECTION.clone()));
|
||||||
@ -619,8 +626,8 @@ mod tests {
|
|||||||
MatchOption::CannotHaveMbid,
|
MatchOption::CannotHaveMbid,
|
||||||
MatchOption::ManualInputMbid,
|
MatchOption::ManualInputMbid,
|
||||||
];
|
];
|
||||||
let expected = MatchStateInfo::artist_search(artist, match_options);
|
let expected = EntityMatches::artist_search(artist, match_options);
|
||||||
assert_eq!(match_state.info, &expected);
|
assert_eq!(match_state.matches, &expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -677,8 +684,8 @@ mod tests {
|
|||||||
assert!(matches!(app, AppState::Fetch(_)));
|
assert!(matches!(app, AppState::Fetch(_)));
|
||||||
|
|
||||||
let artist = COLLECTION[3].meta.clone();
|
let artist = COLLECTION[3].meta.clone();
|
||||||
let match_info = MatchStateInfo::artist_search::<Entity<ArtistMeta>>(artist, vec![]);
|
let match_info = EntityMatches::artist_search::<Entity<ArtistMeta>>(artist, vec![]);
|
||||||
let fetch_result = Ok(match_info);
|
let fetch_result = Ok(MbReturn::Match(match_info));
|
||||||
tx.send(fetch_result).unwrap();
|
tx.send(fetch_result).unwrap();
|
||||||
|
|
||||||
let app = app.unwrap_fetch().fetch_result_ready();
|
let app = app.unwrap_fetch().fetch_result_ready();
|
||||||
|
@ -8,8 +8,8 @@ use musichoard::collection::{
|
|||||||
|
|
||||||
use crate::tui::app::{
|
use crate::tui::app::{
|
||||||
machine::{fetch_state::FetchState, input::Input, App, AppInner, AppMachine},
|
machine::{fetch_state::FetchState, input::Input, App, AppInner, AppMachine},
|
||||||
AlbumMatches, AppPublicState, AppState, ArtistMatches, Delta, IAppInteractMatch, MatchOption,
|
AlbumMatches, AppPublicState, AppState, ArtistMatches, Delta, EntityMatches, IAppInteractMatch,
|
||||||
MatchStateInfo, MatchStatePublic, WidgetState,
|
MatchOption, MatchStatePublic, WidgetState,
|
||||||
};
|
};
|
||||||
|
|
||||||
trait GetInfoMeta {
|
trait GetInfoMeta {
|
||||||
@ -103,7 +103,7 @@ impl AlbumMatches {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MatchStateInfo {
|
impl EntityMatches {
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Self::Artist(a) => a.len(),
|
Self::Artist(a) => a.len(),
|
||||||
@ -127,13 +127,13 @@ impl MatchStateInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct MatchState {
|
pub struct MatchState {
|
||||||
current: MatchStateInfo,
|
current: EntityMatches,
|
||||||
state: WidgetState,
|
state: WidgetState,
|
||||||
fetch: FetchState,
|
fetch: FetchState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MatchState {
|
impl MatchState {
|
||||||
pub fn new(mut current: MatchStateInfo, fetch: FetchState) -> Self {
|
pub fn new(mut current: EntityMatches, fetch: FetchState) -> Self {
|
||||||
current.push_cannot_have_mbid();
|
current.push_cannot_have_mbid();
|
||||||
current.push_manual_input_mbid();
|
current.push_manual_input_mbid();
|
||||||
|
|
||||||
@ -158,11 +158,11 @@ impl AppMachine<MatchState> {
|
|||||||
Err(err) => return AppMachine::error_state(self.inner, err.to_string()).into(),
|
Err(err) => return AppMachine::error_state(self.inner, err.to_string()).into(),
|
||||||
};
|
};
|
||||||
match self.state.current {
|
match self.state.current {
|
||||||
MatchStateInfo::Artist(artist_matches) => {
|
EntityMatches::Artist(artist_matches) => {
|
||||||
let matching = &artist_matches.matching;
|
let matching = &artist_matches.matching;
|
||||||
AppMachine::app_lookup_artist(self.inner, self.state.fetch, matching, mbid)
|
AppMachine::app_lookup_artist(self.inner, self.state.fetch, matching, mbid)
|
||||||
}
|
}
|
||||||
MatchStateInfo::Album(album_matches) => {
|
EntityMatches::Album(album_matches) => {
|
||||||
let artist_id = &album_matches.artist;
|
let artist_id = &album_matches.artist;
|
||||||
let matching = &album_matches.matching;
|
let matching = &album_matches.matching;
|
||||||
AppMachine::app_lookup_album(
|
AppMachine::app_lookup_album(
|
||||||
@ -191,7 +191,7 @@ impl From<AppMachine<MatchState>> for App {
|
|||||||
impl<'a> From<&'a mut MatchState> for AppPublicState<'a> {
|
impl<'a> From<&'a mut MatchState> for AppPublicState<'a> {
|
||||||
fn from(state: &'a mut MatchState) -> Self {
|
fn from(state: &'a mut MatchState) -> Self {
|
||||||
AppState::Match(MatchStatePublic {
|
AppState::Match(MatchStatePublic {
|
||||||
info: &state.current,
|
matches: &state.current,
|
||||||
state: &mut state.state,
|
state: &mut state.state,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -225,14 +225,14 @@ impl IAppInteractMatch for AppMachine<MatchState> {
|
|||||||
|
|
||||||
let mh = &mut self.inner.music_hoard;
|
let mh = &mut self.inner.music_hoard;
|
||||||
let result = match self.state.current {
|
let result = match self.state.current {
|
||||||
MatchStateInfo::Artist(ref mut matches) => {
|
EntityMatches::Artist(ref mut matches) => {
|
||||||
let info: ArtistInfo = matches.matching.info.clone();
|
let info: ArtistInfo = matches.matching.info.clone();
|
||||||
match matches.list.extract_info(index, info) {
|
match matches.list.extract_info(index, info) {
|
||||||
InfoOption::Info(info) => mh.set_artist_info(&matches.matching.id, info),
|
InfoOption::Info(info) => mh.set_artist_info(&matches.matching.id, info),
|
||||||
InfoOption::NeedInput => return self.get_input(),
|
InfoOption::NeedInput => return self.get_input(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MatchStateInfo::Album(ref mut matches) => {
|
EntityMatches::Album(ref mut matches) => {
|
||||||
let info: AlbumInfo = matches.matching.info.clone();
|
let info: AlbumInfo = matches.matching.info.clone();
|
||||||
match matches.list.extract_info(index, info) {
|
match matches.list.extract_info(index, info) {
|
||||||
InfoOption::Info(info) => {
|
InfoOption::Info(info) => {
|
||||||
@ -298,7 +298,7 @@ mod tests {
|
|||||||
meta
|
meta
|
||||||
}
|
}
|
||||||
|
|
||||||
fn artist_match() -> MatchStateInfo {
|
fn artist_match() -> EntityMatches {
|
||||||
let artist = artist_meta();
|
let artist = artist_meta();
|
||||||
|
|
||||||
let artist_1 = artist.clone();
|
let artist_1 = artist.clone();
|
||||||
@ -309,13 +309,13 @@ mod tests {
|
|||||||
artist_match_2.disambiguation = Some(String::from("some disambiguation"));
|
artist_match_2.disambiguation = Some(String::from("some disambiguation"));
|
||||||
|
|
||||||
let list = vec![artist_match_1.clone(), artist_match_2.clone()];
|
let list = vec![artist_match_1.clone(), artist_match_2.clone()];
|
||||||
MatchStateInfo::artist_search(artist, list)
|
EntityMatches::artist_search(artist, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn artist_lookup() -> MatchStateInfo {
|
fn artist_lookup() -> EntityMatches {
|
||||||
let artist = artist_meta();
|
let artist = artist_meta();
|
||||||
let lookup = Entity::new(artist.clone());
|
let lookup = Entity::new(artist.clone());
|
||||||
MatchStateInfo::artist_lookup(artist, lookup)
|
EntityMatches::artist_lookup(artist, lookup)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn album_meta() -> AlbumMeta {
|
fn album_meta() -> AlbumMeta {
|
||||||
@ -330,7 +330,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn album_match() -> MatchStateInfo {
|
fn album_match() -> EntityMatches {
|
||||||
let artist_id = ArtistId::new("Artist");
|
let artist_id = ArtistId::new("Artist");
|
||||||
let album = album_meta();
|
let album = album_meta();
|
||||||
|
|
||||||
@ -343,14 +343,14 @@ mod tests {
|
|||||||
let album_match_2 = Entity::with_score(album_2, 100);
|
let album_match_2 = Entity::with_score(album_2, 100);
|
||||||
|
|
||||||
let list = vec![album_match_1.clone(), album_match_2.clone()];
|
let list = vec![album_match_1.clone(), album_match_2.clone()];
|
||||||
MatchStateInfo::album_search(artist_id, album, list)
|
EntityMatches::album_search(artist_id, album, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn album_lookup() -> MatchStateInfo {
|
fn album_lookup() -> EntityMatches {
|
||||||
let artist_id = ArtistId::new("Artist");
|
let artist_id = ArtistId::new("Artist");
|
||||||
let album = album_meta();
|
let album = album_meta();
|
||||||
let lookup = Entity::new(album.clone());
|
let lookup = Entity::new(album.clone());
|
||||||
MatchStateInfo::album_lookup(artist_id, album, lookup)
|
EntityMatches::album_lookup(artist_id, album, lookup)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_state() -> FetchState {
|
fn fetch_state() -> FetchState {
|
||||||
@ -358,7 +358,7 @@ mod tests {
|
|||||||
FetchState::new(rx)
|
FetchState::new(rx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_state(match_state_info: MatchStateInfo) -> MatchState {
|
fn match_state(match_state_info: EntityMatches) -> MatchState {
|
||||||
MatchState::new(match_state_info, fetch_state())
|
MatchState::new(match_state_info, fetch_state())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,11 +379,11 @@ mod tests {
|
|||||||
let public = app.get();
|
let public = app.get();
|
||||||
let public_matches = public.state.unwrap_match();
|
let public_matches = public.state.unwrap_match();
|
||||||
|
|
||||||
assert_eq!(public_matches.info, &album_match);
|
assert_eq!(public_matches.matches, &album_match);
|
||||||
assert_eq!(public_matches.state, &widget_state);
|
assert_eq!(public_matches.state, &widget_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_state_flow(mut matches_info: MatchStateInfo, len: usize) {
|
fn match_state_flow(mut matches_info: EntityMatches, len: usize) {
|
||||||
// tx must exist for rx to return Empty rather than Disconnected.
|
// tx must exist for rx to return Empty rather than Disconnected.
|
||||||
let (_tx, rx) = mpsc::channel();
|
let (_tx, rx) = mpsc::channel();
|
||||||
let app_matches = MatchState::new(matches_info.clone(), FetchState::new(rx));
|
let app_matches = MatchState::new(matches_info.clone(), FetchState::new(rx));
|
||||||
@ -391,7 +391,7 @@ mod tests {
|
|||||||
let mut music_hoard = music_hoard(vec![]);
|
let mut music_hoard = music_hoard(vec![]);
|
||||||
let artist_id = ArtistId::new("Artist");
|
let artist_id = ArtistId::new("Artist");
|
||||||
match matches_info {
|
match matches_info {
|
||||||
MatchStateInfo::Album(_) => {
|
EntityMatches::Album(_) => {
|
||||||
let album_id = AlbumId::new("Album");
|
let album_id = AlbumId::new("Album");
|
||||||
let mut info = album_meta().info;
|
let mut info = album_meta().info;
|
||||||
info.musicbrainz = MbRefOption::CannotHaveMbid;
|
info.musicbrainz = MbRefOption::CannotHaveMbid;
|
||||||
@ -401,7 +401,7 @@ mod tests {
|
|||||||
.times(1)
|
.times(1)
|
||||||
.return_once(|_, _, _| Ok(()));
|
.return_once(|_, _, _| Ok(()));
|
||||||
}
|
}
|
||||||
MatchStateInfo::Artist(_) => {
|
EntityMatches::Artist(_) => {
|
||||||
let mut info = artist_meta().info;
|
let mut info = artist_meta().info;
|
||||||
info.musicbrainz = MbRefOption::CannotHaveMbid;
|
info.musicbrainz = MbRefOption::CannotHaveMbid;
|
||||||
music_hoard
|
music_hoard
|
||||||
@ -485,8 +485,8 @@ mod tests {
|
|||||||
|
|
||||||
let mut music_hoard = music_hoard(vec![]);
|
let mut music_hoard = music_hoard(vec![]);
|
||||||
match matches_info {
|
match matches_info {
|
||||||
MatchStateInfo::Album(_) => panic!(),
|
EntityMatches::Album(_) => panic!(),
|
||||||
MatchStateInfo::Artist(_) => {
|
EntityMatches::Artist(_) => {
|
||||||
let meta = artist_meta();
|
let meta = artist_meta();
|
||||||
music_hoard
|
music_hoard
|
||||||
.expect_set_artist_info()
|
.expect_set_artist_info()
|
||||||
@ -509,8 +509,8 @@ mod tests {
|
|||||||
|
|
||||||
let mut music_hoard = music_hoard(vec![]);
|
let mut music_hoard = music_hoard(vec![]);
|
||||||
match matches_info {
|
match matches_info {
|
||||||
MatchStateInfo::Artist(_) => panic!(),
|
EntityMatches::Artist(_) => panic!(),
|
||||||
MatchStateInfo::Album(matches) => {
|
EntityMatches::Album(matches) => {
|
||||||
let meta = album_meta();
|
let meta = album_meta();
|
||||||
music_hoard
|
music_hoard
|
||||||
.expect_set_album_info()
|
.expect_set_album_info()
|
||||||
@ -533,8 +533,8 @@ mod tests {
|
|||||||
|
|
||||||
let mut music_hoard = music_hoard(vec![]);
|
let mut music_hoard = music_hoard(vec![]);
|
||||||
match matches_info {
|
match matches_info {
|
||||||
MatchStateInfo::Album(_) => panic!(),
|
EntityMatches::Album(_) => panic!(),
|
||||||
MatchStateInfo::Artist(_) => {
|
EntityMatches::Artist(_) => {
|
||||||
music_hoard.expect_set_artist_info().return_once(|_, _| {
|
music_hoard.expect_set_artist_info().return_once(|_, _| {
|
||||||
Err(musichoard::Error::DatabaseError(String::from("error")))
|
Err(musichoard::Error::DatabaseError(String::from("error")))
|
||||||
});
|
});
|
||||||
@ -598,7 +598,7 @@ mod tests {
|
|||||||
.return_once(|_, _| Ok(()));
|
.return_once(|_, _| Ok(()));
|
||||||
|
|
||||||
let matches_vec: Vec<Entity<ArtistMeta>> = vec![];
|
let matches_vec: Vec<Entity<ArtistMeta>> = vec![];
|
||||||
let artist_match = MatchStateInfo::artist_search(artist.clone(), matches_vec);
|
let artist_match = EntityMatches::artist_search(artist.clone(), matches_vec);
|
||||||
let matches = AppMachine::match_state(
|
let matches = AppMachine::match_state(
|
||||||
inner_with_mb(music_hoard(vec![]), mb_job_sender),
|
inner_with_mb(music_hoard(vec![]), mb_job_sender),
|
||||||
match_state(artist_match),
|
match_state(artist_match),
|
||||||
@ -632,7 +632,7 @@ mod tests {
|
|||||||
|
|
||||||
let matches_vec: Vec<Entity<AlbumMeta>> = vec![];
|
let matches_vec: Vec<Entity<AlbumMeta>> = vec![];
|
||||||
let album_match =
|
let album_match =
|
||||||
MatchStateInfo::album_search(artist_id.clone(), album.clone(), matches_vec);
|
EntityMatches::album_search(artist_id.clone(), album.clone(), matches_vec);
|
||||||
let matches = AppMachine::match_state(
|
let matches = AppMachine::match_state(
|
||||||
inner_with_mb(music_hoard(vec![]), mb_job_sender),
|
inner_with_mb(music_hoard(vec![]), mb_job_sender),
|
||||||
match_state(album_match),
|
match_state(album_match),
|
||||||
|
@ -225,7 +225,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::{AppState, IApp, IAppInput, IAppInteractBrowse, InputEvent, MatchStateInfo},
|
app::{AppState, EntityMatches, IApp, IAppInput, IAppInteractBrowse, InputEvent},
|
||||||
lib::{
|
lib::{
|
||||||
interface::musicbrainz::{api::Entity, daemon::MockIMbJobSender},
|
interface::musicbrainz::{api::Entity, daemon::MockIMbJobSender},
|
||||||
MockIMusicHoard,
|
MockIMusicHoard,
|
||||||
@ -520,7 +520,7 @@ mod tests {
|
|||||||
let (_, rx) = mpsc::channel();
|
let (_, rx) = mpsc::channel();
|
||||||
let fetch = FetchState::new(rx);
|
let fetch = FetchState::new(rx);
|
||||||
let artist = ArtistMeta::new(ArtistId::new("Artist"));
|
let artist = ArtistMeta::new(ArtistId::new("Artist"));
|
||||||
let info = MatchStateInfo::artist_lookup(artist.clone(), Entity::new(artist.clone()));
|
let info = EntityMatches::artist_lookup(artist.clone(), Entity::new(artist.clone()));
|
||||||
app =
|
app =
|
||||||
AppMachine::match_state(app.unwrap_browse().inner, MatchState::new(info, fetch)).into();
|
AppMachine::match_state(app.unwrap_browse().inner, MatchState::new(info, fetch)).into();
|
||||||
|
|
||||||
|
@ -240,18 +240,18 @@ pub struct AlbumMatches {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum MatchStateInfo {
|
pub enum EntityMatches {
|
||||||
Artist(ArtistMatches),
|
Artist(ArtistMatches),
|
||||||
Album(AlbumMatches),
|
Album(AlbumMatches),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MatchStateInfo {
|
impl EntityMatches {
|
||||||
pub fn artist_search<M: Into<MatchOption<ArtistMeta>>>(
|
pub fn artist_search<M: Into<MatchOption<ArtistMeta>>>(
|
||||||
matching: ArtistMeta,
|
matching: ArtistMeta,
|
||||||
list: Vec<M>,
|
list: Vec<M>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let list = list.into_iter().map(Into::into).collect();
|
let list = list.into_iter().map(Into::into).collect();
|
||||||
MatchStateInfo::Artist(ArtistMatches { matching, list })
|
EntityMatches::Artist(ArtistMatches { matching, list })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn album_search<M: Into<MatchOption<AlbumMeta>>>(
|
pub fn album_search<M: Into<MatchOption<AlbumMeta>>>(
|
||||||
@ -260,7 +260,7 @@ impl MatchStateInfo {
|
|||||||
list: Vec<M>,
|
list: Vec<M>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let list = list.into_iter().map(Into::into).collect();
|
let list = list.into_iter().map(Into::into).collect();
|
||||||
MatchStateInfo::Album(AlbumMatches {
|
EntityMatches::Album(AlbumMatches {
|
||||||
artist,
|
artist,
|
||||||
matching,
|
matching,
|
||||||
list,
|
list,
|
||||||
@ -269,7 +269,7 @@ impl MatchStateInfo {
|
|||||||
|
|
||||||
pub fn artist_lookup<M: Into<MatchOption<ArtistMeta>>>(matching: ArtistMeta, item: M) -> Self {
|
pub fn artist_lookup<M: Into<MatchOption<ArtistMeta>>>(matching: ArtistMeta, item: M) -> Self {
|
||||||
let list = vec![item.into()];
|
let list = vec![item.into()];
|
||||||
MatchStateInfo::Artist(ArtistMatches { matching, list })
|
EntityMatches::Artist(ArtistMatches { matching, list })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn album_lookup<M: Into<MatchOption<AlbumMeta>>>(
|
pub fn album_lookup<M: Into<MatchOption<AlbumMeta>>>(
|
||||||
@ -278,7 +278,7 @@ impl MatchStateInfo {
|
|||||||
item: M,
|
item: M,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let list = vec![item.into()];
|
let list = vec![item.into()];
|
||||||
MatchStateInfo::Album(AlbumMatches {
|
EntityMatches::Album(AlbumMatches {
|
||||||
artist,
|
artist,
|
||||||
matching,
|
matching,
|
||||||
list,
|
list,
|
||||||
@ -287,7 +287,7 @@ impl MatchStateInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct MatchStatePublic<'app> {
|
pub struct MatchStatePublic<'app> {
|
||||||
pub info: &'app MatchStateInfo,
|
pub matches: &'app EntityMatches,
|
||||||
pub state: &'app mut WidgetState,
|
pub state: &'app mut WidgetState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
120
src/tui/lib/external/musicbrainz/daemon/mod.rs
vendored
120
src/tui/lib/external/musicbrainz/daemon/mod.rs
vendored
@ -1,11 +1,16 @@
|
|||||||
use std::{collections::VecDeque, sync::mpsc, thread, time};
|
use std::{collections::VecDeque, sync::mpsc, thread, time};
|
||||||
|
|
||||||
|
use musichoard::external::musicbrainz::api::{NextPage, PageSettings};
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::MatchStateInfo,
|
app::EntityMatches,
|
||||||
event::IFetchCompleteEventSender,
|
event::IFetchCompleteEventSender,
|
||||||
lib::interface::musicbrainz::{
|
lib::interface::musicbrainz::{
|
||||||
api::{Error as ApiError, IMusicBrainz},
|
api::{Error as ApiError, IMusicBrainz, Paged},
|
||||||
daemon::{Error, IMbJobSender, LookupParams, MbParams, ResultSender, SearchParams},
|
daemon::{
|
||||||
|
BrowseParams, EntityList, Error, IMbJobSender, LookupParams, MbParams, MbReturn,
|
||||||
|
ResultSender, SearchParams,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,6 +48,7 @@ enum JobPriority {
|
|||||||
struct JobInstance {
|
struct JobInstance {
|
||||||
result_sender: ResultSender,
|
result_sender: ResultSender,
|
||||||
requests: VecDeque<MbParams>,
|
requests: VecDeque<MbParams>,
|
||||||
|
paging: Option<PageSettings>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
@ -62,6 +68,7 @@ impl JobInstance {
|
|||||||
JobInstance {
|
JobInstance {
|
||||||
result_sender,
|
result_sender,
|
||||||
requests,
|
requests,
|
||||||
|
paging: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,8 +228,17 @@ impl JobInstance {
|
|||||||
event_sender: &mut dyn IFetchCompleteEventSender,
|
event_sender: &mut dyn IFetchCompleteEventSender,
|
||||||
) -> Result<JobInstanceStatus, JobInstanceError> {
|
) -> Result<JobInstanceStatus, JobInstanceError> {
|
||||||
// self.requests can be empty if the caller submits an empty job.
|
// self.requests can be empty if the caller submits an empty job.
|
||||||
if let Some(params) = self.requests.pop_front() {
|
self.paging = match self.requests.front() {
|
||||||
self.execute(musicbrainz, event_sender, params)?
|
Some(params) => {
|
||||||
|
let result_sender = &mut self.result_sender;
|
||||||
|
let paging = self.paging.take();
|
||||||
|
Self::execute(musicbrainz, result_sender, event_sender, ¶ms, paging)?
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.paging.is_none() {
|
||||||
|
self.requests.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.requests.is_empty() {
|
if self.requests.is_empty() {
|
||||||
@ -233,38 +249,64 @@ impl JobInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn execute(
|
fn execute(
|
||||||
&mut self,
|
|
||||||
musicbrainz: &mut dyn IMusicBrainz,
|
musicbrainz: &mut dyn IMusicBrainz,
|
||||||
|
result_sender: &mut ResultSender,
|
||||||
event_sender: &mut dyn IFetchCompleteEventSender,
|
event_sender: &mut dyn IFetchCompleteEventSender,
|
||||||
api_params: MbParams,
|
api_params: &MbParams,
|
||||||
) -> Result<(), JobInstanceError> {
|
paging: Option<PageSettings>,
|
||||||
|
) -> Result<Option<PageSettings>, JobInstanceError> {
|
||||||
|
let mut paging = match paging {
|
||||||
|
Some(paging) => paging,
|
||||||
|
None => PageSettings::with_max_limit(),
|
||||||
|
};
|
||||||
|
let mut next_page = NextPage::Complete;
|
||||||
|
|
||||||
let result = match api_params {
|
let result = match api_params {
|
||||||
MbParams::Lookup(lookup) => match lookup {
|
MbParams::Lookup(lookup) => match lookup {
|
||||||
LookupParams::Artist(params) => musicbrainz
|
LookupParams::Artist(p) => musicbrainz
|
||||||
.lookup_artist(¶ms.mbid)
|
.lookup_artist(&p.mbid)
|
||||||
.map(|rv| MatchStateInfo::artist_lookup(params.artist, rv)),
|
.map(|rv| EntityMatches::artist_lookup(p.artist.clone(), rv)),
|
||||||
LookupParams::ReleaseGroup(params) => musicbrainz
|
LookupParams::ReleaseGroup(p) => {
|
||||||
.lookup_release_group(¶ms.mbid)
|
musicbrainz.lookup_release_group(&p.mbid).map(|rv| {
|
||||||
.map(|rv| MatchStateInfo::album_lookup(params.artist_id, params.album, rv)),
|
EntityMatches::album_lookup(p.artist_id.clone(), p.album.clone(), rv)
|
||||||
},
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.map(MbReturn::Match),
|
||||||
MbParams::Search(search) => match search {
|
MbParams::Search(search) => match search {
|
||||||
SearchParams::Artist(params) => musicbrainz
|
SearchParams::Artist(p) => musicbrainz
|
||||||
.search_artist(¶ms.artist)
|
.search_artist(&p.artist)
|
||||||
.map(|rv| MatchStateInfo::artist_search(params.artist, rv)),
|
.map(|rv| EntityMatches::artist_search(p.artist.clone(), rv)),
|
||||||
SearchParams::ReleaseGroup(params) => musicbrainz
|
SearchParams::ReleaseGroup(p) => musicbrainz
|
||||||
.search_release_group(¶ms.artist_mbid, ¶ms.album)
|
.search_release_group(&p.artist_mbid, &p.album)
|
||||||
.map(|rv| MatchStateInfo::album_search(params.artist_id, params.album, rv)),
|
.map(|rv| {
|
||||||
},
|
EntityMatches::album_search(p.artist_id.clone(), p.album.clone(), rv)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
.map(MbReturn::Match),
|
||||||
|
MbParams::Browse(browse) => match browse {
|
||||||
|
BrowseParams::ReleaseGroup(params) => Paged::map_paged_result(
|
||||||
|
musicbrainz.browse_release_group(¶ms.artist, &mut paging),
|
||||||
|
|ents| EntityList::Album(ents.into_iter().map(|rg| rg.entity).collect()),
|
||||||
|
&mut next_page,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
.map(MbReturn::Fetch),
|
||||||
};
|
};
|
||||||
self.return_result(event_sender, result)
|
Self::return_result(result_sender, event_sender, result)?;
|
||||||
|
|
||||||
|
Ok(match next_page {
|
||||||
|
NextPage::Offset(offset) => Some(paging.with_offset(offset)),
|
||||||
|
NextPage::Complete => None,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn return_result(
|
fn return_result(
|
||||||
&mut self,
|
result_sender: &mut ResultSender,
|
||||||
event_sender: &mut dyn IFetchCompleteEventSender,
|
event_sender: &mut dyn IFetchCompleteEventSender,
|
||||||
result: Result<MatchStateInfo, ApiError>,
|
result: Result<MbReturn, ApiError>,
|
||||||
) -> Result<(), JobInstanceError> {
|
) -> Result<(), JobInstanceError> {
|
||||||
self.result_sender
|
result_sender
|
||||||
.send(result)
|
.send(result)
|
||||||
.map_err(|_| JobInstanceError::ReturnChannelDisconnected)?;
|
.map_err(|_| JobInstanceError::ReturnChannelDisconnected)?;
|
||||||
|
|
||||||
@ -575,7 +617,12 @@ mod tests {
|
|||||||
assert_eq!(result, Ok(()));
|
assert_eq!(result, Ok(()));
|
||||||
|
|
||||||
let result = result_receiver.try_recv().unwrap();
|
let result = result_receiver.try_recv().unwrap();
|
||||||
assert_eq!(result, Ok(MatchStateInfo::artist_lookup(artist, lookup)));
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
Ok(MbReturn::Match(EntityMatches::artist_lookup(
|
||||||
|
artist, lookup
|
||||||
|
)))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_release_group_expectation(
|
fn lookup_release_group_expectation(
|
||||||
@ -620,7 +667,9 @@ mod tests {
|
|||||||
let artist_id = album_artist_id();
|
let artist_id = album_artist_id();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
Ok(MatchStateInfo::album_lookup(artist_id, album, lookup))
|
Ok(MbReturn::Match(EntityMatches::album_lookup(
|
||||||
|
artist_id, album, lookup
|
||||||
|
)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -661,7 +710,12 @@ mod tests {
|
|||||||
assert_eq!(result, Ok(()));
|
assert_eq!(result, Ok(()));
|
||||||
|
|
||||||
let result = result_receiver.try_recv().unwrap();
|
let result = result_receiver.try_recv().unwrap();
|
||||||
assert_eq!(result, Ok(MatchStateInfo::artist_search(artist, matches)));
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
Ok(MbReturn::Match(EntityMatches::artist_search(
|
||||||
|
artist, matches
|
||||||
|
)))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_release_group_expectation(
|
fn search_release_group_expectation(
|
||||||
@ -716,21 +770,21 @@ mod tests {
|
|||||||
let result = result_receiver.try_recv().unwrap();
|
let result = result_receiver.try_recv().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
Ok(MatchStateInfo::album_search(
|
Ok(MbReturn::Match(EntityMatches::album_search(
|
||||||
artist_id.clone(),
|
artist_id.clone(),
|
||||||
album_1,
|
album_1,
|
||||||
matches_1
|
matches_1
|
||||||
))
|
)))
|
||||||
);
|
);
|
||||||
|
|
||||||
let result = result_receiver.try_recv().unwrap();
|
let result = result_receiver.try_recv().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
Ok(MatchStateInfo::album_search(
|
Ok(MbReturn::Match(EntityMatches::album_search(
|
||||||
artist_id.clone(),
|
artist_id.clone(),
|
||||||
album_4,
|
album_4,
|
||||||
matches_4
|
matches_4
|
||||||
))
|
)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
//! Module for accessing MusicBrainz metadata.
|
//! Module for accessing MusicBrainz metadata.
|
||||||
|
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use mockall::automock;
|
use mockall::automock;
|
||||||
|
|
||||||
@ -47,4 +49,26 @@ pub struct Paged<T> {
|
|||||||
pub next: NextPage,
|
pub next: NextPage,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pub fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U, E> {
|
||||||
|
// match self {
|
||||||
|
// Ok(t) => Ok(op(t)),
|
||||||
|
// Err(e) => Err(e),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl<T> Paged<T> {
|
||||||
|
pub fn map_paged_result<E, U, F: FnOnce(T) -> U>(
|
||||||
|
result: Result<Paged<T>, E>,
|
||||||
|
op: F,
|
||||||
|
next: &mut NextPage,
|
||||||
|
) -> Result<U, E> {
|
||||||
|
match result {
|
||||||
|
Ok(paged) => {
|
||||||
|
_ = mem::replace(next, paged.next);
|
||||||
|
Ok(op(paged.item))
|
||||||
|
}
|
||||||
|
Err(err) => Err(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
pub type Error = musichoard::external::musicbrainz::api::Error;
|
pub type Error = musichoard::external::musicbrainz::api::Error;
|
||||||
|
@ -6,7 +6,7 @@ use musichoard::collection::{
|
|||||||
musicbrainz::Mbid,
|
musicbrainz::Mbid,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::tui::{app::MatchStateInfo, lib::interface::musicbrainz::api::Error as MbApiError};
|
use crate::tui::{app::EntityMatches, lib::interface::musicbrainz::api::Error as MbApiError};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use mockall::automock;
|
use mockall::automock;
|
||||||
@ -26,9 +26,20 @@ impl fmt::Display for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type MbApiResult = Result<MatchStateInfo, MbApiError>;
|
pub type MbApiResult = Result<MbReturn, MbApiError>;
|
||||||
pub type ResultSender = mpsc::Sender<MbApiResult>;
|
pub type ResultSender = mpsc::Sender<MbApiResult>;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum MbReturn {
|
||||||
|
Match(EntityMatches),
|
||||||
|
Fetch(EntityList),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum EntityList {
|
||||||
|
Album(Vec<AlbumMeta>),
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(test, automock)]
|
#[cfg_attr(test, automock)]
|
||||||
pub trait IMbJobSender {
|
pub trait IMbJobSender {
|
||||||
fn submit_foreground_job(
|
fn submit_foreground_job(
|
||||||
@ -48,6 +59,7 @@ pub trait IMbJobSender {
|
|||||||
pub enum MbParams {
|
pub enum MbParams {
|
||||||
Lookup(LookupParams),
|
Lookup(LookupParams),
|
||||||
Search(SearchParams),
|
Search(SearchParams),
|
||||||
|
Browse(BrowseParams),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
@ -87,6 +99,16 @@ pub struct SearchReleaseGroupParams {
|
|||||||
pub album: AlbumMeta,
|
pub album: AlbumMeta,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum BrowseParams {
|
||||||
|
ReleaseGroup(BrowseReleaseGroupParams),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct BrowseReleaseGroupParams {
|
||||||
|
pub artist: Mbid,
|
||||||
|
}
|
||||||
|
|
||||||
impl MbParams {
|
impl MbParams {
|
||||||
pub fn lookup_artist(artist: ArtistMeta, mbid: Mbid) -> Self {
|
pub fn lookup_artist(artist: ArtistMeta, mbid: Mbid) -> Self {
|
||||||
MbParams::Lookup(LookupParams::Artist(LookupArtistParams { artist, mbid }))
|
MbParams::Lookup(LookupParams::Artist(LookupArtistParams { artist, mbid }))
|
||||||
|
@ -5,7 +5,7 @@ use musichoard::collection::{
|
|||||||
track::{TrackFormat, TrackQuality},
|
track::{TrackFormat, TrackQuality},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::tui::app::{MatchOption, MatchStateInfo};
|
use crate::tui::app::{EntityMatches, MatchOption};
|
||||||
|
|
||||||
pub struct UiDisplay;
|
pub struct UiDisplay;
|
||||||
|
|
||||||
@ -119,10 +119,10 @@ impl UiDisplay {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn display_matching_info(info: &MatchStateInfo) -> String {
|
pub fn display_matching_info(info: &EntityMatches) -> String {
|
||||||
match info {
|
match info {
|
||||||
MatchStateInfo::Artist(m) => UiDisplay::display_artist_matching(&m.matching),
|
EntityMatches::Artist(m) => UiDisplay::display_artist_matching(&m.matching),
|
||||||
MatchStateInfo::Album(m) => UiDisplay::display_album_matching(&m.matching),
|
EntityMatches::Album(m) => UiDisplay::display_album_matching(&m.matching),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use musichoard::collection::{album::AlbumMeta, artist::ArtistMeta};
|
|||||||
use ratatui::widgets::{List, ListItem};
|
use ratatui::widgets::{List, ListItem};
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::{MatchOption, MatchStateInfo, WidgetState},
|
app::{EntityMatches, MatchOption, WidgetState},
|
||||||
ui::display::UiDisplay,
|
ui::display::UiDisplay,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -13,10 +13,10 @@ pub struct MatchOverlay<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> MatchOverlay<'a, 'b> {
|
impl<'a, 'b> MatchOverlay<'a, 'b> {
|
||||||
pub fn new(info: &'a MatchStateInfo, state: &'b mut WidgetState) -> Self {
|
pub fn new(info: &'a EntityMatches, state: &'b mut WidgetState) -> Self {
|
||||||
match info {
|
match info {
|
||||||
MatchStateInfo::Artist(m) => Self::artists(&m.matching, &m.list, state),
|
EntityMatches::Artist(m) => Self::artists(&m.matching, &m.list, state),
|
||||||
MatchStateInfo::Album(m) => Self::albums(&m.matching, &m.list, state),
|
EntityMatches::Album(m) => Self::albums(&m.matching, &m.list, state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ impl Minibuffer<'_> {
|
|||||||
},
|
},
|
||||||
AppState::Match(public) => Minibuffer {
|
AppState::Match(public) => Minibuffer {
|
||||||
paragraphs: vec![
|
paragraphs: vec![
|
||||||
Paragraph::new(UiDisplay::display_matching_info(public.info)),
|
Paragraph::new(UiDisplay::display_matching_info(public.matches)),
|
||||||
Paragraph::new("ctrl+g: abort"),
|
Paragraph::new("ctrl+g: abort"),
|
||||||
],
|
],
|
||||||
columns: 2,
|
columns: 2,
|
||||||
|
@ -18,7 +18,7 @@ use musichoard::collection::{album::Album, Collection};
|
|||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::{
|
app::{
|
||||||
AppPublicState, AppState, Category, IAppAccess, InputPublic, MatchStateInfo, Selection,
|
AppPublicState, AppState, Category, EntityMatches, IAppAccess, InputPublic, Selection,
|
||||||
WidgetState,
|
WidgetState,
|
||||||
},
|
},
|
||||||
ui::{
|
ui::{
|
||||||
@ -140,7 +140,7 @@ impl Ui {
|
|||||||
UiWidget::render_overlay_widget("Fetching", fetch_text, area, false, frame)
|
UiWidget::render_overlay_widget("Fetching", fetch_text, area, false, frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_match_overlay(info: &MatchStateInfo, state: &mut WidgetState, frame: &mut Frame) {
|
fn render_match_overlay(info: &EntityMatches, state: &mut WidgetState, frame: &mut Frame) {
|
||||||
let area = OverlayBuilder::default().build(frame.area());
|
let area = OverlayBuilder::default().build(frame.area());
|
||||||
let st = MatchOverlay::new(info, state);
|
let st = MatchOverlay::new(info, state);
|
||||||
UiWidget::render_overlay_list_widget(&st.matching, st.list, st.state, true, area, frame)
|
UiWidget::render_overlay_list_widget(&st.matching, st.list, st.state, true, area, frame)
|
||||||
@ -182,7 +182,9 @@ impl IUi for Ui {
|
|||||||
AppState::Info(()) => Self::render_info_overlay(collection, selection, frame),
|
AppState::Info(()) => Self::render_info_overlay(collection, selection, frame),
|
||||||
AppState::Reload(()) => Self::render_reload_overlay(frame),
|
AppState::Reload(()) => Self::render_reload_overlay(frame),
|
||||||
AppState::Fetch(()) => Self::render_fetch_overlay(frame),
|
AppState::Fetch(()) => Self::render_fetch_overlay(frame),
|
||||||
AppState::Match(public) => Self::render_match_overlay(public.info, public.state, frame),
|
AppState::Match(public) => {
|
||||||
|
Self::render_match_overlay(public.matches, public.state, frame)
|
||||||
|
}
|
||||||
AppState::Error(msg) => Self::render_error_overlay("Error", msg, frame),
|
AppState::Error(msg) => Self::render_error_overlay("Error", msg, frame),
|
||||||
AppState::Critical(msg) => Self::render_error_overlay("Critical Error", msg, frame),
|
AppState::Critical(msg) => Self::render_error_overlay("Critical Error", msg, frame),
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -226,7 +228,7 @@ mod tests {
|
|||||||
AppState::Search(s) => AppState::Search(s),
|
AppState::Search(s) => AppState::Search(s),
|
||||||
AppState::Fetch(()) => AppState::Fetch(()),
|
AppState::Fetch(()) => AppState::Fetch(()),
|
||||||
AppState::Match(ref mut m) => AppState::Match(MatchStatePublic {
|
AppState::Match(ref mut m) => AppState::Match(MatchStatePublic {
|
||||||
info: m.info,
|
matches: m.matches,
|
||||||
state: m.state,
|
state: m.state,
|
||||||
}),
|
}),
|
||||||
AppState::Error(s) => AppState::Error(s),
|
AppState::Error(s) => AppState::Error(s),
|
||||||
@ -329,22 +331,22 @@ mod tests {
|
|||||||
ArtistMeta::new(ArtistId::new("an artist"))
|
ArtistMeta::new(ArtistId::new("an artist"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn artist_matches() -> MatchStateInfo {
|
fn artist_matches() -> EntityMatches {
|
||||||
let artist = artist_meta();
|
let artist = artist_meta();
|
||||||
let artist_match = Entity::with_score(artist.clone(), 80);
|
let artist_match = Entity::with_score(artist.clone(), 80);
|
||||||
let list = vec![artist_match.clone(), artist_match.clone()];
|
let list = vec![artist_match.clone(), artist_match.clone()];
|
||||||
|
|
||||||
let mut info = MatchStateInfo::artist_search(artist, list);
|
let mut info = EntityMatches::artist_search(artist, list);
|
||||||
info.push_cannot_have_mbid();
|
info.push_cannot_have_mbid();
|
||||||
info.push_manual_input_mbid();
|
info.push_manual_input_mbid();
|
||||||
info
|
info
|
||||||
}
|
}
|
||||||
|
|
||||||
fn artist_lookup() -> MatchStateInfo {
|
fn artist_lookup() -> EntityMatches {
|
||||||
let artist = artist_meta();
|
let artist = artist_meta();
|
||||||
let artist_lookup = Entity::new(artist.clone());
|
let artist_lookup = Entity::new(artist.clone());
|
||||||
|
|
||||||
let mut info = MatchStateInfo::artist_lookup(artist, artist_lookup);
|
let mut info = EntityMatches::artist_lookup(artist, artist_lookup);
|
||||||
info.push_cannot_have_mbid();
|
info.push_cannot_have_mbid();
|
||||||
info.push_manual_input_mbid();
|
info.push_manual_input_mbid();
|
||||||
info
|
info
|
||||||
@ -366,24 +368,24 @@ mod tests {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn album_matches() -> MatchStateInfo {
|
fn album_matches() -> EntityMatches {
|
||||||
let artist_id = album_artist_id();
|
let artist_id = album_artist_id();
|
||||||
let album = album_meta();
|
let album = album_meta();
|
||||||
let album_match = Entity::with_score(album.clone(), 80);
|
let album_match = Entity::with_score(album.clone(), 80);
|
||||||
let list = vec![album_match.clone(), album_match.clone()];
|
let list = vec![album_match.clone(), album_match.clone()];
|
||||||
|
|
||||||
let mut info = MatchStateInfo::album_search(artist_id, album, list);
|
let mut info = EntityMatches::album_search(artist_id, album, list);
|
||||||
info.push_cannot_have_mbid();
|
info.push_cannot_have_mbid();
|
||||||
info.push_manual_input_mbid();
|
info.push_manual_input_mbid();
|
||||||
info
|
info
|
||||||
}
|
}
|
||||||
|
|
||||||
fn album_lookup() -> MatchStateInfo {
|
fn album_lookup() -> EntityMatches {
|
||||||
let artist_id = album_artist_id();
|
let artist_id = album_artist_id();
|
||||||
let album = album_meta();
|
let album = album_meta();
|
||||||
let album_lookup = Entity::new(album.clone());
|
let album_lookup = Entity::new(album.clone());
|
||||||
|
|
||||||
let mut info = MatchStateInfo::album_lookup(artist_id, album, album_lookup);
|
let mut info = EntityMatches::album_lookup(artist_id, album, album_lookup);
|
||||||
info.push_cannot_have_mbid();
|
info.push_cannot_have_mbid();
|
||||||
info.push_manual_input_mbid();
|
info.push_manual_input_mbid();
|
||||||
info
|
info
|
||||||
@ -403,13 +405,13 @@ mod tests {
|
|||||||
album_lookup(),
|
album_lookup(),
|
||||||
];
|
];
|
||||||
|
|
||||||
for info in match_state_infos.iter() {
|
for matches in match_state_infos.iter() {
|
||||||
let mut widget_state = WidgetState::default().with_selected(Some(0));
|
let mut widget_state = WidgetState::default().with_selected(Some(0));
|
||||||
|
|
||||||
let mut app = AppPublic {
|
let mut app = AppPublic {
|
||||||
inner: public_inner(collection, &mut selection),
|
inner: public_inner(collection, &mut selection),
|
||||||
state: AppState::Match(MatchStatePublic {
|
state: AppState::Match(MatchStatePublic {
|
||||||
info,
|
matches,
|
||||||
state: &mut widget_state,
|
state: &mut widget_state,
|
||||||
}),
|
}),
|
||||||
input: None,
|
input: None,
|
||||||
|
Loading…
Reference in New Issue
Block a user