@ -39,6 +39,7 @@ use super::*;
use crate ::{
accounts ::{ JobRequest , MailboxStatus } ,
components ::ExtendShortcutsMaps ,
jobs ::{ JobId , JoinHandle } ,
} ;
pub const DEFAULT_ATTACHMENT_FLAG : & str = concat! ( "📎" , emoji_text_presentation_selector ! ( ) ) ;
@ -1004,6 +1005,40 @@ pub trait ListingTrait: Component {
) ,
}
}
fn jump_to ( & mut self , _text : & str , _context : & mut Context ) { }
}
#[ derive(Debug) ]
pub struct BackgroundSearch {
pub text : String ,
pub timestamp : std ::time ::Instant ,
pub handle : JoinHandle < Result < SmallVec < [ EnvelopeHash ; 512 ] > > > ,
}
impl From < ( String , JoinHandle < Result < SmallVec < [ EnvelopeHash ; 512 ] > > > ) > for BackgroundSearch {
fn from ( ( text , handle ) : ( String , JoinHandle < Result < SmallVec < [ EnvelopeHash ; 512 ] > > > ) ) -> Self {
Self {
text ,
handle ,
timestamp : std ::time ::Instant ::now ( ) ,
}
}
}
#[ derive(Default, Debug) ]
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 , & self . jump_to_job ] . iter ( ) . any (
| bg | matches! ( bg , Some ( BackgroundSearch { handle , .. } ) if handle . job_id = = * job_id ) ,
)
}
}
#[ derive(Debug) ]
@ -1091,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 ,
@ -1110,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 ,
@ -1585,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
@ -1641,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
@ -1724,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 ) ;
@ -1811,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
@ -1834,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
@ -1857,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
@ -1880,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
@ -1903,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
@ -1926,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
@ -2039,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 ( ) = >
{
@ -2054,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 ;
}
_ = > { }
}
}
@ -2160,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
@ -2288,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
@ -2350,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
@ -2586,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
@ -2818,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 ) ;