Input no longer a state

This commit is contained in:
Wojciech Kozlowski 2024-09-14 20:55:17 +02:00
parent 09e1cb7fda
commit 8acf208968
16 changed files with 172 additions and 220 deletions

View File

@ -11,6 +11,7 @@ impl AppMachine<BrowseState> {
AppMachine {
inner,
state: BrowseState,
input: None,
}
}
}
@ -26,6 +27,7 @@ impl<'a> From<&'a mut AppMachine<BrowseState>> for AppPublic<'a> {
AppPublic {
inner: (&mut machine.inner).into(),
state: AppState::Browse(()),
input: (&machine.input.as_ref()).map(Into::into),
}
}
}

View File

@ -14,6 +14,7 @@ impl AppMachine<CriticalState> {
state: CriticalState {
string: string.into(),
},
input: None
}
}
}
@ -29,6 +30,7 @@ impl<'a> From<&'a mut AppMachine<CriticalState>> for AppPublic<'a> {
AppPublic {
inner: (&mut machine.inner).into(),
state: AppState::Critical(&machine.state.string),
input: (&machine.input.as_ref()).map(Into::into),
}
}
}

View File

@ -14,6 +14,7 @@ impl AppMachine<ErrorState> {
state: ErrorState {
string: string.into(),
},
input: None,
}
}
}
@ -29,6 +30,7 @@ impl<'a> From<&'a mut AppMachine<ErrorState>> for AppPublic<'a> {
AppPublic {
inner: (&mut machine.inner).into(),
state: AppState::Error(&machine.state.string),
input: (&machine.input.as_ref()).map(Into::into),
}
}
}

View File

@ -40,7 +40,11 @@ pub type FetchReceiver = mpsc::Receiver<FetchResult>;
impl AppMachine<FetchState> {
fn fetch_state(inner: AppInner, state: FetchState) -> Self {
AppMachine { inner, state }
AppMachine {
inner,
state,
input: None,
}
}
pub fn app_fetch_new(inner: AppInner) -> App {
@ -173,6 +177,7 @@ impl<'a> From<&'a mut AppMachine<FetchState>> for AppPublic<'a> {
AppPublic {
inner: (&mut machine.inner).into(),
state: AppState::Fetch(()),
input: (&machine.input.as_ref()).map(Into::into),
}
}
}

View File

@ -10,6 +10,7 @@ impl AppMachine<InfoState> {
AppMachine {
inner,
state: InfoState,
input: None,
}
}
}
@ -25,6 +26,7 @@ impl<'a> From<&'a mut AppMachine<InfoState>> for AppPublic<'a> {
AppPublic {
inner: (&mut machine.inner).into(),
state: AppState::Info(()),
input: (&machine.input.as_ref()).map(Into::into),
}
}
}

View 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()
}
}

View File

@ -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(),
}
}
}

View File

@ -6,7 +6,7 @@ use crate::tui::app::{
MatchStateInfo, MatchStatePublic, WidgetState,
};
use super::{fetch_state::FetchState, input_state::InputClient};
use super::{fetch_state::FetchState, input::Input};
impl ArtistMatches {
fn len(&self) -> usize {
@ -98,7 +98,11 @@ impl MatchState {
impl AppMachine<MatchState> {
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 {
inner: (&mut machine.inner).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()
}
fn select(self) -> Self::APP {
fn select(mut self) -> Self::APP {
if let Some(index) = self.state.state.list.selected() {
// selected() implies current exists
if self
@ -162,7 +167,8 @@ impl IAppInteractMatch for AppMachine<MatchState> {
.unwrap()
.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)

View File

@ -3,7 +3,7 @@ mod critical_state;
mod error_state;
mod fetch_state;
mod info_state;
mod input_state;
mod input;
mod match_state;
mod reload_state;
mod search_state;
@ -21,11 +21,12 @@ use critical_state::CriticalState;
use error_state::ErrorState;
use fetch_state::FetchState;
use info_state::InfoState;
use input_state::InputState;
use match_state::MatchState;
use reload_state::ReloadState;
use search_state::SearchState;
use input::Input;
use super::IAppBase;
pub type App = AppState<
@ -35,7 +36,6 @@ pub type App = AppState<
AppMachine<SearchState>,
AppMachine<FetchState>,
AppMachine<MatchState>,
AppMachine<InputState>,
AppMachine<ErrorState>,
AppMachine<CriticalState>,
>;
@ -43,6 +43,7 @@ pub type App = AppState<
pub struct AppMachine<STATE> {
inner: AppInner,
state: STATE,
input: Option<Input>,
}
pub struct AppInner {
@ -80,7 +81,6 @@ impl App {
AppState::Search(search_state) => &search_state.inner,
AppState::Fetch(fetch_state) => &fetch_state.inner,
AppState::Match(match_state) => &match_state.inner,
AppState::Input(input_state) => &input_state.inner,
AppState::Error(error_state) => &error_state.inner,
AppState::Critical(critical_state) => &critical_state.inner,
}
@ -94,7 +94,6 @@ impl App {
AppState::Search(search_state) => &mut search_state.inner,
AppState::Fetch(fetch_state) => &mut fetch_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::Critical(critical_state) => &mut critical_state.inner,
}
@ -108,7 +107,6 @@ impl IApp for App {
type SearchState = AppMachine<SearchState>;
type FetchState = AppMachine<FetchState>;
type MatchState = AppMachine<MatchState>;
type InputState = AppMachine<InputState>;
type ErrorState = AppMachine<ErrorState>;
type CriticalState = AppMachine<CriticalState>;
@ -130,7 +128,6 @@ impl IApp for App {
Self::SearchState,
Self::FetchState,
Self::MatchState,
Self::InputState,
Self::ErrorState,
Self::CriticalState,
> {
@ -155,7 +152,6 @@ impl IAppAccess for App {
AppState::Search(state) => state.into(),
AppState::Fetch(state) => state.into(),
AppState::Match(state) => state.into(),
AppState::Input(state) => state.into(),
AppState::Error(state) => state.into(),
AppState::Critical(state) => state.into(),
}
@ -192,7 +188,6 @@ impl<'a> From<&'a mut AppInner> for AppPublicInner<'a> {
mod tests {
use std::sync::mpsc;
use input_state::InputClient;
use musichoard::collection::Collection;
use crate::tui::{
@ -210,7 +205,6 @@ mod tests {
SearchState,
FetchState,
MatchState,
InputState,
ErrorState,
CriticalState,
>
@ -221,7 +215,6 @@ mod tests {
SearchState,
FetchState,
MatchState,
InputState,
ErrorState,
CriticalState,
>
@ -415,7 +408,12 @@ mod tests {
let (_, rx) = mpsc::channel();
let inner = app.unwrap_browse().inner;
let state = FetchState::new(rx);
app = AppMachine { inner, state }.into();
app = AppMachine {
inner,
state,
input: None,
}
.into();
let state = app.state();
assert!(matches!(state, AppState::Fetch(_)));
@ -459,33 +457,6 @@ mod tests {
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]
fn state_error() {
let mut app = App::new(music_hoard_init(vec![]), mb_api(), events());

View File

@ -11,6 +11,7 @@ impl AppMachine<ReloadState> {
AppMachine {
inner,
state: ReloadState,
input: None,
}
}
}
@ -25,6 +26,7 @@ impl<'a> From<&'a mut AppMachine<ReloadState>> for AppPublic<'a> {
AppPublic {
inner: (&mut machine.inner).into(),
state: AppState::Reload(()),
input: (&machine.input.as_ref()).map(Into::into),
}
}
}

View File

@ -40,6 +40,7 @@ impl AppMachine<SearchState> {
orig,
memo: vec![],
},
input: None,
}
}
}
@ -55,6 +56,7 @@ impl<'a> From<&'a mut AppMachine<SearchState>> for AppPublic<'a> {
AppPublic {
inner: (&mut machine.inner).into(),
state: AppState::Search(&machine.state.string),
input: (&machine.input.as_ref()).map(Into::into),
}
}
}

View File

@ -15,7 +15,6 @@ pub enum AppState<
SearchState,
FetchState,
MatchState,
InputState,
ErrorState,
CriticalState,
> {
@ -25,7 +24,6 @@ pub enum AppState<
Search(SearchState),
Fetch(FetchState),
Match(MatchState),
Input(InputState),
Error(ErrorState),
Critical(CriticalState),
}
@ -38,8 +36,7 @@ pub trait IApp {
type FetchState: IAppBase<APP = Self>
+ IAppInteractFetch<APP = Self>
+ IAppEventFetch<APP = Self>;
type MatchState: IAppBase<APP = Self> + IAppInteractMatch<APP = Self>;
type InputState: IAppBase<APP = Self> + IAppInteractInput<APP = Self>;
type MatchState: IAppBase<APP = Self> + IAppInteractMatch<APP = Self> + IAppInput<APP = Self>;
type ErrorState: IAppBase<APP = Self> + IAppInteractError<APP = Self>;
type CriticalState: IAppBase<APP = Self>;
@ -56,7 +53,6 @@ pub trait IApp {
Self::SearchState,
Self::FetchState,
Self::MatchState,
Self::InputState,
Self::ErrorState,
Self::CriticalState,
>;
@ -134,9 +130,11 @@ pub trait IAppInteractMatch {
}
type InputEvent = crossterm::event::KeyEvent;
pub trait IAppInteractInput {
pub trait IAppInput {
type APP: IApp;
fn taking_input(&self) -> bool;
fn input(self, input: InputEvent) -> Self::APP;
fn confirm(self) -> Self::APP;
fn cancel(self) -> Self::APP;
@ -159,6 +157,7 @@ pub trait IAppAccess {
pub struct AppPublic<'app> {
pub inner: AppPublicInner<'app>,
pub state: AppPublicState<'app>,
pub input: AppPublicInput<'app>,
}
pub struct AppPublicInner<'app> {
@ -214,27 +213,8 @@ pub struct MatchStatePublic<'app> {
pub state: &'app mut WidgetState,
}
pub enum InputClientPublic<'app> {
Match(MatchStatePublic<'app>),
}
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,
>;
pub type AppPublicState<'app> =
AppState<(), (), (), &'app str, (), MatchStatePublic<'app>, &'app str, &'app str>;
impl<
BrowseState,
@ -243,7 +223,6 @@ impl<
SearchState,
FetchState,
MatchState,
InputState,
ErrorState,
CriticalState,
>
@ -254,7 +233,6 @@ impl<
SearchState,
FetchState,
MatchState,
InputState,
ErrorState,
CriticalState,
>
@ -264,6 +242,9 @@ impl<
}
}
pub type InputPublic<'app> = &'app tui_input::Input;
pub type AppPublicInput<'app> = Option<InputPublic<'app>>;
#[cfg(test)]
mod tests {
use super::*;

View File

@ -11,7 +11,7 @@ use crate::tui::{
event::{Event, EventError, EventReceiver},
};
use super::app::{IAppBase, IAppEventFetch, IAppInteractInput};
use super::app::{IAppBase, IAppEventFetch, IAppInput};
#[cfg_attr(test, automock)]
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_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_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_critical_key_event(app: <APP as IApp>::CriticalState, key_event: KeyEvent) -> 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 {
@ -75,8 +76,13 @@ impl<APP: IApp> IEventHandlerPrivate<APP> for EventHandler {
Self::handle_search_key_event(search_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::Input(input_state) => Self::handle_input_key_event(input_state, key_event),
AppState::Match(match_state) => {
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::Critical(critical_state) => {
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::Fetch(fetch_state) => fetch_state.fetch_result_ready(),
AppState::Match(state) => state.no_op(),
AppState::Input(state) => state.no_op(),
AppState::Error(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 {
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 {
// 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 {
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 {
// 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 {
// Any key dismisses the error.
app.dismiss_error()
@ -224,5 +227,22 @@ impl<APP: IApp> IEventHandlerPrivate<APP> for EventHandler {
// No action is allowed.
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

View File

@ -28,10 +28,14 @@ pub struct TrackArea {
pub info: Rect,
}
pub struct FrameArea {
pub struct BrowseArea {
pub artist: ArtistArea,
pub album: AlbumArea,
pub track: TrackArea,
}
pub struct FrameArea {
pub browse: BrowseArea,
pub minibuffer: Rect,
}
@ -91,14 +95,16 @@ impl FrameArea {
};
FrameArea {
artist: ArtistArea { list: artist_list },
album: AlbumArea {
list: album_list,
info: album_info,
},
track: TrackArea {
list: track_list,
info: track_info,
browse: BrowseArea {
artist: ArtistArea { list: artist_list },
album: AlbumArea {
list: album_list,
info: album_info,
},
track: TrackArea {
list: track_list,
info: track_info,
},
},
minibuffer,
}

View File

@ -57,20 +57,16 @@ impl Minibuffer<'_> {
columns,
},
AppState::Fetch(()) => Minibuffer {
paragraphs: vec![Paragraph::new("fetching..."), Paragraph::new("q: abort")],
paragraphs: vec![
Paragraph::new("fetching..."),
Paragraph::new("ctrl+g: abort"),
],
columns: 2,
},
AppState::Match(public) => Minibuffer {
paragraphs: vec![
Paragraph::new(UiDisplay::display_matching_info(public.info)),
Paragraph::new("q: abort"),
],
columns: 2,
},
AppState::Input(_) => Minibuffer {
paragraphs: vec![
Paragraph::new("enter: confirm"),
Paragraph::new("ctrl+g: cancel"),
Paragraph::new("ctrl+g: abort"),
],
columns: 2,
},

View File

@ -10,6 +10,7 @@ mod reload_state;
mod style;
mod widgets;
use browse_state::BrowseArea;
use ratatui::{layout::Rect, widgets::Paragraph, Frame};
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 {
fn render<APP: IAppAccess>(app: &mut APP, frame: &mut Frame);
@ -66,11 +67,10 @@ impl Ui {
fn render_browse_frame(
artists: &Collection,
selection: &mut Selection,
state: &AppPublicState,
areas: BrowseArea,
frame: &mut Frame,
) {
let active = selection.category();
let areas = FrameArea::new(frame.area());
let artist_state = ArtistState::new(
active == Category::Artist,
@ -103,8 +103,6 @@ impl Ui {
);
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) {
@ -149,7 +147,7 @@ impl Ui {
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()
.with_width(OverlaySize::MarginFactor(4))
.with_height(OverlaySize::Value(3))
@ -182,24 +180,24 @@ impl IUi for Ui {
let selection = app.inner.selection;
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 {
AppState::Info(()) => Self::render_info_overlay(collection, selection, frame),
AppState::Reload(()) => Self::render_reload_overlay(frame),
AppState::Fetch(()) => Self::render_fetch_overlay(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::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::{
app::{
AppPublic, AppPublicInner, Delta, InputClientPublic, InputStatePublic, MatchOption,
MatchStatePublic,
},
app::{AppPublic, AppPublicInner, Delta, MatchOption, MatchStatePublic},
lib::interface::musicbrainz::Match,
testmod::COLLECTION,
tests::terminal,
@ -240,20 +235,10 @@ mod tests {
info: m.info,
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::Critical(s) => AppState::Critical(s),
},
input: self.input,
}
}
}
@ -286,6 +271,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();
@ -364,6 +350,7 @@ mod tests {
info: None,
state: &mut widget_state,
}),
input: None,
};
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
}
@ -393,6 +380,7 @@ mod tests {
info: Some(&artist_matches),
state: &mut widget_state,
}),
input: None,
};
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
}
@ -427,6 +415,7 @@ mod tests {
info: Some(&album_matches),
state: &mut widget_state,
}),
input: None,
};
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
}