summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2019-04-01 23:53:06 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2019-06-10 19:40:41 +0300
commit11b2abd1d125a41a0fb0c28a166316f6aed5bc39 (patch)
treeddf88e2499d8445eb493230e81b163af648c0a8b
parentf36cb111b5b16614eb0b7930cb342d60bdec6f31 (diff)
ui: fix seen property of threads on open, add env rename events
-rw-r--r--melib/src/mailbox/collection.rs4
-rw-r--r--melib/src/mailbox/thread.rs34
-rw-r--r--ui/src/components/mail/listing/plain.rs35
-rw-r--r--ui/src/components/mail/listing/thread.rs2
-rw-r--r--ui/src/components/mail/view.rs35
-rw-r--r--ui/src/components/mail/view/thread.rs1
-rw-r--r--ui/src/conf/accounts.rs8
-rw-r--r--ui/src/state.rs3
-rw-r--r--ui/src/types.rs4
9 files changed, 105 insertions, 21 deletions
diff --git a/melib/src/mailbox/collection.rs b/melib/src/mailbox/collection.rs
index 54ffaaa3..9dffab4b 100644
--- a/melib/src/mailbox/collection.rs
+++ b/melib/src/mailbox/collection.rs
@@ -107,7 +107,7 @@ impl Collection {
env.set_hash(new_hash);
self.envelopes.insert(new_hash, env);
{
- if self.threads.update_envelope(old_hash, new_hash).is_ok() {
+ if self.threads.update_envelope(old_hash, new_hash, &self.envelopes).is_ok() {
return;
}
}
@@ -123,7 +123,7 @@ impl Collection {
let new_hash = envelope.hash();
self.envelopes.insert(new_hash, envelope);
{
- if self.threads.update_envelope(old_hash, new_hash).is_ok() {
+ if self.threads.update_envelope(old_hash, new_hash, &self.envelopes).is_ok() {
return;
}
}
diff --git a/melib/src/mailbox/thread.rs b/melib/src/mailbox/thread.rs
index b4427b01..8e86b842 100644
--- a/melib/src/mailbox/thread.rs
+++ b/melib/src/mailbox/thread.rs
@@ -822,22 +822,26 @@ impl Threads {
&mut self,
old_hash: EnvelopeHash,
new_hash: EnvelopeHash,
+ collection: &Envelopes,
) -> Result<(), ()> {
/* must update:
* - hash_set
* - message fields in thread_nodes
*/
- self.hash_set.remove(&old_hash);
- if let Some(node) = self
+ let idx = if let Some((idx, node)) = self
.thread_nodes
.iter_mut()
- .find(|n| n.message.map(|n| n == old_hash).unwrap_or(false))
+ .enumerate()
+ .find(|(_, n)| n.message.map(|n| n == old_hash).unwrap_or(false))
{
node.message = Some(new_hash);
+ idx
} else {
return Err(());
- }
+ };
+ self.hash_set.remove(&old_hash);
self.hash_set.insert(new_hash);
+ self.rebuild_thread(idx, collection);
Ok(())
}
@@ -971,6 +975,26 @@ impl Threads {
let mut node_idx = id;
let mut stack = Vec::with_capacity(32);
+ let no_parent: bool = if let Some(node) = self.thread_nodes.get(node_idx) {
+ if node.parent.is_none() {
+ true
+ } else {
+ false
+ }
+ } else {
+ false
+ };
+
+ if no_parent {
+ let tree = self.tree.get_mut();
+ if let Some(tree) = tree.iter_mut().find(|t| t.id == id) {
+ *tree = ThreadTree::new(id);
+ node_build(tree, id, &mut self.thread_nodes, 1, collection);
+ return;
+ }
+ unreachable!();
+ }
+
/* Trace path back to root ThreadNode */
while let Some(p) = &self.thread_nodes[node_idx].parent {
node_idx = *p;
@@ -1310,7 +1334,7 @@ fn node_build(
indentation + 1
};
- let mut has_unseen = thread_nodes[idx].has_unseen;
+ let mut has_unseen = !collection[&thread_nodes[idx].message.unwrap()].is_seen();
let mut child_vec: Vec<ThreadTree> = Vec::new();
thread_nodes[idx].len = thread_nodes[idx].children.len();
diff --git a/ui/src/components/mail/listing/plain.rs b/ui/src/components/mail/listing/plain.rs
index d354aee3..ec3e23cb 100644
--- a/ui/src/components/mail/listing/plain.rs
+++ b/ui/src/components/mail/listing/plain.rs
@@ -86,10 +86,12 @@ impl PlainListing {
/// chosen.
fn refresh_mailbox(&mut self, context: &mut Context) {
self.dirty = true;
- self.cursor_pos.2 = 0;
- self.new_cursor_pos.2 = 0;
- self.cursor_pos.1 = self.new_cursor_pos.1;
- self.cursor_pos.0 = self.new_cursor_pos.0;
+ if !(self.cursor_pos.0 == self.new_cursor_pos.0
+ && self.cursor_pos.1 == self.new_cursor_pos.1)
+ {
+ self.cursor_pos.2 = 0;
+ self.new_cursor_pos.2 = 0;
+ }
// Inform State that we changed the current folder view.
context.replies.push_back(UIEvent {
@@ -98,13 +100,22 @@ impl PlainListing {
});
// Get mailbox as a reference.
//
- loop {
- // TODO: Show progress visually
- if context.accounts[self.cursor_pos.0]
- .status(self.cursor_pos.1)
- .is_ok()
- {
- break;
+ // Get mailbox as a reference.
+ //
+ match context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) {
+ Ok(_) => {}
+ Err(_) => {
+ self.content = CellBuffer::new(MAX_COLS, 1, Cell::with_char(' '));
+ self.length = 0;
+ write_string_to_grid(
+ "Loading.",
+ &mut self.content,
+ Color::Default,
+ Color::Default,
+ ((0, 0), (MAX_COLS - 1, 0)),
+ false,
+ );
+ return;
}
}
let mailbox = &context.accounts[self.cursor_pos.0][self.cursor_pos.1]
@@ -407,7 +418,7 @@ impl Component for PlainListing {
coordinates.1,
self.local_collection[self.cursor_pos.2],
);
- self.view = Some(MailView::new(coordinates, None, None));
+ self.view = Some(MailView::new(coordinates, None, None, context));
}
self.view.as_mut().unwrap().draw(
grid,
diff --git a/ui/src/components/mail/listing/thread.rs b/ui/src/components/mail/listing/thread.rs
index edfbd7dc..4c909ae2 100644
--- a/ui/src/components/mail/listing/thread.rs
+++ b/ui/src/components/mail/listing/thread.rs
@@ -546,7 +546,7 @@ impl Component for ThreadListing {
self.locations[self.cursor_pos.2],
);
- self.view = Some(MailView::new(coordinates, None, None));
+ self.view = Some(MailView::new(coordinates, None, None, context));
self.view.as_mut().unwrap().draw(
grid,
(set_y(upper_left, mid + 1), bottom_right),
diff --git a/ui/src/components/mail/view.rs b/ui/src/components/mail/view.rs
index b8fd4b88..12602e33 100644
--- a/ui/src/components/mail/view.rs
+++ b/ui/src/components/mail/view.rs
@@ -83,7 +83,33 @@ impl MailView {
coordinates: (usize, usize, EnvelopeHash),
pager: Option<Pager>,
subview: Option<Box<Component>>,
+ context: &mut Context,
) -> Self {
+ let account = &mut context.accounts[coordinates.0];
+ let (hash, is_seen) = {
+ let mailbox = &mut account[coordinates.1].as_mut().unwrap();
+ let envelope: &mut Envelope = &mut mailbox
+ .collection
+ .entry(coordinates.2)
+ .or_default();
+ (envelope.hash(), envelope.is_seen())
+ };
+ if !is_seen {
+ let folder_hash = {
+ let mailbox = &mut account[coordinates.1].as_mut().unwrap();
+ mailbox.folder.hash()
+ };
+ let op = {
+ let backend = &account.backend;
+ backend.operation(hash, folder_hash)
+ };
+ let mailbox = &mut account[coordinates.1].as_mut().unwrap();
+ let envelope: &mut Envelope = &mut mailbox
+ .collection
+ .entry(coordinates.2)
+ .or_default();
+ envelope.set_seen(op).unwrap();
+ }
MailView {
coordinates,
pager,
@@ -220,6 +246,11 @@ impl Component for MailView {
let mailbox = &mut accounts[self.coordinates.0][self.coordinates.1]
.as_ref()
.unwrap();
+ if !mailbox.collection.contains_key(&self.coordinates.2) {
+ /* The envelope has been renamed or removed, so wait for the appropriate event to
+ * arrive */
+ return;
+ }
let envelope: &Envelope = &mailbox.collection[&self.coordinates.2];
if self.mode == ViewMode::Raw {
@@ -620,6 +651,10 @@ impl Component for MailView {
}
self.dirty = true;
}
+ UIEventType::EnvelopeRename(_, old_hash, new_hash) if old_hash == self.coordinates.2 => {
+ self.coordinates.2 = new_hash;
+ self.set_dirty();
+ }
_ => {
return false;
}
diff --git a/ui/src/components/mail/view/thread.rs b/ui/src/components/mail/view/thread.rs
index 62775e83..577ea1b5 100644
--- a/ui/src/components/mail/view/thread.rs
+++ b/ui/src/components/mail/view/thread.rs
@@ -585,6 +585,7 @@ impl Component for ThreadView {
),
None,
None,
+ context,
);
}
diff --git a/ui/src/conf/accounts.rs b/ui/src/conf/accounts.rs
index 9ac956cd..d739649c 100644
--- a/ui/src/conf/accounts.rs
+++ b/ui/src/conf/accounts.rs
@@ -38,7 +38,7 @@ use std::mem;
use std::ops::{Index, IndexMut};
use std::result;
use std::sync::Arc;
-use types::UIEventType::{self, Notification};
+use types::UIEventType::{self, Notification, EnvelopeUpdate, EnvelopeRename, EnvelopeRemove};
pub type Worker = Option<Async<Result<Mailbox>>>;
@@ -153,9 +153,14 @@ impl Account {
match kind {
RefreshEventKind::Update(old_hash, envelope) => {
mailbox!(idx, self.folders).update(old_hash, *envelope);
+ return Some(EnvelopeUpdate(old_hash));
}
RefreshEventKind::Rename(old_hash, new_hash) => {
+ if cfg!(feature = "debug_log") {
+ eprintln!("rename {} to {}", old_hash, new_hash);
+ }
mailbox!(idx, self.folders).rename(old_hash, new_hash);
+ return Some(EnvelopeRename(idx, old_hash, new_hash));
}
RefreshEventKind::Create(envelope) => {
if cfg!(feature = "debug_log") {
@@ -176,6 +181,7 @@ impl Account {
}
RefreshEventKind::Remove(envelope_hash) => {
mailbox!(idx, self.folders).remove(envelope_hash);
+ return Some(EnvelopeRemove(envelope_hash));
}
RefreshEventKind::Rescan => {
let ref_folders: Vec<Folder> = self.backend.folders();
diff --git a/ui/src/state.rs b/ui/src/state.rs
index 320d3e2d..723693b1 100644
--- a/ui/src/state.rs
+++ b/ui/src/state.rs
@@ -280,6 +280,9 @@ impl State {
self.context
.sender
.send(ThreadEvent::UIEvent(UIEventType::StartupCheck(hash)));
+ self.context
+ .sender
+ .send(ThreadEvent::UIEvent(UIEventType::MailboxUpdate((idxa, idxm))));
self.context.replies.push_back(UIEvent {
id: 0,
event_type: notification,
diff --git a/ui/src/types.rs b/ui/src/types.rs
index bbbbf547..9f5b19ba 100644
--- a/ui/src/types.rs
+++ b/ui/src/types.rs
@@ -27,6 +27,7 @@ use super::execute::Action;
use super::terminal::*;
use melib::RefreshEvent;
+use melib::EnvelopeHash;
use melib::backends::FolderHash;
use std;
use std::fmt;
@@ -86,6 +87,9 @@ pub enum UIEventType {
EntityKill(Uuid),
StartupCheck(FolderHash),
RefreshEvent(Box<RefreshEvent>),
+ EnvelopeUpdate(EnvelopeHash),
+ EnvelopeRename(usize, EnvelopeHash, EnvelopeHash),
+ EnvelopeRemove(EnvelopeHash),
}
impl From<RefreshEvent> for UIEvent {