parent
d8f81cb596
commit
a20e7ac5c2
|
@ -25,6 +25,8 @@ pub struct AccountSettings {
|
|||
pub root_folder: String,
|
||||
pub format: String,
|
||||
pub sent_folder: String,
|
||||
pub identity: String,
|
||||
pub display_name: Option<String>,
|
||||
}
|
||||
|
||||
impl AccountSettings {
|
||||
|
@ -34,7 +36,16 @@ impl AccountSettings {
|
|||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
pub fn set_name(&mut self, s: String) {
|
||||
self.name = s;
|
||||
}
|
||||
pub fn root_folder(&self) -> &str {
|
||||
&self.root_folder
|
||||
}
|
||||
pub fn identity(&self) -> &str {
|
||||
&self.identity
|
||||
}
|
||||
pub fn display_name(&self) -> Option<&String> {
|
||||
self.display_name.as_ref()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,9 @@ impl Default for Draft {
|
|||
}
|
||||
|
||||
impl Draft {
|
||||
pub fn headers_mut(&mut self) -> &mut FnvHashMap<String, String> {
|
||||
&mut self.headers
|
||||
}
|
||||
pub fn headers(&self) -> &FnvHashMap<String, String> {
|
||||
&self.headers
|
||||
}
|
||||
|
|
|
@ -25,10 +25,13 @@ use melib::Draft;
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Composer {
|
||||
dirty: bool,
|
||||
mode: ViewMode,
|
||||
pager: Pager,
|
||||
|
||||
draft: Draft,
|
||||
account_cursor: usize,
|
||||
|
||||
dirty: bool,
|
||||
}
|
||||
|
||||
impl Default for Composer {
|
||||
|
@ -36,8 +39,9 @@ impl Default for Composer {
|
|||
Composer {
|
||||
dirty: true,
|
||||
mode: ViewMode::Overview,
|
||||
pager: Pager::from_str("", None),
|
||||
pager: Pager::default(),
|
||||
draft: Draft::default(),
|
||||
account_cursor: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,9 +59,79 @@ impl fmt::Display for Composer {
|
|||
}
|
||||
}
|
||||
|
||||
impl Composer {
|
||||
fn draw_header_table(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
let upper_left = upper_left!(area);
|
||||
let bottom_right = bottom_right!(area);
|
||||
|
||||
let headers = self.draft.headers();
|
||||
{
|
||||
let (mut x, mut y) = upper_left;
|
||||
for k in &["Date", "From", "To", "Subject"] {
|
||||
let update = {
|
||||
let (x, y) = write_string_to_grid(
|
||||
k,
|
||||
grid,
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
((x, y), set_y(bottom_right, y)),
|
||||
true,
|
||||
);
|
||||
let (x, y) = write_string_to_grid(
|
||||
": ",
|
||||
grid,
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
((x, y), set_y(bottom_right, y)),
|
||||
true,
|
||||
);
|
||||
let (x, y) = if k == &"From" {
|
||||
write_string_to_grid(
|
||||
"◀ ",
|
||||
grid,
|
||||
Color::Byte(251),
|
||||
Color::Default,
|
||||
((x, y), set_y(bottom_right, y)),
|
||||
true,
|
||||
)
|
||||
} else {
|
||||
(x, y)
|
||||
};
|
||||
let (x, y) = write_string_to_grid(
|
||||
&headers[*k],
|
||||
grid,
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
((x, y), set_y(bottom_right, y)),
|
||||
true,
|
||||
);
|
||||
if k == &"From" {
|
||||
write_string_to_grid(
|
||||
" ▶",
|
||||
grid,
|
||||
Color::Byte(251),
|
||||
Color::Default,
|
||||
((x, y), set_y(bottom_right, y)),
|
||||
true,
|
||||
)
|
||||
} else {
|
||||
(x, y)
|
||||
}
|
||||
};
|
||||
x = get_x(upper_left);
|
||||
y = update.1 + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Composer {
|
||||
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
if self.dirty {
|
||||
self.draft.headers_mut().insert(
|
||||
"From".into(),
|
||||
get_display_name(context, self.account_cursor),
|
||||
);
|
||||
clear_area(grid, area);
|
||||
}
|
||||
let upper_left = upper_left!(area);
|
||||
|
@ -93,6 +167,7 @@ impl Component for Composer {
|
|||
}
|
||||
}
|
||||
|
||||
let header_area = (set_x(upper_left, mid + 1), (mid + 78, header_height + 1));
|
||||
let body_area = (
|
||||
(mid + 1, header_height + 2),
|
||||
(mid + 78, get_y(bottom_right)),
|
||||
|
@ -104,40 +179,7 @@ impl Component for Composer {
|
|||
}
|
||||
match self.mode {
|
||||
ViewMode::Overview => {
|
||||
let headers = self.draft.headers();
|
||||
{
|
||||
let (mut x, mut y) = set_x(upper_left, mid + 1);
|
||||
for k in &["Date", "From", "To", "Subject"] {
|
||||
let update = {
|
||||
let (x, y) = write_string_to_grid(
|
||||
k,
|
||||
grid,
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
((x, y), (mid + 78, y)),
|
||||
true,
|
||||
);
|
||||
let (x, y) = write_string_to_grid(
|
||||
": ",
|
||||
grid,
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
((x, y), (mid + 78, y)),
|
||||
true,
|
||||
);
|
||||
write_string_to_grid(
|
||||
&headers[*k],
|
||||
grid,
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
((x, y), (mid + 78, y)),
|
||||
true,
|
||||
)
|
||||
};
|
||||
x = mid + 1;
|
||||
y = update.1 + 1;
|
||||
}
|
||||
}
|
||||
self.draw_header_table(grid, header_area, context);
|
||||
self.pager.draw(grid, body_area, context);
|
||||
}
|
||||
}
|
||||
|
@ -152,6 +194,26 @@ impl Component for Composer {
|
|||
UIEventType::Resize => {
|
||||
self.dirty = true;
|
||||
}
|
||||
UIEventType::Input(Key::Left) => {
|
||||
self.account_cursor = self.account_cursor.saturating_sub(1);
|
||||
self.draft.headers_mut().insert(
|
||||
"From".into(),
|
||||
get_display_name(context, self.account_cursor),
|
||||
);
|
||||
self.dirty = true;
|
||||
return true;
|
||||
}
|
||||
UIEventType::Input(Key::Right) => {
|
||||
if self.account_cursor + 1 < context.accounts.len() {
|
||||
self.account_cursor += 1;
|
||||
self.draft.headers_mut().insert(
|
||||
"From".into(),
|
||||
get_display_name(context, self.account_cursor),
|
||||
);
|
||||
self.dirty = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
UIEventType::Input(Key::Char('\n')) => {
|
||||
use std::process::{Command, Stdio};
|
||||
/* Kill input thread so that spawned command can be sole receiver of stdin */
|
||||
|
@ -177,6 +239,16 @@ impl Component for Composer {
|
|||
self.dirty = true;
|
||||
return true;
|
||||
}
|
||||
UIEventType::Input(Key::Char('m')) => {
|
||||
let mut f =
|
||||
create_temp_file(self.draft.to_string().unwrap().as_str().as_bytes(), None);
|
||||
context.replies.push_back(UIEvent {
|
||||
id: 0,
|
||||
event_type: UIEventType::EditDraft(f),
|
||||
});
|
||||
self.draft = Draft::default();
|
||||
return true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
false
|
||||
|
@ -191,3 +263,12 @@ impl Component for Composer {
|
|||
self.pager.set_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
fn get_display_name(context: &Context, idx: usize) -> String {
|
||||
let settings = context.accounts[idx].runtime_settings.account();
|
||||
if let Some(d) = settings.display_name.as_ref() {
|
||||
format!("{} <{}>", d, settings.identity)
|
||||
} else {
|
||||
settings.identity.to_string()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -206,11 +206,11 @@ impl AccountMenu {
|
|||
cell.set_fg(Color::Byte(243));
|
||||
x += 1;
|
||||
continue;
|
||||
},
|
||||
}
|
||||
c if c.is_whitespace() => {
|
||||
x += 1;
|
||||
continue;
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ extern crate xdg;
|
|||
pub mod pager;
|
||||
|
||||
use melib::conf::AccountSettings;
|
||||
use melib::error::*;
|
||||
use pager::PagerSettings;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
@ -34,10 +35,36 @@ pub struct FileAccount {
|
|||
root_folder: String,
|
||||
format: String,
|
||||
sent_folder: String,
|
||||
identity: String,
|
||||
display_name: Option<String>,
|
||||
threaded: bool,
|
||||
folders: Option<HashMap<String, String>>,
|
||||
}
|
||||
|
||||
impl From<FileAccount> for AccountConf {
|
||||
fn from(x: FileAccount) -> Self {
|
||||
let format = x.format.to_lowercase();
|
||||
let sent_folder = x.sent_folder.clone();
|
||||
let root_folder = x.root_folder.clone();
|
||||
let identity = x.identity.clone();
|
||||
let display_name = x.display_name.clone();
|
||||
|
||||
let acc = AccountSettings {
|
||||
name: String::new(),
|
||||
root_folder,
|
||||
format,
|
||||
sent_folder,
|
||||
identity,
|
||||
display_name,
|
||||
};
|
||||
|
||||
AccountConf {
|
||||
account: acc,
|
||||
conf: x,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FileAccount {
|
||||
pub fn folders(&self) -> Option<&HashMap<String, String>> {
|
||||
self.folders.as_ref()
|
||||
|
@ -85,45 +112,33 @@ pub struct Settings {
|
|||
|
||||
use self::config::{Config, File, FileFormat};
|
||||
impl FileSettings {
|
||||
pub fn new() -> FileSettings {
|
||||
pub fn new() -> Result<FileSettings> {
|
||||
let xdg_dirs = xdg::BaseDirectories::with_prefix("meli").unwrap();
|
||||
let config_path = xdg_dirs
|
||||
.place_config_file("config")
|
||||
.expect("cannot create configuration directory");
|
||||
//let setts = Config::default().merge(File::new(config_path.to_str().unwrap_or_default(), config::FileFormat::Toml)).unwrap();
|
||||
let mut s = Config::new();
|
||||
let s = s.merge(File::new(config_path.to_str().unwrap(), FileFormat::Toml));
|
||||
|
||||
/* No point in returning without a config file.
|
||||
TODO: Error and exit instead of panic. */
|
||||
s.unwrap().deserialize().unwrap()
|
||||
match s.unwrap().deserialize() {
|
||||
Ok(v) => Ok(v),
|
||||
Err(e) => Err(MeliError::new(e.to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
pub fn new() -> Settings {
|
||||
let fs = FileSettings::new();
|
||||
let fs = FileSettings::new().unwrap_or_else(|e| panic!(format!("{}", e)));
|
||||
let mut s: HashMap<String, AccountConf> = HashMap::new();
|
||||
|
||||
for (id, x) in fs.accounts {
|
||||
let format = x.format.to_lowercase();
|
||||
let sent_folder = x.sent_folder.clone();
|
||||
let root_folder = x.root_folder.clone();
|
||||
let mut ac = AccountConf::from(x);
|
||||
ac.account.set_name(id.clone());
|
||||
|
||||
let acc = AccountSettings {
|
||||
name: id.clone(),
|
||||
root_folder,
|
||||
format,
|
||||
sent_folder,
|
||||
};
|
||||
|
||||
s.insert(
|
||||
id,
|
||||
AccountConf {
|
||||
account: acc,
|
||||
conf: x,
|
||||
},
|
||||
);
|
||||
s.insert(id, ac);
|
||||
}
|
||||
|
||||
Settings {
|
||||
|
|
Loading…
Reference in New Issue