add read-only option in accounts

embed
Manos Pitsidianakis 2019-07-18 20:16:51 +03:00
parent 14f1527e61
commit a62f1d6c01
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
7 changed files with 83 additions and 17 deletions

View File

@ -24,7 +24,7 @@ pub mod mbox;
use crate::async_workers::*;
use crate::conf::AccountSettings;
use crate::error::Result;
use crate::error::{MeliError, Result};
//use mailbox::backends::imap::ImapType;
//use mailbox::backends::mbox::MboxType;
use self::maildir::MaildirType;
@ -210,6 +210,39 @@ pub trait BackendOp: ::std::fmt::Debug + ::std::marker::Send {
fn set_flag(&mut self, envelope: &mut Envelope, flag: Flag) -> Result<()>;
}
/// Wrapper for BackendOps that are to be set read-only.
///
/// Warning: Backend implementations may still cause side-effects (for example IMAP can set the
/// Seen flag when fetching an envelope)
#[derive(Debug)]
pub struct ReadOnlyOp {
op: Box<BackendOp>,
}
impl ReadOnlyOp {
pub fn new(op: Box<BackendOp>) -> Box<BackendOp> {
Box::new(ReadOnlyOp { op })
}
}
impl BackendOp for ReadOnlyOp {
fn description(&self) -> String {
format!("read-only: {}", self.op.description())
}
fn as_bytes(&mut self) -> Result<&[u8]> {
self.op.as_bytes()
}
fn fetch_headers(&mut self) -> Result<&[u8]> {
self.op.fetch_headers()
}
fn fetch_body(&mut self) -> Result<&[u8]> {
self.op.fetch_body()
}
fn fetch_flags(&self) -> Flag {
self.op.fetch_flags()
}
fn set_flag(&mut self, _envelope: &mut Envelope, _flag: Flag) -> Result<()> {
Err(MeliError::new("read-only set."))
}
}

View File

@ -26,6 +26,7 @@ pub struct AccountSettings {
pub format: String,
pub sent_folder: String,
pub identity: String,
pub read_only: bool,
pub display_name: Option<String>,
}
@ -45,6 +46,9 @@ impl AccountSettings {
pub fn identity(&self) -> &str {
&self.identity
}
pub fn read_only(&self) -> bool {
self.read_only
}
pub fn display_name(&self) -> Option<&String> {
self.display_name.as_ref()
}

View File

@ -1229,14 +1229,22 @@ impl Component for CompactListing {
let hash = account.get_env(&i).hash();
let op = account.operation(hash);
let envelope: &mut Envelope = &mut account.get_env_mut(&i);
envelope.set_seen(op).unwrap();
if let Err(e) = envelope.set_seen(op) {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(e.to_string()),
));
}
self.row_updates.push(i);
}
SetUnread => {
let hash = account.get_env(&i).hash();
let op = account.operation(hash);
let envelope: &mut Envelope = &mut account.get_env_mut(&i);
envelope.set_unseen(op).unwrap();
if let Err(e) = envelope.set_unseen(op) {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(e.to_string()),
));
}
self.row_updates.push(i);
}
Delete => { /* do nothing */ }

View File

@ -472,20 +472,14 @@ impl Component for ThreadListing {
&account.get_env(&self.locations[self.cursor_pos.2]);
(envelope.hash(), envelope.is_seen())
};
if !is_seen {
let op = account.operation(hash);
let envelope: &mut Envelope =
account.get_env_mut(&self.locations[self.cursor_pos.2]);
envelope.set_seen(op).unwrap();
true
} else {
false
}
is_seen
}
};
if must_highlight {
self.highlight_line_self(idx, context);
}
let mid = get_y(upper_left) + total_rows - bottom_entity_rows;
self.draw_list(
grid,

View File

@ -298,7 +298,14 @@ impl Component for MailView {
if !is_seen {
let op = account.operation(hash);
let envelope: &mut Envelope = &mut account.get_env_mut(&self.coordinates.2);
envelope.set_seen(op).unwrap();
if let Err(e) = envelope.set_seen(op) {
context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(format!(
"Could not set message as seen: {}",
e
))));
}
}
let envelope: &Envelope = &account.get_env(&self.coordinates.2);

View File

@ -131,6 +131,8 @@ pub struct FileAccount {
#[serde(default = "none", deserialize_with = "non_empty_string")]
html_filter: Option<String>,
#[serde(default = "false_val")]
read_only: bool,
folders: Option<HashMap<String, FolderConf>>,
}
@ -148,6 +150,7 @@ impl From<FileAccount> for AccountConf {
format,
sent_folder,
identity,
read_only: x.read_only,
display_name,
};
@ -366,7 +369,7 @@ where
mod default_vals {
pub(in crate::conf) fn false_val() -> bool {
true
false
}
pub(in crate::conf) fn true_val() -> bool {

View File

@ -28,10 +28,10 @@ use super::ToggleFlag;
use fnv::FnvHashMap;
use melib::async_workers::{Async, AsyncBuilder, AsyncStatus};
use melib::backends::{
BackendOp, Backends, Folder, FolderHash, MailBackend, NotifyFn, RefreshEvent,
BackendOp, Backends, Folder, FolderHash, MailBackend, NotifyFn, ReadOnlyOp, RefreshEvent,
RefreshEventConsumer, RefreshEventKind,
};
use melib::error::Result;
use melib::error::{MeliError, Result};
use melib::mailbox::*;
use melib::thread::ThreadHash;
use melib::AddressBook;
@ -458,11 +458,23 @@ impl Account {
}
pub fn save_draft(&self, draft: Draft) -> Result<()> {
if self.settings.account.read_only() {
return Err(MeliError::new(format!(
"Account {} is read-only.",
self.name.as_str()
)));
}
let finalize = draft.finalise()?;
self.backend
.save(&finalize.as_bytes(), &self.settings.conf.draft_folder)
}
pub fn save(&self, bytes: &[u8], folder: &str) -> Result<()> {
if self.settings.account.read_only() {
return Err(MeliError::new(format!(
"Account {} is read-only.",
self.name.as_str()
)));
}
self.backend.save(bytes, folder)
}
pub fn iter_mailboxes(&self) -> MailboxIterator {
@ -486,7 +498,12 @@ impl Account {
for mailbox in self.folders.values() {
if let Some(Ok(m)) = mailbox {
if m.envelopes.contains(&h) {
return self.backend.operation(h, m.folder.hash());
let operation = self.backend.operation(h, m.folder.hash());
if self.settings.account.read_only() {
return ReadOnlyOp::new(operation);
} else {
return operation;
}
}
}
}