Handle idle time between fetch results #212

Merged
wojtek merged 18 commits from 211---handle-idle-time-between-fetch-results into main 2024-09-08 23:23:53 +02:00
9 changed files with 60 additions and 141 deletions
Showing only changes of commit d0fe2f6450 - Show all commits

View File

@ -13,7 +13,7 @@ use crate::tui::{
app::{ app::{
machine::{App, AppInner, AppMachine}, machine::{App, AppInner, AppMachine},
selection::{Delta, ListSelection}, selection::{Delta, ListSelection},
AppMatchesInfo, AppPublic, AppState, IAppBase, IAppInteractBrowse, AppMatchesInfo, AppPublic, AppState, IAppInteractBrowse,
}, },
event::{Event, EventSender}, event::{Event, EventSender},
lib::interface::musicbrainz::{self, IMusicBrainz}, lib::interface::musicbrainz::{self, IMusicBrainz},
@ -185,14 +185,6 @@ impl IAppInteractBrowse for AppMachine<AppBrowse> {
} }
} }
impl IAppBase for AppMachine<AppBrowse> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use mockall::{predicate, Sequence}; use mockall::{predicate, Sequence};
@ -490,11 +482,4 @@ mod tests {
assert_eq!(fetch_rx.try_recv().unwrap_err(), TryRecvError::Disconnected); assert_eq!(fetch_rx.try_recv().unwrap_err(), TryRecvError::Disconnected);
} }
#[test]
fn no_op() {
let browse = AppMachine::browse(inner(music_hoard(vec![])));
let app = browse.no_op();
app.unwrap_browse();
}
} }

View File

@ -1,6 +1,6 @@
use crate::tui::app::{ use crate::tui::app::{
machine::{App, AppInner, AppMachine}, machine::{App, AppInner, AppMachine},
AppPublic, AppState, IAppBase, AppPublic, AppState,
}; };
pub struct AppCritical { pub struct AppCritical {
@ -32,25 +32,3 @@ impl<'a> From<&'a mut AppMachine<AppCritical>> for AppPublic<'a> {
} }
} }
} }
impl IAppBase for AppMachine<AppCritical> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()
}
}
#[cfg(test)]
mod tests {
use crate::tui::app::machine::tests::{inner, music_hoard};
use super::*;
#[test]
fn no_op() {
let critical = AppMachine::critical(inner(music_hoard(vec![])), "get rekt");
let app = critical.no_op();
app.unwrap_critical();
}
}

View File

@ -1,6 +1,6 @@
use crate::tui::app::{ use crate::tui::app::{
machine::{App, AppInner, AppMachine}, machine::{App, AppInner, AppMachine},
AppPublic, AppState, IAppBase, IAppInteractError, AppPublic, AppState, IAppInteractError,
}; };
pub struct AppError { pub struct AppError {
@ -41,14 +41,6 @@ impl IAppInteractError for AppMachine<AppError> {
} }
} }
impl IAppBase for AppMachine<AppError> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::tui::app::machine::tests::{inner, music_hoard}; use crate::tui::app::machine::tests::{inner, music_hoard};
@ -61,11 +53,4 @@ mod tests {
let app = error.dismiss_error(); let app = error.dismiss_error();
app.unwrap_browse(); app.unwrap_browse();
} }
#[test]
fn no_op() {
let error = AppMachine::error(inner(music_hoard(vec![])), "get rekt");
let app = error.no_op();
app.unwrap_error();
}
} }

View File

@ -3,7 +3,7 @@ use std::sync::mpsc::{self, TryRecvError};
use crate::tui::{ use crate::tui::{
app::{ app::{
machine::{App, AppInner, AppMachine}, machine::{App, AppInner, AppMachine},
AppMatchesInfo, AppPublic, AppState, IAppBase, IAppEventFetch, IAppInteractFetch, AppMatchesInfo, AppPublic, AppState, IAppEventFetch, IAppInteractFetch,
}, },
lib::interface::musicbrainz::Error as MbError, lib::interface::musicbrainz::Error as MbError,
}; };
@ -87,14 +87,6 @@ impl IAppInteractFetch for AppMachine<AppFetch> {
} }
} }
impl IAppBase for AppMachine<AppFetch> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()
}
}
impl IAppEventFetch for AppMachine<AppFetch> { impl IAppEventFetch for AppMachine<AppFetch> {
type APP = App; type APP = App;
@ -188,15 +180,4 @@ mod tests {
let app = app.abort(); let app = app.abort();
assert!(matches!(app, AppState::Browse(_))); assert!(matches!(app, AppState::Browse(_)));
} }
#[test]
fn no_op() {
let (_, rx) = mpsc::channel::<FetchResult>();
let fetch = AppFetch::new(rx);
let app = AppMachine::fetch(inner(music_hoard(COLLECTION.clone())), fetch);
let app = app.no_op();
assert!(matches!(app, AppState::Fetch(_)));
}
} }

View File

@ -1,6 +1,6 @@
use crate::tui::app::{ use crate::tui::app::{
machine::{App, AppInner, AppMachine}, machine::{App, AppInner, AppMachine},
AppPublic, AppState, IAppBase, IAppInteractInfo, AppPublic, AppState, IAppInteractInfo,
}; };
pub struct AppInfo; pub struct AppInfo;
@ -37,14 +37,6 @@ impl IAppInteractInfo for AppMachine<AppInfo> {
} }
} }
impl IAppBase for AppMachine<AppInfo> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::tui::app::machine::tests::{inner, music_hoard}; use crate::tui::app::machine::tests::{inner, music_hoard};
@ -57,11 +49,4 @@ mod tests {
let app = info.hide_info_overlay(); let app = info.hide_info_overlay();
app.unwrap_browse(); app.unwrap_browse();
} }
#[test]
fn no_op() {
let info = AppMachine::info(inner(music_hoard(vec![])));
let app = info.no_op();
app.unwrap_info();
}
} }

View File

@ -3,7 +3,7 @@ use std::cmp;
use crate::tui::app::{ use crate::tui::app::{
machine::{App, AppInner, AppMachine}, machine::{App, AppInner, AppMachine},
AppAlbumMatches, AppArtistMatches, AppMatchesInfo, AppPublic, AppPublicMatches, AppState, AppAlbumMatches, AppArtistMatches, AppMatchesInfo, AppPublic, AppPublicMatches, AppState,
IAppBase, IAppInteractMatches, MatchOption, WidgetState, IAppInteractMatches, MatchOption, WidgetState,
}; };
use super::fetch::AppFetch; use super::fetch::AppFetch;
@ -124,14 +124,6 @@ impl IAppInteractMatches for AppMachine<AppMatches> {
} }
} }
impl IAppBase for AppMachine<AppMatches> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::sync::mpsc; use std::sync::mpsc;
@ -213,7 +205,7 @@ mod tests {
assert_eq!(matches.state.current, None); assert_eq!(matches.state.current, None);
assert_eq!(matches.state.state, widget_state); assert_eq!(matches.state.state, widget_state);
let mut app = matches.no_op(); let mut app: App = matches.into();
let public = app.get(); let public = app.get();
let public_matches = public.state.unwrap_matches(); let public_matches = public.state.unwrap_matches();
@ -236,7 +228,7 @@ mod tests {
assert_eq!(matches.state.current.as_ref(), Some(&album_match)); assert_eq!(matches.state.current.as_ref(), Some(&album_match));
assert_eq!(matches.state.state, widget_state); assert_eq!(matches.state.state, widget_state);
let mut app = matches.no_op(); let mut app: App = matches.into();
let public = app.get(); let public = app.get();
let public_matches = public.state.unwrap_matches(); let public_matches = public.state.unwrap_matches();
@ -319,11 +311,4 @@ mod tests {
let matches = AppMachine::matches(inner(music_hoard(vec![])), matches(None)); let matches = AppMachine::matches(inner(music_hoard(vec![])), matches(None));
matches.select().unwrap_browse(); matches.select().unwrap_browse();
} }
#[test]
fn no_op() {
let matches = AppMachine::matches(inner(music_hoard(vec![])), matches(None));
let app = matches.no_op();
app.unwrap_matches();
}
} }

View File

@ -24,6 +24,8 @@ use matches::AppMatches;
use reload::AppReload; use reload::AppReload;
use search::AppSearch; use search::AppSearch;
use super::IAppBase;
pub type App = AppState< pub type App = AppState<
AppMachine<AppBrowse>, AppMachine<AppBrowse>,
AppMachine<AppInfo>, AppMachine<AppInfo>,
@ -121,6 +123,14 @@ impl IAppInteract for App {
} }
} }
impl<T: Into<App>> IAppBase for T {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()
}
}
impl IAppAccess for App { impl IAppAccess for App {
fn get(&mut self) -> AppPublic { fn get(&mut self) -> AppPublic {
match self { match self {
@ -277,6 +287,11 @@ mod tests {
assert!(matches!(state, AppState::Browse(_))); assert!(matches!(state, AppState::Browse(_)));
app = state; app = state;
app = app.no_op();
let state = app.state();
assert!(matches!(state, AppState::Browse(_)));
app = state;
let public = app.get(); let public = app.get();
assert!(matches!(public.state, AppState::Browse(_))); assert!(matches!(public.state, AppState::Browse(_)));
@ -295,6 +310,11 @@ mod tests {
assert!(matches!(state, AppState::Info(_))); assert!(matches!(state, AppState::Info(_)));
app = state; app = state;
app = app.no_op();
let state = app.state();
assert!(matches!(state, AppState::Info(_)));
app = state;
let public = app.get(); let public = app.get();
assert!(matches!(public.state, AppState::Info(_))); assert!(matches!(public.state, AppState::Info(_)));
@ -313,6 +333,11 @@ mod tests {
assert!(matches!(state, AppState::Reload(_))); assert!(matches!(state, AppState::Reload(_)));
app = state; app = state;
app = app.no_op();
let state = app.state();
assert!(matches!(state, AppState::Reload(_)));
app = state;
let public = app.get(); let public = app.get();
assert!(matches!(public.state, AppState::Reload(_))); assert!(matches!(public.state, AppState::Reload(_)));
@ -331,6 +356,11 @@ mod tests {
assert!(matches!(state, AppState::Search(_))); assert!(matches!(state, AppState::Search(_)));
app = state; app = state;
app = app.no_op();
let state = app.state();
assert!(matches!(state, AppState::Search(_)));
app = state;
let public = app.get(); let public = app.get();
assert!(matches!(public.state, AppState::Search(""))); assert!(matches!(public.state, AppState::Search("")));
@ -352,6 +382,11 @@ mod tests {
assert!(matches!(state, AppState::Fetch(_))); assert!(matches!(state, AppState::Fetch(_)));
app = state; app = state;
app = app.no_op();
let state = app.state();
assert!(matches!(state, AppState::Fetch(_)));
app = state;
let public = app.get(); let public = app.get();
assert!(matches!(public.state, AppState::Fetch(_))); assert!(matches!(public.state, AppState::Fetch(_)));
@ -372,6 +407,11 @@ mod tests {
assert!(matches!(state, AppState::Matches(_))); assert!(matches!(state, AppState::Matches(_)));
app = state; app = state;
app = app.no_op();
let state = app.state();
assert!(matches!(state, AppState::Matches(_)));
app = state;
let public = app.get(); let public = app.get();
assert!(matches!(public.state, AppState::Matches(_))); assert!(matches!(public.state, AppState::Matches(_)));
@ -390,6 +430,11 @@ mod tests {
assert!(matches!(state, AppState::Error(_))); assert!(matches!(state, AppState::Error(_)));
app = state; app = state;
app = app.no_op();
let state = app.state();
assert!(matches!(state, AppState::Error(_)));
app = state;
let public = app.get(); let public = app.get();
assert!(matches!(public.state, AppState::Error("get rekt"))); assert!(matches!(public.state, AppState::Error("get rekt")));
@ -408,6 +453,11 @@ mod tests {
assert!(matches!(state, AppState::Critical(_))); assert!(matches!(state, AppState::Critical(_)));
app = state; app = state;
app = app.no_op();
let state = app.state();
assert!(matches!(state, AppState::Critical(_)));
app = state;
let public = app.get(); let public = app.get();
assert!(matches!(public.state, AppState::Critical("get rekt"))); assert!(matches!(public.state, AppState::Critical("get rekt")));

View File

@ -1,7 +1,7 @@
use crate::tui::app::{ use crate::tui::app::{
machine::{App, AppInner, AppMachine}, machine::{App, AppInner, AppMachine},
selection::KeySelection, selection::KeySelection,
AppPublic, AppState, IAppBase, IAppInteractReload, AppPublic, AppState, IAppInteractReload,
}; };
pub struct AppReload; pub struct AppReload;
@ -55,14 +55,6 @@ impl IAppInteractReload for AppMachine<AppReload> {
} }
} }
impl IAppBase for AppMachine<AppReload> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()
}
}
trait IAppInteractReloadPrivate { trait IAppInteractReloadPrivate {
fn refresh(self, previous: KeySelection, result: Result<(), musichoard::Error>) -> App; fn refresh(self, previous: KeySelection, result: Result<(), musichoard::Error>) -> App;
} }
@ -135,11 +127,4 @@ mod tests {
let app = reload.reload_database(); let app = reload.reload_database();
app.unwrap_error(); app.unwrap_error();
} }
#[test]
fn no_op() {
let reload = AppMachine::reload(inner(music_hoard(vec![])));
let app = reload.no_op();
app.unwrap_reload();
}
} }

View File

@ -6,7 +6,7 @@ use musichoard::collection::{album::Album, artist::Artist, track::Track};
use crate::tui::app::{ use crate::tui::app::{
machine::{App, AppInner, AppMachine}, machine::{App, AppInner, AppMachine},
selection::{ListSelection, SelectionState}, selection::{ListSelection, SelectionState},
AppPublic, AppState, Category, IAppBase, IAppInteractSearch, AppPublic, AppState, Category, IAppInteractSearch,
}; };
// Unlikely that this covers all possible strings, but it should at least cover strings // Unlikely that this covers all possible strings, but it should at least cover strings
@ -100,14 +100,6 @@ impl IAppInteractSearch for AppMachine<AppSearch> {
} }
} }
impl IAppBase for AppMachine<AppSearch> {
type APP = App;
fn no_op(self) -> Self::APP {
self.into()
}
}
trait IAppInteractSearchPrivate { trait IAppInteractSearchPrivate {
fn incremental_search(&mut self, next: bool); fn incremental_search(&mut self, next: bool);
fn next<P, T>(pred: P, name: &str, next: bool, st: SelectionState<'_, T>) -> Option<usize> fn next<P, T>(pred: P, name: &str, next: bool, st: SelectionState<'_, T>) -> Option<usize>
@ -548,13 +540,6 @@ mod tests {
let browse = search.cancel_search().unwrap_browse(); let browse = search.cancel_search().unwrap_browse();
assert_eq!(browse.inner.selection.selected(), None); assert_eq!(browse.inner.selection.selected(), None);
} }
#[test]
fn no_op() {
let search = AppMachine::search(inner(music_hoard(vec![])), orig(None));
let app = search.no_op();
app.unwrap_search();
}
} }
#[cfg(nightly)] #[cfg(nightly)]