summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2020-07-07 17:53:47 +0200
committerMatthias Beyer <mail@beyermatthias.de>2020-07-07 17:53:47 +0200
commit8eadd57a6a6ec1c9a8618ded99ad1869dc84c841 (patch)
tree7010ba427606f5f7adbb9b341b079c3e7419c3e1 /src
parent757e22b8a78b994431a32114280f7752e4705f74 (diff)
Refactor AsyncView creation into Loader / PostProcessor abstraction
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
Diffstat (limited to 'src')
-rw-r--r--src/loader.rs19
-rw-r--r--src/main.rs1
-rw-r--r--src/main_view.rs36
-rw-r--r--src/sidebar.rs13
4 files changed, 53 insertions, 16 deletions
diff --git a/src/loader.rs b/src/loader.rs
new file mode 100644
index 0000000..2a2d573
--- /dev/null
+++ b/src/loader.rs
@@ -0,0 +1,19 @@
+/// Helper trait to load something and then postprocess it
+///
+/// the load() function might fail, but the PostProcessor::postprocess() function should never fail.
+pub trait Loader {
+ type Output: Sized;
+ type Error: Sized;
+ type PostProcessedOutput: Sized;
+ type PostProcessor: PostProcessor<Self::Output, Output = Self::PostProcessedOutput>;
+
+ fn load(self) -> Result<Self::Output, Self::Error>;
+ fn postprocessor(&self) -> Self::PostProcessor;
+}
+
+pub trait PostProcessor<Object: Sized> {
+ type Output: Sized;
+
+ fn postprocess(&self, o: Object) -> Self::Output;
+}
+
diff --git a/src/main.rs b/src/main.rs
index 26f9a47..174fd71 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -11,6 +11,7 @@ use env_logger::Env;
mod mailstore;
mod sidebar;
mod main_view;
+mod loader;
mod util;
fn main() -> Result<()> {
diff --git a/src/main_view.rs b/src/main_view.rs
index 9048fb2..6f45296 100644
--- a/src/main_view.rs
+++ b/src/main_view.rs
@@ -11,6 +11,8 @@ use mailparse::ParsedMail;
use async_std::sync::channel;
use crate::mailstore::{ MailStore, Mail };
+use crate::loader::Loader;
+use crate::loader::PostProcessor;
pub const MAIN_VIEW_NAME: &'static str = "main_view";
@@ -69,11 +71,10 @@ impl MainView {
MainView { tabs }.with_name(MAIN_VIEW_NAME)
}
- pub fn maildir_loader(&mut self, pb: PathBuf) -> (MaildirLoader, MaildirLoaderPostProcessor) {
+ pub fn maildir_loader(&mut self, pb: PathBuf) -> MaildirLoader {
debug!("Creating Loader for: {}", pb.display());
- let maildir_loader = MaildirLoader { maildir_path: pb };
- let postprocessor = MaildirLoaderPostProcessor;
- (maildir_loader, postprocessor)
+ let maildir_loader = MaildirLoader(pb);
+ maildir_loader
}
pub fn add_tab<T: View>(&mut self, id: String, view: T) {
@@ -82,14 +83,17 @@ impl MainView {
}
-pub struct MaildirLoader {
- maildir_path: PathBuf
-}
+pub struct MaildirLoader(PathBuf);
+
+impl Loader for MaildirLoader {
+ type Output = Vec<String>;
+ type Error = String;
+ type PostProcessedOutput = cursive::views::ListView;
+ type PostProcessor = MaildirLoaderPostProcessor;
-impl MaildirLoader {
- pub fn load(self) -> RResult<Vec<String>, String> {
- debug!("Loading: {}", self.maildir_path.display());
- MailStore::build_from_path(self.maildir_path).collect::<Result<MailStore>>()
+ fn load(self) -> Result<Self::Output, Self::Error> {
+ debug!("Loading: {}", self.0.display());
+ MailStore::build_from_path(self.0).collect::<Result<MailStore>>()
.map(|store| {
store.cur_mail()
.iter()
@@ -107,11 +111,17 @@ impl MaildirLoader {
})
.map_err(|e| e.to_string())
}
+
+ fn postprocessor(&self) -> Self::PostProcessor {
+ MaildirLoaderPostProcessor
+ }
}
pub struct MaildirLoaderPostProcessor;
-impl MaildirLoaderPostProcessor {
- pub fn postprocess(&self, list: Vec<String>) -> cursive::views::ListView {
+impl PostProcessor<Vec<String>> for MaildirLoaderPostProcessor {
+ type Output = cursive::views::ListView;
+
+ fn postprocess(&self, list: Vec<String>) -> Self::Output{
list.into_iter()
.fold(cursive::views::ListView::new(), |view, elem| {
view.child("", cursive::views::TextView::new(elem))
diff --git a/src/sidebar.rs b/src/sidebar.rs
index d0427d5..48b7a6a 100644
--- a/src/sidebar.rs
+++ b/src/sidebar.rs
@@ -9,6 +9,9 @@ use cursive::views::NamedView;
use cursive_tree_view::TreeView;
use crate::main_view::MainView;
+use crate::main_view::MaildirLoader;
+use crate::loader::PostProcessor;
+use crate::loader::Loader;
#[derive(Debug)]
pub struct TreeEntry {
@@ -54,7 +57,7 @@ impl Sidebar {
.flatten();
if let Some(path) = borrow {
- let (loader, processor) = {
+ let loader = { // Fetch the loader for the view to be created
let p = path.clone();
siv.call_on_name(crate::main_view::MAIN_VIEW_NAME, move |main_view: &mut MainView| {
Some(main_view.maildir_loader(p))
@@ -63,9 +66,12 @@ impl Sidebar {
.unwrap()
};
+ let postprocessor = loader.postprocessor();
+
+ // Construct the AsyncView with the loader job
let list_view = cursive_async_view::AsyncView::new_with_bg_creator(&mut siv,
- move || { loader.load() },
- move |list| { processor.postprocess(list) });
+ || { loader.load() },
+ move |list| { postprocessor.postprocess(list) });
let name = path.file_name()
.and_then(OsStr::to_str)
@@ -73,6 +79,7 @@ impl Sidebar {
.ok_or_else(|| anyhow!("UTF8 error"))
.unwrap();
+ // Add the AsyncView to the screen
siv.call_on_name(crate::main_view::MAIN_VIEW_NAME, move |main_view: &mut MainView| {
Some(main_view.add_tab(name, list_view))
});