ui: fix seen property of threads on open, add env rename events
parent
f36cb111b5
commit
11b2abd1d1
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -86,10 +86,12 @@ impl PlainListing {
|
|||
/// chosen.
|
||||
fn refresh_mailbox(&mut self, context: &mut Context) {
|
||||
self.dirty = true;
|
||||
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;
|
||||
self.cursor_pos.1 = self.new_cursor_pos.1;
|
||||
self.cursor_pos.0 = self.new_cursor_pos.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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -585,6 +585,7 @@ impl Component for ThreadView {
|
|||
),
|
||||
None,
|
||||
None,
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue