1
1
use anyhow:: Result ;
2
- use passepartout:: { PasswordError , PasswordEvent } ;
3
2
use ratatui:: {
4
3
crossterm:: event:: { self , Event as TerminalEvent , KeyCode , KeyEvent , KeyEventKind , MouseEvent } ,
5
4
DefaultTerminal ,
@@ -14,22 +13,25 @@ mod state;
14
13
use crate :: {
15
14
actions:: { Action , NavigationAction , PasswordAction , SearchAction } ,
16
15
components:: { Component , Dashboard , MouseSupport } ,
16
+ event:: PasswordEvent ,
17
17
} ;
18
18
pub use state:: { MainState , OverlayState , SearchState , State } ;
19
19
20
20
pub struct App < ' a > {
21
21
running : bool ,
22
+ complete_redraw : bool ,
22
23
tick_rate : Duration ,
23
24
event_rx : Receiver < PasswordEvent > ,
24
25
dashboard : Dashboard < ' a > ,
25
26
}
26
27
27
28
impl < ' a > App < ' a > {
28
- pub fn new ( ) -> Self {
29
+ pub fn new ( tty_pinentry : bool ) -> Self {
29
30
let ( event_tx, event_rx) = mpsc:: channel ( ) ;
30
31
Self {
31
- dashboard : Dashboard :: new ( event_tx) ,
32
+ dashboard : Dashboard :: new ( tty_pinentry , event_tx) ,
32
33
running : false ,
34
+ complete_redraw : false ,
33
35
tick_rate : Duration :: from_millis ( 80 ) ,
34
36
event_rx,
35
37
}
@@ -39,6 +41,10 @@ impl<'a> App<'a> {
39
41
self . running = true ;
40
42
// Application loop
41
43
while self . running {
44
+ if self . complete_redraw {
45
+ let _ = terminal. clear ( ) ;
46
+ self . complete_redraw = false ;
47
+ }
42
48
terminal. draw ( |frame| frame. render_widget ( & mut self . dashboard , frame. area ( ) ) ) ?;
43
49
self . handle_events ( ) ?;
44
50
}
@@ -105,8 +111,8 @@ impl<'a> App<'a> {
105
111
KeyCode :: Char ( '/' ) => Some ( Action :: Navigation ( NavigationAction :: Search ) ) ,
106
112
KeyCode :: F ( 1 ) => Some ( Action :: Navigation ( NavigationAction :: Help ) ) ,
107
113
KeyCode :: Char ( 'i' ) => Some ( Action :: Navigation ( NavigationAction :: File ) ) ,
108
- KeyCode :: Char ( 'r' ) => Some ( Action :: Password ( PasswordAction :: FetchOneTimePassword ) ) ,
109
- KeyCode :: Char ( 'x' ) => Some ( Action :: Password ( PasswordAction :: CopyOneTimePassword ) ) ,
114
+ KeyCode :: Char ( 'r' ) => Some ( Action :: Password ( PasswordAction :: FetchOtp ) ) ,
115
+ KeyCode :: Char ( 'x' ) => Some ( Action :: Password ( PasswordAction :: CopyOtp ) ) ,
110
116
KeyCode :: Char ( 'c' ) => Some ( Action :: Password ( PasswordAction :: CopyPassId ) ) ,
111
117
KeyCode :: Char ( 'v' ) => Some ( Action :: Password ( PasswordAction :: CopyLogin ) ) ,
112
118
KeyCode :: Esc => Some ( Action :: Navigation ( NavigationAction :: Leave ) ) ,
@@ -143,7 +149,7 @@ impl<'a> App<'a> {
143
149
KeyCode :: Char ( '/' ) => Some ( Action :: Navigation ( NavigationAction :: Search ) ) ,
144
150
KeyCode :: F ( 1 ) => Some ( Action :: Navigation ( NavigationAction :: Help ) ) ,
145
151
KeyCode :: Char ( 'i' ) => Some ( Action :: Navigation ( NavigationAction :: File ) ) ,
146
- KeyCode :: Char ( 'x' ) => Some ( Action :: Password ( PasswordAction :: CopyOneTimePassword ) ) ,
152
+ KeyCode :: Char ( 'x' ) => Some ( Action :: Password ( PasswordAction :: CopyOtp ) ) ,
147
153
KeyCode :: Char ( 'c' ) => Some ( Action :: Password ( PasswordAction :: CopyPassId ) ) ,
148
154
KeyCode :: Char ( 'v' ) => Some ( Action :: Password ( PasswordAction :: CopyLogin ) ) ,
149
155
KeyCode :: Esc => Some ( Action :: Navigation ( NavigationAction :: Leave ) ) ,
@@ -202,50 +208,58 @@ impl<'a> App<'a> {
202
208
match event {
203
209
PasswordEvent :: Status ( Ok ( None ) ) => Some ( Action :: ResetStatus ) ,
204
210
PasswordEvent :: Status ( Ok ( Some ( message) ) ) => Some ( Action :: SetStatus ( message) ) ,
205
- PasswordEvent :: Status ( Err ( PasswordError :: PassError ( e) ) ) => {
211
+ PasswordEvent :: Status ( Err ( passepartout :: Error :: Pass ( e) ) ) => {
206
212
Some ( Action :: SetStatus ( format ! ( "✗ (pass) {e:?}" ) ) )
207
213
}
208
- PasswordEvent :: Status ( Err ( PasswordError :: ClipboardUnavailable ) ) => {
209
- Some ( Action :: SetStatus ( "✗ Clipboard not available" . to_string ( ) ) )
210
- }
211
- PasswordEvent :: Status ( Err ( PasswordError :: ClipboardError ( e) ) ) => {
212
- Some ( Action :: SetStatus ( format ! ( "✗ {e:?}" ) ) )
214
+ PasswordEvent :: Status ( Err ( passepartout:: Error :: Clipboard ( e) ) ) => {
215
+ Some ( Action :: SetStatus ( format ! ( "✗ Clipboard error: {e:?}" ) ) )
213
216
}
214
- PasswordEvent :: PasswordInfo {
217
+ PasswordEvent :: Status ( Err ( e) ) => Some ( Action :: SetStatus ( format ! ( "✗ {e:?}" ) ) ) ,
218
+ PasswordEvent :: PasswordFile {
215
219
pass_id,
216
220
file_contents,
217
221
} => Some ( Action :: DisplaySecrets {
218
222
pass_id,
219
223
file_contents,
220
224
} ) ,
221
- PasswordEvent :: OneTimePassword {
222
- pass_id,
223
- one_time_password,
224
- } => Some ( Action :: DisplayOneTimePassword {
225
- pass_id,
226
- one_time_password,
227
- } ) ,
225
+ PasswordEvent :: OneTimePassword { pass_id, otp } => {
226
+ Some ( Action :: DisplayOneTimePassword { pass_id, otp } )
227
+ }
228
228
}
229
229
}
230
230
231
231
fn dispatch_action ( & mut self , action : Action ) -> Result < ( ) > {
232
- let mut next_action = self . dashboard . update ( action. clone ( ) ) ?;
233
- while let Some ( action) = next_action {
234
- next_action = self . dashboard . update ( action) ?;
235
- }
232
+ let mut current_action = action;
233
+ loop {
234
+ // Actions from App take precedence
235
+ if let Some ( next) = self . update ( current_action. clone ( ) ) ? {
236
+ current_action = next;
237
+ continue ;
238
+ }
236
239
237
- let _ = self . update ( action) ?;
240
+ if let Some ( next) = self . dashboard . update ( current_action. clone ( ) ) ? {
241
+ current_action = next;
242
+ continue ;
243
+ }
238
244
245
+ break ;
246
+ }
239
247
Ok ( ( ) )
240
248
}
241
249
242
250
fn update ( & mut self , action : Action ) -> Result < Option < Action > > {
243
- if let Action :: Navigation ( NavigationAction :: Quit ) = action {
244
- self . quit ( ) ;
251
+ match action {
252
+ Action :: Navigation ( NavigationAction :: Quit ) => self . quit ( ) ,
253
+ Action :: Redraw => self . request_redraw ( ) ,
254
+ _ => ( ) ,
245
255
}
246
256
Ok ( None )
247
257
}
248
258
259
+ fn request_redraw ( & mut self ) {
260
+ self . complete_redraw = true ;
261
+ }
262
+
249
263
fn quit ( & mut self ) {
250
264
self . running = false ;
251
265
}
0 commit comments