|
|
|
@ -1005,6 +1005,8 @@ pub trait ListingTrait: Component {
|
|
|
|
|
),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn jump_to(&mut self, _text: &str, _context: &mut Context) {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
@ -1028,11 +1030,12 @@ impl From<(String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)> for Backg
|
|
|
|
|
struct BackgroundJobs {
|
|
|
|
|
pub search_job: Option<BackgroundSearch>,
|
|
|
|
|
pub select_job: Option<BackgroundSearch>,
|
|
|
|
|
pub jump_to_job: Option<BackgroundSearch>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl BackgroundJobs {
|
|
|
|
|
pub fn is_match(&self, job_id: &JobId) -> bool {
|
|
|
|
|
[&self.search_job, &self.select_job].iter().any(
|
|
|
|
|
[&self.search_job, &self.select_job, &self.jump_to_job].iter().any(
|
|
|
|
|
|bg| matches!(bg, Some(BackgroundSearch { handle, .. }) if handle.job_id == *job_id),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
@ -1123,6 +1126,66 @@ enum ShowMenuScrollbar {
|
|
|
|
|
False,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
enum CmdBuf {
|
|
|
|
|
Command(String),
|
|
|
|
|
JumpTo(String),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CmdBuf {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn clone(&self) -> String {
|
|
|
|
|
match self {
|
|
|
|
|
Self::Command(ref v) | Self::JumpTo(ref v) => v.clone(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn pop(&mut self) -> Option<char> {
|
|
|
|
|
match self {
|
|
|
|
|
Self::Command(ref mut v) | Self::JumpTo(ref mut v) => v.pop(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn push(&mut self, c: char) -> bool {
|
|
|
|
|
match self {
|
|
|
|
|
Self::Command(_) if !c.is_ascii_digit() => false,
|
|
|
|
|
Self::Command(ref mut v) | Self::JumpTo(ref mut v) => {
|
|
|
|
|
v.push(c);
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn is_empty(&self) -> bool {
|
|
|
|
|
match self {
|
|
|
|
|
Self::Command(ref v) | Self::JumpTo(ref v) => v.is_empty(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn clear(&mut self) {
|
|
|
|
|
*self = Self::Command({
|
|
|
|
|
match self {
|
|
|
|
|
Self::Command(ref mut v) | Self::JumpTo(ref mut v) => {
|
|
|
|
|
v.clear();
|
|
|
|
|
std::mem::take(v)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn parse_usize(&self) -> Option<usize> {
|
|
|
|
|
let Self::Command(ref v) = self else {
|
|
|
|
|
return None;
|
|
|
|
|
};
|
|
|
|
|
v.parse::<usize>().ok()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct Listing {
|
|
|
|
|
component: ListingComponent,
|
|
|
|
@ -1142,7 +1205,7 @@ pub struct Listing {
|
|
|
|
|
sidebar_divider_theme: ThemeAttribute,
|
|
|
|
|
|
|
|
|
|
menu_visibility: bool,
|
|
|
|
|
cmd_buf: String,
|
|
|
|
|
cmd_buf: CmdBuf,
|
|
|
|
|
/// This is the width of the right container to the entire width.
|
|
|
|
|
ratio: usize, // right/(container width) * 100
|
|
|
|
|
prev_ratio: usize,
|
|
|
|
@ -1617,7 +1680,7 @@ impl Component for Listing {
|
|
|
|
|
{
|
|
|
|
|
let amount = if self.cmd_buf.is_empty() {
|
|
|
|
|
1
|
|
|
|
|
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
|
|
|
|
} else if let Some(amount) = self.cmd_buf.parse_usize() {
|
|
|
|
|
self.cmd_buf.clear();
|
|
|
|
|
self.component.set_modifier_active(false);
|
|
|
|
|
context
|
|
|
|
@ -1673,7 +1736,7 @@ impl Component for Listing {
|
|
|
|
|
{
|
|
|
|
|
let amount = if self.cmd_buf.is_empty() {
|
|
|
|
|
1
|
|
|
|
|
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
|
|
|
|
} else if let Some(amount) = self.cmd_buf.parse_usize() {
|
|
|
|
|
self.cmd_buf.clear();
|
|
|
|
|
self.component.set_modifier_active(false);
|
|
|
|
|
context
|
|
|
|
@ -1756,6 +1819,35 @@ impl Component for Listing {
|
|
|
|
|
|
|
|
|
|
if self.status.is_none() {
|
|
|
|
|
match event {
|
|
|
|
|
UIEvent::Input(Key::Esc) | UIEvent::Input(Key::Alt(''))
|
|
|
|
|
if !self.cmd_buf.is_empty() =>
|
|
|
|
|
{
|
|
|
|
|
self.cmd_buf.clear();
|
|
|
|
|
self.component.set_modifier_active(false);
|
|
|
|
|
if let CmdBuf::JumpTo(ref s) = self.cmd_buf {
|
|
|
|
|
self.component.jump_to(s, context);
|
|
|
|
|
}
|
|
|
|
|
context
|
|
|
|
|
.replies
|
|
|
|
|
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
UIEvent::Input(Key::Char(c))
|
|
|
|
|
if matches!(self.cmd_buf, CmdBuf::JumpTo(_))
|
|
|
|
|
|| matches!(self.cmd_buf, CmdBuf::Command(_) if c.is_ascii_digit()) =>
|
|
|
|
|
{
|
|
|
|
|
self.cmd_buf.push(*c);
|
|
|
|
|
self.component.set_modifier_active(true);
|
|
|
|
|
if let CmdBuf::JumpTo(ref s) = self.cmd_buf {
|
|
|
|
|
self.component.jump_to(s, context);
|
|
|
|
|
}
|
|
|
|
|
context
|
|
|
|
|
.replies
|
|
|
|
|
.push_back(UIEvent::StatusEvent(StatusEvent::BufSet(
|
|
|
|
|
self.cmd_buf.clone(),
|
|
|
|
|
)));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
UIEvent::Action(ref action) => match action {
|
|
|
|
|
Action::Listing(ListingAction::SetPlain) => {
|
|
|
|
|
self.set_index_style(IndexStyle::Plain, context);
|
|
|
|
@ -1843,7 +1935,7 @@ impl Component for Listing {
|
|
|
|
|
{
|
|
|
|
|
let amount = if self.cmd_buf.is_empty() {
|
|
|
|
|
1
|
|
|
|
|
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
|
|
|
|
} else if let Some(amount) = self.cmd_buf.parse_usize() {
|
|
|
|
|
self.cmd_buf.clear();
|
|
|
|
|
self.component.set_modifier_active(false);
|
|
|
|
|
context
|
|
|
|
@ -1866,7 +1958,7 @@ impl Component for Listing {
|
|
|
|
|
{
|
|
|
|
|
let amount = if self.cmd_buf.is_empty() {
|
|
|
|
|
1
|
|
|
|
|
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
|
|
|
|
} else if let Some(amount) = self.cmd_buf.parse_usize() {
|
|
|
|
|
self.cmd_buf.clear();
|
|
|
|
|
self.component.set_modifier_active(false);
|
|
|
|
|
context
|
|
|
|
@ -1889,7 +1981,7 @@ impl Component for Listing {
|
|
|
|
|
{
|
|
|
|
|
let amount = if self.cmd_buf.is_empty() {
|
|
|
|
|
1
|
|
|
|
|
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
|
|
|
|
} else if let Some(amount) = self.cmd_buf.parse_usize() {
|
|
|
|
|
self.cmd_buf.clear();
|
|
|
|
|
self.component.set_modifier_active(false);
|
|
|
|
|
context
|
|
|
|
@ -1912,7 +2004,7 @@ impl Component for Listing {
|
|
|
|
|
{
|
|
|
|
|
let amount = if self.cmd_buf.is_empty() {
|
|
|
|
|
1
|
|
|
|
|
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
|
|
|
|
} else if let Some(amount) = self.cmd_buf.parse_usize() {
|
|
|
|
|
self.cmd_buf.clear();
|
|
|
|
|
self.component.set_modifier_active(false);
|
|
|
|
|
context
|
|
|
|
@ -1935,7 +2027,7 @@ impl Component for Listing {
|
|
|
|
|
{
|
|
|
|
|
let mult = if self.cmd_buf.is_empty() {
|
|
|
|
|
1
|
|
|
|
|
} else if let Ok(mult) = self.cmd_buf.parse::<usize>() {
|
|
|
|
|
} else if let Some(mult) = self.cmd_buf.parse_usize() {
|
|
|
|
|
self.cmd_buf.clear();
|
|
|
|
|
self.component.set_modifier_active(false);
|
|
|
|
|
context
|
|
|
|
@ -1958,7 +2050,7 @@ impl Component for Listing {
|
|
|
|
|
{
|
|
|
|
|
let mult = if self.cmd_buf.is_empty() {
|
|
|
|
|
1
|
|
|
|
|
} else if let Ok(mult) = self.cmd_buf.parse::<usize>() {
|
|
|
|
|
} else if let Some(mult) = self.cmd_buf.parse_usize() {
|
|
|
|
|
self.cmd_buf.clear();
|
|
|
|
|
self.component.set_modifier_active(false);
|
|
|
|
|
context
|
|
|
|
@ -2071,6 +2163,15 @@ impl Component for Listing {
|
|
|
|
|
self.component.prev_entry(context);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
UIEvent::Input(ref k)
|
|
|
|
|
if shortcut!(k == shortcuts[Shortcuts::LISTING]["jump_to"]) =>
|
|
|
|
|
{
|
|
|
|
|
if let CmdBuf::Command(ref mut v) = self.cmd_buf {
|
|
|
|
|
v.clear();
|
|
|
|
|
self.cmd_buf = CmdBuf::JumpTo(std::mem::take(v));
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
UIEvent::Input(Key::Esc) | UIEvent::Input(Key::Alt(''))
|
|
|
|
|
if !self.component.unfocused() =>
|
|
|
|
|
{
|
|
|
|
@ -2086,26 +2187,6 @@ impl Component for Listing {
|
|
|
|
|
self.component.set_dirty(true);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
UIEvent::Input(Key::Esc) | UIEvent::Input(Key::Alt(''))
|
|
|
|
|
if !self.cmd_buf.is_empty() =>
|
|
|
|
|
{
|
|
|
|
|
self.cmd_buf.clear();
|
|
|
|
|
self.component.set_modifier_active(false);
|
|
|
|
|
context
|
|
|
|
|
.replies
|
|
|
|
|
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
UIEvent::Input(Key::Char(c)) if c.is_ascii_digit() => {
|
|
|
|
|
self.cmd_buf.push(*c);
|
|
|
|
|
self.component.set_modifier_active(true);
|
|
|
|
|
context
|
|
|
|
|
.replies
|
|
|
|
|
.push_back(UIEvent::StatusEvent(StatusEvent::BufSet(
|
|
|
|
|
self.cmd_buf.clone(),
|
|
|
|
|
)));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2192,7 +2273,7 @@ impl Component for Listing {
|
|
|
|
|
{
|
|
|
|
|
let mut amount = if self.cmd_buf.is_empty() {
|
|
|
|
|
1
|
|
|
|
|
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
|
|
|
|
} else if let Some(amount) = self.cmd_buf.parse_usize() {
|
|
|
|
|
self.cmd_buf.clear();
|
|
|
|
|
self.component.set_modifier_active(false);
|
|
|
|
|
context
|
|
|
|
@ -2320,7 +2401,7 @@ impl Component for Listing {
|
|
|
|
|
{
|
|
|
|
|
let amount = if self.cmd_buf.is_empty() {
|
|
|
|
|
1
|
|
|
|
|
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
|
|
|
|
} else if let Some(amount) = self.cmd_buf.parse_usize() {
|
|
|
|
|
self.cmd_buf.clear();
|
|
|
|
|
self.component.set_modifier_active(false);
|
|
|
|
|
context
|
|
|
|
@ -2382,7 +2463,7 @@ impl Component for Listing {
|
|
|
|
|
{
|
|
|
|
|
let amount = if self.cmd_buf.is_empty() {
|
|
|
|
|
1
|
|
|
|
|
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
|
|
|
|
} else if let Some(amount) = self.cmd_buf.parse_usize() {
|
|
|
|
|
self.cmd_buf.clear();
|
|
|
|
|
self.component.set_modifier_active(false);
|
|
|
|
|
context
|
|
|
|
@ -2618,7 +2699,8 @@ impl Component for Listing {
|
|
|
|
|
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
UIEvent::Input(Key::Char(c)) if c.is_ascii_digit() => {
|
|
|
|
|
UIEvent::Input(Key::Char(c)) if matches!(self.cmd_buf, CmdBuf::JumpTo(_) | CmdBuf::Command(_) if c.is_ascii_digit()) =>
|
|
|
|
|
{
|
|
|
|
|
self.cmd_buf.push(c);
|
|
|
|
|
self.component.set_modifier_active(true);
|
|
|
|
|
context
|
|
|
|
@ -2850,7 +2932,7 @@ impl Listing {
|
|
|
|
|
prev_ratio: *account_settings!(context[first_account_hash].listing.sidebar_ratio),
|
|
|
|
|
menu_width: WidgetWidth::Unset,
|
|
|
|
|
focus: ListingFocus::Mailbox,
|
|
|
|
|
cmd_buf: String::with_capacity(4),
|
|
|
|
|
cmd_buf: CmdBuf::Command(String::with_capacity(8)),
|
|
|
|
|
};
|
|
|
|
|
ret.component.realize(ret.id().into(), context);
|
|
|
|
|
ret.change_account(context);
|
|
|
|
|