diff --git a/Cargo.lock b/Cargo.lock index 79b9304d..8f998c42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -645,18 +645,6 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "nix" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "nodrop" version = "0.1.13" @@ -1155,7 +1143,6 @@ version = "0.3.2" dependencies = [ "melib 0.3.2", "text_processing 0.3.2", - "ui 0.3.2", ] [[package]] @@ -1194,7 +1181,6 @@ dependencies = [ "linkify 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "melib 0.3.2", "mime_apps 0.2.0 (git+https://git.meli.delivery/meli/mime_apps)", - "nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "notify-rust 3.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1372,7 +1358,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" -"checksum nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" "checksum notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3572d71f13ea8ed41867accd971fd564aa75934cf7a1fae03ddb8c74a8a49943" diff --git a/melib/src/email/address.rs b/melib/src/email/address.rs index d5807e44..f9d82c37 100644 --- a/melib/src/email/address.rs +++ b/melib/src/email/address.rs @@ -128,7 +128,7 @@ impl fmt::Debug for Address { } /// Helper struct to return slices from a struct field on demand. -#[derive(Clone, Debug, Serialize, Deserialize, Default, PartialEq, Copy)] +#[derive(Clone, Debug, Serialize, Deserialize, Default, PartialEq, Eq, Copy)] pub struct StrBuilder { pub offset: usize, pub length: usize, diff --git a/melib/src/email/attachment_types.rs b/melib/src/email/attachment_types.rs index 8c3b8f49..9a34e2c1 100644 --- a/melib/src/email/attachment_types.rs +++ b/melib/src/email/attachment_types.rs @@ -24,7 +24,7 @@ use crate::email::parser::BytesExt; use std::fmt::{Display, Formatter, Result as FmtResult}; use std::str; -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum Charset { Ascii, UTF8, @@ -95,7 +95,7 @@ impl Display for Charset { } } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum MultipartType { Mixed, Alternative, @@ -136,7 +136,7 @@ impl From<&[u8]> for MultipartType { } } -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub enum ContentType { Text { kind: Text, @@ -245,7 +245,7 @@ impl ContentType { } } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum Text { Plain, Html, @@ -274,7 +274,7 @@ impl Display for Text { } } -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub enum ContentTransferEncoding { _8Bit, _7Bit, diff --git a/melib/src/email/attachments.rs b/melib/src/email/attachments.rs index 953f6f57..7f54ea80 100644 --- a/melib/src/email/attachments.rs +++ b/melib/src/email/attachments.rs @@ -28,7 +28,7 @@ use data_encoding::BASE64_MIME; pub use crate::email::attachment_types::*; -#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct AttachmentBuilder { pub content_type: ContentType, pub content_transfer_encoding: ContentTransferEncoding, @@ -291,7 +291,7 @@ impl From for Attachment { } /// Immutable attachment type. -#[derive(Clone, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct Attachment { pub content_type: ContentType, pub content_transfer_encoding: ContentTransferEncoding, diff --git a/melib/src/email/compose.rs b/melib/src/email/compose.rs index 58b583d8..b154fd31 100644 --- a/melib/src/email/compose.rs +++ b/melib/src/email/compose.rs @@ -17,7 +17,7 @@ pub mod random; use super::parser; use fnv::FnvHashMap; -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] pub struct Draft { pub headers: FnvHashMap, pub header_order: Vec, diff --git a/ui/src/components/mail/compose.rs b/ui/src/components/mail/compose.rs index 25497994..6316ddd0 100644 --- a/ui/src/components/mail/compose.rs +++ b/ui/src/components/mail/compose.rs @@ -46,6 +46,7 @@ pub struct Composer { mode: ViewMode, sign_mail: ToggleFlag, dirty: bool, + has_changes: bool, initialized: bool, id: ComponentId, } @@ -65,6 +66,7 @@ impl Default for Composer { mode: ViewMode::Edit, sign_mail: ToggleFlag::Unset, dirty: true, + has_changes: false, initialized: false, id: ComponentId::new_v4(), } @@ -246,6 +248,7 @@ impl Composer { fn draw_attachments(&self, grid: &mut CellBuffer, area: Area, context: &Context) { let attachments_no = self.draft.attachments().len(); + clear_area(grid, area); if self.sign_mail.is_true() { write_string_to_grid( &format!( @@ -331,7 +334,6 @@ impl Composer { impl Component for Composer { fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { - clear_area(grid, area); let upper_left = upper_left!(area); let bottom_right = bottom_right!(area); @@ -459,6 +461,7 @@ impl Component for Composer { ), false, ); + clear_area(grid, ((x, y), (set_y(bottom_right, y)))); change_colors( grid, ( @@ -468,28 +471,63 @@ impl Component for Composer { Color::Byte(189), Color::Byte(167), ); + if mid != 0 { + clear_area( + grid, + ( + pos_dec(upper_left, (0, 1)), + set_x(bottom_right, get_x(upper_left) + mid), + ), + ); + clear_area( + grid, + ( + ( + get_x(bottom_right).saturating_sub(mid), + get_y(upper_left) - 1, + ), + bottom_right, + ), + ); + } /* Regardless of view mode, do the following */ self.form.draw(grid, header_area, context); + self.pager.set_dirty(); + self.pager.draw(grid, body_area, context); + if self.cursor == Cursor::Body { + change_colors( + grid, + ( + set_y(upper_left!(body_area), get_y(bottom_right!(body_area))), + bottom_right!(body_area), + ), + Color::Default, + Color::Byte(237), + ); + } else { + change_colors( + grid, + ( + set_y(upper_left!(body_area), get_y(bottom_right!(body_area))), + bottom_right!(body_area), + ), + Color::Default, + Color::Default, + ); + } match self.mode { - ViewMode::ThreadView | ViewMode::Edit => { - self.pager.set_dirty(); - self.pager.draw(grid, body_area, context); - } + ViewMode::ThreadView | ViewMode::Edit => {} ViewMode::SelectRecipients(ref mut s) => { - self.pager.set_dirty(); - self.pager.draw(grid, body_area, context); s.draw(grid, center_area(area, s.content.size()), context); } ViewMode::Discard(_, ref mut s) => { - self.pager.set_dirty(); - self.pager.draw(grid, body_area, context); /* Let user choose whether to quit with/without saving or cancel */ s.draw(grid, center_area(area, s.content.size()), context); } } - + self.dirty = false; self.draw_attachments(grid, attachment_area, context); context.dirty_areas.push_back(area); } @@ -626,7 +664,10 @@ impl Component for Composer { } _ => {} } - if self.form.process_event(event, context) { + if self.cursor == Cursor::Headers && self.form.process_event(event, context) { + if let UIEvent::InsertInput(_) = event { + self.has_changes = true; + } return true; } @@ -659,9 +700,12 @@ impl Component for Composer { }*/ UIEvent::Input(Key::Up) => { self.cursor = Cursor::Headers; + self.form.process_event(event, context); + self.dirty = true; } UIEvent::Input(Key::Down) => { self.cursor = Cursor::Body; + self.dirty = true; } /* Switch to thread view mode if we're on Edit mode */ UIEvent::Input(Key::Char('v')) if self.mode.is_edit() => { @@ -742,6 +786,9 @@ impl Component for Composer { let result = f.read_to_string(); let mut new_draft = Draft::from_str(result.as_str()).unwrap(); std::mem::swap(self.draft.attachments_mut(), new_draft.attachments_mut()); + if self.draft != new_draft { + self.has_changes = true; + } self.draft = new_draft; self.initialized = false; context.replies.push_back(UIEvent::Fork(ForkType::Finished)); @@ -828,6 +875,11 @@ impl Component for Composer { } fn kill(&mut self, uuid: Uuid, context: &mut Context) { + if !self.has_changes { + context.replies.push_back(UIEvent::Action(Tab(Kill(uuid)))); + return; + } + self.mode = ViewMode::Discard( uuid, Selector::new( @@ -876,6 +928,10 @@ impl Component for Composer { } fn can_quit_cleanly(&mut self, context: &Context) -> bool { + if !self.has_changes { + return true; + } + /* Play it safe and ask user for confirmation */ self.mode = ViewMode::Discard( self.id,