From c1e634b473d61effaea5aa9e60f1f324279b4e00 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Sun, 18 Feb 2024 14:24:54 +0100 Subject: [PATCH] Merge app with machine --- src/tui/app/app.rs | 96 -------------------- src/tui/app/machine/browse.rs | 3 +- src/tui/app/machine/critical.rs | 5 +- src/tui/app/machine/error.rs | 3 +- src/tui/app/machine/info.rs | 5 +- src/tui/app/machine/mod.rs | 149 +++++++++++++++++++++++--------- src/tui/app/machine/reload.rs | 4 +- src/tui/app/machine/search.rs | 7 +- src/tui/app/mod.rs | 8 +- src/tui/handler.rs | 4 +- src/tui/mod.rs | 6 +- src/tui/ui.rs | 7 +- 12 files changed, 130 insertions(+), 167 deletions(-) delete mode 100644 src/tui/app/app.rs diff --git a/src/tui/app/app.rs b/src/tui/app/app.rs deleted file mode 100644 index 4d0c7ec..0000000 --- a/src/tui/app/app.rs +++ /dev/null @@ -1,96 +0,0 @@ -// FIXME: combine with mod state into a mod machine -#![allow(clippy::module_inception)] - -use crate::tui::{ - app::{ - machine::{ - browse::AppBrowse, critical::AppCritical, error::AppError, info::AppInfo, - reload::AppReload, search::AppSearch, AppInner, AppMachine, - }, - AppPublic, AppState, IAppAccess, IAppInteract, - }, - lib::IMusicHoard, -}; - -pub type App = AppState< - AppMachine, - AppMachine, - AppMachine, - AppMachine, - AppMachine, - AppMachine, ->; - -impl App { - pub fn new(mut music_hoard: MH) -> Self { - let init_result = Self::init(&mut music_hoard); - let inner = AppInner::new(music_hoard); - match init_result { - Ok(()) => AppMachine::browse(inner).into(), - Err(err) => AppMachine::critical(inner, err.to_string()).into(), - } - } - - fn init(music_hoard: &mut MH) -> Result<(), musichoard::Error> { - music_hoard.load_from_database()?; - music_hoard.rescan_library()?; - Ok(()) - } - - fn inner_ref(&self) -> &AppInner { - match self { - AppState::Browse(browse) => browse.inner_ref(), - AppState::Info(info) => info.inner_ref(), - AppState::Reload(reload) => reload.inner_ref(), - AppState::Search(search) => search.inner_ref(), - AppState::Error(error) => error.inner_ref(), - AppState::Critical(critical) => critical.inner_ref(), - } - } - - fn inner_mut(&mut self) -> &mut AppInner { - match self { - AppState::Browse(browse) => browse.inner_mut(), - AppState::Info(info) => info.inner_mut(), - AppState::Reload(reload) => reload.inner_mut(), - AppState::Search(search) => search.inner_mut(), - AppState::Error(error) => error.inner_mut(), - AppState::Critical(critical) => critical.inner_mut(), - } - } -} - -impl IAppInteract for App { - type BS = AppMachine; - type IS = AppMachine; - type RS = AppMachine; - type SS = AppMachine; - type ES = AppMachine; - type CS = AppMachine; - - fn is_running(&self) -> bool { - self.inner_ref().is_running() - } - - fn force_quit(mut self) -> Self { - self.inner_mut().stop(); - self - } - - fn state(self) -> AppState { - self - } -} - -impl IAppAccess for App { - fn get(&mut self) -> AppPublic { - match self { - AppState::Browse(browse) => browse.into(), - AppState::Info(info) => info.into(), - AppState::Reload(reload) => reload.into(), - AppState::Search(search) => search.into(), - AppState::Error(error) => error.into(), - AppState::Critical(critical) => critical.into(), - } - } -} diff --git a/src/tui/app/machine/browse.rs b/src/tui/app/machine/browse.rs index d7ad5c7..abc73d8 100644 --- a/src/tui/app/machine/browse.rs +++ b/src/tui/app/machine/browse.rs @@ -1,7 +1,6 @@ use crate::tui::{ app::{ - app::App, - machine::{AppInner, AppMachine}, + machine::{App, AppInner, AppMachine}, selection::{Delta, ListSelection}, AppPublic, AppState, IAppInteractBrowse, }, diff --git a/src/tui/app/machine/critical.rs b/src/tui/app/machine/critical.rs index a02d7f2..5fe911d 100644 --- a/src/tui/app/machine/critical.rs +++ b/src/tui/app/machine/critical.rs @@ -1,7 +1,6 @@ use crate::tui::{ app::{ - app::App, - machine::{AppInner, AppMachine}, + machine::{App, AppInner, AppMachine}, AppPublic, AppState, IAppInteractCritical, }, lib::IMusicHoard, @@ -47,7 +46,7 @@ impl IAppInteractCritical for AppMachine { #[cfg(test)] mod tests { - use crate::tui::app::machine::tests::{music_hoard, inner}; + use crate::tui::app::machine::tests::{inner, music_hoard}; use super::*; diff --git a/src/tui/app/machine/error.rs b/src/tui/app/machine/error.rs index 006d4cf..63239d5 100644 --- a/src/tui/app/machine/error.rs +++ b/src/tui/app/machine/error.rs @@ -1,7 +1,6 @@ use crate::tui::{ app::{ - app::App, - machine::{AppInner, AppMachine}, + machine::{App, AppInner, AppMachine}, AppPublic, AppState, IAppInteractError, }, lib::IMusicHoard, diff --git a/src/tui/app/machine/info.rs b/src/tui/app/machine/info.rs index 0b82292..203bb74 100644 --- a/src/tui/app/machine/info.rs +++ b/src/tui/app/machine/info.rs @@ -1,7 +1,6 @@ use crate::tui::{ app::{ - app::App, - machine::{AppInner, AppMachine}, + machine::{App, AppInner, AppMachine}, AppPublic, AppState, IAppInteractInfo, }, lib::IMusicHoard, @@ -47,7 +46,7 @@ impl IAppInteractInfo for AppMachine { #[cfg(test)] mod tests { - use crate::tui::app::machine::tests::{music_hoard, inner}; + use crate::tui::app::machine::tests::{inner, music_hoard}; use super::*; diff --git a/src/tui/app/machine/mod.rs b/src/tui/app/machine/mod.rs index 986f3a2..47c73a8 100644 --- a/src/tui/app/machine/mod.rs +++ b/src/tui/app/machine/mod.rs @@ -1,36 +1,116 @@ -pub mod browse; -pub mod critical; -pub mod error; -pub mod info; -pub mod reload; -pub mod search; +mod browse; +mod critical; +mod error; +mod info; +mod reload; +mod search; use crate::tui::{ - app::{selection::Selection, AppPublicInner}, + app::{selection::Selection, AppPublic, AppPublicInner, AppState, IAppAccess, IAppInteract}, lib::IMusicHoard, }; +use browse::AppBrowse; +use critical::AppCritical; +use error::AppError; +use info::AppInfo; +use reload::AppReload; +use search::AppSearch; + +pub type App = AppState< + AppMachine, + AppMachine, + AppMachine, + AppMachine, + AppMachine, + AppMachine, +>; + pub struct AppMachine { inner: AppInner, state: STATE, } -impl AppMachine { - pub fn inner_ref(&self) -> &AppInner { - &self.inner - } - - pub fn inner_mut(&mut self) -> &mut AppInner { - &mut self.inner - } -} - pub struct AppInner { running: bool, music_hoard: MH, selection: Selection, } +impl App { + pub fn new(mut music_hoard: MH) -> Self { + let init_result = Self::init(&mut music_hoard); + let inner = AppInner::new(music_hoard); + match init_result { + Ok(()) => AppMachine::browse(inner).into(), + Err(err) => AppMachine::critical(inner, err.to_string()).into(), + } + } + + fn init(music_hoard: &mut MH) -> Result<(), musichoard::Error> { + music_hoard.load_from_database()?; + music_hoard.rescan_library()?; + Ok(()) + } + + fn inner_ref(&self) -> &AppInner { + match self { + AppState::Browse(browse) => &browse.inner, + AppState::Info(info) => &info.inner, + AppState::Reload(reload) => &reload.inner, + AppState::Search(search) => &search.inner, + AppState::Error(error) => &error.inner, + AppState::Critical(critical) => &critical.inner, + } + } + + fn inner_mut(&mut self) -> &mut AppInner { + match self { + AppState::Browse(browse) => &mut browse.inner, + AppState::Info(info) => &mut info.inner, + AppState::Reload(reload) => &mut reload.inner, + AppState::Search(search) => &mut search.inner, + AppState::Error(error) => &mut error.inner, + AppState::Critical(critical) => &mut critical.inner, + } + } +} + +impl IAppInteract for App { + type BS = AppMachine; + type IS = AppMachine; + type RS = AppMachine; + type SS = AppMachine; + type ES = AppMachine; + type CS = AppMachine; + + fn is_running(&self) -> bool { + self.inner_ref().running + } + + fn force_quit(mut self) -> Self { + self.inner_mut().running = false; + self + } + + fn state(self) -> AppState { + self + } +} + +impl IAppAccess for App { + fn get(&mut self) -> AppPublic { + match self { + AppState::Browse(browse) => browse.into(), + AppState::Info(info) => info.into(), + AppState::Reload(reload) => reload.into(), + AppState::Search(search) => search.into(), + AppState::Error(error) => error.into(), + AppState::Critical(critical) => critical.into(), + } + } +} + impl AppInner { pub fn new(music_hoard: MH) -> Self { let selection = Selection::new(music_hoard.get_collection()); @@ -40,14 +120,6 @@ impl AppInner { selection, } } - - pub fn is_running(&self) -> bool { - self.running - } - - pub fn stop(&mut self) { - self.running = false; - } } impl<'a, MH: IMusicHoard> From<&'a mut AppInner> for AppPublicInner<'a> { @@ -59,14 +131,12 @@ impl<'a, MH: IMusicHoard> From<&'a mut AppInner> for AppPublicInner<'a> { } } -// FIXME: split tests - into parts that test functionality in isolation and move those where -// appropriate, and parts that verify transitions between states. #[cfg(test)] mod tests { use musichoard::collection::Collection; use crate::tui::{ - app::{app::App, AppState, IAppInteract}, + app::{AppState, IAppInteract}, lib::MockIMusicHoard, testmod::COLLECTION, }; @@ -117,8 +187,15 @@ mod tests { } } - fn music_hoard_app(collection: Collection) -> MockIMusicHoard { + pub fn music_hoard(collection: Collection) -> MockIMusicHoard { let mut music_hoard = MockIMusicHoard::new(); + music_hoard.expect_get_collection().return_const(collection); + + music_hoard + } + + fn music_hoard_init(collection: Collection) -> MockIMusicHoard { + let mut music_hoard = music_hoard(collection); music_hoard .expect_load_from_database() @@ -128,14 +205,6 @@ mod tests { .expect_rescan_library() .times(1) .return_once(|| Ok(())); - music_hoard.expect_get_collection().return_const(collection); - - music_hoard - } - - pub fn music_hoard(collection: Collection) -> MockIMusicHoard { - let mut music_hoard = MockIMusicHoard::new(); - music_hoard.expect_get_collection().return_const(collection); music_hoard } @@ -145,8 +214,8 @@ mod tests { } #[test] - fn running_force_quit() { - let app = App::new(music_hoard_app(COLLECTION.to_owned())); + fn force_quit() { + let app = App::new(music_hoard_init(COLLECTION.to_owned())); assert!(app.is_running()); let app = app.force_quit(); @@ -155,7 +224,7 @@ mod tests { #[test] fn error_force_quit() { - let mut app = App::new(music_hoard_app(COLLECTION.to_owned())); + let mut app = App::new(music_hoard_init(COLLECTION.to_owned())); assert!(app.is_running()); app = AppMachine::error(app.unwrap_browse().inner, "get rekt").into(); diff --git a/src/tui/app/machine/reload.rs b/src/tui/app/machine/reload.rs index 55d276d..19a0164 100644 --- a/src/tui/app/machine/reload.rs +++ b/src/tui/app/machine/reload.rs @@ -1,8 +1,7 @@ use crate::tui::{ app::{ - app::App, + machine::{App, AppInner, AppMachine}, selection::IdSelection, - machine::{AppInner, AppMachine}, AppPublic, AppState, IAppInteractReload, }, lib::IMusicHoard, @@ -94,7 +93,6 @@ mod tests { app.unwrap_browse(); } - #[test] fn reload_database() { let mut music_hoard = music_hoard(vec![]); diff --git a/src/tui/app/machine/search.rs b/src/tui/app/machine/search.rs index 6273799..783e816 100644 --- a/src/tui/app/machine/search.rs +++ b/src/tui/app/machine/search.rs @@ -2,9 +2,8 @@ use musichoard::collection::artist::Artist; use crate::tui::{ app::{ - app::App, + machine::{App, AppInner, AppMachine}, selection::ListSelection, - machine::{AppInner, AppMachine}, AppPublic, AppState, IAppInteractSearch, }, lib::IMusicHoard, @@ -99,7 +98,7 @@ trait IAppInteractSearchPrivate { fn incremental_search_predicate( case_sensitive: bool, char_sensitive: bool, - search_name: &String, + search_name: &str, probe: &Artist, ) -> bool; @@ -137,7 +136,7 @@ impl IAppInteractSearchPrivate for AppMachine { fn incremental_search_predicate( case_sensitive: bool, char_sensitive: bool, - search_name: &String, + search_name: &str, probe: &Artist, ) -> bool { let name = Self::normalize_search(&probe.id.name, !case_sensitive, !char_sensitive); diff --git a/src/tui/app/mod.rs b/src/tui/app/mod.rs index 59fc2bb..66f612a 100644 --- a/src/tui/app/mod.rs +++ b/src/tui/app/mod.rs @@ -1,11 +1,11 @@ -pub mod app; -pub mod selection; mod machine; +mod selection; + +pub use machine::App; +pub use selection::{Category, Delta, Selection, WidgetState}; use musichoard::collection::Collection; -use selection::{Delta, Selection}; - pub enum AppState { Browse(BS), Info(IS), diff --git a/src/tui/handler.rs b/src/tui/handler.rs index be88bb2..1f63d5d 100644 --- a/src/tui/handler.rs +++ b/src/tui/handler.rs @@ -5,8 +5,8 @@ use mockall::automock; use crate::tui::{ app::{ - selection::Delta, AppState, IAppInteract, IAppInteractBrowse, IAppInteractCritical, - IAppInteractError, IAppInteractInfo, IAppInteractReload, IAppInteractSearch, + AppState, Delta, IAppInteract, IAppInteractBrowse, IAppInteractCritical, IAppInteractError, + IAppInteractInfo, IAppInteractReload, IAppInteractSearch, }, event::{Event, EventError, EventReceiver}, }; diff --git a/src/tui/mod.rs b/src/tui/mod.rs index 629ecaa..e11acb6 100644 --- a/src/tui/mod.rs +++ b/src/tui/mod.rs @@ -5,7 +5,7 @@ mod lib; mod listener; mod ui; -pub use app::app::App; +pub use app::App; pub use event::EventChannel; pub use handler::EventHandler; pub use listener::EventListener; @@ -178,8 +178,8 @@ mod tests { use musichoard::collection::Collection; use crate::tui::{ - app::app::App, handler::MockIEventHandler, lib::MockIMusicHoard, - listener::MockIEventListener, ui::Ui, + app::App, handler::MockIEventHandler, lib::MockIMusicHoard, listener::MockIEventListener, + ui::Ui, }; use super::*; diff --git a/src/tui/ui.rs b/src/tui/ui.rs index 80536a9..289035a 100644 --- a/src/tui/ui.rs +++ b/src/tui/ui.rs @@ -13,10 +13,7 @@ use ratatui::{ Frame, }; -use crate::tui::app::{ - selection::{Category, Selection, WidgetState}, - AppPublicState, AppState, IAppAccess, -}; +use crate::tui::app::{AppPublicState, AppState, Category, IAppAccess, Selection, WidgetState}; pub trait IUi { fn render(app: &mut APP, frame: &mut Frame); @@ -695,7 +692,7 @@ impl IUi for Ui { #[cfg(test)] mod tests { use crate::tui::{ - app::{selection::Delta, AppPublic, AppPublicInner}, + app::{AppPublic, AppPublicInner, Delta}, testmod::COLLECTION, tests::terminal, };