Replace MH: IMusicHoard
generic with a trait object (#194)
Closes #192 Reviewed-on: #194
This commit is contained in:
parent
cf7e23c38c
commit
b70499d8de
@ -70,8 +70,10 @@ struct DbOpt {
|
|||||||
no_database: bool,
|
no_database: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with<Database: IDatabase, Library: ILibrary>(builder: MusicHoardBuilder<Database, Library>) {
|
fn with<Database: IDatabase + 'static, Library: ILibrary + 'static>(
|
||||||
let music_hoard = builder.build().expect("failed to initialise MusicHoard");
|
builder: MusicHoardBuilder<Database, Library>,
|
||||||
|
) {
|
||||||
|
let music_hoard = Box::new(builder.build().expect("failed to initialise MusicHoard"));
|
||||||
|
|
||||||
// Initialize the terminal user interface.
|
// Initialize the terminal user interface.
|
||||||
let backend = CrosstermBackend::new(io::stdout());
|
let backend = CrosstermBackend::new(io::stdout());
|
||||||
@ -92,7 +94,7 @@ fn with<Database: IDatabase, Library: ILibrary>(builder: MusicHoardBuilder<Datab
|
|||||||
Tui::run(terminal, app, ui, handler, listener).expect("failed to run tui");
|
Tui::run(terminal, app, ui, handler, listener).expect("failed to run tui");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_database<Library: ILibrary>(
|
fn with_database<Library: ILibrary + 'static>(
|
||||||
db_opt: DbOpt,
|
db_opt: DbOpt,
|
||||||
builder: MusicHoardBuilder<NoDatabase, Library>,
|
builder: MusicHoardBuilder<NoDatabase, Library>,
|
||||||
) {
|
) {
|
||||||
|
@ -2,19 +2,16 @@ use std::{thread, time};
|
|||||||
|
|
||||||
use musichoard::collection::musicbrainz::IMusicBrainzRef;
|
use musichoard::collection::musicbrainz::IMusicBrainzRef;
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::app::{
|
||||||
app::{
|
machine::{matches::AppMatchesInfo, App, AppInner, AppMachine},
|
||||||
machine::{matches::AppMatchesInfo, App, AppInner, AppMachine},
|
selection::{Delta, ListSelection},
|
||||||
selection::{Delta, ListSelection},
|
AppPublic, AppState, IAppInteractBrowse,
|
||||||
AppPublic, AppState, IAppInteractBrowse,
|
|
||||||
},
|
|
||||||
lib::IMusicHoard,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct AppBrowse;
|
pub struct AppBrowse;
|
||||||
|
|
||||||
impl<MH: IMusicHoard> AppMachine<MH, AppBrowse> {
|
impl AppMachine<AppBrowse> {
|
||||||
pub fn browse(inner: AppInner<MH>) -> Self {
|
pub fn browse(inner: AppInner) -> Self {
|
||||||
AppMachine {
|
AppMachine {
|
||||||
inner,
|
inner,
|
||||||
state: AppBrowse,
|
state: AppBrowse,
|
||||||
@ -22,14 +19,14 @@ impl<MH: IMusicHoard> AppMachine<MH, AppBrowse> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> From<AppMachine<MH, AppBrowse>> for App<MH> {
|
impl From<AppMachine<AppBrowse>> for App {
|
||||||
fn from(machine: AppMachine<MH, AppBrowse>) -> Self {
|
fn from(machine: AppMachine<AppBrowse>) -> Self {
|
||||||
AppState::Browse(machine)
|
AppState::Browse(machine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, MH: IMusicHoard> From<&'a mut AppMachine<MH, AppBrowse>> for AppPublic<'a> {
|
impl<'a> From<&'a mut AppMachine<AppBrowse>> for AppPublic<'a> {
|
||||||
fn from(machine: &'a mut AppMachine<MH, AppBrowse>) -> Self {
|
fn from(machine: &'a mut AppMachine<AppBrowse>) -> Self {
|
||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Browse(()),
|
state: AppState::Browse(()),
|
||||||
@ -37,8 +34,8 @@ impl<'a, MH: IMusicHoard> From<&'a mut AppMachine<MH, AppBrowse>> for AppPublic<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> IAppInteractBrowse for AppMachine<MH, AppBrowse> {
|
impl IAppInteractBrowse for AppMachine<AppBrowse> {
|
||||||
type APP = App<MH>;
|
type APP = App;
|
||||||
|
|
||||||
fn quit(mut self) -> Self::APP {
|
fn quit(mut self) -> Self::APP {
|
||||||
self.inner.running = false;
|
self.inner.running = false;
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
use crate::tui::{
|
use crate::tui::app::{
|
||||||
app::{
|
machine::{App, AppInner, AppMachine},
|
||||||
machine::{App, AppInner, AppMachine},
|
AppPublic, AppState, IAppInteractCritical,
|
||||||
AppPublic, AppState, IAppInteractCritical,
|
|
||||||
},
|
|
||||||
lib::IMusicHoard,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct AppCritical {
|
pub struct AppCritical {
|
||||||
string: String,
|
string: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> AppMachine<MH, AppCritical> {
|
impl AppMachine<AppCritical> {
|
||||||
pub fn critical<S: Into<String>>(inner: AppInner<MH>, string: S) -> Self {
|
pub fn critical<S: Into<String>>(inner: AppInner, string: S) -> Self {
|
||||||
AppMachine {
|
AppMachine {
|
||||||
inner,
|
inner,
|
||||||
state: AppCritical {
|
state: AppCritical {
|
||||||
@ -21,14 +18,14 @@ impl<MH: IMusicHoard> AppMachine<MH, AppCritical> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> From<AppMachine<MH, AppCritical>> for App<MH> {
|
impl From<AppMachine<AppCritical>> for App {
|
||||||
fn from(machine: AppMachine<MH, AppCritical>) -> Self {
|
fn from(machine: AppMachine<AppCritical>) -> Self {
|
||||||
AppState::Critical(machine)
|
AppState::Critical(machine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, MH: IMusicHoard> From<&'a mut AppMachine<MH, AppCritical>> for AppPublic<'a> {
|
impl<'a> From<&'a mut AppMachine<AppCritical>> for AppPublic<'a> {
|
||||||
fn from(machine: &'a mut AppMachine<MH, AppCritical>) -> Self {
|
fn from(machine: &'a mut AppMachine<AppCritical>) -> Self {
|
||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Critical(&machine.state.string),
|
state: AppState::Critical(&machine.state.string),
|
||||||
@ -36,8 +33,8 @@ impl<'a, MH: IMusicHoard> From<&'a mut AppMachine<MH, AppCritical>> for AppPubli
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> IAppInteractCritical for AppMachine<MH, AppCritical> {
|
impl IAppInteractCritical for AppMachine<AppCritical> {
|
||||||
type APP = App<MH>;
|
type APP = App;
|
||||||
|
|
||||||
fn no_op(self) -> Self::APP {
|
fn no_op(self) -> Self::APP {
|
||||||
self.into()
|
self.into()
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
use crate::tui::{
|
use crate::tui::app::{
|
||||||
app::{
|
machine::{App, AppInner, AppMachine},
|
||||||
machine::{App, AppInner, AppMachine},
|
AppPublic, AppState, IAppInteractError,
|
||||||
AppPublic, AppState, IAppInteractError,
|
|
||||||
},
|
|
||||||
lib::IMusicHoard,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct AppError {
|
pub struct AppError {
|
||||||
string: String,
|
string: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> AppMachine<MH, AppError> {
|
impl AppMachine<AppError> {
|
||||||
pub fn error<S: Into<String>>(inner: AppInner<MH>, string: S) -> Self {
|
pub fn error<S: Into<String>>(inner: AppInner, string: S) -> Self {
|
||||||
AppMachine {
|
AppMachine {
|
||||||
inner,
|
inner,
|
||||||
state: AppError {
|
state: AppError {
|
||||||
@ -21,14 +18,14 @@ impl<MH: IMusicHoard> AppMachine<MH, AppError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> From<AppMachine<MH, AppError>> for App<MH> {
|
impl From<AppMachine<AppError>> for App {
|
||||||
fn from(machine: AppMachine<MH, AppError>) -> Self {
|
fn from(machine: AppMachine<AppError>) -> Self {
|
||||||
AppState::Error(machine)
|
AppState::Error(machine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, MH: IMusicHoard> From<&'a mut AppMachine<MH, AppError>> for AppPublic<'a> {
|
impl<'a> From<&'a mut AppMachine<AppError>> for AppPublic<'a> {
|
||||||
fn from(machine: &'a mut AppMachine<MH, AppError>) -> Self {
|
fn from(machine: &'a mut AppMachine<AppError>) -> Self {
|
||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Error(&machine.state.string),
|
state: AppState::Error(&machine.state.string),
|
||||||
@ -36,8 +33,8 @@ impl<'a, MH: IMusicHoard> From<&'a mut AppMachine<MH, AppError>> for AppPublic<'
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> IAppInteractError for AppMachine<MH, AppError> {
|
impl IAppInteractError for AppMachine<AppError> {
|
||||||
type APP = App<MH>;
|
type APP = App;
|
||||||
|
|
||||||
fn dismiss_error(self) -> Self::APP {
|
fn dismiss_error(self) -> Self::APP {
|
||||||
AppMachine::browse(self.inner).into()
|
AppMachine::browse(self.inner).into()
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
use crate::tui::{
|
use crate::tui::app::{
|
||||||
app::{
|
machine::{App, AppInner, AppMachine},
|
||||||
machine::{App, AppInner, AppMachine},
|
AppPublic, AppState, IAppInteractInfo,
|
||||||
AppPublic, AppState, IAppInteractInfo,
|
|
||||||
},
|
|
||||||
lib::IMusicHoard,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct AppInfo;
|
pub struct AppInfo;
|
||||||
|
|
||||||
impl<MH: IMusicHoard> AppMachine<MH, AppInfo> {
|
impl AppMachine<AppInfo> {
|
||||||
pub fn info(inner: AppInner<MH>) -> Self {
|
pub fn info(inner: AppInner) -> Self {
|
||||||
AppMachine {
|
AppMachine {
|
||||||
inner,
|
inner,
|
||||||
state: AppInfo,
|
state: AppInfo,
|
||||||
@ -17,14 +14,14 @@ impl<MH: IMusicHoard> AppMachine<MH, AppInfo> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> From<AppMachine<MH, AppInfo>> for App<MH> {
|
impl From<AppMachine<AppInfo>> for App {
|
||||||
fn from(machine: AppMachine<MH, AppInfo>) -> Self {
|
fn from(machine: AppMachine<AppInfo>) -> Self {
|
||||||
AppState::Info(machine)
|
AppState::Info(machine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, MH: IMusicHoard> From<&'a mut AppMachine<MH, AppInfo>> for AppPublic<'a> {
|
impl<'a> From<&'a mut AppMachine<AppInfo>> for AppPublic<'a> {
|
||||||
fn from(machine: &'a mut AppMachine<MH, AppInfo>) -> Self {
|
fn from(machine: &'a mut AppMachine<AppInfo>) -> Self {
|
||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Info(()),
|
state: AppState::Info(()),
|
||||||
@ -32,8 +29,8 @@ impl<'a, MH: IMusicHoard> From<&'a mut AppMachine<MH, AppInfo>> for AppPublic<'a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> IAppInteractInfo for AppMachine<MH, AppInfo> {
|
impl IAppInteractInfo for AppMachine<AppInfo> {
|
||||||
type APP = App<MH>;
|
type APP = App;
|
||||||
|
|
||||||
fn hide_info_overlay(self) -> Self::APP {
|
fn hide_info_overlay(self) -> Self::APP {
|
||||||
AppMachine::browse(self.inner).into()
|
AppMachine::browse(self.inner).into()
|
||||||
|
@ -2,12 +2,9 @@ use std::cmp;
|
|||||||
|
|
||||||
use musichoard::{collection::album::Album, interface::musicbrainz::Match};
|
use musichoard::{collection::album::Album, interface::musicbrainz::Match};
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::app::{
|
||||||
app::{
|
machine::{App, AppInner, AppMachine},
|
||||||
machine::{App, AppInner, AppMachine},
|
AppPublic, AppPublicMatches, AppState, IAppInteractMatches, WidgetState,
|
||||||
AppPublic, AppPublicMatches, AppState, IAppInteractMatches, WidgetState,
|
|
||||||
},
|
|
||||||
lib::IMusicHoard,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
@ -22,8 +19,8 @@ pub struct AppMatches {
|
|||||||
state: WidgetState,
|
state: WidgetState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> AppMachine<MH, AppMatches> {
|
impl AppMachine<AppMatches> {
|
||||||
pub fn matches(inner: AppInner<MH>, matches_info_vec: Vec<AppMatchesInfo>) -> Self {
|
pub fn matches(inner: AppInner, matches_info_vec: Vec<AppMatchesInfo>) -> Self {
|
||||||
let mut index = None;
|
let mut index = None;
|
||||||
let mut state = WidgetState::default();
|
let mut state = WidgetState::default();
|
||||||
if let Some(matches_info) = matches_info_vec.first() {
|
if let Some(matches_info) = matches_info_vec.first() {
|
||||||
@ -44,14 +41,14 @@ impl<MH: IMusicHoard> AppMachine<MH, AppMatches> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> From<AppMachine<MH, AppMatches>> for App<MH> {
|
impl From<AppMachine<AppMatches>> for App {
|
||||||
fn from(machine: AppMachine<MH, AppMatches>) -> Self {
|
fn from(machine: AppMachine<AppMatches>) -> Self {
|
||||||
AppState::Matches(machine)
|
AppState::Matches(machine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, MH: IMusicHoard> From<&'a mut AppMachine<MH, AppMatches>> for AppPublic<'a> {
|
impl<'a> From<&'a mut AppMachine<AppMatches>> for AppPublic<'a> {
|
||||||
fn from(machine: &'a mut AppMachine<MH, AppMatches>) -> Self {
|
fn from(machine: &'a mut AppMachine<AppMatches>) -> Self {
|
||||||
let (matching, matches) = match machine.state.index {
|
let (matching, matches) = match machine.state.index {
|
||||||
Some(index) => (
|
Some(index) => (
|
||||||
Some(&machine.state.matches_info_vec[index].matching),
|
Some(&machine.state.matches_info_vec[index].matching),
|
||||||
@ -71,8 +68,8 @@ impl<'a, MH: IMusicHoard> From<&'a mut AppMachine<MH, AppMatches>> for AppPublic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> IAppInteractMatches for AppMachine<MH, AppMatches> {
|
impl IAppInteractMatches for AppMachine<AppMatches> {
|
||||||
type APP = App<MH>;
|
type APP = App;
|
||||||
|
|
||||||
fn prev_match(mut self) -> Self::APP {
|
fn prev_match(mut self) -> Self::APP {
|
||||||
if let Some(list_index) = self.state.state.list.selected() {
|
if let Some(list_index) = self.state.state.list.selected() {
|
||||||
|
@ -19,30 +19,30 @@ use matches::AppMatches;
|
|||||||
use reload::AppReload;
|
use reload::AppReload;
|
||||||
use search::AppSearch;
|
use search::AppSearch;
|
||||||
|
|
||||||
pub type App<MH> = AppState<
|
pub type App = AppState<
|
||||||
AppMachine<MH, AppBrowse>,
|
AppMachine<AppBrowse>,
|
||||||
AppMachine<MH, AppInfo>,
|
AppMachine<AppInfo>,
|
||||||
AppMachine<MH, AppReload>,
|
AppMachine<AppReload>,
|
||||||
AppMachine<MH, AppSearch>,
|
AppMachine<AppSearch>,
|
||||||
AppMachine<MH, AppMatches>,
|
AppMachine<AppMatches>,
|
||||||
AppMachine<MH, AppError>,
|
AppMachine<AppError>,
|
||||||
AppMachine<MH, AppCritical>,
|
AppMachine<AppCritical>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
pub struct AppMachine<MH: IMusicHoard, STATE> {
|
pub struct AppMachine<STATE> {
|
||||||
inner: AppInner<MH>,
|
inner: AppInner,
|
||||||
state: STATE,
|
state: STATE,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AppInner<MH: IMusicHoard> {
|
pub struct AppInner {
|
||||||
running: bool,
|
running: bool,
|
||||||
music_hoard: MH,
|
music_hoard: Box<dyn IMusicHoard>,
|
||||||
mb_api: Box<dyn IMusicBrainz>,
|
mb_api: Box<dyn IMusicBrainz>,
|
||||||
selection: Selection,
|
selection: Selection,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> App<MH> {
|
impl App {
|
||||||
pub fn new(mut music_hoard: MH, mb_api: Box<dyn IMusicBrainz>) -> Self {
|
pub fn new(mut music_hoard: Box<dyn IMusicHoard>, mb_api: Box<dyn IMusicBrainz>) -> Self {
|
||||||
let init_result = Self::init(&mut music_hoard);
|
let init_result = Self::init(&mut music_hoard);
|
||||||
let inner = AppInner::new(music_hoard, mb_api);
|
let inner = AppInner::new(music_hoard, mb_api);
|
||||||
match init_result {
|
match init_result {
|
||||||
@ -51,12 +51,12 @@ impl<MH: IMusicHoard> App<MH> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(music_hoard: &mut MH) -> Result<(), musichoard::Error> {
|
fn init(music_hoard: &mut Box<dyn IMusicHoard>) -> Result<(), musichoard::Error> {
|
||||||
music_hoard.rescan_library()?;
|
music_hoard.rescan_library()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inner_ref(&self) -> &AppInner<MH> {
|
fn inner_ref(&self) -> &AppInner {
|
||||||
match self {
|
match self {
|
||||||
AppState::Browse(browse) => &browse.inner,
|
AppState::Browse(browse) => &browse.inner,
|
||||||
AppState::Info(info) => &info.inner,
|
AppState::Info(info) => &info.inner,
|
||||||
@ -68,7 +68,7 @@ impl<MH: IMusicHoard> App<MH> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inner_mut(&mut self) -> &mut AppInner<MH> {
|
fn inner_mut(&mut self) -> &mut AppInner {
|
||||||
match self {
|
match self {
|
||||||
AppState::Browse(browse) => &mut browse.inner,
|
AppState::Browse(browse) => &mut browse.inner,
|
||||||
AppState::Info(info) => &mut info.inner,
|
AppState::Info(info) => &mut info.inner,
|
||||||
@ -81,14 +81,14 @@ impl<MH: IMusicHoard> App<MH> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> IAppInteract for App<MH> {
|
impl IAppInteract for App {
|
||||||
type BS = AppMachine<MH, AppBrowse>;
|
type BS = AppMachine<AppBrowse>;
|
||||||
type IS = AppMachine<MH, AppInfo>;
|
type IS = AppMachine<AppInfo>;
|
||||||
type RS = AppMachine<MH, AppReload>;
|
type RS = AppMachine<AppReload>;
|
||||||
type SS = AppMachine<MH, AppSearch>;
|
type SS = AppMachine<AppSearch>;
|
||||||
type MS = AppMachine<MH, AppMatches>;
|
type MS = AppMachine<AppMatches>;
|
||||||
type ES = AppMachine<MH, AppError>;
|
type ES = AppMachine<AppError>;
|
||||||
type CS = AppMachine<MH, AppCritical>;
|
type CS = AppMachine<AppCritical>;
|
||||||
|
|
||||||
fn is_running(&self) -> bool {
|
fn is_running(&self) -> bool {
|
||||||
self.inner_ref().running
|
self.inner_ref().running
|
||||||
@ -106,7 +106,7 @@ impl<MH: IMusicHoard> IAppInteract for App<MH> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> IAppAccess for App<MH> {
|
impl IAppAccess for App {
|
||||||
fn get(&mut self) -> AppPublic {
|
fn get(&mut self) -> AppPublic {
|
||||||
match self {
|
match self {
|
||||||
AppState::Browse(browse) => browse.into(),
|
AppState::Browse(browse) => browse.into(),
|
||||||
@ -120,8 +120,8 @@ impl<MH: IMusicHoard> IAppAccess for App<MH> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> AppInner<MH> {
|
impl AppInner {
|
||||||
pub fn new(music_hoard: MH, mb_api: Box<dyn IMusicBrainz>) -> Self {
|
pub fn new(music_hoard: Box<dyn IMusicHoard>, mb_api: Box<dyn IMusicBrainz>) -> Self {
|
||||||
let selection = Selection::new(music_hoard.get_collection());
|
let selection = Selection::new(music_hoard.get_collection());
|
||||||
AppInner {
|
AppInner {
|
||||||
running: true,
|
running: true,
|
||||||
@ -132,8 +132,8 @@ impl<MH: IMusicHoard> AppInner<MH> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, MH: IMusicHoard> From<&'a mut AppInner<MH>> for AppPublicInner<'a> {
|
impl<'a> From<&'a mut AppInner> for AppPublicInner<'a> {
|
||||||
fn from(inner: &'a mut AppInner<MH>) -> Self {
|
fn from(inner: &'a mut AppInner) -> Self {
|
||||||
AppPublicInner {
|
AppPublicInner {
|
||||||
collection: inner.music_hoard.get_collection(),
|
collection: inner.music_hoard.get_collection(),
|
||||||
selection: &mut inner.selection,
|
selection: &mut inner.selection,
|
||||||
@ -203,14 +203,14 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn music_hoard(collection: Collection) -> MockIMusicHoard {
|
pub fn music_hoard(collection: Collection) -> Box<MockIMusicHoard> {
|
||||||
let mut music_hoard = MockIMusicHoard::new();
|
let mut music_hoard = Box::new(MockIMusicHoard::new());
|
||||||
music_hoard.expect_get_collection().return_const(collection);
|
music_hoard.expect_get_collection().return_const(collection);
|
||||||
|
|
||||||
music_hoard
|
music_hoard
|
||||||
}
|
}
|
||||||
|
|
||||||
fn music_hoard_init(collection: Collection) -> MockIMusicHoard {
|
fn music_hoard_init(collection: Collection) -> Box<MockIMusicHoard> {
|
||||||
let mut music_hoard = music_hoard(collection);
|
let mut music_hoard = music_hoard(collection);
|
||||||
|
|
||||||
music_hoard
|
music_hoard
|
||||||
@ -225,14 +225,14 @@ mod tests {
|
|||||||
Box::new(MockIMusicBrainz::new())
|
Box::new(MockIMusicBrainz::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner(music_hoard: MockIMusicHoard) -> AppInner<MockIMusicHoard> {
|
pub fn inner(music_hoard: Box<MockIMusicHoard>) -> AppInner {
|
||||||
AppInner::new(music_hoard, mb_api())
|
AppInner::new(music_hoard, mb_api())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner_with_mb(
|
pub fn inner_with_mb(
|
||||||
music_hoard: MockIMusicHoard,
|
music_hoard: Box<MockIMusicHoard>,
|
||||||
mb_api: Box<MockIMusicBrainz>,
|
mb_api: Box<MockIMusicBrainz>,
|
||||||
) -> AppInner<MockIMusicHoard> {
|
) -> AppInner {
|
||||||
AppInner::new(music_hoard, mb_api)
|
AppInner::new(music_hoard, mb_api)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,7 +362,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn init_error() {
|
fn init_error() {
|
||||||
let mut music_hoard = MockIMusicHoard::new();
|
let mut music_hoard = Box::new(MockIMusicHoard::new());
|
||||||
|
|
||||||
music_hoard
|
music_hoard
|
||||||
.expect_rescan_library()
|
.expect_rescan_library()
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
use crate::tui::{
|
use crate::tui::app::{
|
||||||
app::{
|
machine::{App, AppInner, AppMachine},
|
||||||
machine::{App, AppInner, AppMachine},
|
selection::KeySelection,
|
||||||
selection::KeySelection,
|
AppPublic, AppState, IAppInteractReload,
|
||||||
AppPublic, AppState, IAppInteractReload,
|
|
||||||
},
|
|
||||||
lib::IMusicHoard,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct AppReload;
|
pub struct AppReload;
|
||||||
|
|
||||||
impl<MH: IMusicHoard> AppMachine<MH, AppReload> {
|
impl AppMachine<AppReload> {
|
||||||
pub fn reload(inner: AppInner<MH>) -> Self {
|
pub fn reload(inner: AppInner) -> Self {
|
||||||
AppMachine {
|
AppMachine {
|
||||||
inner,
|
inner,
|
||||||
state: AppReload,
|
state: AppReload,
|
||||||
@ -18,13 +15,13 @@ impl<MH: IMusicHoard> AppMachine<MH, AppReload> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> From<AppMachine<MH, AppReload>> for App<MH> {
|
impl From<AppMachine<AppReload>> for App {
|
||||||
fn from(machine: AppMachine<MH, AppReload>) -> Self {
|
fn from(machine: AppMachine<AppReload>) -> Self {
|
||||||
AppState::Reload(machine)
|
AppState::Reload(machine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a, MH: IMusicHoard> From<&'a mut AppMachine<MH, AppReload>> for AppPublic<'a> {
|
impl<'a> From<&'a mut AppMachine<AppReload>> for AppPublic<'a> {
|
||||||
fn from(machine: &'a mut AppMachine<MH, AppReload>) -> Self {
|
fn from(machine: &'a mut AppMachine<AppReload>) -> Self {
|
||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Reload(()),
|
state: AppState::Reload(()),
|
||||||
@ -32,8 +29,8 @@ impl<'a, MH: IMusicHoard> From<&'a mut AppMachine<MH, AppReload>> for AppPublic<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> IAppInteractReload for AppMachine<MH, AppReload> {
|
impl IAppInteractReload for AppMachine<AppReload> {
|
||||||
type APP = App<MH>;
|
type APP = App;
|
||||||
|
|
||||||
fn reload_library(mut self) -> Self::APP {
|
fn reload_library(mut self) -> Self::APP {
|
||||||
let previous = KeySelection::get(
|
let previous = KeySelection::get(
|
||||||
@ -62,12 +59,12 @@ impl<MH: IMusicHoard> IAppInteractReload for AppMachine<MH, AppReload> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait IAppInteractReloadPrivate<MH: IMusicHoard> {
|
trait IAppInteractReloadPrivate {
|
||||||
fn refresh(self, previous: KeySelection, result: Result<(), musichoard::Error>) -> App<MH>;
|
fn refresh(self, previous: KeySelection, result: Result<(), musichoard::Error>) -> App;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> IAppInteractReloadPrivate<MH> for AppMachine<MH, AppReload> {
|
impl IAppInteractReloadPrivate for AppMachine<AppReload> {
|
||||||
fn refresh(mut self, previous: KeySelection, result: Result<(), musichoard::Error>) -> App<MH> {
|
fn refresh(mut self, previous: KeySelection, result: Result<(), musichoard::Error>) -> App {
|
||||||
match result {
|
match result {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
self.inner
|
self.inner
|
||||||
|
@ -3,13 +3,10 @@ use once_cell::sync::Lazy;
|
|||||||
|
|
||||||
use musichoard::collection::{album::Album, artist::Artist, track::Track};
|
use musichoard::collection::{album::Album, artist::Artist, track::Track};
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::app::{
|
||||||
app::{
|
machine::{App, AppInner, AppMachine},
|
||||||
machine::{App, AppInner, AppMachine},
|
selection::{ListSelection, SelectionState},
|
||||||
selection::{ListSelection, SelectionState},
|
AppPublic, AppState, Category, IAppInteractSearch,
|
||||||
AppPublic, AppState, Category, IAppInteractSearch,
|
|
||||||
},
|
|
||||||
lib::IMusicHoard,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Unlikely that this covers all possible strings, but it should at least cover strings
|
// Unlikely that this covers all possible strings, but it should at least cover strings
|
||||||
@ -34,8 +31,8 @@ struct AppSearchMemo {
|
|||||||
char: bool,
|
char: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> AppMachine<MH, AppSearch> {
|
impl AppMachine<AppSearch> {
|
||||||
pub fn search(inner: AppInner<MH>, orig: ListSelection) -> Self {
|
pub fn search(inner: AppInner, orig: ListSelection) -> Self {
|
||||||
AppMachine {
|
AppMachine {
|
||||||
inner,
|
inner,
|
||||||
state: AppSearch {
|
state: AppSearch {
|
||||||
@ -47,14 +44,14 @@ impl<MH: IMusicHoard> AppMachine<MH, AppSearch> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> From<AppMachine<MH, AppSearch>> for App<MH> {
|
impl From<AppMachine<AppSearch>> for App {
|
||||||
fn from(machine: AppMachine<MH, AppSearch>) -> Self {
|
fn from(machine: AppMachine<AppSearch>) -> Self {
|
||||||
AppState::Search(machine)
|
AppState::Search(machine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, MH: IMusicHoard> From<&'a mut AppMachine<MH, AppSearch>> for AppPublic<'a> {
|
impl<'a> From<&'a mut AppMachine<AppSearch>> for AppPublic<'a> {
|
||||||
fn from(machine: &'a mut AppMachine<MH, AppSearch>) -> Self {
|
fn from(machine: &'a mut AppMachine<AppSearch>) -> Self {
|
||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Search(&machine.state.string),
|
state: AppState::Search(&machine.state.string),
|
||||||
@ -62,8 +59,8 @@ impl<'a, MH: IMusicHoard> From<&'a mut AppMachine<MH, AppSearch>> for AppPublic<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> IAppInteractSearch for AppMachine<MH, AppSearch> {
|
impl IAppInteractSearch for AppMachine<AppSearch> {
|
||||||
type APP = App<MH>;
|
type APP = App;
|
||||||
|
|
||||||
fn append_character(mut self, ch: char) -> Self::APP {
|
fn append_character(mut self, ch: char) -> Self::APP {
|
||||||
self.state.string.push(ch);
|
self.state.string.push(ch);
|
||||||
@ -127,7 +124,7 @@ trait IAppInteractSearchPrivate {
|
|||||||
fn normalize_search(search: &str, lowercase: bool, asciify: bool) -> String;
|
fn normalize_search(search: &str, lowercase: bool, asciify: bool) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MH: IMusicHoard> IAppInteractSearchPrivate for AppMachine<MH, AppSearch> {
|
impl IAppInteractSearchPrivate for AppMachine<AppSearch> {
|
||||||
fn incremental_search(&mut self, next: bool) {
|
fn incremental_search(&mut self, next: bool) {
|
||||||
let collection = self.inner.music_hoard.get_collection();
|
let collection = self.inner.music_hoard.get_collection();
|
||||||
let search = &self.state.string;
|
let search = &self.state.string;
|
||||||
|
@ -191,8 +191,8 @@ mod tests {
|
|||||||
Terminal::new(backend).unwrap()
|
Terminal::new(backend).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn music_hoard(collection: Collection) -> MockIMusicHoard {
|
fn music_hoard(collection: Collection) -> Box<MockIMusicHoard> {
|
||||||
let mut music_hoard = MockIMusicHoard::new();
|
let mut music_hoard = Box::new(MockIMusicHoard::new());
|
||||||
|
|
||||||
music_hoard.expect_reload_database().returning(|| Ok(()));
|
music_hoard.expect_reload_database().returning(|| Ok(()));
|
||||||
music_hoard.expect_rescan_library().returning(|| Ok(()));
|
music_hoard.expect_rescan_library().returning(|| Ok(()));
|
||||||
@ -201,7 +201,7 @@ mod tests {
|
|||||||
music_hoard
|
music_hoard
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app(collection: Collection) -> App<MockIMusicHoard> {
|
fn app(collection: Collection) -> App {
|
||||||
App::new(music_hoard(collection), Box::new(MockIMusicBrainz::new()))
|
App::new(music_hoard(collection), Box::new(MockIMusicBrainz::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,11 +216,11 @@ mod tests {
|
|||||||
listener
|
listener
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handler() -> MockIEventHandler<App<MockIMusicHoard>> {
|
fn handler() -> MockIEventHandler<App> {
|
||||||
let mut handler = MockIEventHandler::new();
|
let mut handler = MockIEventHandler::new();
|
||||||
handler
|
handler
|
||||||
.expect_handle_next_event()
|
.expect_handle_next_event()
|
||||||
.return_once(|app: App<MockIMusicHoard>| Ok(app.force_quit()));
|
.return_once(|app: App| Ok(app.force_quit()));
|
||||||
handler
|
handler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user