Compartamentalize machine traits

This commit is contained in:
Wojciech Kozlowski 2024-09-08 08:44:49 +02:00
parent 706e30f587
commit 56bf99f985
11 changed files with 54 additions and 42 deletions

View File

@ -94,7 +94,6 @@ fn with<Database: IDatabase + 'static, Library: ILibrary + 'static>(
let app = App::new(music_hoard, musicbrainz, app_sender);
let ui = Ui;
// Run the TUI application.
Tui::run(terminal, app, ui, handler, listener).expect("failed to run tui");
}

View File

@ -13,7 +13,7 @@ use crate::tui::{
app::{
machine::{App, AppInner, AppMachine},
selection::{Delta, ListSelection},
AppMatchesInfo, AppPublic, AppState, IAppInteractBrowse,
AppMatchesInfo, AppPublic, AppState, IAppBase, IAppInteractBrowse,
},
event::{Event, EventSender},
lib::interface::musicbrainz::{self, IMusicBrainz},
@ -183,6 +183,10 @@ impl IAppInteractBrowse for AppMachine<AppBrowse> {
AppMachine::app_fetch_new(self.inner, fetch_rx)
}
}
impl IAppBase for AppMachine<AppBrowse> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()

View File

@ -1,6 +1,6 @@
use crate::tui::app::{
machine::{App, AppInner, AppMachine},
AppPublic, AppState, IAppInteractCritical,
AppPublic, AppState, IAppBase,
};
pub struct AppCritical {
@ -33,7 +33,7 @@ impl<'a> From<&'a mut AppMachine<AppCritical>> for AppPublic<'a> {
}
}
impl IAppInteractCritical for AppMachine<AppCritical> {
impl IAppBase for AppMachine<AppCritical> {
type APP = App;
fn no_op(self) -> Self::APP {

View File

@ -1,6 +1,6 @@
use crate::tui::app::{
machine::{App, AppInner, AppMachine},
AppPublic, AppState, IAppInteractError,
AppPublic, AppState, IAppBase, IAppInteractError,
};
pub struct AppError {
@ -39,6 +39,10 @@ impl IAppInteractError for AppMachine<AppError> {
fn dismiss_error(self) -> Self::APP {
AppMachine::browse(self.inner).into()
}
}
impl IAppBase for AppMachine<AppError> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()

View File

@ -3,7 +3,7 @@ use std::sync::mpsc::{self, TryRecvError};
use crate::tui::{
app::{
machine::{App, AppInner, AppMachine},
AppMatchesInfo, AppPublic, AppState, IAppEventFetch, IAppInteractFetch,
AppMatchesInfo, AppPublic, AppState, IAppBase, IAppEventFetch, IAppInteractFetch,
},
lib::interface::musicbrainz::Error as MbError,
};
@ -85,6 +85,10 @@ impl IAppInteractFetch for AppMachine<AppFetch> {
fn abort(self) -> Self::APP {
AppMachine::browse(self.inner).into()
}
}
impl IAppBase for AppMachine<AppFetch> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()

View File

@ -1,6 +1,6 @@
use crate::tui::app::{
machine::{App, AppInner, AppMachine},
AppPublic, AppState, IAppInteractInfo,
AppPublic, AppState, IAppBase, IAppInteractInfo,
};
pub struct AppInfo;
@ -35,6 +35,10 @@ impl IAppInteractInfo for AppMachine<AppInfo> {
fn hide_info_overlay(self) -> Self::APP {
AppMachine::browse(self.inner).into()
}
}
impl IAppBase for AppMachine<AppInfo> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()

View File

@ -3,7 +3,7 @@ use std::cmp;
use crate::tui::app::{
machine::{App, AppInner, AppMachine},
AppAlbumMatches, AppArtistMatches, AppMatchesInfo, AppPublic, AppPublicMatches, AppState,
IAppInteractMatches, MatchOption, WidgetState,
IAppBase, IAppInteractMatches, MatchOption, WidgetState,
};
use super::fetch::AppFetch;
@ -122,6 +122,10 @@ impl IAppInteractMatches for AppMachine<AppMatches> {
fn abort(self) -> Self::APP {
AppMachine::browse(self.inner).into()
}
}
impl IAppBase for AppMachine<AppMatches> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()

View File

@ -1,7 +1,7 @@
use crate::tui::app::{
machine::{App, AppInner, AppMachine},
selection::KeySelection,
AppPublic, AppState, IAppInteractReload,
AppPublic, AppState, IAppBase, IAppInteractReload,
};
pub struct AppReload;
@ -53,6 +53,10 @@ impl IAppInteractReload for AppMachine<AppReload> {
fn hide_reload_menu(self) -> Self::APP {
AppMachine::browse(self.inner).into()
}
}
impl IAppBase for AppMachine<AppReload> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()

View File

@ -6,7 +6,7 @@ use musichoard::collection::{album::Album, artist::Artist, track::Track};
use crate::tui::app::{
machine::{App, AppInner, AppMachine},
selection::{ListSelection, SelectionState},
AppPublic, AppState, Category, IAppInteractSearch,
AppPublic, AppState, Category, IAppBase, IAppInteractSearch,
};
// Unlikely that this covers all possible strings, but it should at least cover strings
@ -98,6 +98,10 @@ impl IAppInteractSearch for AppMachine<AppSearch> {
self.inner.selection.select_by_list(self.state.orig);
AppMachine::browse(self.inner).into()
}
}
impl IAppBase for AppMachine<AppSearch> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()

View File

@ -20,14 +20,14 @@ pub enum AppState<BS, IS, RS, SS, FS, MS, ES, CS> {
}
pub trait IAppInteract {
type BS: IAppInteractBrowse<APP = Self>;
type IS: IAppInteractInfo<APP = Self>;
type RS: IAppInteractReload<APP = Self>;
type SS: IAppInteractSearch<APP = Self>;
type FS: IAppInteractFetch<APP = Self> + IAppEventFetch<APP = Self>;
type MS: IAppInteractMatches<APP = Self>;
type ES: IAppInteractError<APP = Self>;
type CS: IAppInteractCritical<APP = Self>;
type BS: IAppBase<APP = Self> + IAppInteractBrowse<APP = Self>;
type IS: IAppBase<APP = Self> + IAppInteractInfo<APP = Self>;
type RS: IAppBase<APP = Self> + IAppInteractReload<APP = Self>;
type SS: IAppBase<APP = Self> + IAppInteractSearch<APP = Self>;
type FS: IAppBase<APP = Self> + IAppInteractFetch<APP = Self> + IAppEventFetch<APP = Self>;
type MS: IAppBase<APP = Self> + IAppInteractMatches<APP = Self>;
type ES: IAppBase<APP = Self> + IAppInteractError<APP = Self>;
type CS: IAppBase<APP = Self>;
fn is_running(&self) -> bool;
fn force_quit(self) -> Self;
@ -38,6 +38,12 @@ pub trait IAppInteract {
) -> AppState<Self::BS, Self::IS, Self::RS, Self::SS, Self::FS, Self::MS, Self::ES, Self::CS>;
}
pub trait IAppBase {
type APP: IAppInteract;
fn no_op(self) -> Self::APP;
}
pub trait IAppInteractBrowse {
type APP: IAppInteract;
@ -55,16 +61,12 @@ pub trait IAppInteractBrowse {
fn begin_search(self) -> Self::APP;
fn fetch_musicbrainz(self) -> Self::APP;
fn no_op(self) -> Self::APP;
}
pub trait IAppInteractInfo {
type APP: IAppInteract;
fn hide_info_overlay(self) -> Self::APP;
fn no_op(self) -> Self::APP;
}
pub trait IAppInteractReload {
@ -73,8 +75,6 @@ pub trait IAppInteractReload {
fn reload_library(self) -> Self::APP;
fn reload_database(self) -> Self::APP;
fn hide_reload_menu(self) -> Self::APP;
fn no_op(self) -> Self::APP;
}
pub trait IAppInteractSearch {
@ -85,16 +85,12 @@ pub trait IAppInteractSearch {
fn step_back(self) -> Self::APP;
fn finish_search(self) -> Self::APP;
fn cancel_search(self) -> Self::APP;
fn no_op(self) -> Self::APP;
}
pub trait IAppInteractFetch {
type APP: IAppInteract;
fn abort(self) -> Self::APP;
fn no_op(self) -> Self::APP;
}
pub trait IAppEventFetch {
@ -111,22 +107,12 @@ pub trait IAppInteractMatches {
fn select(self) -> Self::APP;
fn abort(self) -> Self::APP;
fn no_op(self) -> Self::APP;
}
pub trait IAppInteractError {
type APP: IAppInteract;
fn dismiss_error(self) -> Self::APP;
fn no_op(self) -> Self::APP;
}
pub trait IAppInteractCritical {
type APP: IAppInteract;
fn no_op(self) -> Self::APP;
}
// It would be preferable to have a getter for each field separately. However, the selection field

View File

@ -5,14 +5,13 @@ use mockall::automock;
use crate::tui::{
app::{
AppState, Delta, IAppInteract, IAppInteractBrowse, IAppInteractCritical, IAppInteractError,
IAppInteractFetch, IAppInteractInfo, IAppInteractMatches, IAppInteractReload,
IAppInteractSearch,
AppState, Delta, IAppInteract, IAppInteractBrowse, IAppInteractError, IAppInteractFetch,
IAppInteractInfo, IAppInteractMatches, IAppInteractReload, IAppInteractSearch,
},
event::{Event, EventError, EventReceiver},
};
use super::app::IAppEventFetch;
use super::app::{IAppBase, IAppEventFetch};
#[cfg_attr(test, automock)]
pub trait IEventHandler<APP: IAppInteract> {