melib: add special_usage() method to BackendFolder

Eventually after loading potential usage values from configuration,
backends will be able to change the usage values themselves. IMAP and
JMAP have the ability to set Mailbox roles (IMAP needs LIST-SPECIAL
extension
master
Manos Pitsidianakis 2019-12-11 00:15:36 +02:00
parent bce97d71bb
commit 6f76cd9acc
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
13 changed files with 77 additions and 35 deletions

View File

@ -339,7 +339,7 @@ impl BackendOp for ReadOnlyOp {
}
#[derive(Debug, Copy, Hash, Eq, Clone, Serialize, Deserialize, PartialEq)]
pub enum SpecialUseMailbox {
pub enum SpecialUsageMailbox {
Normal,
Inbox,
Archive,
@ -350,6 +350,12 @@ pub enum SpecialUseMailbox {
Trash,
}
impl Default for SpecialUsageMailbox {
fn default() -> Self {
SpecialUsageMailbox::Normal
}
}
pub trait BackendFolder: Debug {
fn hash(&self) -> FolderHash;
fn name(&self) -> &str;
@ -359,7 +365,7 @@ pub trait BackendFolder: Debug {
fn clone(&self) -> Folder;
fn children(&self) -> &[FolderHash];
fn parent(&self) -> Option<FolderHash>;
fn special_usage(&self) -> SpecialUsageMailbox;
fn permissions(&self) -> FolderPermissions;
}
@ -387,6 +393,10 @@ impl BackendFolder for DummyFolder {
folder_default()
}
fn special_usage(&self) -> SpecialUsageMailbox {
SpecialUsageMailbox::Normal
}
fn children(&self) -> &[FolderHash] {
&self.v
}

View File

@ -18,7 +18,7 @@
* You should have received a copy of the GNU General Public License
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use crate::backends::{BackendFolder, Folder, FolderHash, FolderPermissions};
use crate::backends::{BackendFolder, Folder, FolderHash, FolderPermissions, SpecialUsageMailbox};
use std::sync::{Arc, Mutex};
#[derive(Debug, Default, Clone)]
@ -28,6 +28,7 @@ pub struct ImapFolder {
pub(super) name: String,
pub(super) parent: Option<FolderHash>,
pub(super) children: Vec<FolderHash>,
pub usage: SpecialUsageMailbox,
pub no_select: bool,
pub permissions: Arc<Mutex<FolderPermissions>>,
@ -62,12 +63,17 @@ impl BackendFolder for ImapFolder {
name: self.name.clone(),
parent: self.parent,
children: self.children.clone(),
usage: self.usage,
no_select: self.no_select,
permissions: self.permissions.clone(),
exists: self.exists.clone(),
})
}
fn special_usage(&self) -> SpecialUsageMailbox {
self.usage
}
fn parent(&self) -> Option<FolderHash> {
self.parent
}

View File

@ -89,8 +89,15 @@ named!(
let mut f = ImapFolder::default();
f.no_select = false;
for p in properties.split(|&b| b == b' ') {
use crate::backends::SpecialUsageMailbox;
if p.eq_ignore_ascii_case(b"\\NoSelect") {
f.no_select = true;
} else if p.eq_ignore_ascii_case(b"\\Sent") {
f.usage = SpecialUsageMailbox::Sent;
} else if p.eq_ignore_ascii_case(b"\\Junk") {
f.usage = SpecialUsageMailbox::Trash;
} else if p.eq_ignore_ascii_case(b"\\Drafts") {
f.usage = SpecialUsageMailbox::Drafts;
}
}
f.hash = get_path_hash!(path);

View File

@ -19,6 +19,7 @@
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use super::*;
use crate::backends::SpecialUsageMailbox;
use std::sync::{Arc, Mutex, RwLock};
/// Arguments for IMAP watching functions
@ -123,7 +124,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
.read()
.unwrap()
.values()
.find(|f| f.parent.is_none() && f.path().eq_ignore_ascii_case("INBOX"))
.find(|f| f.parent.is_none() && (f.usage == SpecialUsageMailbox::Inbox))
.map(std::clone::Clone::clone)
{
Some(folder) => folder,

View File

@ -176,6 +176,7 @@ pub struct MaildirFolder {
path: PathBuf,
parent: Option<FolderHash>,
children: Vec<FolderHash>,
usage: SpecialUsageMailbox,
permissions: FolderPermissions,
}
@ -237,6 +238,7 @@ impl MaildirFolder {
fs_path: pathbuf,
parent,
children,
usage: SpecialUsageMailbox::Normal,
permissions: FolderPermissions {
create_messages: !read_only,
remove_messages: !read_only,
@ -300,11 +302,16 @@ impl BackendFolder for MaildirFolder {
fs_path: self.fs_path.clone(),
path: self.path.clone(),
children: self.children.clone(),
usage: self.usage,
parent: self.parent,
permissions: self.permissions,
})
}
fn special_usage(&self) -> SpecialUsageMailbox {
self.usage
}
fn parent(&self) -> Option<FolderHash> {
self.parent
}

View File

@ -28,7 +28,7 @@ use crate::backends::BackendOp;
use crate::backends::FolderHash;
use crate::backends::{
BackendFolder, Folder, FolderPermissions, MailBackend, RefreshEvent, RefreshEventConsumer,
RefreshEventKind,
RefreshEventKind, SpecialUsageMailbox,
};
use crate::conf::AccountSettings;
use crate::email::parser::BytesExt;
@ -128,6 +128,10 @@ impl BackendFolder for MboxFolder {
self.parent
}
fn special_usage(&self) -> SpecialUsageMailbox {
SpecialUsageMailbox::Normal
}
fn permissions(&self) -> FolderPermissions {
self.permissions
}

View File

@ -2,6 +2,7 @@ use crate::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext};
use crate::backends::FolderHash;
use crate::backends::{
BackendFolder, BackendOp, Folder, FolderPermissions, MailBackend, RefreshEventConsumer,
SpecialUsageMailbox,
};
use crate::conf::AccountSettings;
use crate::email::{Envelope, EnvelopeHash, Flag};
@ -66,6 +67,7 @@ struct NotmuchFolder {
parent: Option<FolderHash>,
name: String,
path: String,
usage: SpecialUsageMailbox,
query_str: String,
query: Option<*mut notmuch_query_t>,
phantom: std::marker::PhantomData<&'static mut notmuch_query_t>,
@ -98,6 +100,10 @@ impl BackendFolder for NotmuchFolder {
self.parent
}
fn special_usage(&self) -> SpecialUsageMailbox {
self.usage
}
fn permissions(&self) -> FolderPermissions {
FolderPermissions::default()
}
@ -156,6 +162,7 @@ impl NotmuchDb {
parent: None,
query: None,
query_str: query_str.to_string(),
usage: SpecialUsageMailbox::Normal,
phantom: std::marker::PhantomData,
},
);

View File

@ -18,7 +18,7 @@
* You should have received a copy of the GNU General Public License
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use crate::backends::SpecialUseMailbox;
use crate::backends::SpecialUsageMailbox;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::HashMap;
@ -81,7 +81,7 @@ pub struct FolderConf {
#[serde(deserialize_with = "toggleflag_de")]
pub ignore: ToggleFlag,
#[serde(default = "none")]
pub usage: Option<SpecialUseMailbox>,
pub usage: Option<SpecialUsageMailbox>,
#[serde(flatten)]
pub extra: HashMap<String, String>,
}

View File

@ -141,7 +141,7 @@ extern crate uuid;
pub use crate::conf::*;
pub use crate::mailbox::*;
pub use crate::backends::{Backends, RefreshEvent, RefreshEventConsumer, SpecialUseMailbox};
pub use crate::backends::{Backends, RefreshEvent, RefreshEventConsumer, SpecialUsageMailbox};
pub use crate::email::{Envelope, Flag};
pub use crate::error::{MeliError, Result};

View File

@ -574,7 +574,7 @@ impl Component for Composer {
context,
self.account_cursor,
self.draft.clone(),
SpecialUseMailbox::Sent,
SpecialUsageMailbox::Sent,
Flag::SEEN,
) {
context
@ -584,7 +584,7 @@ impl Component for Composer {
save_draft(
self.draft.clone().finalise().unwrap().as_bytes(),
context,
SpecialUseMailbox::Drafts,
SpecialUsageMailbox::Drafts,
Flag::SEEN | Flag::DRAFT,
self.account_cursor,
);
@ -633,7 +633,7 @@ impl Component for Composer {
save_draft(
self.draft.clone().finalise().unwrap().as_bytes(),
context,
SpecialUseMailbox::Drafts,
SpecialUsageMailbox::Drafts,
Flag::SEEN | Flag::DRAFT,
self.account_cursor,
);
@ -1069,7 +1069,7 @@ pub fn send_draft(
context: &mut Context,
account_cursor: usize,
mut draft: Draft,
folder_type: SpecialUseMailbox,
folder_type: SpecialUsageMailbox,
flags: Flag,
) -> bool {
use std::io::Write;
@ -1216,7 +1216,7 @@ pub fn send_draft(
pub fn save_draft(
bytes: &[u8],
context: &mut Context,
folder_type: SpecialUseMailbox,
folder_type: SpecialUsageMailbox,
flags: Flag,
account_cursor: usize,
) {

View File

@ -1200,7 +1200,7 @@ impl Component for MailView {
unsafe { &mut *(unsafe_context) },
self.coordinates.0,
draft,
SpecialUseMailbox::Sent,
SpecialUsageMailbox::Sent,
Flag::SEEN,
);
}

View File

@ -44,7 +44,7 @@ use self::default_vals::*;
use self::notifications::NotificationsSettings;
use self::terminal::TerminalSettings;
use crate::pager::PagerSettings;
use melib::backends::SpecialUseMailbox;
use melib::backends::SpecialUsageMailbox;
use melib::conf::{toggleflag_de, AccountSettings, FolderConf, ToggleFlag};
use melib::error::*;
@ -186,7 +186,7 @@ impl From<FileAccount> for AccountConf {
}
if folder_confs[s].folder_conf().ignore.is_unset() {
use SpecialUseMailbox::*;
use SpecialUsageMailbox::*;
if [Junk, Sent, Trash]
.contains(&folder_confs[s].folder_conf().usage.as_ref().unwrap())
{
@ -564,23 +564,23 @@ impl Serialize for CacheType {
}
}
pub fn usage(name: &str) -> Option<SpecialUseMailbox> {
pub fn usage(name: &str) -> Option<SpecialUsageMailbox> {
if name.eq_ignore_ascii_case("inbox") {
Some(SpecialUseMailbox::Inbox)
Some(SpecialUsageMailbox::Inbox)
} else if name.eq_ignore_ascii_case("archive") {
Some(SpecialUseMailbox::Archive)
Some(SpecialUsageMailbox::Archive)
} else if name.eq_ignore_ascii_case("drafts") {
Some(SpecialUseMailbox::Drafts)
Some(SpecialUsageMailbox::Drafts)
} else if name.eq_ignore_ascii_case("junk") {
Some(SpecialUseMailbox::Junk)
Some(SpecialUsageMailbox::Junk)
} else if name.eq_ignore_ascii_case("spam") {
Some(SpecialUseMailbox::Junk)
Some(SpecialUsageMailbox::Junk)
} else if name.eq_ignore_ascii_case("sent") {
Some(SpecialUseMailbox::Sent)
Some(SpecialUsageMailbox::Sent)
} else if name.eq_ignore_ascii_case("trash") {
Some(SpecialUseMailbox::Trash)
Some(SpecialUsageMailbox::Trash)
} else {
Some(SpecialUseMailbox::Normal)
Some(SpecialUsageMailbox::Normal)
}
}

View File

@ -28,7 +28,7 @@ use fnv::FnvHashMap;
use melib::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext};
use melib::backends::{
BackendOp, Backends, Folder, FolderHash, FolderOperation, MailBackend, NotifyFn, ReadOnlyOp,
RefreshEvent, RefreshEventConsumer, RefreshEventKind, SpecialUseMailbox,
RefreshEvent, RefreshEventConsumer, RefreshEventKind, SpecialUsageMailbox,
};
use melib::error::{MeliError, Result};
use melib::mailbox::*;
@ -335,7 +335,7 @@ impl Account {
if self.settings.folder_confs.contains_key(f.path()) {
match self.settings.folder_confs[f.path()].folder_conf().usage {
Some(SpecialUseMailbox::Sent) => {
Some(SpecialUsageMailbox::Sent) => {
sent_folder = Some(f.hash());
}
_ => {}
@ -452,9 +452,9 @@ impl Account {
let our_tx = builder.tx();
let folder_hash = folder.hash();
let priority = match folder_confs[&folder.hash()].folder_conf().usage {
Some(SpecialUseMailbox::Inbox) => 0,
Some(SpecialUseMailbox::Sent) => 1,
Some(SpecialUseMailbox::Drafts) | Some(SpecialUseMailbox::Trash) => 2,
Some(SpecialUsageMailbox::Inbox) => 0,
Some(SpecialUsageMailbox::Sent) => 1,
Some(SpecialUsageMailbox::Drafts) | Some(SpecialUsageMailbox::Trash) => 2,
Some(_) | None => {
3 * folder
.path()
@ -876,14 +876,14 @@ impl Account {
pub fn save_special(
&self,
bytes: &[u8],
folder_type: SpecialUseMailbox,
folder_type: SpecialUsageMailbox,
flags: Flag,
) -> Result<()> {
let mut failure = true;
for folder in &[
self.special_use_folder(folder_type),
self.special_use_folder(SpecialUseMailbox::Inbox),
self.special_use_folder(SpecialUseMailbox::Normal),
self.special_use_folder(SpecialUsageMailbox::Inbox),
self.special_use_folder(SpecialUsageMailbox::Normal),
] {
if folder.is_none() {
continue;
@ -965,7 +965,7 @@ impl Account {
let sent_folder = self
.folder_confs
.iter()
.find(|(_, f)| f.folder_conf().usage == Some(SpecialUseMailbox::Sent));
.find(|(_, f)| f.folder_conf().usage == Some(SpecialUsageMailbox::Sent));
if let Some(sent_folder) = sent_folder.as_ref() {
&self.folder_names[&sent_folder.0]
} else {
@ -973,7 +973,7 @@ impl Account {
}
}
pub fn special_use_folder(&self, special_use: SpecialUseMailbox) -> Option<&str> {
pub fn special_use_folder(&self, special_use: SpecialUsageMailbox) -> Option<&str> {
let ret = self
.folder_confs
.iter()