Compare commits
3 Commits
66681a7ea9
...
d0fe2f6450
Author | SHA1 | Date | |
---|---|---|---|
d0fe2f6450 | |||
56bf99f985 | |||
706e30f587 |
10
src/main.rs
10
src/main.rs
@ -85,13 +85,15 @@ fn with<Database: IDatabase + 'static, Library: ILibrary + 'static>(
|
||||
let musicbrainz = MusicBrainz::new(client);
|
||||
|
||||
let channel = EventChannel::new();
|
||||
let listener = EventListener::new(channel.sender());
|
||||
|
||||
let app = App::new(music_hoard, musicbrainz, channel.sender());
|
||||
let ui = Ui;
|
||||
let listener_sender = channel.sender();
|
||||
let app_sender = channel.sender();
|
||||
|
||||
let listener = EventListener::new(listener_sender);
|
||||
let handler = EventHandler::new(channel.receiver());
|
||||
|
||||
let app = App::new(music_hoard, musicbrainz, app_sender);
|
||||
let ui = Ui;
|
||||
|
||||
// Run the TUI application.
|
||||
Tui::run(terminal, app, ui, handler, listener).expect("failed to run tui");
|
||||
}
|
||||
|
@ -183,10 +183,6 @@ impl IAppInteractBrowse for AppMachine<AppBrowse> {
|
||||
|
||||
AppMachine::app_fetch_new(self.inner, fetch_rx)
|
||||
}
|
||||
|
||||
fn no_op(self) -> Self::APP {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -486,11 +482,4 @@ mod tests {
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::tui::app::{
|
||||
machine::{App, AppInner, AppMachine},
|
||||
AppPublic, AppState, IAppInteractCritical,
|
||||
AppPublic, AppState,
|
||||
};
|
||||
|
||||
pub struct AppCritical {
|
||||
@ -32,25 +32,3 @@ impl<'a> From<&'a mut AppMachine<AppCritical>> for AppPublic<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IAppInteractCritical 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();
|
||||
}
|
||||
}
|
||||
|
@ -39,10 +39,6 @@ impl IAppInteractError for AppMachine<AppError> {
|
||||
fn dismiss_error(self) -> Self::APP {
|
||||
AppMachine::browse(self.inner).into()
|
||||
}
|
||||
|
||||
fn no_op(self) -> Self::APP {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -57,11 +53,4 @@ mod tests {
|
||||
let app = error.dismiss_error();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -85,10 +85,6 @@ impl IAppInteractFetch for AppMachine<AppFetch> {
|
||||
fn abort(self) -> Self::APP {
|
||||
AppMachine::browse(self.inner).into()
|
||||
}
|
||||
|
||||
fn no_op(self) -> Self::APP {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl IAppEventFetch for AppMachine<AppFetch> {
|
||||
@ -184,15 +180,4 @@ mod tests {
|
||||
let app = app.abort();
|
||||
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(_)));
|
||||
}
|
||||
}
|
||||
|
@ -35,10 +35,6 @@ impl IAppInteractInfo for AppMachine<AppInfo> {
|
||||
fn hide_info_overlay(self) -> Self::APP {
|
||||
AppMachine::browse(self.inner).into()
|
||||
}
|
||||
|
||||
fn no_op(self) -> Self::APP {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -53,11 +49,4 @@ mod tests {
|
||||
let app = info.hide_info_overlay();
|
||||
app.unwrap_browse();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_op() {
|
||||
let info = AppMachine::info(inner(music_hoard(vec![])));
|
||||
let app = info.no_op();
|
||||
app.unwrap_info();
|
||||
}
|
||||
}
|
||||
|
@ -122,10 +122,6 @@ impl IAppInteractMatches for AppMachine<AppMatches> {
|
||||
fn abort(self) -> Self::APP {
|
||||
AppMachine::browse(self.inner).into()
|
||||
}
|
||||
|
||||
fn no_op(self) -> Self::APP {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -209,7 +205,7 @@ mod tests {
|
||||
assert_eq!(matches.state.current, None);
|
||||
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_matches = public.state.unwrap_matches();
|
||||
|
||||
@ -232,7 +228,7 @@ mod tests {
|
||||
assert_eq!(matches.state.current.as_ref(), Some(&album_match));
|
||||
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_matches = public.state.unwrap_matches();
|
||||
|
||||
@ -315,11 +311,4 @@ mod tests {
|
||||
let matches = AppMachine::matches(inner(music_hoard(vec![])), matches(None));
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ use matches::AppMatches;
|
||||
use reload::AppReload;
|
||||
use search::AppSearch;
|
||||
|
||||
use super::IAppBase;
|
||||
|
||||
pub type App = AppState<
|
||||
AppMachine<AppBrowse>,
|
||||
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 {
|
||||
fn get(&mut self) -> AppPublic {
|
||||
match self {
|
||||
@ -277,6 +287,11 @@ mod tests {
|
||||
assert!(matches!(state, AppState::Browse(_)));
|
||||
app = state;
|
||||
|
||||
app = app.no_op();
|
||||
let state = app.state();
|
||||
assert!(matches!(state, AppState::Browse(_)));
|
||||
app = state;
|
||||
|
||||
let public = app.get();
|
||||
assert!(matches!(public.state, AppState::Browse(_)));
|
||||
|
||||
@ -295,6 +310,11 @@ mod tests {
|
||||
assert!(matches!(state, AppState::Info(_)));
|
||||
app = state;
|
||||
|
||||
app = app.no_op();
|
||||
let state = app.state();
|
||||
assert!(matches!(state, AppState::Info(_)));
|
||||
app = state;
|
||||
|
||||
let public = app.get();
|
||||
assert!(matches!(public.state, AppState::Info(_)));
|
||||
|
||||
@ -313,6 +333,11 @@ mod tests {
|
||||
assert!(matches!(state, AppState::Reload(_)));
|
||||
app = state;
|
||||
|
||||
app = app.no_op();
|
||||
let state = app.state();
|
||||
assert!(matches!(state, AppState::Reload(_)));
|
||||
app = state;
|
||||
|
||||
let public = app.get();
|
||||
assert!(matches!(public.state, AppState::Reload(_)));
|
||||
|
||||
@ -331,6 +356,11 @@ mod tests {
|
||||
assert!(matches!(state, AppState::Search(_)));
|
||||
app = state;
|
||||
|
||||
app = app.no_op();
|
||||
let state = app.state();
|
||||
assert!(matches!(state, AppState::Search(_)));
|
||||
app = state;
|
||||
|
||||
let public = app.get();
|
||||
assert!(matches!(public.state, AppState::Search("")));
|
||||
|
||||
@ -352,6 +382,11 @@ mod tests {
|
||||
assert!(matches!(state, AppState::Fetch(_)));
|
||||
app = state;
|
||||
|
||||
app = app.no_op();
|
||||
let state = app.state();
|
||||
assert!(matches!(state, AppState::Fetch(_)));
|
||||
app = state;
|
||||
|
||||
let public = app.get();
|
||||
assert!(matches!(public.state, AppState::Fetch(_)));
|
||||
|
||||
@ -372,6 +407,11 @@ mod tests {
|
||||
assert!(matches!(state, AppState::Matches(_)));
|
||||
app = state;
|
||||
|
||||
app = app.no_op();
|
||||
let state = app.state();
|
||||
assert!(matches!(state, AppState::Matches(_)));
|
||||
app = state;
|
||||
|
||||
let public = app.get();
|
||||
assert!(matches!(public.state, AppState::Matches(_)));
|
||||
|
||||
@ -390,6 +430,11 @@ mod tests {
|
||||
assert!(matches!(state, AppState::Error(_)));
|
||||
app = state;
|
||||
|
||||
app = app.no_op();
|
||||
let state = app.state();
|
||||
assert!(matches!(state, AppState::Error(_)));
|
||||
app = state;
|
||||
|
||||
let public = app.get();
|
||||
assert!(matches!(public.state, AppState::Error("get rekt")));
|
||||
|
||||
@ -408,6 +453,11 @@ mod tests {
|
||||
assert!(matches!(state, AppState::Critical(_)));
|
||||
app = state;
|
||||
|
||||
app = app.no_op();
|
||||
let state = app.state();
|
||||
assert!(matches!(state, AppState::Critical(_)));
|
||||
app = state;
|
||||
|
||||
let public = app.get();
|
||||
assert!(matches!(public.state, AppState::Critical("get rekt")));
|
||||
|
||||
|
@ -53,10 +53,6 @@ impl IAppInteractReload for AppMachine<AppReload> {
|
||||
fn hide_reload_menu(self) -> Self::APP {
|
||||
AppMachine::browse(self.inner).into()
|
||||
}
|
||||
|
||||
fn no_op(self) -> Self::APP {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
trait IAppInteractReloadPrivate {
|
||||
@ -131,11 +127,4 @@ mod tests {
|
||||
let app = reload.reload_database();
|
||||
app.unwrap_error();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_op() {
|
||||
let reload = AppMachine::reload(inner(music_hoard(vec![])));
|
||||
let app = reload.no_op();
|
||||
app.unwrap_reload();
|
||||
}
|
||||
}
|
||||
|
@ -98,10 +98,6 @@ impl IAppInteractSearch for AppMachine<AppSearch> {
|
||||
self.inner.selection.select_by_list(self.state.orig);
|
||||
AppMachine::browse(self.inner).into()
|
||||
}
|
||||
|
||||
fn no_op(self) -> Self::APP {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
trait IAppInteractSearchPrivate {
|
||||
@ -544,13 +540,6 @@ mod tests {
|
||||
let browse = search.cancel_search().unwrap_browse();
|
||||
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)]
|
||||
|
@ -20,14 +20,14 @@ pub enum AppState<BS, IS, RS, SS, FS, MS, ES, CS> {
|
||||
}
|
||||
|
||||
pub trait IAppInteract {
|
||||
type BS: IAppInteractBrowse<APP = Self>;
|
||||
type IS: IAppInteractInfo<APP = Self>;
|
||||
type RS: IAppInteractReload<APP = Self>;
|
||||
type SS: IAppInteractSearch<APP = Self>;
|
||||
type FS: IAppInteractFetch<APP = Self> + IAppEventFetch<APP = Self>;
|
||||
type MS: IAppInteractMatches<APP = Self>;
|
||||
type ES: IAppInteractError<APP = Self>;
|
||||
type CS: IAppInteractCritical<APP = Self>;
|
||||
type BS: IAppBase<APP = Self> + IAppInteractBrowse<APP = Self>;
|
||||
type IS: IAppBase<APP = Self> + IAppInteractInfo<APP = Self>;
|
||||
type RS: IAppBase<APP = Self> + IAppInteractReload<APP = Self>;
|
||||
type SS: IAppBase<APP = Self> + IAppInteractSearch<APP = Self>;
|
||||
type FS: IAppBase<APP = Self> + IAppInteractFetch<APP = Self> + IAppEventFetch<APP = Self>;
|
||||
type MS: IAppBase<APP = Self> + IAppInteractMatches<APP = Self>;
|
||||
type ES: IAppBase<APP = Self> + IAppInteractError<APP = Self>;
|
||||
type CS: IAppBase<APP = Self>;
|
||||
|
||||
fn is_running(&self) -> bool;
|
||||
fn force_quit(self) -> Self;
|
||||
@ -38,6 +38,12 @@ pub trait IAppInteract {
|
||||
) -> AppState<Self::BS, Self::IS, Self::RS, Self::SS, Self::FS, Self::MS, Self::ES, Self::CS>;
|
||||
}
|
||||
|
||||
pub trait IAppBase {
|
||||
type APP: IAppInteract;
|
||||
|
||||
fn no_op(self) -> Self::APP;
|
||||
}
|
||||
|
||||
pub trait IAppInteractBrowse {
|
||||
type APP: IAppInteract;
|
||||
|
||||
@ -55,16 +61,12 @@ pub trait IAppInteractBrowse {
|
||||
fn begin_search(self) -> Self::APP;
|
||||
|
||||
fn fetch_musicbrainz(self) -> Self::APP;
|
||||
|
||||
fn no_op(self) -> Self::APP;
|
||||
}
|
||||
|
||||
pub trait IAppInteractInfo {
|
||||
type APP: IAppInteract;
|
||||
|
||||
fn hide_info_overlay(self) -> Self::APP;
|
||||
|
||||
fn no_op(self) -> Self::APP;
|
||||
}
|
||||
|
||||
pub trait IAppInteractReload {
|
||||
@ -73,8 +75,6 @@ pub trait IAppInteractReload {
|
||||
fn reload_library(self) -> Self::APP;
|
||||
fn reload_database(self) -> Self::APP;
|
||||
fn hide_reload_menu(self) -> Self::APP;
|
||||
|
||||
fn no_op(self) -> Self::APP;
|
||||
}
|
||||
|
||||
pub trait IAppInteractSearch {
|
||||
@ -85,16 +85,12 @@ pub trait IAppInteractSearch {
|
||||
fn step_back(self) -> Self::APP;
|
||||
fn finish_search(self) -> Self::APP;
|
||||
fn cancel_search(self) -> Self::APP;
|
||||
|
||||
fn no_op(self) -> Self::APP;
|
||||
}
|
||||
|
||||
pub trait IAppInteractFetch {
|
||||
type APP: IAppInteract;
|
||||
|
||||
fn abort(self) -> Self::APP;
|
||||
|
||||
fn no_op(self) -> Self::APP;
|
||||
}
|
||||
|
||||
pub trait IAppEventFetch {
|
||||
@ -111,22 +107,12 @@ pub trait IAppInteractMatches {
|
||||
fn select(self) -> Self::APP;
|
||||
|
||||
fn abort(self) -> Self::APP;
|
||||
|
||||
fn no_op(self) -> Self::APP;
|
||||
}
|
||||
|
||||
pub trait IAppInteractError {
|
||||
type APP: IAppInteract;
|
||||
|
||||
fn dismiss_error(self) -> Self::APP;
|
||||
|
||||
fn no_op(self) -> Self::APP;
|
||||
}
|
||||
|
||||
pub trait IAppInteractCritical {
|
||||
type APP: IAppInteract;
|
||||
|
||||
fn no_op(self) -> Self::APP;
|
||||
}
|
||||
|
||||
// It would be preferable to have a getter for each field separately. However, the selection field
|
||||
|
@ -5,14 +5,13 @@ use mockall::automock;
|
||||
|
||||
use crate::tui::{
|
||||
app::{
|
||||
AppState, Delta, IAppInteract, IAppInteractBrowse, IAppInteractCritical, IAppInteractError,
|
||||
IAppInteractFetch, IAppInteractInfo, IAppInteractMatches, IAppInteractReload,
|
||||
IAppInteractSearch,
|
||||
AppState, Delta, IAppInteract, IAppInteractBrowse, IAppInteractError, IAppInteractFetch,
|
||||
IAppInteractInfo, IAppInteractMatches, IAppInteractReload, IAppInteractSearch,
|
||||
},
|
||||
event::{Event, EventError, EventReceiver},
|
||||
};
|
||||
|
||||
use super::app::IAppEventFetch;
|
||||
use super::app::{IAppBase, IAppEventFetch};
|
||||
|
||||
#[cfg_attr(test, automock)]
|
||||
pub trait IEventHandler<APP: IAppInteract> {
|
||||
|
Loading…
Reference in New Issue
Block a user