ui: Use FolderHash instead of usize for folder cursor
Use FolderHash directly as a cursor type for folders within an account isntead of having a usize (being the order of the folder within the account) and figuring out the folder_hash everytime it's needed. Add OfflineListing for offline accounts and AccountStatusChange event.memfd
parent
42747ef590
commit
647cb10b33
|
@ -305,7 +305,7 @@ fn run_app() -> Result<()> {
|
|||
let mut state = State::new(sender, receiver.clone())?;
|
||||
|
||||
let window = Box::new(Tabbed::new(vec![
|
||||
Box::new(listing::Listing::new(&state.context.accounts)),
|
||||
Box::new(listing::Listing::new(&mut state.context)),
|
||||
Box::new(ContactList::new(&state.context)),
|
||||
Box::new(StatusPanel::new()),
|
||||
]));
|
||||
|
|
|
@ -36,6 +36,9 @@ pub use self::thread::*;
|
|||
mod plain;
|
||||
pub use self::plain::*;
|
||||
|
||||
mod offline;
|
||||
pub use self::offline::*;
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct DataColumns {
|
||||
pub columns: [CellBuffer; 12],
|
||||
|
@ -122,6 +125,7 @@ struct AccountMenuEntry {
|
|||
name: String,
|
||||
// Index in the config account vector.
|
||||
index: usize,
|
||||
entries: SmallVec<[(usize, FolderHash); 16]>,
|
||||
}
|
||||
|
||||
pub trait MailListingTrait: ListingTrait {
|
||||
|
@ -206,8 +210,8 @@ pub trait MailListingTrait: ListingTrait {
|
|||
}
|
||||
|
||||
pub trait ListingTrait: Component {
|
||||
fn coordinates(&self) -> (usize, usize);
|
||||
fn set_coordinates(&mut self, _: (usize, usize));
|
||||
fn coordinates(&self) -> (usize, FolderHash);
|
||||
fn set_coordinates(&mut self, _: (usize, FolderHash));
|
||||
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context);
|
||||
fn highlight_line(&mut self, grid: &mut CellBuffer, area: Area, idx: usize, context: &Context);
|
||||
fn filter(&mut self, _filter_term: &str, _context: &Context) {}
|
||||
|
@ -220,6 +224,7 @@ pub enum ListingComponent {
|
|||
Threaded(ThreadListing),
|
||||
Compact(CompactListing),
|
||||
Conversations(ConversationsListing),
|
||||
Offline(OfflineListing),
|
||||
}
|
||||
use crate::ListingComponent::*;
|
||||
|
||||
|
@ -232,6 +237,7 @@ impl core::ops::Deref for ListingComponent {
|
|||
Plain(ref l) => l,
|
||||
Threaded(ref l) => l,
|
||||
Conversations(ref l) => l,
|
||||
Offline(ref l) => l,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -243,6 +249,7 @@ impl core::ops::DerefMut for ListingComponent {
|
|||
Plain(l) => l,
|
||||
Threaded(l) => l,
|
||||
Conversations(l) => l,
|
||||
Offline(l) => l,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,37 +261,25 @@ impl ListingComponent {
|
|||
if let Plain(_) = self {
|
||||
return;
|
||||
}
|
||||
let mut new_l = PlainListing::default();
|
||||
let coors = self.coordinates();
|
||||
new_l.set_coordinates((coors.0, coors.1));
|
||||
*self = Plain(new_l);
|
||||
*self = Plain(PlainListing::new(self.coordinates()));
|
||||
}
|
||||
IndexStyle::Threaded => {
|
||||
if let Threaded(_) = self {
|
||||
return;
|
||||
}
|
||||
let mut new_l = ThreadListing::default();
|
||||
let coors = self.coordinates();
|
||||
new_l.set_coordinates((coors.0, coors.1));
|
||||
*self = Threaded(new_l);
|
||||
*self = Threaded(ThreadListing::new(self.coordinates()));
|
||||
}
|
||||
IndexStyle::Compact => {
|
||||
if let Compact(_) = self {
|
||||
return;
|
||||
}
|
||||
let mut new_l = CompactListing::default();
|
||||
let coors = self.coordinates();
|
||||
new_l.set_coordinates((coors.0, coors.1));
|
||||
*self = Compact(new_l);
|
||||
*self = Compact(CompactListing::new(self.coordinates()));
|
||||
}
|
||||
IndexStyle::Conversations => {
|
||||
if let Conversations(_) = self {
|
||||
return;
|
||||
}
|
||||
let mut new_l = ConversationsListing::default();
|
||||
let coors = self.coordinates();
|
||||
new_l.set_coordinates((coors.0, coors.1));
|
||||
*self = Conversations(new_l);
|
||||
*self = Conversations(ConversationsListing::new(self.coordinates()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -315,6 +310,7 @@ impl fmt::Display for Listing {
|
|||
Plain(ref l) => write!(f, "{}", l),
|
||||
Threaded(ref l) => write!(f, "{}", l),
|
||||
Conversations(ref l) => write!(f, "{}", l),
|
||||
Offline(ref l) => write!(f, "{}", l),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -331,7 +327,6 @@ impl Component for Listing {
|
|||
if !is_valid_area!(area) {
|
||||
return;
|
||||
}
|
||||
self.theme_default = crate::conf::value(context, "theme_default");
|
||||
let upper_left = upper_left!(area);
|
||||
let bottom_right = bottom_right!(area);
|
||||
let total_cols = get_x(bottom_right) - get_x(upper_left);
|
||||
|
@ -431,12 +426,7 @@ impl Component for Listing {
|
|||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||
match event {
|
||||
UIEvent::StartupCheck(ref f) => {
|
||||
if context.accounts[self.component.coordinates().0]
|
||||
.folders_order
|
||||
.get(self.component.coordinates().1)
|
||||
.map(|&folder_hash| *f == folder_hash)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
if self.component.coordinates().1 == *f {
|
||||
if !self.startup_checks_rate.tick() {
|
||||
return false;
|
||||
}
|
||||
|
@ -445,27 +435,52 @@ impl Component for Listing {
|
|||
UIEvent::Timer(n) if *n == self.startup_checks_rate.id() => {
|
||||
if self.startup_checks_rate.active {
|
||||
self.startup_checks_rate.reset();
|
||||
if let Some(folder_hash) = context.accounts[self.component.coordinates().0]
|
||||
.folders_order
|
||||
.get(self.component.coordinates().1)
|
||||
{
|
||||
return self
|
||||
.process_event(&mut UIEvent::StartupCheck(*folder_hash), context);
|
||||
}
|
||||
return self.process_event(
|
||||
&mut UIEvent::StartupCheck(self.component.coordinates().1),
|
||||
context,
|
||||
);
|
||||
}
|
||||
}
|
||||
UIEvent::AccountStatusChange(account_index) => {
|
||||
if self.cursor_pos.0 == *account_index {
|
||||
self.change_account(context);
|
||||
} else {
|
||||
self.accounts[*account_index].entries = context.accounts[*account_index]
|
||||
.list_folders()
|
||||
.into_iter()
|
||||
.filter(|folder_node| {
|
||||
context.accounts[*account_index].ref_folders()[&folder_node.hash]
|
||||
.is_subscribed()
|
||||
})
|
||||
.map(|f| (f.depth, f.hash))
|
||||
.collect::<_>();
|
||||
self.set_dirty(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
UIEvent::MailboxDelete((account_index, _folder_hash))
|
||||
| UIEvent::MailboxCreate((account_index, _folder_hash)) => {
|
||||
self.accounts[*account_index].entries = context.accounts[*account_index]
|
||||
.list_folders()
|
||||
.into_iter()
|
||||
.filter(|folder_node| {
|
||||
context.accounts[*account_index].ref_folders()[&folder_node.hash]
|
||||
.is_subscribed()
|
||||
})
|
||||
.map(|f| (f.depth, f.hash))
|
||||
.collect::<_>();
|
||||
if self.cursor_pos.0 == *account_index {
|
||||
self.cursor_pos.1 = std::cmp::min(
|
||||
context.accounts[*account_index].len() - 1,
|
||||
self.accounts[self.cursor_pos.0].entries.len() - 1,
|
||||
self.cursor_pos.1,
|
||||
);
|
||||
self.component
|
||||
.set_coordinates((self.cursor_pos.0, self.cursor_pos.1));
|
||||
self.component.set_coordinates((
|
||||
self.cursor_pos.0,
|
||||
self.accounts[self.cursor_pos.0].entries[self.cursor_pos.1].1,
|
||||
));
|
||||
self.component.refresh_mailbox(context, true);
|
||||
self.set_dirty(true);
|
||||
}
|
||||
self.set_dirty(true);
|
||||
return true;
|
||||
}
|
||||
_ => {}
|
||||
|
@ -496,15 +511,15 @@ impl Component for Listing {
|
|||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
return true;
|
||||
};
|
||||
let folder_length = context.accounts[self.cursor_pos.0].len();
|
||||
match k {
|
||||
k if shortcut!(k == shortcuts[Listing::DESCRIPTION]["next_folder"])
|
||||
&& folder_length > 0 =>
|
||||
{
|
||||
if self.cursor_pos.1 + amount < folder_length {
|
||||
k if shortcut!(k == shortcuts[Listing::DESCRIPTION]["next_folder"]) => {
|
||||
if let Some((_, folder_hash)) = self.accounts[self.cursor_pos.0]
|
||||
.entries
|
||||
.get(self.cursor_pos.1 + amount)
|
||||
{
|
||||
self.cursor_pos.1 += amount;
|
||||
self.component
|
||||
.set_coordinates((self.cursor_pos.0, self.cursor_pos.1));
|
||||
.set_coordinates((self.cursor_pos.0, *folder_hash));
|
||||
self.set_dirty(true);
|
||||
} else {
|
||||
return true;
|
||||
|
@ -512,25 +527,32 @@ impl Component for Listing {
|
|||
}
|
||||
k if shortcut!(k == shortcuts[Listing::DESCRIPTION]["prev_folder"]) => {
|
||||
if self.cursor_pos.1 >= amount {
|
||||
self.cursor_pos.1 -= amount;
|
||||
self.component
|
||||
.set_coordinates((self.cursor_pos.0, self.cursor_pos.1));
|
||||
self.set_dirty(true);
|
||||
if let Some((_, folder_hash)) = self.accounts[self.cursor_pos.0]
|
||||
.entries
|
||||
.get(self.cursor_pos.1 - amount)
|
||||
{
|
||||
self.cursor_pos.1 -= amount;
|
||||
self.component
|
||||
.set_coordinates((self.cursor_pos.0, *folder_hash));
|
||||
self.set_dirty(true);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_ => return false,
|
||||
_ => {}
|
||||
}
|
||||
/* Account might have no folders yet if it's offline */
|
||||
if let Some(&folder_hash) = context.accounts[self.cursor_pos.0]
|
||||
.folders_order
|
||||
if let Some((_, folder_hash)) = self.accounts[self.cursor_pos.0]
|
||||
.entries
|
||||
.get(self.cursor_pos.1)
|
||||
{
|
||||
/* Account might have no folders yet if it's offline */
|
||||
/* Check if per-folder configuration overrides general configuration */
|
||||
if let Some(index_style) =
|
||||
context.accounts.get(self.cursor_pos.0).and_then(|account| {
|
||||
account.folder_confs(folder_hash).conf_override.index_style
|
||||
account.folder_confs(*folder_hash).conf_override.index_style
|
||||
})
|
||||
{
|
||||
self.component.set_style(index_style);
|
||||
|
@ -572,8 +594,6 @@ impl Component for Listing {
|
|||
k if shortcut!(k == shortcuts[Listing::DESCRIPTION]["next_account"]) => {
|
||||
if self.cursor_pos.0 + amount < self.accounts.len() {
|
||||
self.cursor_pos = (self.cursor_pos.0 + amount, 0);
|
||||
self.component.set_coordinates((self.cursor_pos.0, 0));
|
||||
self.set_dirty(true);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
@ -581,40 +601,14 @@ impl Component for Listing {
|
|||
k if shortcut!(k == shortcuts[Listing::DESCRIPTION]["prev_account"]) => {
|
||||
if self.cursor_pos.0 >= amount {
|
||||
self.cursor_pos = (self.cursor_pos.0 - amount, 0);
|
||||
self.component.set_coordinates((self.cursor_pos.0, 0));
|
||||
self.set_dirty(true);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_ => return false,
|
||||
}
|
||||
self.change_account(context);
|
||||
|
||||
/* Account might have no folders yet if it's offline */
|
||||
if let Some(&folder_hash) = context.accounts[self.cursor_pos.0]
|
||||
.folders_order
|
||||
.get(self.cursor_pos.1)
|
||||
{
|
||||
/* Check if per-folder configuration overrides general configuration */
|
||||
if let Some(index_style) =
|
||||
context.accounts.get(self.cursor_pos.0).and_then(|account| {
|
||||
account.folder_confs(folder_hash).conf_override.index_style
|
||||
})
|
||||
{
|
||||
self.component.set_style(index_style);
|
||||
} else if let Some(index_style) = context
|
||||
.accounts
|
||||
.get(self.cursor_pos.0)
|
||||
.and_then(|account| Some(account.settings.conf.index_style()))
|
||||
{
|
||||
self.component.set_style(index_style);
|
||||
}
|
||||
}
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::UpdateStatus(
|
||||
self.get_status(context),
|
||||
)));
|
||||
return true;
|
||||
}
|
||||
UIEvent::Action(ref action) => match action {
|
||||
|
@ -876,57 +870,55 @@ impl Component for Listing {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<IndexStyle> for ListingComponent {
|
||||
fn from(index_style: IndexStyle) -> Self {
|
||||
impl From<(IndexStyle, (usize, FolderHash))> for ListingComponent {
|
||||
fn from((index_style, coordinates): (IndexStyle, (usize, FolderHash))) -> Self {
|
||||
match index_style {
|
||||
IndexStyle::Plain => Plain(Default::default()),
|
||||
IndexStyle::Threaded => Threaded(Default::default()),
|
||||
IndexStyle::Compact => Compact(Default::default()),
|
||||
IndexStyle::Conversations => Conversations(Default::default()),
|
||||
IndexStyle::Plain => Plain(PlainListing::new(coordinates)),
|
||||
IndexStyle::Threaded => Threaded(ThreadListing::new(coordinates)),
|
||||
IndexStyle::Compact => Compact(CompactListing::new(coordinates)),
|
||||
IndexStyle::Conversations => Conversations(ConversationsListing::new(coordinates)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Listing {
|
||||
const DESCRIPTION: &'static str = "listing";
|
||||
pub fn new(accounts: &[Account]) -> Self {
|
||||
let account_entries = accounts
|
||||
pub fn new(context: &mut Context) -> Self {
|
||||
let account_entries: Vec<AccountMenuEntry> = context
|
||||
.accounts
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, a)| AccountMenuEntry {
|
||||
name: a.name().to_string(),
|
||||
index: i,
|
||||
.map(|(i, a)| {
|
||||
let entries: SmallVec<[(usize, FolderHash); 16]> = a
|
||||
.list_folders()
|
||||
.into_iter()
|
||||
.filter(|folder_node| a.ref_folders()[&folder_node.hash].is_subscribed())
|
||||
.map(|f| (f.depth, f.hash))
|
||||
.collect::<_>();
|
||||
|
||||
AccountMenuEntry {
|
||||
name: a.name().to_string(),
|
||||
index: i,
|
||||
entries,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
/* Check if per-folder configuration overrides general configuration */
|
||||
let component = if let Some(index_style) = accounts.get(0).and_then(|account| {
|
||||
account.folders_order.get(0).and_then(|folder_hash| {
|
||||
account.folder_confs(*folder_hash).conf_override.index_style
|
||||
})
|
||||
}) {
|
||||
ListingComponent::from(index_style)
|
||||
} else if let Some(index_style) = accounts
|
||||
.get(0)
|
||||
.and_then(|account| Some(account.settings.conf.index_style()))
|
||||
{
|
||||
ListingComponent::from(index_style)
|
||||
} else {
|
||||
Conversations(Default::default())
|
||||
};
|
||||
Listing {
|
||||
component,
|
||||
let mut ret = Listing {
|
||||
component: Offline(OfflineListing::new((0, 0))),
|
||||
accounts: account_entries,
|
||||
visible: true,
|
||||
dirty: true,
|
||||
cursor_pos: (0, 0),
|
||||
startup_checks_rate: RateLimit::new(2, 1000),
|
||||
theme_default: ThemeAttribute::default(),
|
||||
theme_default: conf::value(context, "theme_default"),
|
||||
id: ComponentId::new_v4(),
|
||||
show_divider: false,
|
||||
menu_visibility: true,
|
||||
ratio: 90,
|
||||
cmd_buf: String::with_capacity(4),
|
||||
}
|
||||
};
|
||||
ret.change_account(context);
|
||||
ret
|
||||
}
|
||||
|
||||
fn draw_menu(&mut self, grid: &mut CellBuffer, mut area: Area, context: &mut Context) {
|
||||
|
@ -969,86 +961,31 @@ impl Listing {
|
|||
debug!("BUG: invalid area in print_account");
|
||||
}
|
||||
// Each entry and its index in the account
|
||||
let entries: FnvHashMap<FolderHash, Folder> = context.accounts[a.index]
|
||||
.list_folders()
|
||||
.into_iter()
|
||||
.map(|f| (f.hash(), f))
|
||||
.collect();
|
||||
let folders_order: FnvHashMap<FolderHash, usize> = context.accounts[a.index]
|
||||
.folders_order()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, &fh)| (fh, i))
|
||||
.collect();
|
||||
let folders: FnvHashMap<FolderHash, Folder> =
|
||||
context.accounts[a.index].ref_folders().clone();
|
||||
|
||||
let upper_left = upper_left!(area);
|
||||
let bottom_right = bottom_right!(area);
|
||||
|
||||
let must_highlight_account: bool = self.cursor_pos.0 == a.index;
|
||||
|
||||
let mut inc = 0;
|
||||
let mut depth = 0;
|
||||
let mut lines: Vec<(usize, usize, FolderHash, Option<usize>)> = Vec::new();
|
||||
|
||||
/* Gather the folder tree structure in `lines` recursively */
|
||||
fn print(
|
||||
folder_idx: FolderHash,
|
||||
depth: &mut usize,
|
||||
inc: &mut usize,
|
||||
entries: &FnvHashMap<FolderHash, Folder>,
|
||||
folders_order: &FnvHashMap<FolderHash, usize>,
|
||||
lines: &mut Vec<(usize, usize, FolderHash, Option<usize>)>,
|
||||
index: usize, //account index
|
||||
context: &mut Context,
|
||||
) {
|
||||
match context.accounts[index].status(entries[&folder_idx].hash()) {
|
||||
Ok(_) => {
|
||||
lines.push((
|
||||
*depth,
|
||||
*inc,
|
||||
folder_idx,
|
||||
entries[&folder_idx].count().ok().map(|(v, _)| v),
|
||||
));
|
||||
for (i, &(depth, folder_hash)) in a.entries.iter().enumerate() {
|
||||
if folders[&folder_hash].is_subscribed() {
|
||||
match context.accounts[a.index].status(folder_hash) {
|
||||
Ok(_) => {
|
||||
lines.push((
|
||||
depth,
|
||||
i,
|
||||
folder_hash,
|
||||
folders[&folder_hash].count().ok().map(|(v, _)| v),
|
||||
));
|
||||
}
|
||||
Err(_) => {
|
||||
lines.push((depth, i, folder_hash, None));
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
lines.push((*depth, *inc, folder_idx, None));
|
||||
}
|
||||
}
|
||||
*inc += 1;
|
||||
let mut children: Vec<FolderHash> = entries[&folder_idx].children().to_vec();
|
||||
children
|
||||
.sort_unstable_by(|a, b| folders_order[a].partial_cmp(&folders_order[b]).unwrap());
|
||||
*depth += 1;
|
||||
for child in children {
|
||||
print(
|
||||
child,
|
||||
depth,
|
||||
inc,
|
||||
entries,
|
||||
folders_order,
|
||||
lines,
|
||||
index,
|
||||
context,
|
||||
);
|
||||
}
|
||||
*depth -= 1;
|
||||
}
|
||||
let mut keys = entries.keys().cloned().collect::<Vec<FolderHash>>();
|
||||
keys.sort_unstable_by(|a, b| folders_order[a].partial_cmp(&folders_order[b]).unwrap());
|
||||
|
||||
/* Start with roots */
|
||||
for f in keys {
|
||||
if entries[&f].parent().is_none() {
|
||||
print(
|
||||
f,
|
||||
&mut depth,
|
||||
&mut inc,
|
||||
&entries,
|
||||
&folders_order,
|
||||
&mut lines,
|
||||
a.index,
|
||||
context,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1155,7 +1092,7 @@ impl Listing {
|
|||
None,
|
||||
);
|
||||
let (x, _) = write_string_to_grid(
|
||||
entries[&folder_idx].name(),
|
||||
folders[&folder_idx].name(),
|
||||
grid,
|
||||
att.fg,
|
||||
att.bg,
|
||||
|
@ -1207,4 +1144,46 @@ impl Listing {
|
|||
idx - 1
|
||||
}
|
||||
}
|
||||
|
||||
fn change_account(&mut self, context: &mut Context) {
|
||||
self.accounts[self.cursor_pos.0].entries = context.accounts[self.cursor_pos.0]
|
||||
.list_folders()
|
||||
.into_iter()
|
||||
.filter(|folder_node| {
|
||||
context.accounts[self.cursor_pos.0].ref_folders()[&folder_node.hash].is_subscribed()
|
||||
})
|
||||
.map(|f| (f.depth, f.hash))
|
||||
.collect::<_>();
|
||||
/* Account might have no folders yet if it's offline */
|
||||
if let Some((_, folder_hash)) = self.accounts[self.cursor_pos.0]
|
||||
.entries
|
||||
.get(self.cursor_pos.1)
|
||||
{
|
||||
self.component
|
||||
.set_coordinates((self.cursor_pos.0, *folder_hash));
|
||||
/* Check if per-folder configuration overrides general configuration */
|
||||
if let Some(index_style) = context
|
||||
.accounts
|
||||
.get(self.cursor_pos.0)
|
||||
.and_then(|account| account.folder_confs(*folder_hash).conf_override.index_style)
|
||||
{
|
||||
self.component.set_style(index_style);
|
||||
} else if let Some(index_style) = context
|
||||
.accounts
|
||||
.get(self.cursor_pos.0)
|
||||
.and_then(|account| Some(account.settings.conf.index_style()))
|
||||
{
|
||||
self.component.set_style(index_style);
|
||||
}
|
||||
} else {
|
||||
/* Set to dummy */
|
||||
self.component = Offline(OfflineListing::new((self.cursor_pos.0, 0)));
|
||||
}
|
||||
self.set_dirty(true);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::UpdateStatus(debug!(
|
||||
self.get_status(context)
|
||||
))));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,9 +49,8 @@ macro_rules! address_list {
|
|||
#[derive(Debug)]
|
||||
pub struct CompactListing {
|
||||
/// (x, y, z): x is accounts, y is folders, z is index inside a folder.
|
||||
cursor_pos: (usize, usize, usize),
|
||||
new_cursor_pos: (usize, usize, usize),
|
||||
folder_hash: FolderHash,
|
||||
cursor_pos: (usize, FolderHash, usize),
|
||||
new_cursor_pos: (usize, FolderHash, usize),
|
||||
length: usize,
|
||||
sort: (SortField, SortOrder),
|
||||
subsort: (SortField, SortOrder),
|
||||
|
@ -114,16 +113,6 @@ impl MailListingTrait for CompactListing {
|
|||
}
|
||||
self.cursor_pos.1 = self.new_cursor_pos.1;
|
||||
self.cursor_pos.0 = self.new_cursor_pos.0;
|
||||
self.folder_hash = if let Some(h) = context.accounts[self.cursor_pos.0]
|
||||
.folders_order
|
||||
.get(self.cursor_pos.1)
|
||||
{
|
||||
*h
|
||||
} else {
|
||||
self.cursor_pos.1 = old_cursor_pos.1;
|
||||
self.dirty = false;
|
||||
return;
|
||||
};
|
||||
|
||||
self.color_cache = ColorCache {
|
||||
unseen: crate::conf::value(context, "mail.listing.compact.unseen"),
|
||||
|
@ -145,7 +134,7 @@ impl MailListingTrait for CompactListing {
|
|||
|
||||
// Get mailbox as a reference.
|
||||
//
|
||||
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
|
||||
match context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) {
|
||||
Ok(()) => {}
|
||||
Err(_) => {
|
||||
let default_cell = {
|
||||
|
@ -156,7 +145,7 @@ impl MailListingTrait for CompactListing {
|
|||
ret
|
||||
};
|
||||
let message: String =
|
||||
context.accounts[self.cursor_pos.0][self.folder_hash].to_string();
|
||||
context.accounts[self.cursor_pos.0][self.cursor_pos.1].to_string();
|
||||
self.data_columns.columns[0] =
|
||||
CellBuffer::new_with_context(message.len(), 1, default_cell, context);
|
||||
self.length = 0;
|
||||
|
@ -173,7 +162,7 @@ impl MailListingTrait for CompactListing {
|
|||
}
|
||||
}
|
||||
|
||||
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&self.folder_hash];
|
||||
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&self.cursor_pos.1];
|
||||
self.all_threads.clear();
|
||||
let mut roots = threads.roots();
|
||||
threads.group_inner_sort_by(
|
||||
|
@ -198,11 +187,11 @@ impl MailListingTrait for CompactListing {
|
|||
}
|
||||
|
||||
impl ListingTrait for CompactListing {
|
||||
fn coordinates(&self) -> (usize, usize) {
|
||||
fn coordinates(&self) -> (usize, FolderHash) {
|
||||
(self.new_cursor_pos.0, self.new_cursor_pos.1)
|
||||
}
|
||||
|
||||
fn set_coordinates(&mut self, coordinates: (usize, usize)) {
|
||||
fn set_coordinates(&mut self, coordinates: (usize, FolderHash)) {
|
||||
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
||||
self.unfocused = false;
|
||||
self.view = ThreadView::default();
|
||||
|
@ -219,7 +208,7 @@ impl ListingTrait for CompactListing {
|
|||
let thread_hash = self.get_thread_under_cursor(idx);
|
||||
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.folder_hash];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let thread = threads.thread_ref(thread_hash);
|
||||
|
||||
let fg_color = if thread.unseen() > 0 {
|
||||
|
@ -541,9 +530,9 @@ impl ListingTrait for CompactListing {
|
|||
}
|
||||
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
match account.search(&self.filter_term, self.sort, self.folder_hash) {
|
||||
match account.search(&self.filter_term, self.sort, self.cursor_pos.1) {
|
||||
Ok(results) => {
|
||||
let threads = &account.collection.threads[&self.folder_hash];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
for env_hash in results {
|
||||
if !account.collection.contains_key(&env_hash) {
|
||||
continue;
|
||||
|
@ -633,19 +622,12 @@ impl fmt::Display for CompactListing {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for CompactListing {
|
||||
fn default() -> Self {
|
||||
CompactListing::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl CompactListing {
|
||||
const DESCRIPTION: &'static str = "compact listing";
|
||||
fn new() -> Self {
|
||||
pub fn new(coordinates: (usize, FolderHash)) -> Self {
|
||||
CompactListing {
|
||||
cursor_pos: (0, 1, 0),
|
||||
new_cursor_pos: (0, 0, 0),
|
||||
folder_hash: 0,
|
||||
new_cursor_pos: (coordinates.0, coordinates.1, 0),
|
||||
length: 0,
|
||||
sort: (Default::default(), Default::default()),
|
||||
subsort: (SortField::Date, SortOrder::Desc),
|
||||
|
@ -674,7 +656,7 @@ impl CompactListing {
|
|||
hash: ThreadHash,
|
||||
) -> EntryStrings {
|
||||
let thread = threads.thread_ref(hash);
|
||||
let folder = &context.accounts[self.cursor_pos.0].folder_confs[&self.folder_hash];
|
||||
let folder = &context.accounts[self.cursor_pos.0].folder_confs[&self.cursor_pos.1];
|
||||
let mut tags = String::new();
|
||||
let mut colors: SmallVec<[_; 8]> = SmallVec::new();
|
||||
let backend_lck = context.accounts[self.cursor_pos.0].backend.read().unwrap();
|
||||
|
@ -1026,7 +1008,7 @@ impl CompactListing {
|
|||
|
||||
fn update_line(&mut self, context: &Context, thread_hash: ThreadHash) {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.folder_hash];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let thread = threads.thread_ref(thread_hash);
|
||||
let thread_node_hash = threads.thread_group_iter(thread_hash).next().unwrap().1;
|
||||
if let Some(env_hash) = threads.thread_nodes()[&thread_node_hash].message() {
|
||||
|
@ -1310,7 +1292,7 @@ impl Component for CompactListing {
|
|||
account
|
||||
.collection
|
||||
.threads
|
||||
.entry(self.folder_hash)
|
||||
.entry(self.cursor_pos.1)
|
||||
.and_modify(|threads| {
|
||||
let is_snoozed = threads.thread_ref(thread).snoozed();
|
||||
threads.thread_ref_mut(thread).set_snoozed(!is_snoozed);
|
||||
|
@ -1328,18 +1310,18 @@ impl Component for CompactListing {
|
|||
}
|
||||
match *event {
|
||||
UIEvent::MailboxUpdate((ref idxa, ref idxf))
|
||||
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
|
||||
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.cursor_pos.1) =>
|
||||
{
|
||||
self.refresh_mailbox(context, false);
|
||||
self.set_dirty(true);
|
||||
}
|
||||
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
|
||||
UIEvent::StartupCheck(ref f) if *f == self.cursor_pos.1 => {
|
||||
self.refresh_mailbox(context, false);
|
||||
self.set_dirty(true);
|
||||
}
|
||||
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.folder_hash];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
if !account.collection.contains_key(&new_hash) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -28,9 +28,8 @@ use std::iter::FromIterator;
|
|||
#[derive(Debug)]
|
||||
pub struct ConversationsListing {
|
||||
/// (x, y, z): x is accounts, y is folders, z is index inside a folder.
|
||||
cursor_pos: (usize, usize, usize),
|
||||
new_cursor_pos: (usize, usize, usize),
|
||||
folder_hash: FolderHash,
|
||||
cursor_pos: (usize, FolderHash, usize),
|
||||
new_cursor_pos: (usize, FolderHash, usize),
|
||||
length: usize,
|
||||
sort: (SortField, SortOrder),
|
||||
subsort: (SortField, SortOrder),
|
||||
|
@ -84,7 +83,7 @@ impl MailListingTrait for ConversationsListing {
|
|||
/// chosen.
|
||||
fn refresh_mailbox(&mut self, context: &mut Context, force: bool) {
|
||||
self.dirty = true;
|
||||
let old_folder_hash = self.folder_hash;
|
||||
let old_folder_hash = self.cursor_pos.1;
|
||||
let old_cursor_pos = self.cursor_pos;
|
||||
if !(self.cursor_pos.0 == self.new_cursor_pos.0
|
||||
&& self.cursor_pos.1 == self.new_cursor_pos.1)
|
||||
|
@ -94,16 +93,6 @@ impl MailListingTrait for ConversationsListing {
|
|||
}
|
||||
self.cursor_pos.1 = self.new_cursor_pos.1;
|
||||
self.cursor_pos.0 = self.new_cursor_pos.0;
|
||||
self.folder_hash = if let Some(h) = context.accounts[self.cursor_pos.0]
|
||||
.folders_order
|
||||
.get(self.cursor_pos.1)
|
||||
{
|
||||
*h
|
||||
} else {
|
||||
self.cursor_pos.1 = old_cursor_pos.1;
|
||||
self.dirty = false;
|
||||
return;
|
||||
};
|
||||
|
||||
self.color_cache = ColorCache {
|
||||
theme_default: crate::conf::value(context, "mail.listing.conversations"),
|
||||
|
@ -130,7 +119,7 @@ impl MailListingTrait for ConversationsListing {
|
|||
}
|
||||
// Get mailbox as a reference.
|
||||
//
|
||||
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
|
||||
match context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) {
|
||||
Ok(()) => {}
|
||||
Err(_) => {
|
||||
let default_cell = {
|
||||
|
@ -141,7 +130,7 @@ impl MailListingTrait for ConversationsListing {
|
|||
ret
|
||||
};
|
||||
let message: String =
|
||||
context.accounts[self.cursor_pos.0][self.folder_hash].to_string();
|
||||
context.accounts[self.cursor_pos.0][self.cursor_pos.1].to_string();
|
||||
self.content =
|
||||
CellBuffer::new_with_context(message.len(), 1, default_cell, context);
|
||||
self.length = 0;
|
||||
|
@ -158,7 +147,7 @@ impl MailListingTrait for ConversationsListing {
|
|||
}
|
||||
}
|
||||
|
||||
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&self.folder_hash];
|
||||
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&self.cursor_pos.1];
|
||||
self.all_threads.clear();
|
||||
let mut roots = threads.roots();
|
||||
threads.group_inner_sort_by(
|
||||
|
@ -172,7 +161,7 @@ impl MailListingTrait for ConversationsListing {
|
|||
Box::new(roots.into_iter()) as Box<dyn Iterator<Item = ThreadHash>>,
|
||||
);
|
||||
|
||||
if !force && old_cursor_pos == self.new_cursor_pos && old_folder_hash == self.folder_hash {
|
||||
if !force && old_cursor_pos == self.new_cursor_pos && old_folder_hash == self.cursor_pos.1 {
|
||||
self.view.update(context);
|
||||
} else if self.unfocused {
|
||||
let thread_group = self.get_thread_under_cursor(self.cursor_pos.2);
|
||||
|
@ -183,11 +172,11 @@ impl MailListingTrait for ConversationsListing {
|
|||
}
|
||||
|
||||
impl ListingTrait for ConversationsListing {
|
||||
fn coordinates(&self) -> (usize, usize) {
|
||||
fn coordinates(&self) -> (usize, FolderHash) {
|
||||
(self.new_cursor_pos.0, self.new_cursor_pos.1)
|
||||
}
|
||||
|
||||
fn set_coordinates(&mut self, coordinates: (usize, usize)) {
|
||||
fn set_coordinates(&mut self, coordinates: (usize, FolderHash)) {
|
||||
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
||||
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
||||
self.unfocused = false;
|
||||
|
@ -205,7 +194,7 @@ impl ListingTrait for ConversationsListing {
|
|||
let thread_hash = self.get_thread_under_cursor(idx);
|
||||
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.folder_hash];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let thread = threads.thread_ref(thread_hash);
|
||||
|
||||
let fg_color = if thread.unseen() > 0 {
|
||||
|
@ -475,9 +464,9 @@ impl ListingTrait for ConversationsListing {
|
|||
}
|
||||
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
match account.search(&self.filter_term, self.sort, self.folder_hash) {
|
||||
match account.search(&self.filter_term, self.sort, self.cursor_pos.1) {
|
||||
Ok(results) => {
|
||||
let threads = &account.collection.threads[&self.folder_hash];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
for env_hash in results {
|
||||
if !account.collection.contains_key(&env_hash) {
|
||||
continue;
|
||||
|
@ -566,19 +555,12 @@ impl fmt::Display for ConversationsListing {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for ConversationsListing {
|
||||
fn default() -> Self {
|
||||
ConversationsListing::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ConversationsListing {
|
||||
const DESCRIPTION: &'static str = "compact listing";
|
||||
fn new() -> Self {
|
||||
pub fn new(coordinates: (usize, FolderHash)) -> Self {
|
||||
ConversationsListing {
|
||||
cursor_pos: (0, 1, 0),
|
||||
new_cursor_pos: (0, 0, 0),
|
||||
folder_hash: 0,
|
||||
new_cursor_pos: (coordinates.0, coordinates.1, 0),
|
||||
length: 0,
|
||||
sort: (Default::default(), Default::default()),
|
||||
subsort: (SortField::Date, SortOrder::Desc),
|
||||
|
@ -608,7 +590,7 @@ impl ConversationsListing {
|
|||
hash: ThreadHash,
|
||||
) -> EntryStrings {
|
||||
let thread = threads.thread_ref(hash);
|
||||
let folder = &context.accounts[self.cursor_pos.0].folder_confs[&self.folder_hash];
|
||||
let folder = &context.accounts[self.cursor_pos.0].folder_confs[&self.cursor_pos.1];
|
||||
let mut tags = String::new();
|
||||
let mut colors = SmallVec::new();
|
||||
let backend_lck = context.accounts[self.cursor_pos.0].backend.read().unwrap();
|
||||
|
@ -935,7 +917,7 @@ impl ConversationsListing {
|
|||
|
||||
fn update_line(&mut self, context: &Context, thread_hash: ThreadHash) {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.folder_hash];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let thread = threads.thread_ref(thread_hash);
|
||||
let thread_node_hash = threads.thread_group_iter(thread_hash).next().unwrap().1;
|
||||
let idx: usize = self.order[&thread_hash];
|
||||
|
@ -1218,7 +1200,7 @@ impl Component for ConversationsListing {
|
|||
}
|
||||
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.folder_hash];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
if !account.collection.contains_key(&new_hash) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1243,7 +1225,7 @@ impl Component for ConversationsListing {
|
|||
self.subsort = (*field, *order);
|
||||
// FIXME subsort
|
||||
//if !self.filtered_selection.is_empty() {
|
||||
// let threads = &account.collection.threads[&self.folder_hash];
|
||||
// let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
// threads.vec_inner_sort_by(&mut self.filtered_selection, self.sort, &account.collection);
|
||||
//} else {
|
||||
// self.refresh_mailbox(context, false);
|
||||
|
@ -1257,7 +1239,7 @@ impl Component for ConversationsListing {
|
|||
self.sort = (*field, *order);
|
||||
if !self.filtered_selection.is_empty() {
|
||||
let threads = &context.accounts[self.cursor_pos.0].collection.threads
|
||||
[&self.folder_hash];
|
||||
[&self.cursor_pos.1];
|
||||
threads.vec_inner_sort_by(
|
||||
&mut self.filtered_selection,
|
||||
self.sort,
|
||||
|
@ -1276,7 +1258,7 @@ impl Component for ConversationsListing {
|
|||
account
|
||||
.collection
|
||||
.threads
|
||||
.entry(self.folder_hash)
|
||||
.entry(self.cursor_pos.1)
|
||||
.and_modify(|threads| {
|
||||
let is_snoozed = threads.thread_ref(thread).snoozed();
|
||||
threads.thread_ref_mut(thread).set_snoozed(!is_snoozed);
|
||||
|
@ -1292,12 +1274,12 @@ impl Component for ConversationsListing {
|
|||
}
|
||||
match *event {
|
||||
UIEvent::MailboxUpdate((ref idxa, ref idxf))
|
||||
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
|
||||
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.cursor_pos.1) =>
|
||||
{
|
||||
self.refresh_mailbox(context, false);
|
||||
self.set_dirty(true);
|
||||
}
|
||||
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
|
||||
UIEvent::StartupCheck(ref f) if *f == self.cursor_pos.1 => {
|
||||
self.refresh_mailbox(context, false);
|
||||
self.set_dirty(true);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* meli
|
||||
*
|
||||
* Copyright 2020 Manos Pitsidianakis
|
||||
*
|
||||
* This file is part of meli.
|
||||
*
|
||||
* meli is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* meli is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use super::*;
|
||||
use crate::components::utilities::PageMovement;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OfflineListing {
|
||||
cursor_pos: (usize, FolderHash),
|
||||
_row_updates: SmallVec<[ThreadHash; 8]>,
|
||||
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl MailListingTrait for OfflineListing {
|
||||
fn row_updates(&mut self) -> &mut SmallVec<[ThreadHash; 8]> {
|
||||
&mut self._row_updates
|
||||
}
|
||||
|
||||
fn get_focused_items(&self, _context: &Context) -> SmallVec<[ThreadHash; 8]> {
|
||||
return SmallVec::new();
|
||||
}
|
||||
|
||||
/// chosen.
|
||||
fn refresh_mailbox(&mut self, _context: &mut Context, _force: bool) {}
|
||||
}
|
||||
|
||||
impl ListingTrait for OfflineListing {
|
||||
fn coordinates(&self) -> (usize, FolderHash) {
|
||||
self.cursor_pos
|
||||
}
|
||||
|
||||
fn set_coordinates(&mut self, coordinates: (usize, FolderHash)) {
|
||||
self.cursor_pos = coordinates;
|
||||
}
|
||||
|
||||
fn highlight_line(
|
||||
&mut self,
|
||||
_grid: &mut CellBuffer,
|
||||
_area: Area,
|
||||
_idx: usize,
|
||||
_context: &Context,
|
||||
) {
|
||||
}
|
||||
|
||||
fn draw_list(&mut self, _: &mut CellBuffer, _: Area, _: &mut Context) {}
|
||||
|
||||
fn filter(&mut self, _: &str, _: &Context) {}
|
||||
|
||||
fn set_movement(&mut self, _: PageMovement) {}
|
||||
}
|
||||
|
||||
impl fmt::Display for OfflineListing {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "mail")
|
||||
}
|
||||
}
|
||||
|
||||
impl OfflineListing {
|
||||
pub fn new(cursor_pos: (usize, FolderHash)) -> Self {
|
||||
OfflineListing {
|
||||
cursor_pos,
|
||||
_row_updates: SmallVec::new(),
|
||||
id: ComponentId::new_v4(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for OfflineListing {
|
||||
fn draw(&mut self, _grid: &mut CellBuffer, _area: Area, _context: &mut Context) {}
|
||||
fn process_event(&mut self, _event: &mut UIEvent, _context: &mut Context) -> bool {
|
||||
false
|
||||
}
|
||||
fn is_dirty(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn set_dirty(&mut self, _value: bool) {}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
|
@ -48,9 +48,8 @@ macro_rules! address_list {
|
|||
#[derive(Debug)]
|
||||
pub struct PlainListing {
|
||||
/// (x, y, z): x is accounts, y is folders, z is index inside a folder.
|
||||
cursor_pos: (usize, usize, usize),
|
||||
new_cursor_pos: (usize, usize, usize),
|
||||
folder_hash: FolderHash,
|
||||
cursor_pos: (usize, FolderHash, usize),
|
||||
new_cursor_pos: (usize, FolderHash, usize),
|
||||
length: usize,
|
||||
sort: (SortField, SortOrder),
|
||||
subsort: (SortField, SortOrder),
|
||||
|
@ -115,16 +114,6 @@ impl MailListingTrait for PlainListing {
|
|||
}
|
||||
self.cursor_pos.1 = self.new_cursor_pos.1;
|
||||
self.cursor_pos.0 = self.new_cursor_pos.0;
|
||||
self.folder_hash = if let Some(h) = context.accounts[self.cursor_pos.0]
|
||||
.folders_order
|
||||
.get(self.cursor_pos.1)
|
||||
{
|
||||
*h
|
||||
} else {
|
||||
self.cursor_pos.1 = old_cursor_pos.1;
|
||||
self.dirty = false;
|
||||
return;
|
||||
};
|
||||
|
||||
self.color_cache = ColorCache {
|
||||
unseen: crate::conf::value(context, "mail.listing.plain.unseen"),
|
||||
|
@ -145,7 +134,7 @@ impl MailListingTrait for PlainListing {
|
|||
|
||||
// Get mailbox as a reference.
|
||||
//
|
||||
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
|
||||
match context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) {
|
||||
Ok(()) => {}
|
||||
Err(_) => {
|
||||
let default_cell = {
|
||||
|
@ -156,7 +145,7 @@ impl MailListingTrait for PlainListing {
|
|||
ret
|
||||
};
|
||||
let message: String =
|
||||
context.accounts[self.cursor_pos.0][self.folder_hash].to_string();
|
||||
context.accounts[self.cursor_pos.0][self.cursor_pos.1].to_string();
|
||||
self.data_columns.columns[0] =
|
||||
CellBuffer::new_with_context(message.len(), 1, default_cell, context);
|
||||
self.length = 0;
|
||||
|
@ -172,7 +161,7 @@ impl MailListingTrait for PlainListing {
|
|||
return;
|
||||
}
|
||||
}
|
||||
self.local_collection = context.accounts[self.cursor_pos.0][self.folder_hash]
|
||||
self.local_collection = context.accounts[self.cursor_pos.0][self.cursor_pos.1]
|
||||
.unwrap()
|
||||
.envelopes
|
||||
.iter()
|
||||
|
@ -183,7 +172,7 @@ impl MailListingTrait for PlainListing {
|
|||
.envelopes
|
||||
.read()
|
||||
.unwrap();
|
||||
self.thread_node_hashes = context.accounts[self.cursor_pos.0][self.folder_hash]
|
||||
self.thread_node_hashes = context.accounts[self.cursor_pos.0][self.cursor_pos.1]
|
||||
.unwrap()
|
||||
.envelopes
|
||||
.iter()
|
||||
|
@ -205,11 +194,11 @@ impl MailListingTrait for PlainListing {
|
|||
}
|
||||
|
||||
impl ListingTrait for PlainListing {
|
||||
fn coordinates(&self) -> (usize, usize) {
|
||||
fn coordinates(&self) -> (usize, FolderHash) {
|
||||
(self.new_cursor_pos.0, self.new_cursor_pos.1)
|
||||
}
|
||||
|
||||
fn set_coordinates(&mut self, coordinates: (usize, usize)) {
|
||||
fn set_coordinates(&mut self, coordinates: (usize, FolderHash)) {
|
||||
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
||||
self.unfocused = false;
|
||||
self.view = MailView::default();
|
||||
|
@ -523,7 +512,7 @@ impl ListingTrait for PlainListing {
|
|||
}
|
||||
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
match account.search(&self.filter_term, self.sort, self.folder_hash) {
|
||||
match account.search(&self.filter_term, self.sort, self.cursor_pos.1) {
|
||||
Ok(results) => {
|
||||
for env_hash in results {
|
||||
if !account.collection.contains_key(&env_hash) {
|
||||
|
@ -599,19 +588,12 @@ impl fmt::Display for PlainListing {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for PlainListing {
|
||||
fn default() -> Self {
|
||||
PlainListing::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl PlainListing {
|
||||
const DESCRIPTION: &'static str = "plain listing";
|
||||
fn new() -> Self {
|
||||
pub fn new(coordinates: (usize, FolderHash)) -> Self {
|
||||
PlainListing {
|
||||
cursor_pos: (0, 1, 0),
|
||||
new_cursor_pos: (0, 0, 0),
|
||||
folder_hash: 0,
|
||||
new_cursor_pos: (coordinates.0, coordinates.1, 0),
|
||||
length: 0,
|
||||
sort: (Default::default(), Default::default()),
|
||||
subsort: (SortField::Date, SortOrder::Desc),
|
||||
|
@ -637,7 +619,7 @@ impl PlainListing {
|
|||
}
|
||||
}
|
||||
fn make_entry_string(&self, e: EnvelopeRef, context: &Context) -> EntryStrings {
|
||||
let folder = &context.accounts[self.cursor_pos.0].folder_confs[&self.folder_hash];
|
||||
let folder = &context.accounts[self.cursor_pos.0].folder_confs[&self.cursor_pos.1];
|
||||
let mut tags = String::new();
|
||||
let mut colors = SmallVec::new();
|
||||
let backend_lck = context.accounts[self.cursor_pos.0].backend.read().unwrap();
|
||||
|
@ -1097,7 +1079,7 @@ impl Component for PlainListing {
|
|||
debug!("SubSort {:?} , {:?}", field, order);
|
||||
self.subsort = (*field, *order);
|
||||
//if !self.filtered_selection.is_empty() {
|
||||
// let threads = &account.collection.threads[&self.folder_hash];
|
||||
// let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
// threads.vec_inner_sort_by(&mut self.filtered_selection, self.sort, &account.collection);
|
||||
//} else {
|
||||
// self.refresh_mailbox(contex, falset);
|
||||
|
@ -1148,19 +1130,19 @@ impl Component for PlainListing {
|
|||
}
|
||||
match *event {
|
||||
UIEvent::MailboxUpdate((ref idxa, ref idxf))
|
||||
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
|
||||
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.cursor_pos.1) =>
|
||||
{
|
||||
self.refresh_mailbox(context, false);
|
||||
self.set_dirty(true);
|
||||
}
|
||||
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
|
||||
UIEvent::StartupCheck(ref f) if *f == self.cursor_pos.1 => {
|
||||
self.refresh_mailbox(context, false);
|
||||
self.set_dirty(true);
|
||||
}
|
||||
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
if !account.collection.contains_key(new_hash)
|
||||
|| !account[self.folder_hash]
|
||||
|| !account[self.cursor_pos.1]
|
||||
.unwrap()
|
||||
.envelopes
|
||||
.contains(new_hash)
|
||||
|
|
|
@ -29,9 +29,8 @@ const MAX_COLS: usize = 500;
|
|||
#[derive(Debug)]
|
||||
pub struct ThreadListing {
|
||||
/// (x, y, z): x is accounts, y is folders, z is index inside a folder.
|
||||
cursor_pos: (usize, usize, usize),
|
||||
new_cursor_pos: (usize, usize, usize),
|
||||
folder_hash: FolderHash,
|
||||
cursor_pos: (usize, FolderHash, usize),
|
||||
new_cursor_pos: (usize, FolderHash, usize),
|
||||
length: usize,
|
||||
sort: (SortField, SortOrder),
|
||||
subsort: (SortField, SortOrder),
|
||||
|
@ -72,14 +71,6 @@ impl MailListingTrait for ThreadListing {
|
|||
}
|
||||
self.cursor_pos.1 = self.new_cursor_pos.1;
|
||||
self.cursor_pos.0 = self.new_cursor_pos.0;
|
||||
self.folder_hash = if let Some(h) = context.accounts[self.cursor_pos.0]
|
||||
.folders_order
|
||||
.get(self.cursor_pos.1)
|
||||
{
|
||||
*h
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
self.color_cache = ColorCache {
|
||||
unseen: crate::conf::value(context, "mail.listing.plain.unseen"),
|
||||
|
@ -100,7 +91,7 @@ impl MailListingTrait for ThreadListing {
|
|||
|
||||
// Get mailbox as a reference.
|
||||
//
|
||||
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
|
||||
match context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) {
|
||||
Ok(_) => {}
|
||||
Err(_) => {
|
||||
let default_cell = {
|
||||
|
@ -234,10 +225,10 @@ impl MailListingTrait for ThreadListing {
|
|||
}
|
||||
|
||||
impl ListingTrait for ThreadListing {
|
||||
fn coordinates(&self) -> (usize, usize) {
|
||||
fn coordinates(&self) -> (usize, FolderHash) {
|
||||
(self.new_cursor_pos.0, self.new_cursor_pos.1)
|
||||
}
|
||||
fn set_coordinates(&mut self, coordinates: (usize, usize)) {
|
||||
fn set_coordinates(&mut self, coordinates: (usize, FolderHash)) {
|
||||
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
||||
self.unfocused = false;
|
||||
self.view = None;
|
||||
|
@ -398,12 +389,6 @@ impl ListingTrait for ThreadListing {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for ThreadListing {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ThreadListing {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "mail")
|
||||
|
@ -411,12 +396,10 @@ impl fmt::Display for ThreadListing {
|
|||
}
|
||||
|
||||
impl ThreadListing {
|
||||
pub fn new() -> Self {
|
||||
let content = CellBuffer::new(0, 0, Cell::with_char(' '));
|
||||
pub fn new(coordinates: (usize, FolderHash)) -> Self {
|
||||
ThreadListing {
|
||||
cursor_pos: (0, 1, 0),
|
||||
new_cursor_pos: (0, 0, 0),
|
||||
folder_hash: 0,
|
||||
new_cursor_pos: (coordinates.0, coordinates.1, 0),
|
||||
length: 0,
|
||||
sort: (Default::default(), Default::default()),
|
||||
subsort: (Default::default(), Default::default()),
|
||||
|
@ -662,12 +645,12 @@ impl Component for ThreadListing {
|
|||
return true;
|
||||
}
|
||||
UIEvent::MailboxUpdate((ref idxa, ref idxf))
|
||||
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
|
||||
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.cursor_pos.1) =>
|
||||
{
|
||||
self.refresh_mailbox(context, false);
|
||||
self.set_dirty(true);
|
||||
}
|
||||
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
|
||||
UIEvent::StartupCheck(ref f) if *f == self.cursor_pos.1 => {
|
||||
self.refresh_mailbox(context, false);
|
||||
self.set_dirty(true);
|
||||
}
|
||||
|
|
|
@ -484,7 +484,8 @@ impl Component for AccountStatus {
|
|||
None,
|
||||
);
|
||||
line += 2;
|
||||
for f in a.list_folders() {
|
||||
for folder_node in a.list_folders() {
|
||||
let f: &Folder = &a.ref_folders()[&folder_node.hash];
|
||||
if f.is_subscribed() {
|
||||
write_string_to_grid(
|
||||
f.path(),
|
||||
|
|
|
@ -80,7 +80,7 @@ impl ViewMode {
|
|||
/// menus
|
||||
#[derive(Debug, Default)]
|
||||
pub struct MailView {
|
||||
coordinates: (usize, usize, EnvelopeHash),
|
||||
coordinates: (usize, FolderHash, EnvelopeHash),
|
||||
pager: Pager,
|
||||
subview: Option<Box<dyn Component>>,
|
||||
dirty: bool,
|
||||
|
@ -117,7 +117,7 @@ impl fmt::Display for MailView {
|
|||
impl MailView {
|
||||
const DESCRIPTION: &'static str = "view mail";
|
||||
pub fn new(
|
||||
coordinates: (usize, usize, EnvelopeHash),
|
||||
coordinates: (usize, FolderHash, EnvelopeHash),
|
||||
pager: Option<Pager>,
|
||||
subview: Option<Box<dyn Component>>,
|
||||
context: &Context,
|
||||
|
@ -331,7 +331,7 @@ impl MailView {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, new_coordinates: (usize, usize, EnvelopeHash)) {
|
||||
pub fn update(&mut self, new_coordinates: (usize, FolderHash, EnvelopeHash)) {
|
||||
self.coordinates = new_coordinates;
|
||||
self.mode = ViewMode::Normal;
|
||||
self.set_dirty(true);
|
||||
|
@ -791,10 +791,8 @@ impl Component for MailView {
|
|||
UIEvent::Input(ref key)
|
||||
if shortcut!(key == shortcuts[MailView::DESCRIPTION]["reply"]) =>
|
||||
{
|
||||
let account = &context.accounts[self.coordinates.0];
|
||||
let folder_hash = account[self.coordinates.1].unwrap().folder.hash();
|
||||
context.replies.push_back(UIEvent::Action(Tab(Reply(
|
||||
(self.coordinates.0, folder_hash),
|
||||
(self.coordinates.0, self.coordinates.1),
|
||||
self.coordinates.2,
|
||||
))));
|
||||
return true;
|
||||
|
|
|
@ -51,7 +51,7 @@ pub struct ThreadView {
|
|||
expanded_pos: usize,
|
||||
new_expanded_pos: usize,
|
||||
reversed: bool,
|
||||
coordinates: (usize, usize, usize),
|
||||
coordinates: (usize, FolderHash, usize),
|
||||
thread_group: ThreadHash,
|
||||
mailview: MailView,
|
||||
show_mailview: bool,
|
||||
|
@ -75,7 +75,7 @@ impl ThreadView {
|
|||
* context: current context
|
||||
*/
|
||||
pub fn new(
|
||||
coordinates: (usize, usize, usize),
|
||||
coordinates: (usize, FolderHash, usize),
|
||||
thread_group: ThreadHash,
|
||||
expanded_hash: Option<ThreadNodeHash>,
|
||||
context: &Context,
|
||||
|
|
|
@ -62,6 +62,7 @@ pub enum MailboxEntry {
|
|||
Failed(MeliError),
|
||||
/// first argument is done work, and second is total work
|
||||
Parsing(Mailbox, usize, usize),
|
||||
None,
|
||||
}
|
||||
|
||||
impl Default for MailboxEntry {
|
||||
|
@ -78,6 +79,7 @@ impl std::fmt::Display for MailboxEntry {
|
|||
match self {
|
||||
MailboxEntry::Available(ref m) => m.name().to_string(),
|
||||
MailboxEntry::Failed(ref e) => e.to_string(),
|
||||
MailboxEntry::None => "Not subscribed, is this a bug?".to_string(),
|
||||
MailboxEntry::Parsing(_, done, total) => {
|
||||
format!("Parsing messages. [{}/{}]", done, total)
|
||||
}
|
||||
|
@ -109,6 +111,7 @@ impl MailboxEntry {
|
|||
"Mailbox is not available: {}",
|
||||
e.to_string()
|
||||
))),
|
||||
MailboxEntry::None => Err(MeliError::new("Mailbox is not subscribed.")),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,6 +123,7 @@ impl MailboxEntry {
|
|||
"Mailbox is not available: {}",
|
||||
e.to_string()
|
||||
))),
|
||||
MailboxEntry::None => Err(MeliError::new("Mailbox is not subscribed.")),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,10 +238,11 @@ impl<'a> Iterator for MailboxIterator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug, Default)]
|
||||
struct FolderNode {
|
||||
hash: FolderHash,
|
||||
kids: Vec<FolderNode>,
|
||||
#[derive(Serialize, Debug, Clone, Default)]
|
||||
pub struct FolderNode {
|
||||
pub hash: FolderHash,
|
||||
pub depth: usize,
|
||||
pub children: Vec<FolderNode>,
|
||||
}
|
||||
|
||||
impl Account {
|
||||
|
@ -393,7 +398,7 @@ impl Account {
|
|||
collection.threads.insert(*h, Threads::default());
|
||||
}
|
||||
|
||||
build_folders_order(&folder_confs, &mut tree, &ref_folders, &mut folders_order);
|
||||
build_folders_order(&mut tree, &ref_folders, &mut folders_order);
|
||||
self.folders = folders;
|
||||
self.ref_folders = ref_folders;
|
||||
self.folder_confs = folder_confs;
|
||||
|
@ -717,50 +722,25 @@ impl Account {
|
|||
pub fn is_empty(&self) -> bool {
|
||||
self.folders.is_empty()
|
||||
}
|
||||
pub fn list_folders(&self) -> Vec<Folder> {
|
||||
let mut folders = self.ref_folders.clone();
|
||||
let folder_confs = &self.folder_confs;
|
||||
//debug!("folder renames: {:?}", folder_renames);
|
||||
for f in folders.values_mut() {
|
||||
if let Some(r) = folder_confs.get(&f.hash()) {
|
||||
if let Some(rename) = r.folder_conf().alias() {
|
||||
f.change_name(rename);
|
||||
}
|
||||
|
||||
pub fn ref_folders(&self) -> &FnvHashMap<FolderHash, Folder> {
|
||||
&self.ref_folders
|
||||
}
|
||||
|
||||
pub fn list_folders(&self) -> Vec<FolderNode> {
|
||||
let mut ret = Vec::with_capacity(self.folders.len());
|
||||
fn rec(node: &FolderNode, ret: &mut Vec<FolderNode>) {
|
||||
ret.push(node.clone());
|
||||
for c in node.children.iter() {
|
||||
rec(c, ret);
|
||||
}
|
||||
}
|
||||
/*
|
||||
if let Some(pos) = folders
|
||||
.iter()
|
||||
.position(|f| f.name().eq_ignore_ascii_case("INBOX"))
|
||||
{
|
||||
folders.swap(pos, 0);
|
||||
for node in &self.tree {
|
||||
rec(node, &mut ret);
|
||||
}
|
||||
*/
|
||||
let order: FnvHashMap<FolderHash, usize> = self
|
||||
.folders_order
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, &fh)| (fh, i))
|
||||
.collect();
|
||||
let mut folders: Vec<Folder> = folders
|
||||
.drain()
|
||||
.map(|(_, f)| f)
|
||||
.filter(|f| {
|
||||
self.folders.contains_key(&f.hash())
|
||||
|| self
|
||||
.settings
|
||||
.account
|
||||
.subscribed_folders
|
||||
.iter()
|
||||
.any(|m| f.path().matches_glob(m))
|
||||
})
|
||||
.collect();
|
||||
if order.is_empty() {
|
||||
return Vec::new();
|
||||
}
|
||||
folders.sort_unstable_by(|a, b| order[&a.hash()].partial_cmp(&order[&b.hash()]).unwrap());
|
||||
folders
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn folders_order(&self) -> &Vec<FolderHash> {
|
||||
&self.folders_order
|
||||
}
|
||||
|
@ -786,7 +766,7 @@ impl Account {
|
|||
.map(|e| (e.hash(), e))
|
||||
.collect::<FnvHashMap<EnvelopeHash, Envelope>>();
|
||||
match self.folders.entry(folder_hash).or_default() {
|
||||
MailboxEntry::Failed(_) => {}
|
||||
MailboxEntry::Failed(_) | MailboxEntry::None => {}
|
||||
MailboxEntry::Parsing(ref mut m, _, _) | MailboxEntry::Available(ref mut m) => {
|
||||
m.merge(&envelopes);
|
||||
if let Some(updated_folders) =
|
||||
|
@ -807,6 +787,9 @@ impl Account {
|
|||
}
|
||||
|
||||
pub fn status(&mut self, folder_hash: FolderHash) -> result::Result<(), usize> {
|
||||
if folder_hash == 0 {
|
||||
return Err(0);
|
||||
}
|
||||
loop {
|
||||
match self.workers.get_mut(&folder_hash).unwrap() {
|
||||
None => {
|
||||
|
@ -1007,12 +990,7 @@ impl Account {
|
|||
.threads
|
||||
.insert(folder.hash(), Threads::default());
|
||||
self.ref_folders = self.backend.read().unwrap().folders()?;
|
||||
build_folders_order(
|
||||
&self.folder_confs,
|
||||
&mut self.tree,
|
||||
&self.ref_folders,
|
||||
&mut self.folders_order,
|
||||
);
|
||||
build_folders_order(&mut self.tree, &self.ref_folders, &mut self.folders_order);
|
||||
Ok(format!("`{}` successfully created.", &path))
|
||||
}
|
||||
FolderOperation::Delete(path) => {
|
||||
|
@ -1190,7 +1168,6 @@ impl IndexMut<usize> for Account {
|
|||
}
|
||||
|
||||
fn build_folders_order(
|
||||
folder_confs: &FnvHashMap<FolderHash, FileFolderConf>,
|
||||
tree: &mut Vec<FolderNode>,
|
||||
ref_folders: &FnvHashMap<FolderHash, Folder>,
|
||||
folders_order: &mut Vec<FolderHash>,
|
||||
|
@ -1199,23 +1176,24 @@ fn build_folders_order(
|
|||
tree.clear();
|
||||
folders_order.clear();
|
||||
for (h, f) in ref_folders.iter() {
|
||||
if !folder_confs.contains_key(&h) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if f.parent().is_none() {
|
||||
fn rec(h: FolderHash, ref_folders: &FnvHashMap<FolderHash, Folder>) -> FolderNode {
|
||||
fn rec(
|
||||
h: FolderHash,
|
||||
ref_folders: &FnvHashMap<FolderHash, Folder>,
|
||||
depth: usize,
|
||||
) -> FolderNode {
|
||||
let mut node = FolderNode {
|
||||
hash: h,
|
||||
kids: Vec::new(),
|
||||
children: Vec::new(),
|
||||
depth,
|
||||
};
|
||||
for &c in ref_folders[&h].children() {
|
||||
node.kids.push(rec(c, ref_folders));
|
||||
node.children.push(rec(c, ref_folders, depth + 1));
|
||||
}
|
||||
node
|
||||
};
|
||||
|
||||
tree.push(rec(*h, &ref_folders));
|
||||
tree.push(rec(*h, &ref_folders, 0));
|
||||
for &c in f.children() {
|
||||
stack.push(c);
|
||||
}
|
||||
|
@ -1239,10 +1217,10 @@ fn build_folders_order(
|
|||
}
|
||||
});
|
||||
|
||||
let mut stack: SmallVec<[Option<&FolderNode>; 8]> = SmallVec::new();
|
||||
let mut stack: SmallVec<[Option<&FolderNode>; 16]> = SmallVec::new();
|
||||
for n in tree.iter_mut() {
|
||||
folders_order.push(n.hash);
|
||||
n.kids.sort_unstable_by(|a, b| {
|
||||
n.children.sort_unstable_by(|a, b| {
|
||||
if ref_folders[&b.hash].path().eq_ignore_ascii_case("INBOX") {
|
||||
std::cmp::Ordering::Greater
|
||||
} else if ref_folders[&a.hash].path().eq_ignore_ascii_case("INBOX") {
|
||||
|
@ -1253,10 +1231,10 @@ fn build_folders_order(
|
|||
.cmp(&ref_folders[&b.hash].path())
|
||||
}
|
||||
});
|
||||
stack.extend(n.kids.iter().rev().map(Some));
|
||||
stack.extend(n.children.iter().rev().map(Some));
|
||||
while let Some(Some(next)) = stack.pop() {
|
||||
folders_order.push(next.hash);
|
||||
stack.extend(next.kids.iter().rev().map(Some));
|
||||
stack.extend(next.children.iter().rev().map(Some));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
13
src/state.rs
13
src/state.rs
|
@ -142,15 +142,20 @@ impl Context {
|
|||
let Context {
|
||||
ref mut accounts,
|
||||
ref mut mailbox_hashes,
|
||||
ref mut replies,
|
||||
..
|
||||
} = self;
|
||||
let was_online = accounts[account_pos].is_online;
|
||||
let ret = accounts[account_pos].is_online();
|
||||
if ret.is_ok() {
|
||||
if !was_online {
|
||||
for folder in accounts[account_pos].list_folders() {
|
||||
debug!("hash & folder: {:?} {}", folder.hash(), folder.name());
|
||||
mailbox_hashes.insert(folder.hash(), account_pos);
|
||||
for folder_node in accounts[account_pos].list_folders() {
|
||||
debug!(
|
||||
"hash & folder: {:?} {}",
|
||||
folder_node.hash,
|
||||
accounts[account_pos].ref_folders()[&folder_node.hash].name()
|
||||
);
|
||||
mailbox_hashes.insert(folder_node.hash, account_pos);
|
||||
}
|
||||
/* Account::watch() needs
|
||||
* - work_controller to pass `work_context` to the watcher threads and then add them
|
||||
|
@ -160,6 +165,8 @@ impl Context {
|
|||
* - replies to report any failures to the user
|
||||
*/
|
||||
accounts[account_pos].watch();
|
||||
|
||||
replies.push_back(UIEvent::AccountStatusChange(account_pos));
|
||||
}
|
||||
}
|
||||
ret
|
||||
|
|
|
@ -113,6 +113,7 @@ pub enum UIEvent {
|
|||
MailboxUpdate((usize, FolderHash)), // (account_idx, mailbox_idx)
|
||||
MailboxDelete((usize, FolderHash)),
|
||||
MailboxCreate((usize, FolderHash)),
|
||||
AccountStatusChange(usize),
|
||||
ComponentKill(Uuid),
|
||||
WorkerProgress(FolderHash),
|
||||
StartupCheck(FolderHash),
|
||||
|
|
Loading…
Reference in New Issue