Input no longer a state
This commit is contained in:
parent
09e1cb7fda
commit
8acf208968
@ -11,6 +11,7 @@ impl AppMachine<BrowseState> {
|
|||||||
AppMachine {
|
AppMachine {
|
||||||
inner,
|
inner,
|
||||||
state: BrowseState,
|
state: BrowseState,
|
||||||
|
input: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -26,6 +27,7 @@ impl<'a> From<&'a mut AppMachine<BrowseState>> for AppPublic<'a> {
|
|||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Browse(()),
|
state: AppState::Browse(()),
|
||||||
|
input: (&machine.input.as_ref()).map(Into::into),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ impl AppMachine<CriticalState> {
|
|||||||
state: CriticalState {
|
state: CriticalState {
|
||||||
string: string.into(),
|
string: string.into(),
|
||||||
},
|
},
|
||||||
|
input: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,6 +30,7 @@ impl<'a> From<&'a mut AppMachine<CriticalState>> for AppPublic<'a> {
|
|||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Critical(&machine.state.string),
|
state: AppState::Critical(&machine.state.string),
|
||||||
|
input: (&machine.input.as_ref()).map(Into::into),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ impl AppMachine<ErrorState> {
|
|||||||
state: ErrorState {
|
state: ErrorState {
|
||||||
string: string.into(),
|
string: string.into(),
|
||||||
},
|
},
|
||||||
|
input: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,6 +30,7 @@ impl<'a> From<&'a mut AppMachine<ErrorState>> for AppPublic<'a> {
|
|||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Error(&machine.state.string),
|
state: AppState::Error(&machine.state.string),
|
||||||
|
input: (&machine.input.as_ref()).map(Into::into),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,11 @@ pub type FetchReceiver = mpsc::Receiver<FetchResult>;
|
|||||||
|
|
||||||
impl AppMachine<FetchState> {
|
impl AppMachine<FetchState> {
|
||||||
fn fetch_state(inner: AppInner, state: FetchState) -> Self {
|
fn fetch_state(inner: AppInner, state: FetchState) -> Self {
|
||||||
AppMachine { inner, state }
|
AppMachine {
|
||||||
|
inner,
|
||||||
|
state,
|
||||||
|
input: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn app_fetch_new(inner: AppInner) -> App {
|
pub fn app_fetch_new(inner: AppInner) -> App {
|
||||||
@ -173,6 +177,7 @@ impl<'a> From<&'a mut AppMachine<FetchState>> for AppPublic<'a> {
|
|||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Fetch(()),
|
state: AppState::Fetch(()),
|
||||||
|
input: (&machine.input.as_ref()).map(Into::into),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ impl AppMachine<InfoState> {
|
|||||||
AppMachine {
|
AppMachine {
|
||||||
inner,
|
inner,
|
||||||
state: InfoState,
|
state: InfoState,
|
||||||
|
input: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -25,6 +26,7 @@ impl<'a> From<&'a mut AppMachine<InfoState>> for AppPublic<'a> {
|
|||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Info(()),
|
state: AppState::Info(()),
|
||||||
|
input: (&machine.input.as_ref()).map(Into::into),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
44
src/tui/app/machine/input.rs
Normal file
44
src/tui/app/machine/input.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
use tui_input::backend::crossterm::EventHandler;
|
||||||
|
|
||||||
|
use crate::tui::app::{
|
||||||
|
machine::{App, AppMachine},
|
||||||
|
IAppInput, InputEvent, InputPublic,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Input(tui_input::Input);
|
||||||
|
|
||||||
|
impl<'app> From<&'app Input> for InputPublic<'app> {
|
||||||
|
fn from(value: &'app Input) -> Self {
|
||||||
|
&value.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<State> IAppInput for AppMachine<State>
|
||||||
|
where
|
||||||
|
AppMachine<State>: Into<App>,
|
||||||
|
{
|
||||||
|
type APP = App;
|
||||||
|
|
||||||
|
fn taking_input(&self) -> bool {
|
||||||
|
self.input.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn input(mut self, input: InputEvent) -> Self::APP {
|
||||||
|
self.input
|
||||||
|
.as_mut()
|
||||||
|
.unwrap() // FIXME
|
||||||
|
.0
|
||||||
|
.handle_event(&crossterm::event::Event::Key(input));
|
||||||
|
self.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn confirm(self) -> Self::APP {
|
||||||
|
self.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cancel(mut self) -> Self::APP {
|
||||||
|
self.input = None;
|
||||||
|
self.into()
|
||||||
|
}
|
||||||
|
}
|
@ -1,78 +0,0 @@
|
|||||||
use tui_input::{backend::crossterm::EventHandler, Input};
|
|
||||||
|
|
||||||
use crate::tui::app::{
|
|
||||||
machine::{App, AppInner, AppMachine},
|
|
||||||
AppPublic, AppState, IAppInteractInput, InputClientPublic, InputEvent, InputStatePublic,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::match_state::MatchState;
|
|
||||||
|
|
||||||
pub struct InputState {
|
|
||||||
input: Input,
|
|
||||||
client: InputClient,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum InputClient {
|
|
||||||
Match(MatchState),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AppMachine<InputState> {
|
|
||||||
pub fn input_state(inner: AppInner, client: InputClient) -> Self {
|
|
||||||
AppMachine {
|
|
||||||
inner,
|
|
||||||
state: InputState {
|
|
||||||
input: Input::default(),
|
|
||||||
client,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<AppMachine<InputState>> for App {
|
|
||||||
fn from(machine: AppMachine<InputState>) -> Self {
|
|
||||||
AppState::Input(machine)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<&'a mut InputClient> for InputClientPublic<'a> {
|
|
||||||
fn from(client: &'a mut InputClient) -> Self {
|
|
||||||
match client {
|
|
||||||
InputClient::Match(state) => InputClientPublic::Match(state.into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<&'a mut AppMachine<InputState>> for AppPublic<'a> {
|
|
||||||
fn from(machine: &'a mut AppMachine<InputState>) -> Self {
|
|
||||||
AppPublic {
|
|
||||||
inner: (&mut machine.inner).into(),
|
|
||||||
state: AppState::Input(InputStatePublic {
|
|
||||||
input: &machine.state.input,
|
|
||||||
client: (&mut machine.state.client).into(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IAppInteractInput for AppMachine<InputState> {
|
|
||||||
type APP = App;
|
|
||||||
|
|
||||||
fn input(mut self, input: InputEvent) -> Self::APP {
|
|
||||||
self.state
|
|
||||||
.input
|
|
||||||
.handle_event(&crossterm::event::Event::Key(input));
|
|
||||||
self.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn confirm(self) -> Self::APP {
|
|
||||||
match self.state.client {
|
|
||||||
InputClient::Match(state) => AppMachine::match_state(self.inner, state).into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cancel(self) -> Self::APP {
|
|
||||||
match self.state.client {
|
|
||||||
InputClient::Match(state) => AppMachine::match_state(self.inner, state).into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,7 +6,7 @@ use crate::tui::app::{
|
|||||||
MatchStateInfo, MatchStatePublic, WidgetState,
|
MatchStateInfo, MatchStatePublic, WidgetState,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{fetch_state::FetchState, input_state::InputClient};
|
use super::{fetch_state::FetchState, input::Input};
|
||||||
|
|
||||||
impl ArtistMatches {
|
impl ArtistMatches {
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
@ -98,7 +98,11 @@ impl MatchState {
|
|||||||
|
|
||||||
impl AppMachine<MatchState> {
|
impl AppMachine<MatchState> {
|
||||||
pub fn match_state(inner: AppInner, state: MatchState) -> Self {
|
pub fn match_state(inner: AppInner, state: MatchState) -> Self {
|
||||||
AppMachine { inner, state }
|
AppMachine {
|
||||||
|
inner,
|
||||||
|
state,
|
||||||
|
input: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,6 +126,7 @@ impl<'a> From<&'a mut AppMachine<MatchState>> for AppPublic<'a> {
|
|||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Match((&mut machine.state).into()),
|
state: AppState::Match((&mut machine.state).into()),
|
||||||
|
input: (&machine.input.as_ref()).map(Into::into),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,7 +157,7 @@ impl IAppInteractMatch for AppMachine<MatchState> {
|
|||||||
self.into()
|
self.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select(self) -> Self::APP {
|
fn select(mut self) -> Self::APP {
|
||||||
if let Some(index) = self.state.state.list.selected() {
|
if let Some(index) = self.state.state.list.selected() {
|
||||||
// selected() implies current exists
|
// selected() implies current exists
|
||||||
if self
|
if self
|
||||||
@ -162,7 +167,8 @@ impl IAppInteractMatch for AppMachine<MatchState> {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.is_manual_input_mbid(index)
|
.is_manual_input_mbid(index)
|
||||||
{
|
{
|
||||||
return AppMachine::input_state(self.inner, InputClient::Match(self.state)).into();
|
self.input = Some(Input::default());
|
||||||
|
return self.into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AppMachine::app_fetch_next(self.inner, self.state.fetch)
|
AppMachine::app_fetch_next(self.inner, self.state.fetch)
|
||||||
|
@ -3,7 +3,7 @@ mod critical_state;
|
|||||||
mod error_state;
|
mod error_state;
|
||||||
mod fetch_state;
|
mod fetch_state;
|
||||||
mod info_state;
|
mod info_state;
|
||||||
mod input_state;
|
mod input;
|
||||||
mod match_state;
|
mod match_state;
|
||||||
mod reload_state;
|
mod reload_state;
|
||||||
mod search_state;
|
mod search_state;
|
||||||
@ -21,11 +21,12 @@ use critical_state::CriticalState;
|
|||||||
use error_state::ErrorState;
|
use error_state::ErrorState;
|
||||||
use fetch_state::FetchState;
|
use fetch_state::FetchState;
|
||||||
use info_state::InfoState;
|
use info_state::InfoState;
|
||||||
use input_state::InputState;
|
|
||||||
use match_state::MatchState;
|
use match_state::MatchState;
|
||||||
use reload_state::ReloadState;
|
use reload_state::ReloadState;
|
||||||
use search_state::SearchState;
|
use search_state::SearchState;
|
||||||
|
|
||||||
|
use input::Input;
|
||||||
|
|
||||||
use super::IAppBase;
|
use super::IAppBase;
|
||||||
|
|
||||||
pub type App = AppState<
|
pub type App = AppState<
|
||||||
@ -35,7 +36,6 @@ pub type App = AppState<
|
|||||||
AppMachine<SearchState>,
|
AppMachine<SearchState>,
|
||||||
AppMachine<FetchState>,
|
AppMachine<FetchState>,
|
||||||
AppMachine<MatchState>,
|
AppMachine<MatchState>,
|
||||||
AppMachine<InputState>,
|
|
||||||
AppMachine<ErrorState>,
|
AppMachine<ErrorState>,
|
||||||
AppMachine<CriticalState>,
|
AppMachine<CriticalState>,
|
||||||
>;
|
>;
|
||||||
@ -43,6 +43,7 @@ pub type App = AppState<
|
|||||||
pub struct AppMachine<STATE> {
|
pub struct AppMachine<STATE> {
|
||||||
inner: AppInner,
|
inner: AppInner,
|
||||||
state: STATE,
|
state: STATE,
|
||||||
|
input: Option<Input>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AppInner {
|
pub struct AppInner {
|
||||||
@ -80,7 +81,6 @@ impl App {
|
|||||||
AppState::Search(search_state) => &search_state.inner,
|
AppState::Search(search_state) => &search_state.inner,
|
||||||
AppState::Fetch(fetch_state) => &fetch_state.inner,
|
AppState::Fetch(fetch_state) => &fetch_state.inner,
|
||||||
AppState::Match(match_state) => &match_state.inner,
|
AppState::Match(match_state) => &match_state.inner,
|
||||||
AppState::Input(input_state) => &input_state.inner,
|
|
||||||
AppState::Error(error_state) => &error_state.inner,
|
AppState::Error(error_state) => &error_state.inner,
|
||||||
AppState::Critical(critical_state) => &critical_state.inner,
|
AppState::Critical(critical_state) => &critical_state.inner,
|
||||||
}
|
}
|
||||||
@ -94,7 +94,6 @@ impl App {
|
|||||||
AppState::Search(search_state) => &mut search_state.inner,
|
AppState::Search(search_state) => &mut search_state.inner,
|
||||||
AppState::Fetch(fetch_state) => &mut fetch_state.inner,
|
AppState::Fetch(fetch_state) => &mut fetch_state.inner,
|
||||||
AppState::Match(match_state) => &mut match_state.inner,
|
AppState::Match(match_state) => &mut match_state.inner,
|
||||||
AppState::Input(input_state) => &mut input_state.inner,
|
|
||||||
AppState::Error(error_state) => &mut error_state.inner,
|
AppState::Error(error_state) => &mut error_state.inner,
|
||||||
AppState::Critical(critical_state) => &mut critical_state.inner,
|
AppState::Critical(critical_state) => &mut critical_state.inner,
|
||||||
}
|
}
|
||||||
@ -108,7 +107,6 @@ impl IApp for App {
|
|||||||
type SearchState = AppMachine<SearchState>;
|
type SearchState = AppMachine<SearchState>;
|
||||||
type FetchState = AppMachine<FetchState>;
|
type FetchState = AppMachine<FetchState>;
|
||||||
type MatchState = AppMachine<MatchState>;
|
type MatchState = AppMachine<MatchState>;
|
||||||
type InputState = AppMachine<InputState>;
|
|
||||||
type ErrorState = AppMachine<ErrorState>;
|
type ErrorState = AppMachine<ErrorState>;
|
||||||
type CriticalState = AppMachine<CriticalState>;
|
type CriticalState = AppMachine<CriticalState>;
|
||||||
|
|
||||||
@ -130,7 +128,6 @@ impl IApp for App {
|
|||||||
Self::SearchState,
|
Self::SearchState,
|
||||||
Self::FetchState,
|
Self::FetchState,
|
||||||
Self::MatchState,
|
Self::MatchState,
|
||||||
Self::InputState,
|
|
||||||
Self::ErrorState,
|
Self::ErrorState,
|
||||||
Self::CriticalState,
|
Self::CriticalState,
|
||||||
> {
|
> {
|
||||||
@ -155,7 +152,6 @@ impl IAppAccess for App {
|
|||||||
AppState::Search(state) => state.into(),
|
AppState::Search(state) => state.into(),
|
||||||
AppState::Fetch(state) => state.into(),
|
AppState::Fetch(state) => state.into(),
|
||||||
AppState::Match(state) => state.into(),
|
AppState::Match(state) => state.into(),
|
||||||
AppState::Input(state) => state.into(),
|
|
||||||
AppState::Error(state) => state.into(),
|
AppState::Error(state) => state.into(),
|
||||||
AppState::Critical(state) => state.into(),
|
AppState::Critical(state) => state.into(),
|
||||||
}
|
}
|
||||||
@ -192,7 +188,6 @@ impl<'a> From<&'a mut AppInner> for AppPublicInner<'a> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
use input_state::InputClient;
|
|
||||||
use musichoard::collection::Collection;
|
use musichoard::collection::Collection;
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
@ -210,7 +205,6 @@ mod tests {
|
|||||||
SearchState,
|
SearchState,
|
||||||
FetchState,
|
FetchState,
|
||||||
MatchState,
|
MatchState,
|
||||||
InputState,
|
|
||||||
ErrorState,
|
ErrorState,
|
||||||
CriticalState,
|
CriticalState,
|
||||||
>
|
>
|
||||||
@ -221,7 +215,6 @@ mod tests {
|
|||||||
SearchState,
|
SearchState,
|
||||||
FetchState,
|
FetchState,
|
||||||
MatchState,
|
MatchState,
|
||||||
InputState,
|
|
||||||
ErrorState,
|
ErrorState,
|
||||||
CriticalState,
|
CriticalState,
|
||||||
>
|
>
|
||||||
@ -415,7 +408,12 @@ mod tests {
|
|||||||
let (_, rx) = mpsc::channel();
|
let (_, rx) = mpsc::channel();
|
||||||
let inner = app.unwrap_browse().inner;
|
let inner = app.unwrap_browse().inner;
|
||||||
let state = FetchState::new(rx);
|
let state = FetchState::new(rx);
|
||||||
app = AppMachine { inner, state }.into();
|
app = AppMachine {
|
||||||
|
inner,
|
||||||
|
state,
|
||||||
|
input: None,
|
||||||
|
}
|
||||||
|
.into();
|
||||||
|
|
||||||
let state = app.state();
|
let state = app.state();
|
||||||
assert!(matches!(state, AppState::Fetch(_)));
|
assert!(matches!(state, AppState::Fetch(_)));
|
||||||
@ -459,33 +457,6 @@ mod tests {
|
|||||||
assert!(!app.is_running());
|
assert!(!app.is_running());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn state_input() {
|
|
||||||
let mut app = App::new(music_hoard_init(vec![]), mb_api(), events());
|
|
||||||
assert!(app.is_running());
|
|
||||||
|
|
||||||
let (_, rx) = mpsc::channel();
|
|
||||||
let fetch = FetchState::new(rx);
|
|
||||||
let match_state = MatchState::new(None, fetch);
|
|
||||||
let input_client = InputClient::Match(match_state);
|
|
||||||
app = AppMachine::input_state(app.unwrap_browse().inner, input_client).into();
|
|
||||||
|
|
||||||
let state = app.state();
|
|
||||||
assert!(matches!(state, AppState::Input(_)));
|
|
||||||
app = state;
|
|
||||||
|
|
||||||
app = app.no_op();
|
|
||||||
let state = app.state();
|
|
||||||
assert!(matches!(state, AppState::Input(_)));
|
|
||||||
app = state;
|
|
||||||
|
|
||||||
let public = app.get();
|
|
||||||
assert!(matches!(public.state, AppState::Input(_)));
|
|
||||||
|
|
||||||
app = app.force_quit();
|
|
||||||
assert!(!app.is_running());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn state_error() {
|
fn state_error() {
|
||||||
let mut app = App::new(music_hoard_init(vec![]), mb_api(), events());
|
let mut app = App::new(music_hoard_init(vec![]), mb_api(), events());
|
||||||
|
@ -11,6 +11,7 @@ impl AppMachine<ReloadState> {
|
|||||||
AppMachine {
|
AppMachine {
|
||||||
inner,
|
inner,
|
||||||
state: ReloadState,
|
state: ReloadState,
|
||||||
|
input: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -25,6 +26,7 @@ impl<'a> From<&'a mut AppMachine<ReloadState>> for AppPublic<'a> {
|
|||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Reload(()),
|
state: AppState::Reload(()),
|
||||||
|
input: (&machine.input.as_ref()).map(Into::into),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ impl AppMachine<SearchState> {
|
|||||||
orig,
|
orig,
|
||||||
memo: vec![],
|
memo: vec![],
|
||||||
},
|
},
|
||||||
|
input: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,6 +56,7 @@ impl<'a> From<&'a mut AppMachine<SearchState>> for AppPublic<'a> {
|
|||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Search(&machine.state.string),
|
state: AppState::Search(&machine.state.string),
|
||||||
|
input: (&machine.input.as_ref()).map(Into::into),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@ pub enum AppState<
|
|||||||
SearchState,
|
SearchState,
|
||||||
FetchState,
|
FetchState,
|
||||||
MatchState,
|
MatchState,
|
||||||
InputState,
|
|
||||||
ErrorState,
|
ErrorState,
|
||||||
CriticalState,
|
CriticalState,
|
||||||
> {
|
> {
|
||||||
@ -25,7 +24,6 @@ pub enum AppState<
|
|||||||
Search(SearchState),
|
Search(SearchState),
|
||||||
Fetch(FetchState),
|
Fetch(FetchState),
|
||||||
Match(MatchState),
|
Match(MatchState),
|
||||||
Input(InputState),
|
|
||||||
Error(ErrorState),
|
Error(ErrorState),
|
||||||
Critical(CriticalState),
|
Critical(CriticalState),
|
||||||
}
|
}
|
||||||
@ -38,8 +36,7 @@ pub trait IApp {
|
|||||||
type FetchState: IAppBase<APP = Self>
|
type FetchState: IAppBase<APP = Self>
|
||||||
+ IAppInteractFetch<APP = Self>
|
+ IAppInteractFetch<APP = Self>
|
||||||
+ IAppEventFetch<APP = Self>;
|
+ IAppEventFetch<APP = Self>;
|
||||||
type MatchState: IAppBase<APP = Self> + IAppInteractMatch<APP = Self>;
|
type MatchState: IAppBase<APP = Self> + IAppInteractMatch<APP = Self> + IAppInput<APP = Self>;
|
||||||
type InputState: IAppBase<APP = Self> + IAppInteractInput<APP = Self>;
|
|
||||||
type ErrorState: IAppBase<APP = Self> + IAppInteractError<APP = Self>;
|
type ErrorState: IAppBase<APP = Self> + IAppInteractError<APP = Self>;
|
||||||
type CriticalState: IAppBase<APP = Self>;
|
type CriticalState: IAppBase<APP = Self>;
|
||||||
|
|
||||||
@ -56,7 +53,6 @@ pub trait IApp {
|
|||||||
Self::SearchState,
|
Self::SearchState,
|
||||||
Self::FetchState,
|
Self::FetchState,
|
||||||
Self::MatchState,
|
Self::MatchState,
|
||||||
Self::InputState,
|
|
||||||
Self::ErrorState,
|
Self::ErrorState,
|
||||||
Self::CriticalState,
|
Self::CriticalState,
|
||||||
>;
|
>;
|
||||||
@ -134,9 +130,11 @@ pub trait IAppInteractMatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type InputEvent = crossterm::event::KeyEvent;
|
type InputEvent = crossterm::event::KeyEvent;
|
||||||
pub trait IAppInteractInput {
|
pub trait IAppInput {
|
||||||
type APP: IApp;
|
type APP: IApp;
|
||||||
|
|
||||||
|
fn taking_input(&self) -> bool;
|
||||||
|
|
||||||
fn input(self, input: InputEvent) -> Self::APP;
|
fn input(self, input: InputEvent) -> Self::APP;
|
||||||
fn confirm(self) -> Self::APP;
|
fn confirm(self) -> Self::APP;
|
||||||
fn cancel(self) -> Self::APP;
|
fn cancel(self) -> Self::APP;
|
||||||
@ -159,6 +157,7 @@ pub trait IAppAccess {
|
|||||||
pub struct AppPublic<'app> {
|
pub struct AppPublic<'app> {
|
||||||
pub inner: AppPublicInner<'app>,
|
pub inner: AppPublicInner<'app>,
|
||||||
pub state: AppPublicState<'app>,
|
pub state: AppPublicState<'app>,
|
||||||
|
pub input: AppPublicInput<'app>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AppPublicInner<'app> {
|
pub struct AppPublicInner<'app> {
|
||||||
@ -214,27 +213,8 @@ pub struct MatchStatePublic<'app> {
|
|||||||
pub state: &'app mut WidgetState,
|
pub state: &'app mut WidgetState,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum InputClientPublic<'app> {
|
pub type AppPublicState<'app> =
|
||||||
Match(MatchStatePublic<'app>),
|
AppState<(), (), (), &'app str, (), MatchStatePublic<'app>, &'app str, &'app str>;
|
||||||
}
|
|
||||||
|
|
||||||
pub type Input = tui_input::Input;
|
|
||||||
pub struct InputStatePublic<'app> {
|
|
||||||
pub input: &'app Input,
|
|
||||||
pub client: InputClientPublic<'app>
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type AppPublicState<'app> = AppState<
|
|
||||||
(),
|
|
||||||
(),
|
|
||||||
(),
|
|
||||||
&'app str,
|
|
||||||
(),
|
|
||||||
MatchStatePublic<'app>,
|
|
||||||
InputStatePublic<'app>,
|
|
||||||
&'app str,
|
|
||||||
&'app str,
|
|
||||||
>;
|
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
BrowseState,
|
BrowseState,
|
||||||
@ -243,7 +223,6 @@ impl<
|
|||||||
SearchState,
|
SearchState,
|
||||||
FetchState,
|
FetchState,
|
||||||
MatchState,
|
MatchState,
|
||||||
InputState,
|
|
||||||
ErrorState,
|
ErrorState,
|
||||||
CriticalState,
|
CriticalState,
|
||||||
>
|
>
|
||||||
@ -254,7 +233,6 @@ impl<
|
|||||||
SearchState,
|
SearchState,
|
||||||
FetchState,
|
FetchState,
|
||||||
MatchState,
|
MatchState,
|
||||||
InputState,
|
|
||||||
ErrorState,
|
ErrorState,
|
||||||
CriticalState,
|
CriticalState,
|
||||||
>
|
>
|
||||||
@ -264,6 +242,9 @@ impl<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type InputPublic<'app> = &'app tui_input::Input;
|
||||||
|
pub type AppPublicInput<'app> = Option<InputPublic<'app>>;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -11,7 +11,7 @@ use crate::tui::{
|
|||||||
event::{Event, EventError, EventReceiver},
|
event::{Event, EventError, EventReceiver},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::app::{IAppBase, IAppEventFetch, IAppInteractInput};
|
use super::app::{IAppBase, IAppEventFetch, IAppInput};
|
||||||
|
|
||||||
#[cfg_attr(test, automock)]
|
#[cfg_attr(test, automock)]
|
||||||
pub trait IEventHandler<APP: IApp> {
|
pub trait IEventHandler<APP: IApp> {
|
||||||
@ -26,11 +26,12 @@ trait IEventHandlerPrivate<APP: IApp> {
|
|||||||
fn handle_search_key_event(app: <APP as IApp>::SearchState, key_event: KeyEvent) -> APP;
|
fn handle_search_key_event(app: <APP as IApp>::SearchState, key_event: KeyEvent) -> APP;
|
||||||
fn handle_fetch_key_event(app: <APP as IApp>::FetchState, key_event: KeyEvent) -> APP;
|
fn handle_fetch_key_event(app: <APP as IApp>::FetchState, key_event: KeyEvent) -> APP;
|
||||||
fn handle_match_key_event(app: <APP as IApp>::MatchState, key_event: KeyEvent) -> APP;
|
fn handle_match_key_event(app: <APP as IApp>::MatchState, key_event: KeyEvent) -> APP;
|
||||||
fn handle_input_key_event(app: <APP as IApp>::InputState, key_event: KeyEvent) -> APP;
|
|
||||||
fn handle_error_key_event(app: <APP as IApp>::ErrorState, key_event: KeyEvent) -> APP;
|
fn handle_error_key_event(app: <APP as IApp>::ErrorState, key_event: KeyEvent) -> APP;
|
||||||
fn handle_critical_key_event(app: <APP as IApp>::CriticalState, key_event: KeyEvent) -> APP;
|
fn handle_critical_key_event(app: <APP as IApp>::CriticalState, key_event: KeyEvent) -> APP;
|
||||||
|
|
||||||
fn handle_fetch_result_ready_event(app: APP) -> APP;
|
fn handle_fetch_result_ready_event(app: APP) -> APP;
|
||||||
|
|
||||||
|
fn handle_input_key_event<Input: IAppInput<APP = APP>>(app: Input, key_event: KeyEvent) -> APP;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventHandler {
|
pub struct EventHandler {
|
||||||
@ -75,8 +76,13 @@ impl<APP: IApp> IEventHandlerPrivate<APP> for EventHandler {
|
|||||||
Self::handle_search_key_event(search_state, key_event)
|
Self::handle_search_key_event(search_state, key_event)
|
||||||
}
|
}
|
||||||
AppState::Fetch(fetch_state) => Self::handle_fetch_key_event(fetch_state, key_event),
|
AppState::Fetch(fetch_state) => Self::handle_fetch_key_event(fetch_state, key_event),
|
||||||
AppState::Match(match_state) => Self::handle_match_key_event(match_state, key_event),
|
AppState::Match(match_state) => {
|
||||||
AppState::Input(input_state) => Self::handle_input_key_event(input_state, key_event),
|
if match_state.taking_input() {
|
||||||
|
Self::handle_input_key_event(match_state, key_event)
|
||||||
|
} else {
|
||||||
|
Self::handle_match_key_event(match_state, key_event)
|
||||||
|
}
|
||||||
|
}
|
||||||
AppState::Error(error_state) => Self::handle_error_key_event(error_state, key_event),
|
AppState::Error(error_state) => Self::handle_error_key_event(error_state, key_event),
|
||||||
AppState::Critical(critical_state) => {
|
AppState::Critical(critical_state) => {
|
||||||
Self::handle_critical_key_event(critical_state, key_event)
|
Self::handle_critical_key_event(critical_state, key_event)
|
||||||
@ -92,7 +98,6 @@ impl<APP: IApp> IEventHandlerPrivate<APP> for EventHandler {
|
|||||||
AppState::Search(state) => state.no_op(),
|
AppState::Search(state) => state.no_op(),
|
||||||
AppState::Fetch(fetch_state) => fetch_state.fetch_result_ready(),
|
AppState::Fetch(fetch_state) => fetch_state.fetch_result_ready(),
|
||||||
AppState::Match(state) => state.no_op(),
|
AppState::Match(state) => state.no_op(),
|
||||||
AppState::Input(state) => state.no_op(),
|
|
||||||
AppState::Error(state) => state.no_op(),
|
AppState::Error(state) => state.no_op(),
|
||||||
AppState::Critical(state) => state.no_op(),
|
AppState::Critical(state) => state.no_op(),
|
||||||
}
|
}
|
||||||
@ -178,6 +183,13 @@ impl<APP: IApp> IEventHandlerPrivate<APP> for EventHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_fetch_key_event(app: <APP as IApp>::FetchState, key_event: KeyEvent) -> APP {
|
fn handle_fetch_key_event(app: <APP as IApp>::FetchState, key_event: KeyEvent) -> APP {
|
||||||
|
if key_event.modifiers == KeyModifiers::CONTROL {
|
||||||
|
return match key_event.code {
|
||||||
|
KeyCode::Char('g') | KeyCode::Char('G') => app.abort(),
|
||||||
|
_ => app.no_op(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match key_event.code {
|
match key_event.code {
|
||||||
// Abort.
|
// Abort.
|
||||||
KeyCode::Esc | KeyCode::Char('q') | KeyCode::Char('Q') => app.abort(),
|
KeyCode::Esc | KeyCode::Char('q') | KeyCode::Char('Q') => app.abort(),
|
||||||
@ -187,6 +199,13 @@ impl<APP: IApp> IEventHandlerPrivate<APP> for EventHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_match_key_event(app: <APP as IApp>::MatchState, key_event: KeyEvent) -> APP {
|
fn handle_match_key_event(app: <APP as IApp>::MatchState, key_event: KeyEvent) -> APP {
|
||||||
|
if key_event.modifiers == KeyModifiers::CONTROL {
|
||||||
|
return match key_event.code {
|
||||||
|
KeyCode::Char('g') | KeyCode::Char('G') => app.abort(),
|
||||||
|
_ => app.no_op(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match key_event.code {
|
match key_event.code {
|
||||||
// Abort.
|
// Abort.
|
||||||
KeyCode::Esc | KeyCode::Char('q') | KeyCode::Char('Q') => app.abort(),
|
KeyCode::Esc | KeyCode::Char('q') | KeyCode::Char('Q') => app.abort(),
|
||||||
@ -199,22 +218,6 @@ impl<APP: IApp> IEventHandlerPrivate<APP> for EventHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_input_key_event(app: <APP as IApp>::InputState, key_event: KeyEvent) -> APP {
|
|
||||||
if key_event.modifiers == KeyModifiers::CONTROL {
|
|
||||||
match key_event.code {
|
|
||||||
KeyCode::Char('g') | KeyCode::Char('G') => return app.cancel(),
|
|
||||||
_ => {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
match key_event.code {
|
|
||||||
// Return.
|
|
||||||
KeyCode::Esc | KeyCode::Enter => app.confirm(),
|
|
||||||
// Othey keys.
|
|
||||||
_ => app.input(key_event),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_error_key_event(app: <APP as IApp>::ErrorState, _key_event: KeyEvent) -> APP {
|
fn handle_error_key_event(app: <APP as IApp>::ErrorState, _key_event: KeyEvent) -> APP {
|
||||||
// Any key dismisses the error.
|
// Any key dismisses the error.
|
||||||
app.dismiss_error()
|
app.dismiss_error()
|
||||||
@ -224,5 +227,22 @@ impl<APP: IApp> IEventHandlerPrivate<APP> for EventHandler {
|
|||||||
// No action is allowed.
|
// No action is allowed.
|
||||||
app.no_op()
|
app.no_op()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_input_key_event<Input: IAppInput<APP = APP>>(app: Input, key_event: KeyEvent) -> APP {
|
||||||
|
if key_event.modifiers == KeyModifiers::CONTROL {
|
||||||
|
match key_event.code {
|
||||||
|
KeyCode::Char('g') | KeyCode::Char('G') => return app.cancel(),
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
match key_event.code {
|
||||||
|
// Return.
|
||||||
|
KeyCode::Esc => app.cancel(),
|
||||||
|
KeyCode::Enter => app.confirm(),
|
||||||
|
// Othey keys.
|
||||||
|
_ => app.input(key_event),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// GRCOV_EXCL_STOP
|
// GRCOV_EXCL_STOP
|
||||||
|
@ -28,10 +28,14 @@ pub struct TrackArea {
|
|||||||
pub info: Rect,
|
pub info: Rect,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FrameArea {
|
pub struct BrowseArea {
|
||||||
pub artist: ArtistArea,
|
pub artist: ArtistArea,
|
||||||
pub album: AlbumArea,
|
pub album: AlbumArea,
|
||||||
pub track: TrackArea,
|
pub track: TrackArea,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FrameArea {
|
||||||
|
pub browse: BrowseArea,
|
||||||
pub minibuffer: Rect,
|
pub minibuffer: Rect,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,6 +95,7 @@ impl FrameArea {
|
|||||||
};
|
};
|
||||||
|
|
||||||
FrameArea {
|
FrameArea {
|
||||||
|
browse: BrowseArea {
|
||||||
artist: ArtistArea { list: artist_list },
|
artist: ArtistArea { list: artist_list },
|
||||||
album: AlbumArea {
|
album: AlbumArea {
|
||||||
list: album_list,
|
list: album_list,
|
||||||
@ -100,6 +105,7 @@ impl FrameArea {
|
|||||||
list: track_list,
|
list: track_list,
|
||||||
info: track_info,
|
info: track_info,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
minibuffer,
|
minibuffer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,20 +57,16 @@ impl Minibuffer<'_> {
|
|||||||
columns,
|
columns,
|
||||||
},
|
},
|
||||||
AppState::Fetch(()) => Minibuffer {
|
AppState::Fetch(()) => Minibuffer {
|
||||||
paragraphs: vec![Paragraph::new("fetching..."), Paragraph::new("q: abort")],
|
paragraphs: vec![
|
||||||
|
Paragraph::new("fetching..."),
|
||||||
|
Paragraph::new("ctrl+g: abort"),
|
||||||
|
],
|
||||||
columns: 2,
|
columns: 2,
|
||||||
},
|
},
|
||||||
AppState::Match(public) => Minibuffer {
|
AppState::Match(public) => Minibuffer {
|
||||||
paragraphs: vec![
|
paragraphs: vec![
|
||||||
Paragraph::new(UiDisplay::display_matching_info(public.info)),
|
Paragraph::new(UiDisplay::display_matching_info(public.info)),
|
||||||
Paragraph::new("q: abort"),
|
Paragraph::new("ctrl+g: abort"),
|
||||||
],
|
|
||||||
columns: 2,
|
|
||||||
},
|
|
||||||
AppState::Input(_) => Minibuffer {
|
|
||||||
paragraphs: vec![
|
|
||||||
Paragraph::new("enter: confirm"),
|
|
||||||
Paragraph::new("ctrl+g: cancel"),
|
|
||||||
],
|
],
|
||||||
columns: 2,
|
columns: 2,
|
||||||
},
|
},
|
||||||
|
@ -10,6 +10,7 @@ mod reload_state;
|
|||||||
mod style;
|
mod style;
|
||||||
mod widgets;
|
mod widgets;
|
||||||
|
|
||||||
|
use browse_state::BrowseArea;
|
||||||
use ratatui::{layout::Rect, widgets::Paragraph, Frame};
|
use ratatui::{layout::Rect, widgets::Paragraph, Frame};
|
||||||
|
|
||||||
use musichoard::collection::{album::Album, Collection};
|
use musichoard::collection::{album::Album, Collection};
|
||||||
@ -32,7 +33,7 @@ use crate::tui::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::app::{Input, InputClientPublic};
|
use super::app::InputPublic;
|
||||||
|
|
||||||
pub trait IUi {
|
pub trait IUi {
|
||||||
fn render<APP: IAppAccess>(app: &mut APP, frame: &mut Frame);
|
fn render<APP: IAppAccess>(app: &mut APP, frame: &mut Frame);
|
||||||
@ -66,11 +67,10 @@ impl Ui {
|
|||||||
fn render_browse_frame(
|
fn render_browse_frame(
|
||||||
artists: &Collection,
|
artists: &Collection,
|
||||||
selection: &mut Selection,
|
selection: &mut Selection,
|
||||||
state: &AppPublicState,
|
areas: BrowseArea,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
) {
|
) {
|
||||||
let active = selection.category();
|
let active = selection.category();
|
||||||
let areas = FrameArea::new(frame.area());
|
|
||||||
|
|
||||||
let artist_state = ArtistState::new(
|
let artist_state = ArtistState::new(
|
||||||
active == Category::Artist,
|
active == Category::Artist,
|
||||||
@ -103,8 +103,6 @@ impl Ui {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Self::render_track_column(track_state, areas.track, frame);
|
Self::render_track_column(track_state, areas.track, frame);
|
||||||
|
|
||||||
Self::render_minibuffer(state, areas.minibuffer, frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_info_overlay(artists: &Collection, selection: &mut Selection, frame: &mut Frame) {
|
fn render_info_overlay(artists: &Collection, selection: &mut Selection, frame: &mut Frame) {
|
||||||
@ -149,7 +147,7 @@ impl Ui {
|
|||||||
UiWidget::render_overlay_list_widget(&st.matching, st.list, st.state, true, area, frame)
|
UiWidget::render_overlay_list_widget(&st.matching, st.list, st.state, true, area, frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_input_overlay(input: &Input, frame: &mut Frame) {
|
fn render_input_overlay(input: InputPublic, frame: &mut Frame) {
|
||||||
let area = OverlayBuilder::default()
|
let area = OverlayBuilder::default()
|
||||||
.with_width(OverlaySize::MarginFactor(4))
|
.with_width(OverlaySize::MarginFactor(4))
|
||||||
.with_height(OverlaySize::Value(3))
|
.with_height(OverlaySize::Value(3))
|
||||||
@ -182,24 +180,24 @@ impl IUi for Ui {
|
|||||||
let selection = app.inner.selection;
|
let selection = app.inner.selection;
|
||||||
let state = app.state;
|
let state = app.state;
|
||||||
|
|
||||||
Self::render_browse_frame(collection, selection, &state, frame);
|
let areas = FrameArea::new(frame.area());
|
||||||
|
|
||||||
|
Self::render_browse_frame(collection, selection, areas.browse, frame);
|
||||||
|
Self::render_minibuffer(&state, areas.minibuffer, frame);
|
||||||
|
|
||||||
match state {
|
match state {
|
||||||
AppState::Info(()) => Self::render_info_overlay(collection, selection, frame),
|
AppState::Info(()) => Self::render_info_overlay(collection, selection, frame),
|
||||||
AppState::Reload(()) => Self::render_reload_overlay(frame),
|
AppState::Reload(()) => Self::render_reload_overlay(frame),
|
||||||
AppState::Fetch(()) => Self::render_fetch_overlay(frame),
|
AppState::Fetch(()) => Self::render_fetch_overlay(frame),
|
||||||
AppState::Match(public) => Self::render_match_overlay(public.info, public.state, frame),
|
AppState::Match(public) => Self::render_match_overlay(public.info, public.state, frame),
|
||||||
AppState::Input(input) => {
|
|
||||||
match input.client {
|
|
||||||
InputClientPublic::Match(public) => {
|
|
||||||
Self::render_match_overlay(public.info, public.state, frame)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Self::render_input_overlay(input.input, frame);
|
|
||||||
}
|
|
||||||
AppState::Error(msg) => Self::render_error_overlay("Error", msg, frame),
|
AppState::Error(msg) => Self::render_error_overlay("Error", msg, frame),
|
||||||
AppState::Critical(msg) => Self::render_error_overlay("Critical Error", msg, frame),
|
AppState::Critical(msg) => Self::render_error_overlay("Critical Error", msg, frame),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(input) = app.input {
|
||||||
|
Self::render_input_overlay(input, frame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,10 +209,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::{
|
app::{AppPublic, AppPublicInner, Delta, MatchOption, MatchStatePublic},
|
||||||
AppPublic, AppPublicInner, Delta, InputClientPublic, InputStatePublic, MatchOption,
|
|
||||||
MatchStatePublic,
|
|
||||||
},
|
|
||||||
lib::interface::musicbrainz::Match,
|
lib::interface::musicbrainz::Match,
|
||||||
testmod::COLLECTION,
|
testmod::COLLECTION,
|
||||||
tests::terminal,
|
tests::terminal,
|
||||||
@ -240,20 +235,10 @@ mod tests {
|
|||||||
info: m.info,
|
info: m.info,
|
||||||
state: m.state,
|
state: m.state,
|
||||||
}),
|
}),
|
||||||
AppState::Input(ref mut i) => AppState::Input(InputStatePublic {
|
|
||||||
input: i.input,
|
|
||||||
client: match i.client {
|
|
||||||
InputClientPublic::Match(ref mut m) => {
|
|
||||||
InputClientPublic::Match(MatchStatePublic {
|
|
||||||
info: m.info,
|
|
||||||
state: m.state,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
AppState::Error(s) => AppState::Error(s),
|
AppState::Error(s) => AppState::Error(s),
|
||||||
AppState::Critical(s) => AppState::Critical(s),
|
AppState::Critical(s) => AppState::Critical(s),
|
||||||
},
|
},
|
||||||
|
input: self.input,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -286,6 +271,7 @@ mod tests {
|
|||||||
let mut app = AppPublic {
|
let mut app = AppPublic {
|
||||||
inner: public_inner(collection, selection),
|
inner: public_inner(collection, selection),
|
||||||
state: AppState::Browse(()),
|
state: AppState::Browse(()),
|
||||||
|
input: None,
|
||||||
};
|
};
|
||||||
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
||||||
|
|
||||||
@ -364,6 +350,7 @@ mod tests {
|
|||||||
info: None,
|
info: None,
|
||||||
state: &mut widget_state,
|
state: &mut widget_state,
|
||||||
}),
|
}),
|
||||||
|
input: None,
|
||||||
};
|
};
|
||||||
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
||||||
}
|
}
|
||||||
@ -393,6 +380,7 @@ mod tests {
|
|||||||
info: Some(&artist_matches),
|
info: Some(&artist_matches),
|
||||||
state: &mut widget_state,
|
state: &mut widget_state,
|
||||||
}),
|
}),
|
||||||
|
input: None,
|
||||||
};
|
};
|
||||||
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
||||||
}
|
}
|
||||||
@ -427,6 +415,7 @@ mod tests {
|
|||||||
info: Some(&album_matches),
|
info: Some(&album_matches),
|
||||||
state: &mut widget_state,
|
state: &mut widget_state,
|
||||||
}),
|
}),
|
||||||
|
input: None,
|
||||||
};
|
};
|
||||||
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user