From e4c77c982d0c1a7be3ccb111001e9048abb14e5e Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Sun, 15 Sep 2024 10:23:44 +0200 Subject: [PATCH] Make input part of machine to reset between states --- src/tui/app/machine/browse_state.rs | 16 +++------- src/tui/app/machine/critical_state.rs | 26 +++++++-------- src/tui/app/machine/error_state.rs | 26 +++++++-------- src/tui/app/machine/fetch_state.rs | 13 +++----- src/tui/app/machine/info_state.rs | 16 +++------- src/tui/app/machine/input.rs | 2 +- src/tui/app/machine/match_state.rs | 21 ++++-------- src/tui/app/machine/mod.rs | 46 +++++++++++++++++++++++---- src/tui/app/machine/reload_state.rs | 17 ++++------ src/tui/app/machine/search_state.rs | 30 ++++++++--------- src/tui/app/mod.rs | 2 +- src/tui/ui/mod.rs | 9 ++++-- 12 files changed, 116 insertions(+), 108 deletions(-) diff --git a/src/tui/app/machine/browse_state.rs b/src/tui/app/machine/browse_state.rs index 2e71f73..06c8cfb 100644 --- a/src/tui/app/machine/browse_state.rs +++ b/src/tui/app/machine/browse_state.rs @@ -1,17 +1,14 @@ use crate::tui::app::{ machine::{App, AppInner, AppMachine}, selection::{Delta, ListSelection}, - AppPublic, AppState, IAppInteractBrowse, + AppPublicState, AppState, IAppInteractBrowse, }; pub struct BrowseState; impl AppMachine { pub fn browse_state(inner: AppInner) -> Self { - AppMachine { - inner, - state: BrowseState, - } + AppMachine::new(inner, BrowseState) } } @@ -21,12 +18,9 @@ impl From> for App { } } -impl<'a> From<&'a mut AppMachine> for AppPublic<'a> { - fn from(machine: &'a mut AppMachine) -> Self { - AppPublic { - inner: (&mut machine.inner).into(), - state: AppState::Browse(()), - } +impl<'a> From<&'a mut BrowseState> for AppPublicState<'a> { + fn from(_state: &'a mut BrowseState) -> Self { + AppState::Browse(()) } } diff --git a/src/tui/app/machine/critical_state.rs b/src/tui/app/machine/critical_state.rs index 9242cbc..b6268c3 100644 --- a/src/tui/app/machine/critical_state.rs +++ b/src/tui/app/machine/critical_state.rs @@ -1,20 +1,23 @@ use crate::tui::app::{ machine::{App, AppInner, AppMachine}, - AppPublic, AppState, + AppPublicState, AppState, }; pub struct CriticalState { string: String, } +impl CriticalState { + fn new>(string: S) -> Self { + CriticalState { + string: string.into(), + } + } +} + impl AppMachine { pub fn critical_state>(inner: AppInner, string: S) -> Self { - AppMachine { - inner, - state: CriticalState { - string: string.into(), - }, - } + AppMachine::new(inner, CriticalState::new(string)) } } @@ -24,11 +27,8 @@ impl From> for App { } } -impl<'a> From<&'a mut AppMachine> for AppPublic<'a> { - fn from(machine: &'a mut AppMachine) -> Self { - AppPublic { - inner: (&mut machine.inner).into(), - state: AppState::Critical(&machine.state.string), - } +impl<'a> From<&'a mut CriticalState> for AppPublicState<'a> { + fn from(state: &'a mut CriticalState) -> Self { + AppState::Critical(&state.string) } } diff --git a/src/tui/app/machine/error_state.rs b/src/tui/app/machine/error_state.rs index 2150b2d..0ff6561 100644 --- a/src/tui/app/machine/error_state.rs +++ b/src/tui/app/machine/error_state.rs @@ -1,20 +1,23 @@ use crate::tui::app::{ machine::{App, AppInner, AppMachine}, - AppPublic, AppState, IAppInteractError, + AppPublicState, AppState, IAppInteractError, }; pub struct ErrorState { string: String, } +impl ErrorState { + fn new>(string: S) -> Self { + ErrorState { + string: string.into(), + } + } +} + impl AppMachine { pub fn error_state>(inner: AppInner, string: S) -> Self { - AppMachine { - inner, - state: ErrorState { - string: string.into(), - }, - } + AppMachine::new(inner, ErrorState::new(string)) } } @@ -24,12 +27,9 @@ impl From> for App { } } -impl<'a> From<&'a mut AppMachine> for AppPublic<'a> { - fn from(machine: &'a mut AppMachine) -> Self { - AppPublic { - inner: (&mut machine.inner).into(), - state: AppState::Error(&machine.state.string), - } +impl<'a> From<&'a mut ErrorState> for AppPublicState<'a> { + fn from(state: &'a mut ErrorState) -> Self { + AppState::Error(&state.string) } } diff --git a/src/tui/app/machine/fetch_state.rs b/src/tui/app/machine/fetch_state.rs index 78d09eb..275e5f9 100644 --- a/src/tui/app/machine/fetch_state.rs +++ b/src/tui/app/machine/fetch_state.rs @@ -15,7 +15,7 @@ use musichoard::collection::{ use crate::tui::{ app::{ machine::{App, AppInner, AppMachine}, - AppPublic, AppState, IAppEventFetch, IAppInteractFetch, MatchStateInfo, + AppPublicState, AppState, IAppEventFetch, IAppInteractFetch, MatchStateInfo, }, event::{Event, EventSender}, lib::interface::musicbrainz::{self, Error as MbError, IMusicBrainz}, @@ -40,7 +40,7 @@ pub type FetchReceiver = mpsc::Receiver; impl AppMachine { fn fetch_state(inner: AppInner, state: FetchState) -> Self { - AppMachine { inner, state } + AppMachine::new(inner, state) } pub fn app_fetch_new(inner: AppInner) -> App { @@ -168,12 +168,9 @@ impl From> for App { } } -impl<'a> From<&'a mut AppMachine> for AppPublic<'a> { - fn from(machine: &'a mut AppMachine) -> Self { - AppPublic { - inner: (&mut machine.inner).into(), - state: AppState::Fetch(()), - } +impl<'a> From<&'a mut FetchState> for AppPublicState<'a> { + fn from(_state: &'a mut FetchState) -> Self { + AppState::Fetch(()) } } diff --git a/src/tui/app/machine/info_state.rs b/src/tui/app/machine/info_state.rs index a4e5ef6..9dd7ddc 100644 --- a/src/tui/app/machine/info_state.rs +++ b/src/tui/app/machine/info_state.rs @@ -1,16 +1,13 @@ use crate::tui::app::{ machine::{App, AppInner, AppMachine}, - AppPublic, AppState, IAppInteractInfo, + AppPublicState, AppState, IAppInteractInfo, }; pub struct InfoState; impl AppMachine { pub fn info_state(inner: AppInner) -> Self { - AppMachine { - inner, - state: InfoState, - } + AppMachine::new(inner, InfoState) } } @@ -20,12 +17,9 @@ impl From> for App { } } -impl<'a> From<&'a mut AppMachine> for AppPublic<'a> { - fn from(machine: &'a mut AppMachine) -> Self { - AppPublic { - inner: (&mut machine.inner).into(), - state: AppState::Info(()), - } +impl<'a> From<&'a mut InfoState> for AppPublicState<'a> { + fn from(_state: &'a mut InfoState) -> Self { + AppState::Info(()) } } diff --git a/src/tui/app/machine/input.rs b/src/tui/app/machine/input.rs index 5653cf9..d1873ff 100644 --- a/src/tui/app/machine/input.rs +++ b/src/tui/app/machine/input.rs @@ -20,7 +20,7 @@ impl IAppInput for AppInputMode { self.input .0 .handle_event(&crossterm::event::Event::Key(input)); - self.app.inner_mut().input.replace(self.input); + self.app.input_mut().replace(self.input); self.app } diff --git a/src/tui/app/machine/match_state.rs b/src/tui/app/machine/match_state.rs index 085d7ce..3414cbb 100644 --- a/src/tui/app/machine/match_state.rs +++ b/src/tui/app/machine/match_state.rs @@ -2,7 +2,7 @@ use std::cmp; use crate::tui::app::{ machine::{App, AppInner, AppMachine}, - AlbumMatches, AppPublic, AppState, ArtistMatches, IAppInteractMatch, MatchOption, + AlbumMatches, AppPublicState, AppState, ArtistMatches, IAppInteractMatch, MatchOption, MatchStateInfo, MatchStatePublic, WidgetState, }; @@ -98,7 +98,7 @@ impl MatchState { impl AppMachine { pub fn match_state(inner: AppInner, state: MatchState) -> Self { - AppMachine { inner, state } + AppMachine::new(inner, state) } pub fn submit_input(&mut self, _input: Input) {} @@ -110,21 +110,12 @@ impl From> for App { } } -impl<'a> From<&'a mut MatchState> for MatchStatePublic<'a> { +impl<'a> From<&'a mut MatchState> for AppPublicState<'a> { fn from(state: &'a mut MatchState) -> Self { - MatchStatePublic { + AppState::Match(MatchStatePublic { info: state.current.as_ref().map(Into::into), state: &mut state.state, - } - } -} - -impl<'a> From<&'a mut AppMachine> for AppPublic<'a> { - fn from(machine: &'a mut AppMachine) -> Self { - AppPublic { - inner: (&mut machine.inner).into(), - state: AppState::Match((&mut machine.state).into()), - } + }) } } @@ -164,7 +155,7 @@ impl IAppInteractMatch for AppMachine { .unwrap() .is_manual_input_mbid(index) { - self.inner.input = Some(Input::default()); + self.input.replace(Input::default()); return self.into(); } } diff --git a/src/tui/app/machine/mod.rs b/src/tui/app/machine/mod.rs index 5aee12b..acabcd1 100644 --- a/src/tui/app/machine/mod.rs +++ b/src/tui/app/machine/mod.rs @@ -26,7 +26,7 @@ use match_state::MatchState; use reload_state::ReloadState; use search_state::SearchState; -use super::{AppMode, IAppBase, IAppState}; +use super::{AppMode, AppPublicState, IAppBase, IAppState}; pub type App = AppState< AppMachine, @@ -42,6 +42,7 @@ pub type App = AppState< pub struct AppMachine { inner: AppInner, state: STATE, + input: Option, } pub struct AppInner { @@ -50,7 +51,6 @@ pub struct AppInner { musicbrainz: Arc>, selection: Selection, events: EventSender, - input: Option, } pub struct AppInputMode { @@ -108,6 +108,19 @@ impl App { AppState::Critical(critical_state) => &mut critical_state.inner, } } + + fn input_mut(&mut self) -> &mut Option { + match self { + AppState::Browse(state) => &mut state.input, + AppState::Info(state) => &mut state.input, + AppState::Reload(state) => &mut state.input, + AppState::Search(state) => &mut state.input, + AppState::Fetch(state) => &mut state.input, + AppState::Match(state) => &mut state.input, + AppState::Error(state) => &mut state.input, + AppState::Critical(state) => &mut state.input, + } + } } impl IApp for App { @@ -135,7 +148,7 @@ impl IApp for App { } fn mode(mut self) -> super::AppMode { - if let Some(input) = self.inner_mut().input.take() { + if let Some(input) = self.input_mut().take() { AppMode::Input(AppInputMode::new(input, self.state())) } else { AppMode::State(self.state()) @@ -179,7 +192,6 @@ impl AppInner { musicbrainz: Arc::new(Mutex::new(musicbrainz)), selection, events, - input: None, } } } @@ -189,7 +201,29 @@ impl<'a> From<&'a mut AppInner> for AppPublicInner<'a> { AppPublicInner { collection: inner.music_hoard.get_collection(), selection: &mut inner.selection, - input: inner.input.as_ref().map(Into::into), + } + } +} + +impl AppMachine { + pub fn new(inner: AppInner, state: State) -> Self { + AppMachine { + inner, + state, + input: None, + } + } +} + +impl<'a, State> From<&'a mut AppMachine> for AppPublic<'a> +where + &'a mut State: Into>, +{ + fn from(machine: &'a mut AppMachine) -> Self { + AppPublic { + inner: (&mut machine.inner).into(), + state: (&mut machine.state).into(), + input: machine.input.as_ref().map(Into::into), } } } @@ -418,7 +452,7 @@ mod tests { let (_, rx) = mpsc::channel(); let inner = app.unwrap_browse().inner; let state = FetchState::new(rx); - app = AppMachine { inner, state }.into(); + app = AppMachine::new(inner, state).into(); let state = app.state(); assert!(matches!(state, AppState::Fetch(_))); diff --git a/src/tui/app/machine/reload_state.rs b/src/tui/app/machine/reload_state.rs index 4c9323f..25def5b 100644 --- a/src/tui/app/machine/reload_state.rs +++ b/src/tui/app/machine/reload_state.rs @@ -1,17 +1,14 @@ use crate::tui::app::{ machine::{App, AppInner, AppMachine}, selection::KeySelection, - AppPublic, AppState, IAppInteractReload, + AppPublicState, AppState, IAppInteractReload, }; pub struct ReloadState; impl AppMachine { pub fn reload_state(inner: AppInner) -> Self { - AppMachine { - inner, - state: ReloadState, - } + AppMachine::new(inner, ReloadState) } } @@ -20,12 +17,10 @@ impl From> for App { AppState::Reload(machine) } } -impl<'a> From<&'a mut AppMachine> for AppPublic<'a> { - fn from(machine: &'a mut AppMachine) -> Self { - AppPublic { - inner: (&mut machine.inner).into(), - state: AppState::Reload(()), - } + +impl<'a> From<&'a mut ReloadState> for AppPublicState<'a> { + fn from(_state: &'a mut ReloadState) -> Self { + AppState::Reload(()) } } diff --git a/src/tui/app/machine/search_state.rs b/src/tui/app/machine/search_state.rs index a658dd1..dbcb9d8 100644 --- a/src/tui/app/machine/search_state.rs +++ b/src/tui/app/machine/search_state.rs @@ -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, + AppPublicState, AppState, Category, IAppInteractSearch, }; // Unlikely that this covers all possible strings, but it should at least cover strings @@ -31,16 +31,19 @@ struct SearchStateMemo { char: bool, } +impl SearchState { + fn new(orig: ListSelection) -> Self { + SearchState { + string: String::new(), + orig, + memo: vec![], + } + } +} + impl AppMachine { pub fn search_state(inner: AppInner, orig: ListSelection) -> Self { - AppMachine { - inner, - state: SearchState { - string: String::new(), - orig, - memo: vec![], - }, - } + AppMachine::new(inner, SearchState::new(orig)) } } @@ -50,12 +53,9 @@ impl From> for App { } } -impl<'a> From<&'a mut AppMachine> for AppPublic<'a> { - fn from(machine: &'a mut AppMachine) -> Self { - AppPublic { - inner: (&mut machine.inner).into(), - state: AppState::Search(&machine.state.string), - } +impl<'a> From<&'a mut SearchState> for AppPublicState<'a> { + fn from(state: &'a mut SearchState) -> Self { + AppState::Search(&state.string) } } diff --git a/src/tui/app/mod.rs b/src/tui/app/mod.rs index 644f7f7..3506fd5 100644 --- a/src/tui/app/mod.rs +++ b/src/tui/app/mod.rs @@ -151,12 +151,12 @@ pub trait IAppAccess { pub struct AppPublic<'app> { pub inner: AppPublicInner<'app>, pub state: AppPublicState<'app>, + pub input: Option>, } pub struct AppPublicInner<'app> { pub collection: &'app Collection, pub selection: &'app mut Selection, - pub input: Option>, } pub type InputPublic<'app> = &'app tui_input::Input; diff --git a/src/tui/ui/mod.rs b/src/tui/ui/mod.rs index 70573c8..51306c6 100644 --- a/src/tui/ui/mod.rs +++ b/src/tui/ui/mod.rs @@ -191,7 +191,7 @@ impl IUi for Ui { _ => {} } - if let Some(input) = app.inner.input { + if let Some(input) = app.input { Self::render_input_overlay(input, frame); } } @@ -220,7 +220,6 @@ mod tests { inner: AppPublicInner { collection: self.inner.collection, selection: self.inner.selection, - input: self.inner.input, }, state: match self.state { AppState::Browse(()) => AppState::Browse(()), @@ -235,6 +234,7 @@ mod tests { AppState::Error(s) => AppState::Error(s), AppState::Critical(s) => AppState::Critical(s), }, + input: self.input, } } } @@ -246,7 +246,6 @@ mod tests { AppPublicInner { collection, selection, - input: None, } } @@ -268,6 +267,7 @@ mod tests { let mut app = AppPublic { inner: public_inner(collection, selection), state: AppState::Browse(()), + input: None, }; terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap(); @@ -346,6 +346,7 @@ mod tests { info: None, state: &mut widget_state, }), + input: None, }; terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap(); } @@ -375,6 +376,7 @@ mod tests { info: Some(&artist_matches), state: &mut widget_state, }), + input: None, }; terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap(); } @@ -409,6 +411,7 @@ mod tests { info: Some(&album_matches), state: &mut widget_state, }), + input: None, }; terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap(); }