summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2020-07-05 13:28:18 +0200
committerMatthias Beyer <mail@beyermatthias.de>2020-07-05 13:30:03 +0200
commit4cf5e76ed4c2d5b179e166628295e0a09a022aaf (patch)
treea539c77545befbaef25a3dc4e4b5b0def667b04d
parentd76040741bd237c92f6969a562f82fb2045850f3 (diff)
Add main view implementation
This patch adds a main view that can be used to list mails from boxes. Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
-rw-r--r--Cargo.toml5
-rw-r--r--src/main.rs30
-rw-r--r--src/main_view.rs98
-rw-r--r--src/sidebar.rs34
4 files changed, 134 insertions, 33 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 4b34c61..3259871 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,3 +16,8 @@ cursive = "0.15"
[dependencies.cursive_tree_view]
git = "https://github.com/matthiasbeyer/cursive_tree_view"
branch = "update-deps"
+
+[dependencies.cursive-tabs]
+git = "https://github.com/matthiasbeyer/cursive-tabs"
+branch = "update-deps"
+
diff --git a/src/main.rs b/src/main.rs
index 646a9fe..04f041d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,30 +3,12 @@
use std::path::PathBuf;
use anyhow::Result;
use cursive::CursiveExt;
-use cursive::view::Nameable;
use mailparse::MailHeaderMap;
use mailparse::ParsedMail;
mod mailstore;
mod sidebar;
-
-fn list_view_for<'a, I>(i: I) -> Result<cursive::views::ListView>
- where I: Iterator<Item = &'a ParsedMail>
-{
- let mut lv = cursive::views::ListView::new();
-
- for elem in i {
- let s = format!("{}: {} -> {} | {}",
- elem.headers.get_first_value("Date").unwrap_or_else(|| String::from("No date")),
- elem.headers.get_first_value("From").unwrap_or_else(|| String::from("No From")),
- elem.headers.get_first_value("To").unwrap_or_else(|| String::from("No To")),
- elem.headers.get_first_value("Subject").unwrap_or_else(|| String::from("No Subject")));
-
- lv.add_child("", cursive::views::TextView::new(s));
- }
-
- Ok(lv)
-}
+mod main_view;
fn main() -> Result<()> {
let maildir_path = std::env::args()
@@ -36,7 +18,7 @@ fn main() -> Result<()> {
.ok_or_else(|| anyhow!("No path to maildir passed"))?;
let dirs = walkdir::WalkDir::new(maildir_path.clone())
- .max_depth(0)
+ .max_depth(1)
.follow_links(false)
.same_file_system(true)
.into_iter()
@@ -45,13 +27,11 @@ fn main() -> Result<()> {
.map(|de| de.path().to_path_buf());
let sidebar = sidebar::sidebar(dirs)?;
- let mut md = mailstore::MailStore::from_path(maildir_path);
- md.load()?;
- let list_view = list_view_for(md.cur_mail().iter().map(mailstore::Mail::parsed))?;
+ let mainview = main_view::MainView::new();
let mut layout = cursive::views::LinearLayout::horizontal();
- layout.add_child(sidebar.with_name("Sidebar"));
- layout.add_child(list_view);
+ layout.add_child(sidebar);
+ layout.add_child(mainview);
let mut siv = cursive::Cursive::default();
siv.add_layer(layout);
diff --git a/src/main_view.rs b/src/main_view.rs
new file mode 100644
index 0000000..9c92a7e
--- /dev/null
+++ b/src/main_view.rs
@@ -0,0 +1,98 @@
+use std::path::PathBuf;
+use anyhow::Result;
+use cursive::{View, Printer, XY, direction::Direction, view::Selector, Rect, event::Event, event::EventResult};
+use cursive::view::Nameable;
+use cursive::Cursive;
+use cursive::views::NamedView;
+use mailparse::MailHeaderMap;
+use mailparse::ParsedMail;
+
+use crate::mailstore::{ MailStore, Mail };
+
+pub const MAIN_VIEW_NAME: &'static str = "main_view";
+
+pub struct MainView {
+ tabs: cursive_tabs::TabView<usize>,
+}
+
+impl View for MainView {
+ fn draw(&self, printer: &Printer) {
+ self.tabs.draw(printer)
+ }
+
+ fn layout(&mut self, xy: XY<usize>) {
+ self.tabs.layout(xy)
+ }
+
+ fn needs_relayout(&self) -> bool {
+ self.tabs.needs_relayout()
+ }
+
+ fn required_size(&mut self, constraint: XY<usize>) -> XY<usize> {
+ self.tabs.required_size(constraint)
+ }
+
+ fn on_event(&mut self, e: Event) -> EventResult {
+ self.tabs.on_event(e)
+ }
+
+ fn call_on_any<'a>(&mut self, s: &Selector, tpl: &'a mut (dyn FnMut(&mut (dyn View + 'static)) + 'a)) {
+ self.tabs.call_on_any(s, tpl);
+ }
+
+ fn focus_view(&mut self, s: &Selector) -> Result<(), ()> {
+ self.tabs.focus_view(s)
+ }
+
+ fn take_focus(&mut self, source: Direction) -> bool {
+ self.tabs.take_focus(source)
+ }
+
+ fn important_area(&self, view_size: XY<usize>) -> Rect {
+ self.tabs.important_area(view_size)
+ }
+
+ fn type_name(&self) -> &'static str {
+ self.tabs.type_name()
+ }
+
+}
+
+impl MainView {
+ pub fn new() -> NamedView<Self> {
+ let mut tabs = cursive_tabs::TabView::default();
+ tabs.add_tab(0, cursive::views::TextView::new("Test"));
+ MainView { tabs }.with_name(MAIN_VIEW_NAME)
+ }
+
+ pub fn load_maildir(&mut self, pb: PathBuf) -> Result<()> {
+ let mut md = MailStore::from_path(pb);
+ md.load()?;
+ let list_view = MainView::list_view_for(md.cur_mail().iter().map(Mail::parsed))?;
+
+ self.tabs.add_tab(1, list_view.with_name("Tab"));
+ Ok(())
+ }
+
+ fn list_view_for<'a, I>(i: I) -> Result<cursive::views::ListView>
+ where I: Iterator<Item = &'a ParsedMail>
+ {
+ let mut lv = cursive::views::ListView::new();
+
+ for elem in i {
+ let s = format!("{}: {} -> {} | {}",
+ elem.headers.get_first_value("Date").unwrap_or_else(|| String::from("No date")),
+ elem.headers.get_first_value("From").unwrap_or_else(|| String::from("No From")),
+ elem.headers.get_first_value("To").unwrap_or_else(|| String::from("No To")),
+ elem.headers.get_first_value("Subject").unwrap_or_else(|| String::from("No Subject")));
+
+ lv.add_child("", cursive::views::TextView::new(s));
+ }
+
+ Ok(lv)
+ }
+
+}
+
+
+
diff --git a/src/sidebar.rs b/src/sidebar.rs
index ecc2e29..922e446 100644
--- a/src/sidebar.rs
+++ b/src/sidebar.rs
@@ -2,11 +2,17 @@ use std::path::PathBuf;
use anyhow::Result;
use std::fmt;
use std::ffi::OsStr;
+use cursive::view::Nameable;
+use cursive::views::NamedView;
+use cursive::Cursive;
+
+use crate::main_view::MainView;
+use cursive_tree_view::TreeView;
#[derive(Debug)]
pub struct TreeEntry {
name: String,
- dir: Option<PathBuf>,
+ path: PathBuf,
}
impl fmt::Display for TreeEntry {
@@ -15,23 +21,34 @@ impl fmt::Display for TreeEntry {
}
}
+pub const SIDEBAR_VIEW_NAME: &'static str = "sidebar_tree_view";
-pub fn sidebar<I>(iter: I) -> Result<cursive_tree_view::TreeView<TreeEntry>>
+pub fn sidebar<I>(iter: I) -> Result<NamedView<cursive_tree_view::TreeView<TreeEntry>>>
where I: Iterator<Item = PathBuf>
{
let mut tv = cursive_tree_view::TreeView::default();
+ tv.set_on_submit(|siv: &mut Cursive, row: usize| {
+ let borrow = siv.call_on_name(SIDEBAR_VIEW_NAME, move |tree: &mut TreeView<TreeEntry>| {
+ tree.borrow_item(row).map(|b| b.path.clone())
+ })
+ .flatten();
+
+ if let Some(path) = borrow {
+ siv.call_on_name(crate::main_view::MAIN_VIEW_NAME, move |main_view: &mut MainView| {
+ main_view.load_maildir(path);
+ None as Option<()>
+ });
+ }
+ });
+
+ // Fill the tree from the iterator
iter.map(|path| {
path.file_name()
.and_then(OsStr::to_str)
.map(String::from)
.ok_or_else(|| anyhow!("UTF8 error"))
- .map(|name| {
- TreeEntry {
- name,
- dir: Some(path)
- }
- })
+ .map(|name| TreeEntry { name, path })
})
.enumerate()
.fold(Ok(tv), |accu, (i, item)| {
@@ -40,4 +57,5 @@ pub fn sidebar<I>(iter: I) -> Result<cursive_tree_view::TreeView<TreeEntry>>
.map(|_| tv)
})
})
+ .map(|tv| tv.with_name(SIDEBAR_VIEW_NAME))
}