Add browse to TUI API and other simplifcations
This commit is contained in:
parent
4db09667fd
commit
7e63999edf
@ -66,14 +66,10 @@ fn main() {
|
|||||||
println!("{rg:?}\n");
|
println!("{rg:?}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
let offset = response.page.release_group_offset;
|
|
||||||
let count = response.release_groups.len();
|
let count = response.release_groups.len();
|
||||||
response_counts.push(count);
|
response_counts.push(count);
|
||||||
let total = response.page.release_group_count;
|
|
||||||
|
|
||||||
println!("Release group offset : {offset}");
|
|
||||||
println!("Release groups in this response: {count}");
|
println!("Release groups in this response: {count}");
|
||||||
println!("Release groups in total : {total}");
|
|
||||||
|
|
||||||
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.with_offset(next_offset),
|
||||||
|
4
src/external/musicbrainz/api/browse.rs
vendored
4
src/external/musicbrainz/api/browse.rs
vendored
@ -16,8 +16,8 @@ use crate::{
|
|||||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq)]
|
||||||
#[serde(rename_all(deserialize = "kebab-case"))]
|
#[serde(rename_all(deserialize = "kebab-case"))]
|
||||||
pub struct BrowseReleaseGroupPage {
|
pub struct BrowseReleaseGroupPage {
|
||||||
pub release_group_offset: usize,
|
release_group_offset: usize,
|
||||||
pub release_group_count: usize,
|
release_group_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BrowseReleaseGroupPage {
|
impl BrowseReleaseGroupPage {
|
||||||
|
4
src/external/musicbrainz/api/mod.rs
vendored
4
src/external/musicbrainz/api/mod.rs
vendored
@ -63,8 +63,8 @@ impl<Http> MusicBrainzClient<Http> {
|
|||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct PageSettings {
|
pub struct PageSettings {
|
||||||
pub limit: Option<usize>,
|
limit: Option<usize>,
|
||||||
pub offset: Option<usize>,
|
offset: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PageSettings {
|
impl PageSettings {
|
||||||
|
4
src/external/musicbrainz/api/search/mod.rs
vendored
4
src/external/musicbrainz/api/search/mod.rs
vendored
@ -28,8 +28,8 @@ use super::NextPage;
|
|||||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq)]
|
||||||
#[serde(rename_all(deserialize = "kebab-case"))]
|
#[serde(rename_all(deserialize = "kebab-case"))]
|
||||||
pub struct SearchPage {
|
pub struct SearchPage {
|
||||||
pub offset: usize,
|
offset: usize,
|
||||||
pub count: usize,
|
count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SearchPage {
|
impl SearchPage {
|
||||||
|
@ -290,11 +290,7 @@ mod tests {
|
|||||||
machine::tests::{inner, music_hoard},
|
machine::tests::{inner, music_hoard},
|
||||||
Delta, IApp, IAppAccess, IAppInteractBrowse, MatchOption, MatchStateInfo,
|
Delta, IApp, IAppAccess, IAppInteractBrowse, MatchOption, MatchStateInfo,
|
||||||
},
|
},
|
||||||
lib::interface::musicbrainz::{
|
lib::interface::musicbrainz::{self, api::Match, daemon::MockIMbJobSender},
|
||||||
self,
|
|
||||||
api::{Lookup, Match},
|
|
||||||
daemon::MockIMbJobSender,
|
|
||||||
},
|
|
||||||
testmod::COLLECTION,
|
testmod::COLLECTION,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -320,7 +316,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(fetch.try_recv(), Err(TryRecvError::Empty));
|
assert_eq!(fetch.try_recv(), Err(TryRecvError::Empty));
|
||||||
|
|
||||||
let lookup = Lookup::new(artist.clone());
|
let lookup = Match::item(artist.clone());
|
||||||
let lookup_result = MatchStateInfo::artist_lookup(artist.clone(), lookup);
|
let lookup_result = MatchStateInfo::artist_lookup(artist.clone(), lookup);
|
||||||
lookup_tx.send(Ok(lookup_result.clone())).unwrap();
|
lookup_tx.send(Ok(lookup_result.clone())).unwrap();
|
||||||
|
|
||||||
@ -605,7 +601,7 @@ mod tests {
|
|||||||
let (tx, rx) = mpsc::channel::<MbApiResult>();
|
let (tx, rx) = mpsc::channel::<MbApiResult>();
|
||||||
|
|
||||||
let artist = COLLECTION[3].meta.clone();
|
let artist = COLLECTION[3].meta.clone();
|
||||||
let artist_match = Match::new(80, COLLECTION[2].meta.clone());
|
let artist_match = Match::with_score(COLLECTION[2].meta.clone(), 80);
|
||||||
let artist_match_info =
|
let artist_match_info =
|
||||||
MatchStateInfo::artist_search(artist.clone(), vec![artist_match.clone()]);
|
MatchStateInfo::artist_search(artist.clone(), vec![artist_match.clone()]);
|
||||||
let fetch_result = Ok(artist_match_info);
|
let fetch_result = Ok(artist_match_info);
|
||||||
|
@ -6,13 +6,10 @@ use musichoard::collection::{
|
|||||||
musicbrainz::{MbRefOption, Mbid},
|
musicbrainz::{MbRefOption, Mbid},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::app::{
|
||||||
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, IAppInteractMatch,
|
MatchStateInfo, MatchStatePublic, WidgetState,
|
||||||
ListOption, MatchOption, MatchStateInfo, MatchStatePublic, WidgetState,
|
|
||||||
},
|
|
||||||
lib::interface::musicbrainz::api::{Lookup, Match},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
trait GetInfoMeta {
|
trait GetInfoMeta {
|
||||||
@ -27,7 +24,7 @@ impl GetInfoMeta for AlbumMeta {
|
|||||||
|
|
||||||
trait GetInfo {
|
trait GetInfo {
|
||||||
type InfoType;
|
type InfoType;
|
||||||
fn into_info(self, info: Self::InfoType) -> InfoOption<Self::InfoType>;
|
fn into_info(&self, info: Self::InfoType) -> InfoOption<Self::InfoType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum InfoOption<T> {
|
enum InfoOption<T> {
|
||||||
@ -35,86 +32,46 @@ enum InfoOption<T> {
|
|||||||
NeedInput,
|
NeedInput,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_match_option_artist_into_info {
|
impl GetInfo for MatchOption<ArtistMeta> {
|
||||||
($holder:ident) => {
|
type InfoType = ArtistInfo;
|
||||||
impl GetInfo for MatchOption<$holder<ArtistMeta>> {
|
|
||||||
type InfoType = ArtistInfo;
|
|
||||||
|
|
||||||
fn into_info(self, mut info: Self::InfoType) -> InfoOption<Self::InfoType> {
|
fn into_info(&self, mut info: Self::InfoType) -> InfoOption<Self::InfoType> {
|
||||||
match self {
|
match self {
|
||||||
MatchOption::Some(option) => info.musicbrainz = option.item.info.musicbrainz,
|
MatchOption::Some(option) => info.musicbrainz = option.item.info.musicbrainz.clone(),
|
||||||
MatchOption::CannotHaveMbid => info.musicbrainz = MbRefOption::CannotHaveMbid,
|
MatchOption::CannotHaveMbid => info.musicbrainz = MbRefOption::CannotHaveMbid,
|
||||||
MatchOption::ManualInputMbid => return InfoOption::NeedInput,
|
MatchOption::ManualInputMbid => return InfoOption::NeedInput,
|
||||||
}
|
|
||||||
InfoOption::Info(info)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
InfoOption::Info(info)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_match_option_artist_into_info!(Match);
|
impl GetInfo for MatchOption<AlbumMeta> {
|
||||||
impl_match_option_artist_into_info!(Lookup);
|
type InfoType = AlbumInfo;
|
||||||
|
|
||||||
macro_rules! impl_match_option_album_into_info {
|
fn into_info(&self, mut info: Self::InfoType) -> InfoOption<Self::InfoType> {
|
||||||
($holder:ident) => {
|
|
||||||
impl GetInfo for MatchOption<$holder<AlbumMeta>> {
|
|
||||||
type InfoType = AlbumInfo;
|
|
||||||
|
|
||||||
fn into_info(self, mut info: Self::InfoType) -> InfoOption<Self::InfoType> {
|
|
||||||
match self {
|
|
||||||
MatchOption::Some(option) => info = option.item.info,
|
|
||||||
MatchOption::CannotHaveMbid => info.musicbrainz = MbRefOption::CannotHaveMbid,
|
|
||||||
MatchOption::ManualInputMbid => return InfoOption::NeedInput,
|
|
||||||
}
|
|
||||||
InfoOption::Info(info)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_match_option_album_into_info!(Match);
|
|
||||||
impl_match_option_album_into_info!(Lookup);
|
|
||||||
|
|
||||||
impl<T> ListOption<T> {
|
|
||||||
fn len(&self) -> usize {
|
|
||||||
match self {
|
match self {
|
||||||
ListOption::Lookup(list) => list.len(),
|
MatchOption::Some(option) => info = option.item.info.clone(),
|
||||||
ListOption::Search(list) => list.len(),
|
MatchOption::CannotHaveMbid => info.musicbrainz = MbRefOption::CannotHaveMbid,
|
||||||
}
|
MatchOption::ManualInputMbid => return InfoOption::NeedInput,
|
||||||
}
|
|
||||||
|
|
||||||
fn push_cannot_have_mbid(&mut self) {
|
|
||||||
match self {
|
|
||||||
ListOption::Lookup(list) => list.push(MatchOption::CannotHaveMbid),
|
|
||||||
ListOption::Search(list) => list.push(MatchOption::CannotHaveMbid),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_manual_input_mbid(&mut self) {
|
|
||||||
match self {
|
|
||||||
ListOption::Lookup(list) => list.push(MatchOption::ManualInputMbid),
|
|
||||||
ListOption::Search(list) => list.push(MatchOption::ManualInputMbid),
|
|
||||||
}
|
}
|
||||||
|
InfoOption::Info(info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ExtractInfo {
|
trait ExtractInfo {
|
||||||
type InfoType;
|
type InfoType;
|
||||||
fn extract_info(&mut self, index: usize, info: Self::InfoType) -> InfoOption<Self::InfoType>;
|
fn extract_info(&self, index: usize, info: Self::InfoType) -> InfoOption<Self::InfoType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: GetInfoMeta> ExtractInfo for ListOption<T>
|
impl<T: GetInfoMeta> ExtractInfo for Vec<MatchOption<T>>
|
||||||
where
|
where
|
||||||
MatchOption<Match<T>>: GetInfo<InfoType = T::InfoType>,
|
MatchOption<T>: GetInfo<InfoType = T::InfoType>,
|
||||||
MatchOption<Lookup<T>>: GetInfo<InfoType = T::InfoType>,
|
MatchOption<T>: GetInfo<InfoType = T::InfoType>,
|
||||||
{
|
{
|
||||||
type InfoType = T::InfoType;
|
type InfoType = T::InfoType;
|
||||||
|
|
||||||
fn extract_info(&mut self, index: usize, info: Self::InfoType) -> InfoOption<Self::InfoType> {
|
fn extract_info(&self, index: usize, info: Self::InfoType) -> InfoOption<Self::InfoType> {
|
||||||
match self {
|
self.get(index).unwrap().into_info(info)
|
||||||
ListOption::Lookup(ref mut list) => list.swap_remove(index).into_info(info),
|
|
||||||
ListOption::Search(ref mut list) => list.swap_remove(index).into_info(info),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,11 +81,11 @@ impl ArtistMatches {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn push_cannot_have_mbid(&mut self) {
|
fn push_cannot_have_mbid(&mut self) {
|
||||||
self.list.push_cannot_have_mbid();
|
self.list.push(MatchOption::CannotHaveMbid);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_manual_input_mbid(&mut self) {
|
fn push_manual_input_mbid(&mut self) {
|
||||||
self.list.push_manual_input_mbid();
|
self.list.push(MatchOption::ManualInputMbid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,11 +95,11 @@ impl AlbumMatches {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn push_cannot_have_mbid(&mut self) {
|
fn push_cannot_have_mbid(&mut self) {
|
||||||
self.list.push_cannot_have_mbid();
|
self.list.push(MatchOption::CannotHaveMbid);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_manual_input_mbid(&mut self) {
|
fn push_manual_input_mbid(&mut self) {
|
||||||
self.list.push_manual_input_mbid();
|
self.list.push(MatchOption::ManualInputMbid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,7 +271,7 @@ mod tests {
|
|||||||
IApp, IAppAccess, IAppInput,
|
IApp, IAppAccess, IAppInput,
|
||||||
},
|
},
|
||||||
lib::interface::musicbrainz::{
|
lib::interface::musicbrainz::{
|
||||||
api::{Lookup, Match},
|
api::Match,
|
||||||
daemon::{MbParams, MockIMbJobSender},
|
daemon::{MbParams, MockIMbJobSender},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -322,18 +279,9 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
impl<T> Match<T> {
|
impl<T> Match<T> {
|
||||||
pub fn new(score: u8, item: T) -> Self {
|
pub fn with_score(item: T, score: u8) -> Self {
|
||||||
Match {
|
Match {
|
||||||
score,
|
score: Some(score),
|
||||||
item,
|
|
||||||
disambiguation: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Lookup<T> {
|
|
||||||
pub fn new(item: T) -> Self {
|
|
||||||
Lookup {
|
|
||||||
item,
|
item,
|
||||||
disambiguation: None,
|
disambiguation: None,
|
||||||
}
|
}
|
||||||
@ -354,10 +302,10 @@ mod tests {
|
|||||||
let artist = artist_meta();
|
let artist = artist_meta();
|
||||||
|
|
||||||
let artist_1 = artist.clone();
|
let artist_1 = artist.clone();
|
||||||
let artist_match_1 = Match::new(100, artist_1);
|
let artist_match_1 = Match::with_score(artist_1, 100);
|
||||||
|
|
||||||
let artist_2 = artist.clone();
|
let artist_2 = artist.clone();
|
||||||
let mut artist_match_2 = Match::new(100, artist_2);
|
let mut artist_match_2 = Match::with_score(artist_2, 100);
|
||||||
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()];
|
||||||
@ -366,7 +314,7 @@ mod tests {
|
|||||||
|
|
||||||
fn artist_lookup() -> MatchStateInfo {
|
fn artist_lookup() -> MatchStateInfo {
|
||||||
let artist = artist_meta();
|
let artist = artist_meta();
|
||||||
let lookup = Lookup::new(artist.clone());
|
let lookup = Match::item(artist.clone());
|
||||||
MatchStateInfo::artist_lookup(artist, lookup)
|
MatchStateInfo::artist_lookup(artist, lookup)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,12 +335,12 @@ mod tests {
|
|||||||
let album = album_meta();
|
let album = album_meta();
|
||||||
|
|
||||||
let album_1 = album.clone();
|
let album_1 = album.clone();
|
||||||
let album_match_1 = Match::new(100, album_1);
|
let album_match_1 = Match::with_score(album_1, 100);
|
||||||
|
|
||||||
let mut album_2 = album.clone();
|
let mut album_2 = album.clone();
|
||||||
album_2.id.title.push_str(" extra title part");
|
album_2.id.title.push_str(" extra title part");
|
||||||
album_2.info.secondary_types.pop();
|
album_2.info.secondary_types.pop();
|
||||||
let album_match_2 = Match::new(100, album_2);
|
let album_match_2 = Match::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)
|
MatchStateInfo::album_search(artist_id, album, list)
|
||||||
@ -401,7 +349,7 @@ mod tests {
|
|||||||
fn album_lookup() -> MatchStateInfo {
|
fn album_lookup() -> MatchStateInfo {
|
||||||
let artist_id = ArtistId::new("Artist");
|
let artist_id = ArtistId::new("Artist");
|
||||||
let album = album_meta();
|
let album = album_meta();
|
||||||
let lookup = Lookup::new(album.clone());
|
let lookup = Match::item(album.clone());
|
||||||
MatchStateInfo::album_lookup(artist_id, album, lookup)
|
MatchStateInfo::album_lookup(artist_id, album, lookup)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,10 +226,7 @@ mod tests {
|
|||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::{AppState, IApp, IAppInput, IAppInteractBrowse, InputEvent, MatchStateInfo},
|
app::{AppState, IApp, IAppInput, IAppInteractBrowse, InputEvent, MatchStateInfo},
|
||||||
lib::{
|
lib::{interface::musicbrainz::{api::Match, daemon::MockIMbJobSender}, MockIMusicHoard},
|
||||||
interface::musicbrainz::{api::Lookup, daemon::MockIMbJobSender},
|
|
||||||
MockIMusicHoard,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -520,7 +517,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(), Lookup::new(artist.clone()));
|
let info = MatchStateInfo::artist_lookup(artist.clone(), Match::item(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();
|
||||||
|
|
||||||
|
@ -37,8 +37,6 @@ macro_rules! IAppState {
|
|||||||
}
|
}
|
||||||
use IAppState;
|
use IAppState;
|
||||||
|
|
||||||
use super::lib::interface::musicbrainz::api::Lookup;
|
|
||||||
|
|
||||||
pub trait IApp {
|
pub trait IApp {
|
||||||
type BrowseState: IAppBase<APP = Self> + IAppInteractBrowse<APP = Self>;
|
type BrowseState: IAppBase<APP = Self> + IAppInteractBrowse<APP = Self>;
|
||||||
type InfoState: IAppBase<APP = Self> + IAppInteractInfo<APP = Self>;
|
type InfoState: IAppBase<APP = Self> + IAppInteractInfo<APP = Self>;
|
||||||
@ -217,19 +215,13 @@ pub type InputPublic<'app> = &'app tui_input::Input;
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum MatchOption<T> {
|
pub enum MatchOption<T> {
|
||||||
Some(T),
|
Some(Match<T>),
|
||||||
CannotHaveMbid,
|
CannotHaveMbid,
|
||||||
ManualInputMbid,
|
ManualInputMbid,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
impl<T> From<Match<T>> for MatchOption<T> {
|
||||||
pub enum ListOption<T> {
|
fn from(value: Match<T>) -> Self {
|
||||||
Search(Vec<MatchOption<Match<T>>>),
|
|
||||||
Lookup(Vec<MatchOption<Lookup<T>>>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> From<T> for MatchOption<T> {
|
|
||||||
fn from(value: T) -> Self {
|
|
||||||
MatchOption::Some(value)
|
MatchOption::Some(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,14 +229,14 @@ impl<T> From<T> for MatchOption<T> {
|
|||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct ArtistMatches {
|
pub struct ArtistMatches {
|
||||||
pub matching: ArtistMeta,
|
pub matching: ArtistMeta,
|
||||||
pub list: ListOption<ArtistMeta>,
|
pub list: Vec<MatchOption<ArtistMeta>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct AlbumMatches {
|
pub struct AlbumMatches {
|
||||||
pub artist: ArtistId,
|
pub artist: ArtistId,
|
||||||
pub matching: AlbumMeta,
|
pub matching: AlbumMeta,
|
||||||
pub list: ListOption<AlbumMeta>,
|
pub list: Vec<MatchOption<AlbumMeta>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
@ -254,20 +246,20 @@ pub enum MatchStateInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MatchStateInfo {
|
impl MatchStateInfo {
|
||||||
pub fn artist_search<M: Into<MatchOption<Match<ArtistMeta>>>>(
|
pub fn artist_search<M: Into<MatchOption<ArtistMeta>>>(
|
||||||
matching: ArtistMeta,
|
matching: ArtistMeta,
|
||||||
list: Vec<M>,
|
list: Vec<M>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let list = ListOption::Search(list.into_iter().map(Into::into).collect());
|
let list = list.into_iter().map(Into::into).collect();
|
||||||
MatchStateInfo::Artist(ArtistMatches { matching, list })
|
MatchStateInfo::Artist(ArtistMatches { matching, list })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn album_search<M: Into<MatchOption<Match<AlbumMeta>>>>(
|
pub fn album_search<M: Into<MatchOption<AlbumMeta>>>(
|
||||||
artist: ArtistId,
|
artist: ArtistId,
|
||||||
matching: AlbumMeta,
|
matching: AlbumMeta,
|
||||||
list: Vec<M>,
|
list: Vec<M>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let list = ListOption::Search(list.into_iter().map(Into::into).collect());
|
let list = list.into_iter().map(Into::into).collect();
|
||||||
MatchStateInfo::Album(AlbumMatches {
|
MatchStateInfo::Album(AlbumMatches {
|
||||||
artist,
|
artist,
|
||||||
matching,
|
matching,
|
||||||
@ -275,20 +267,17 @@ impl MatchStateInfo {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn artist_lookup<M: Into<MatchOption<Lookup<ArtistMeta>>>>(
|
pub fn artist_lookup<M: Into<MatchOption<ArtistMeta>>>(matching: ArtistMeta, item: M) -> Self {
|
||||||
matching: ArtistMeta,
|
let list = vec![item.into()];
|
||||||
item: M,
|
|
||||||
) -> Self {
|
|
||||||
let list = ListOption::Lookup(vec![item.into()]);
|
|
||||||
MatchStateInfo::Artist(ArtistMatches { matching, list })
|
MatchStateInfo::Artist(ArtistMatches { matching, list })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn album_lookup<M: Into<MatchOption<Lookup<AlbumMeta>>>>(
|
pub fn album_lookup<M: Into<MatchOption<AlbumMeta>>>(
|
||||||
artist: ArtistId,
|
artist: ArtistId,
|
||||||
matching: AlbumMeta,
|
matching: AlbumMeta,
|
||||||
item: M,
|
item: M,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let list = ListOption::Lookup(vec![item.into()]);
|
let list = vec![item.into()];
|
||||||
MatchStateInfo::Album(AlbumMatches {
|
MatchStateInfo::Album(AlbumMatches {
|
||||||
artist,
|
artist,
|
||||||
matching,
|
matching,
|
||||||
|
121
src/tui/lib/external/musicbrainz/api/mod.rs
vendored
121
src/tui/lib/external/musicbrainz/api/mod.rs
vendored
@ -10,6 +10,7 @@ use musichoard::{
|
|||||||
},
|
},
|
||||||
external::musicbrainz::{
|
external::musicbrainz::{
|
||||||
api::{
|
api::{
|
||||||
|
browse::{BrowseReleaseGroupRequest, BrowseReleaseGroupResponse},
|
||||||
lookup::{
|
lookup::{
|
||||||
LookupArtistRequest, LookupArtistResponse, LookupReleaseGroupRequest,
|
LookupArtistRequest, LookupArtistResponse, LookupReleaseGroupRequest,
|
||||||
LookupReleaseGroupResponse,
|
LookupReleaseGroupResponse,
|
||||||
@ -18,13 +19,13 @@ use musichoard::{
|
|||||||
SearchArtistRequest, SearchArtistResponseArtist, SearchReleaseGroupRequest,
|
SearchArtistRequest, SearchArtistResponseArtist, SearchReleaseGroupRequest,
|
||||||
SearchReleaseGroupResponseReleaseGroup,
|
SearchReleaseGroupResponseReleaseGroup,
|
||||||
},
|
},
|
||||||
MusicBrainzClient, PageSettings,
|
MbArtistMeta, MbReleaseGroupMeta, MusicBrainzClient, PageSettings,
|
||||||
},
|
},
|
||||||
IMusicBrainzHttp,
|
IMusicBrainzHttp,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::tui::lib::interface::musicbrainz::api::{Error, IMusicBrainz, Lookup, Match};
|
use crate::tui::lib::interface::musicbrainz::api::{Error, IMusicBrainz, Match, Paged};
|
||||||
|
|
||||||
// GRCOV_EXCL_START
|
// GRCOV_EXCL_START
|
||||||
pub struct MusicBrainz<Http> {
|
pub struct MusicBrainz<Http> {
|
||||||
@ -38,7 +39,7 @@ impl<Http> MusicBrainz<Http> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<Http: IMusicBrainzHttp> IMusicBrainz for MusicBrainz<Http> {
|
impl<Http: IMusicBrainzHttp> IMusicBrainz for MusicBrainz<Http> {
|
||||||
fn lookup_artist(&mut self, mbid: &Mbid) -> Result<Lookup<ArtistMeta>, Error> {
|
fn lookup_artist(&mut self, mbid: &Mbid) -> Result<Match<ArtistMeta>, Error> {
|
||||||
let request = LookupArtistRequest::new(mbid);
|
let request = LookupArtistRequest::new(mbid);
|
||||||
|
|
||||||
let mb_response = self.client.lookup_artist(&request)?;
|
let mb_response = self.client.lookup_artist(&request)?;
|
||||||
@ -46,7 +47,7 @@ impl<Http: IMusicBrainzHttp> IMusicBrainz for MusicBrainz<Http> {
|
|||||||
Ok(from_lookup_artist_response(mb_response))
|
Ok(from_lookup_artist_response(mb_response))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_release_group(&mut self, mbid: &Mbid) -> Result<Lookup<AlbumMeta>, Error> {
|
fn lookup_release_group(&mut self, mbid: &Mbid) -> Result<Match<AlbumMeta>, Error> {
|
||||||
let request = LookupReleaseGroupRequest::new(mbid);
|
let request = LookupReleaseGroupRequest::new(mbid);
|
||||||
|
|
||||||
let mb_response = self.client.lookup_release_group(&request)?;
|
let mb_response = self.client.lookup_release_group(&request)?;
|
||||||
@ -92,52 +93,75 @@ impl<Http: IMusicBrainzHttp> IMusicBrainz for MusicBrainz<Http> {
|
|||||||
.map(from_search_release_group_response_release_group)
|
.map(from_search_release_group_response_release_group)
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn from_lookup_artist_response(entity: LookupArtistResponse) -> Lookup<ArtistMeta> {
|
fn browse_release_group(
|
||||||
let sort = Some(entity.meta.sort_name).filter(|s| s != &entity.meta.name);
|
&mut self,
|
||||||
Lookup {
|
artist: &Mbid,
|
||||||
item: ArtistMeta {
|
paging: &mut PageSettings,
|
||||||
id: entity.meta.name.into(),
|
) -> Result<Paged<Vec<Match<AlbumMeta>>>, Error> {
|
||||||
sort,
|
let request = BrowseReleaseGroupRequest::artist(artist);
|
||||||
info: ArtistInfo {
|
|
||||||
musicbrainz: MbRefOption::Some(entity.meta.id.into()),
|
let mb_response = self.client.browse_release_group(&request, paging)?;
|
||||||
properties: HashMap::new(),
|
|
||||||
},
|
let page_count = mb_response.release_groups.len();
|
||||||
},
|
let next = mb_response.page.next_page_offset(page_count);
|
||||||
disambiguation: entity.meta.disambiguation,
|
let item = from_browse_release_group_response(mb_response);
|
||||||
|
|
||||||
|
Ok(Paged { item, next })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_lookup_release_group_response(entity: LookupReleaseGroupResponse) -> Lookup<AlbumMeta> {
|
fn from_mb_artist_meta(meta: MbArtistMeta) -> (ArtistMeta, Option<String>) {
|
||||||
Lookup {
|
let sort = Some(meta.sort_name).filter(|s| s != &meta.name);
|
||||||
item: AlbumMeta {
|
(
|
||||||
id: entity.meta.title.into(),
|
ArtistMeta {
|
||||||
date: entity.meta.first_release_date,
|
id: meta.name.into(),
|
||||||
seq: AlbumSeq::default(),
|
sort,
|
||||||
info: AlbumInfo {
|
info: ArtistInfo {
|
||||||
musicbrainz: MbRefOption::Some(entity.meta.id.into()),
|
musicbrainz: MbRefOption::Some(meta.id.into()),
|
||||||
primary_type: entity.meta.primary_type,
|
properties: HashMap::new(),
|
||||||
secondary_types: entity.meta.secondary_types.unwrap_or_default(),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
meta.disambiguation,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_mb_release_group_meta(meta: MbReleaseGroupMeta) -> AlbumMeta {
|
||||||
|
AlbumMeta {
|
||||||
|
id: meta.title.into(),
|
||||||
|
date: meta.first_release_date,
|
||||||
|
seq: AlbumSeq::default(),
|
||||||
|
info: AlbumInfo {
|
||||||
|
musicbrainz: MbRefOption::Some(meta.id.into()),
|
||||||
|
primary_type: meta.primary_type,
|
||||||
|
secondary_types: meta.secondary_types.unwrap_or_default(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_lookup_artist_response(entity: LookupArtistResponse) -> Match<ArtistMeta> {
|
||||||
|
let (item, disambiguation) = from_mb_artist_meta(entity.meta);
|
||||||
|
Match {
|
||||||
|
score: None,
|
||||||
|
item,
|
||||||
|
disambiguation,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_lookup_release_group_response(entity: LookupReleaseGroupResponse) -> Match<AlbumMeta> {
|
||||||
|
Match {
|
||||||
|
score: None,
|
||||||
|
item: from_mb_release_group_meta(entity.meta),
|
||||||
disambiguation: None,
|
disambiguation: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_search_artist_response_artist(entity: SearchArtistResponseArtist) -> Match<ArtistMeta> {
|
fn from_search_artist_response_artist(entity: SearchArtistResponseArtist) -> Match<ArtistMeta> {
|
||||||
let sort = Some(entity.meta.sort_name).filter(|s| s != &entity.meta.name);
|
let (item, disambiguation) = from_mb_artist_meta(entity.meta);
|
||||||
Match {
|
Match {
|
||||||
score: entity.score,
|
score: Some(entity.score),
|
||||||
item: ArtistMeta {
|
item,
|
||||||
id: entity.meta.name.into(),
|
disambiguation,
|
||||||
sort,
|
|
||||||
info: ArtistInfo {
|
|
||||||
musicbrainz: MbRefOption::Some(entity.meta.id.into()),
|
|
||||||
properties: HashMap::new(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
disambiguation: entity.meta.disambiguation,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,18 +169,17 @@ fn from_search_release_group_response_release_group(
|
|||||||
entity: SearchReleaseGroupResponseReleaseGroup,
|
entity: SearchReleaseGroupResponseReleaseGroup,
|
||||||
) -> Match<AlbumMeta> {
|
) -> Match<AlbumMeta> {
|
||||||
Match {
|
Match {
|
||||||
score: entity.score,
|
score: Some(entity.score),
|
||||||
item: AlbumMeta {
|
item: from_mb_release_group_meta(entity.meta),
|
||||||
id: entity.meta.title.into(),
|
|
||||||
date: entity.meta.first_release_date,
|
|
||||||
seq: AlbumSeq::default(),
|
|
||||||
info: AlbumInfo {
|
|
||||||
musicbrainz: MbRefOption::Some(entity.meta.id.into()),
|
|
||||||
primary_type: entity.meta.primary_type,
|
|
||||||
secondary_types: entity.meta.secondary_types.unwrap_or_default(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
disambiguation: None,
|
disambiguation: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn from_browse_release_group_response(
|
||||||
|
entity: BrowseReleaseGroupResponse,
|
||||||
|
) -> Vec<Match<AlbumMeta>> {
|
||||||
|
let rgs = entity.release_groups.into_iter();
|
||||||
|
let metas = rgs.map(from_mb_release_group_meta);
|
||||||
|
metas.map(|meta| Match::item(meta)).collect()
|
||||||
|
}
|
||||||
// GRCOV_EXCL_STOP
|
// GRCOV_EXCL_STOP
|
||||||
|
22
src/tui/lib/external/musicbrainz/daemon/mod.rs
vendored
22
src/tui/lib/external/musicbrainz/daemon/mod.rs
vendored
@ -321,7 +321,7 @@ mod tests {
|
|||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
event::{Event, EventError, MockIFetchCompleteEventSender},
|
event::{Event, EventError, MockIFetchCompleteEventSender},
|
||||||
lib::interface::musicbrainz::api::{Lookup, Match, MockIMusicBrainz},
|
lib::interface::musicbrainz::api::{Match, MockIMusicBrainz},
|
||||||
testmod::COLLECTION,
|
testmod::COLLECTION,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -411,8 +411,8 @@ mod tests {
|
|||||||
fn search_artist_expectations() -> (ArtistMeta, Vec<Match<ArtistMeta>>) {
|
fn search_artist_expectations() -> (ArtistMeta, Vec<Match<ArtistMeta>>) {
|
||||||
let artist = COLLECTION[3].meta.clone();
|
let artist = COLLECTION[3].meta.clone();
|
||||||
|
|
||||||
let artist_match_1 = Match::new(100, artist.clone());
|
let artist_match_1 = Match::with_score(artist.clone(), 100);
|
||||||
let artist_match_2 = Match::new(50, artist.clone());
|
let artist_match_2 = Match::with_score(artist.clone(), 50);
|
||||||
let matches = vec![artist_match_1.clone(), artist_match_2.clone()];
|
let matches = vec![artist_match_1.clone(), artist_match_2.clone()];
|
||||||
|
|
||||||
(artist, matches)
|
(artist, matches)
|
||||||
@ -445,8 +445,8 @@ mod tests {
|
|||||||
let album_1 = COLLECTION[1].albums[0].meta.clone();
|
let album_1 = COLLECTION[1].albums[0].meta.clone();
|
||||||
let album_4 = COLLECTION[1].albums[3].meta.clone();
|
let album_4 = COLLECTION[1].albums[3].meta.clone();
|
||||||
|
|
||||||
let album_match_1_1 = Match::new(100, album_1.clone());
|
let album_match_1_1 = Match::with_score(album_1.clone(), 100);
|
||||||
let album_match_1_2 = Match::new(50, album_4.clone());
|
let album_match_1_2 = Match::with_score(album_4.clone(), 50);
|
||||||
let matches_1 = vec![album_match_1_1.clone(), album_match_1_2.clone()];
|
let matches_1 = vec![album_match_1_1.clone(), album_match_1_2.clone()];
|
||||||
|
|
||||||
(album_1, matches_1)
|
(album_1, matches_1)
|
||||||
@ -456,8 +456,8 @@ mod tests {
|
|||||||
let album_1 = COLLECTION[1].albums[0].meta.clone();
|
let album_1 = COLLECTION[1].albums[0].meta.clone();
|
||||||
let album_4 = COLLECTION[1].albums[3].meta.clone();
|
let album_4 = COLLECTION[1].albums[3].meta.clone();
|
||||||
|
|
||||||
let album_match_4_1 = Match::new(100, album_4.clone());
|
let album_match_4_1 = Match::with_score(album_4.clone(), 100);
|
||||||
let album_match_4_2 = Match::new(30, album_1.clone());
|
let album_match_4_2 = Match::with_score(album_1.clone(), 30);
|
||||||
let matches_4 = vec![album_match_4_1.clone(), album_match_4_2.clone()];
|
let matches_4 = vec![album_match_4_1.clone(), album_match_4_2.clone()];
|
||||||
|
|
||||||
(album_4, matches_4)
|
(album_4, matches_4)
|
||||||
@ -539,7 +539,7 @@ mod tests {
|
|||||||
fn lookup_artist_expectation(
|
fn lookup_artist_expectation(
|
||||||
musicbrainz: &mut MockIMusicBrainz,
|
musicbrainz: &mut MockIMusicBrainz,
|
||||||
mbid: &Mbid,
|
mbid: &Mbid,
|
||||||
lookup: &Lookup<ArtistMeta>,
|
lookup: &Match<ArtistMeta>,
|
||||||
) {
|
) {
|
||||||
let result = Ok(lookup.clone());
|
let result = Ok(lookup.clone());
|
||||||
musicbrainz
|
musicbrainz
|
||||||
@ -554,7 +554,7 @@ mod tests {
|
|||||||
let mut musicbrainz = musicbrainz();
|
let mut musicbrainz = musicbrainz();
|
||||||
let mbid = mbid();
|
let mbid = mbid();
|
||||||
let artist = COLLECTION[3].meta.clone();
|
let artist = COLLECTION[3].meta.clone();
|
||||||
let lookup = Lookup::new(artist.clone());
|
let lookup = Match::item(artist.clone());
|
||||||
lookup_artist_expectation(&mut musicbrainz, &mbid, &lookup);
|
lookup_artist_expectation(&mut musicbrainz, &mbid, &lookup);
|
||||||
|
|
||||||
let mut event_sender = event_sender();
|
let mut event_sender = event_sender();
|
||||||
@ -581,7 +581,7 @@ mod tests {
|
|||||||
fn lookup_release_group_expectation(
|
fn lookup_release_group_expectation(
|
||||||
musicbrainz: &mut MockIMusicBrainz,
|
musicbrainz: &mut MockIMusicBrainz,
|
||||||
mbid: &Mbid,
|
mbid: &Mbid,
|
||||||
lookup: &Lookup<AlbumMeta>,
|
lookup: &Match<AlbumMeta>,
|
||||||
) {
|
) {
|
||||||
let result = Ok(lookup.clone());
|
let result = Ok(lookup.clone());
|
||||||
musicbrainz
|
musicbrainz
|
||||||
@ -596,7 +596,7 @@ mod tests {
|
|||||||
let mut musicbrainz = musicbrainz();
|
let mut musicbrainz = musicbrainz();
|
||||||
let mbid = mbid();
|
let mbid = mbid();
|
||||||
let album = COLLECTION[1].albums[0].meta.clone();
|
let album = COLLECTION[1].albums[0].meta.clone();
|
||||||
let lookup = Lookup::new(album.clone());
|
let lookup = Match::item(album.clone());
|
||||||
lookup_release_group_expectation(&mut musicbrainz, &mbid, &lookup);
|
lookup_release_group_expectation(&mut musicbrainz, &mbid, &lookup);
|
||||||
|
|
||||||
let mut event_sender = event_sender();
|
let mut event_sender = event_sender();
|
||||||
|
@ -3,32 +3,48 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use mockall::automock;
|
use mockall::automock;
|
||||||
|
|
||||||
use musichoard::collection::{album::AlbumMeta, artist::ArtistMeta, musicbrainz::Mbid};
|
use musichoard::{
|
||||||
|
collection::{album::AlbumMeta, artist::ArtistMeta, musicbrainz::Mbid},
|
||||||
|
external::musicbrainz::api::{NextPage, PageSettings},
|
||||||
|
};
|
||||||
|
|
||||||
/// Trait for interacting with the MusicBrainz API.
|
|
||||||
#[cfg_attr(test, automock)]
|
#[cfg_attr(test, automock)]
|
||||||
pub trait IMusicBrainz {
|
pub trait IMusicBrainz {
|
||||||
fn lookup_artist(&mut self, mbid: &Mbid) -> Result<Lookup<ArtistMeta>, Error>;
|
fn lookup_artist(&mut self, mbid: &Mbid) -> Result<Match<ArtistMeta>, Error>;
|
||||||
fn lookup_release_group(&mut self, mbid: &Mbid) -> Result<Lookup<AlbumMeta>, Error>;
|
fn lookup_release_group(&mut self, mbid: &Mbid) -> Result<Match<AlbumMeta>, Error>;
|
||||||
fn search_artist(&mut self, artist: &ArtistMeta) -> Result<Vec<Match<ArtistMeta>>, Error>;
|
fn search_artist(&mut self, artist: &ArtistMeta) -> Result<Vec<Match<ArtistMeta>>, Error>;
|
||||||
fn search_release_group(
|
fn search_release_group(
|
||||||
&mut self,
|
&mut self,
|
||||||
arid: &Mbid,
|
arid: &Mbid,
|
||||||
album: &AlbumMeta,
|
album: &AlbumMeta,
|
||||||
) -> Result<Vec<Match<AlbumMeta>>, Error>;
|
) -> Result<Vec<Match<AlbumMeta>>, Error>;
|
||||||
|
fn browse_release_group(
|
||||||
|
&mut self,
|
||||||
|
artist: &Mbid,
|
||||||
|
paging: &mut PageSettings,
|
||||||
|
) -> Result<Paged<Vec<Match<AlbumMeta>>>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Match<T> {
|
pub struct Match<T> {
|
||||||
pub score: u8,
|
pub score: Option<u8>,
|
||||||
pub item: T,
|
pub item: T,
|
||||||
pub disambiguation: Option<String>,
|
pub disambiguation: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
impl<T> Match<T> {
|
||||||
pub struct Lookup<T> {
|
pub fn item(item: T) -> Self {
|
||||||
|
Match {
|
||||||
|
score: None,
|
||||||
|
item,
|
||||||
|
disambiguation: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Paged<T> {
|
||||||
pub item: T,
|
pub item: T,
|
||||||
pub disambiguation: Option<String>,
|
pub next: NextPage,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Error = musichoard::external::musicbrainz::api::Error;
|
pub type Error = musichoard::external::musicbrainz::api::Error;
|
||||||
|
@ -5,10 +5,7 @@ use musichoard::collection::{
|
|||||||
track::{TrackFormat, TrackQuality},
|
track::{TrackFormat, TrackQuality},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::app::{MatchOption, MatchStateInfo};
|
||||||
app::{MatchOption, MatchStateInfo},
|
|
||||||
lib::interface::musicbrainz::api::{Lookup, Match},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct UiDisplay;
|
pub struct UiDisplay;
|
||||||
|
|
||||||
@ -129,23 +126,24 @@ impl UiDisplay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn display_search_option_artist(match_option: &MatchOption<Match<ArtistMeta>>) -> String {
|
pub fn display_match_option_artist(match_option: &MatchOption<ArtistMeta>) -> String {
|
||||||
match match_option {
|
Self::display_match_option(Self::display_option_artist, match_option)
|
||||||
MatchOption::Some(match_artist) => format!(
|
|
||||||
"{} ({}%)",
|
|
||||||
Self::display_option_artist(&match_artist.item, &match_artist.disambiguation),
|
|
||||||
match_artist.score,
|
|
||||||
),
|
|
||||||
MatchOption::CannotHaveMbid => Self::display_cannot_have_mbid().to_string(),
|
|
||||||
MatchOption::ManualInputMbid => Self::display_manual_input_mbid().to_string(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn display_lookup_option_artist(lookup_option: &MatchOption<Lookup<ArtistMeta>>) -> String {
|
pub fn display_match_option_album(match_option: &MatchOption<AlbumMeta>) -> String {
|
||||||
match lookup_option {
|
Self::display_match_option(Self::display_option_album, match_option)
|
||||||
MatchOption::Some(match_artist) => {
|
}
|
||||||
Self::display_option_artist(&match_artist.item, &match_artist.disambiguation)
|
|
||||||
}
|
fn display_match_option<Fn, T>(display_fn: Fn, match_option: &MatchOption<T>) -> String
|
||||||
|
where
|
||||||
|
Fn: FnOnce(&T, &Option<String>) -> String,
|
||||||
|
{
|
||||||
|
match match_option {
|
||||||
|
MatchOption::Some(match_artist) => format!(
|
||||||
|
"{}{}",
|
||||||
|
display_fn(&match_artist.item, &match_artist.disambiguation),
|
||||||
|
Self::display_option_score(match_artist.score),
|
||||||
|
),
|
||||||
MatchOption::CannotHaveMbid => Self::display_cannot_have_mbid().to_string(),
|
MatchOption::CannotHaveMbid => Self::display_cannot_have_mbid().to_string(),
|
||||||
MatchOption::ManualInputMbid => Self::display_manual_input_mbid().to_string(),
|
MatchOption::ManualInputMbid => Self::display_manual_input_mbid().to_string(),
|
||||||
}
|
}
|
||||||
@ -163,27 +161,7 @@ impl UiDisplay {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn display_search_option_album(match_option: &MatchOption<Match<AlbumMeta>>) -> String {
|
fn display_option_album(album: &AlbumMeta, _disambiguation: &Option<String>) -> String {
|
||||||
match match_option {
|
|
||||||
MatchOption::Some(match_album) => format!(
|
|
||||||
"{} ({}%)",
|
|
||||||
Self::display_option_album(&match_album.item),
|
|
||||||
match_album.score,
|
|
||||||
),
|
|
||||||
MatchOption::CannotHaveMbid => Self::display_cannot_have_mbid().to_string(),
|
|
||||||
MatchOption::ManualInputMbid => Self::display_manual_input_mbid().to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn display_lookup_option_album(lookup_option: &MatchOption<Lookup<AlbumMeta>>) -> String {
|
|
||||||
match lookup_option {
|
|
||||||
MatchOption::Some(match_album) => Self::display_option_album(&match_album.item),
|
|
||||||
MatchOption::CannotHaveMbid => Self::display_cannot_have_mbid().to_string(),
|
|
||||||
MatchOption::ManualInputMbid => Self::display_manual_input_mbid().to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn display_option_album(album: &AlbumMeta) -> String {
|
|
||||||
format!(
|
format!(
|
||||||
"{:010} | {} [{}]",
|
"{:010} | {} [{}]",
|
||||||
UiDisplay::display_album_date(&album.date),
|
UiDisplay::display_album_date(&album.date),
|
||||||
@ -192,6 +170,10 @@ impl UiDisplay {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn display_option_score(score: Option<u8>) -> String {
|
||||||
|
score.map(|s| format!(" ({s}%)")).unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
fn display_cannot_have_mbid() -> &'static str {
|
fn display_cannot_have_mbid() -> &'static str {
|
||||||
"-- Cannot have a MusicBrainz Identifier --"
|
"-- Cannot have a MusicBrainz Identifier --"
|
||||||
}
|
}
|
||||||
|
@ -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::{ListOption, MatchStateInfo, WidgetState},
|
app::{MatchOption, MatchStateInfo, WidgetState},
|
||||||
ui::display::UiDisplay,
|
ui::display::UiDisplay,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -22,19 +22,12 @@ impl<'a, 'b> MatchOverlay<'a, 'b> {
|
|||||||
|
|
||||||
fn artists(
|
fn artists(
|
||||||
matching: &ArtistMeta,
|
matching: &ArtistMeta,
|
||||||
matches: &'a ListOption<ArtistMeta>,
|
matches: &'a Vec<MatchOption<ArtistMeta>>,
|
||||||
state: &'b mut WidgetState,
|
state: &'b mut WidgetState,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let matching = UiDisplay::display_artist_matching(matching);
|
let matching = UiDisplay::display_artist_matching(matching);
|
||||||
|
|
||||||
let list = match matches {
|
let list = Self::display_list(UiDisplay::display_match_option_artist, matches);
|
||||||
ListOption::Search(matches) => {
|
|
||||||
Self::display_list(UiDisplay::display_search_option_artist, matches)
|
|
||||||
}
|
|
||||||
ListOption::Lookup(matches) => {
|
|
||||||
Self::display_list(UiDisplay::display_lookup_option_artist, matches)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MatchOverlay {
|
MatchOverlay {
|
||||||
matching,
|
matching,
|
||||||
@ -45,19 +38,12 @@ impl<'a, 'b> MatchOverlay<'a, 'b> {
|
|||||||
|
|
||||||
fn albums(
|
fn albums(
|
||||||
matching: &AlbumMeta,
|
matching: &AlbumMeta,
|
||||||
matches: &'a ListOption<AlbumMeta>,
|
matches: &'a Vec<MatchOption<AlbumMeta>>,
|
||||||
state: &'b mut WidgetState,
|
state: &'b mut WidgetState,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let matching = UiDisplay::display_album_matching(matching);
|
let matching = UiDisplay::display_album_matching(matching);
|
||||||
|
|
||||||
let list = match matches {
|
let list = Self::display_list(UiDisplay::display_match_option_album, matches);
|
||||||
ListOption::Search(matches) => {
|
|
||||||
Self::display_list(UiDisplay::display_search_option_album, matches)
|
|
||||||
}
|
|
||||||
ListOption::Lookup(matches) => {
|
|
||||||
Self::display_list(UiDisplay::display_lookup_option_album, matches)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MatchOverlay {
|
MatchOverlay {
|
||||||
matching,
|
matching,
|
||||||
|
@ -204,7 +204,7 @@ mod tests {
|
|||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::{AppPublic, AppPublicInner, Delta, MatchStatePublic},
|
app::{AppPublic, AppPublicInner, Delta, MatchStatePublic},
|
||||||
lib::interface::musicbrainz::api::{Lookup, Match},
|
lib::interface::musicbrainz::api::Match,
|
||||||
testmod::COLLECTION,
|
testmod::COLLECTION,
|
||||||
tests::terminal,
|
tests::terminal,
|
||||||
};
|
};
|
||||||
@ -331,7 +331,7 @@ mod tests {
|
|||||||
|
|
||||||
fn artist_matches() -> MatchStateInfo {
|
fn artist_matches() -> MatchStateInfo {
|
||||||
let artist = artist_meta();
|
let artist = artist_meta();
|
||||||
let artist_match = Match::new(80, artist.clone());
|
let artist_match = Match::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 = MatchStateInfo::artist_search(artist, list);
|
||||||
@ -342,7 +342,7 @@ mod tests {
|
|||||||
|
|
||||||
fn artist_lookup() -> MatchStateInfo {
|
fn artist_lookup() -> MatchStateInfo {
|
||||||
let artist = artist_meta();
|
let artist = artist_meta();
|
||||||
let artist_lookup = Lookup::new(artist.clone());
|
let artist_lookup = Match::item(artist.clone());
|
||||||
|
|
||||||
let mut info = MatchStateInfo::artist_lookup(artist, artist_lookup);
|
let mut info = MatchStateInfo::artist_lookup(artist, artist_lookup);
|
||||||
info.push_cannot_have_mbid();
|
info.push_cannot_have_mbid();
|
||||||
@ -369,7 +369,7 @@ mod tests {
|
|||||||
fn album_matches() -> MatchStateInfo {
|
fn album_matches() -> MatchStateInfo {
|
||||||
let artist_id = album_artist_id();
|
let artist_id = album_artist_id();
|
||||||
let album = album_meta();
|
let album = album_meta();
|
||||||
let album_match = Match::new(80, album.clone());
|
let album_match = Match::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 = MatchStateInfo::album_search(artist_id, album, list);
|
||||||
@ -381,7 +381,7 @@ mod tests {
|
|||||||
fn album_lookup() -> MatchStateInfo {
|
fn album_lookup() -> MatchStateInfo {
|
||||||
let artist_id = album_artist_id();
|
let artist_id = album_artist_id();
|
||||||
let album = album_meta();
|
let album = album_meta();
|
||||||
let album_lookup = Lookup::new(album.clone());
|
let album_lookup = Match::item(album.clone());
|
||||||
|
|
||||||
let mut info = MatchStateInfo::album_lookup(artist_id, album, album_lookup);
|
let mut info = MatchStateInfo::album_lookup(artist_id, album, album_lookup);
|
||||||
info.push_cannot_have_mbid();
|
info.push_cannot_have_mbid();
|
||||||
|
Loading…
Reference in New Issue
Block a user