@@ -49,7 +49,8 @@ use crate::{
4949 DeserializedUsb , PrintablePortInfo , ReconnectType , Reconnections , SerialDisconnectReason ,
5050 SerialEvent ,
5151 handle:: { BlockingCommandError , SerialHandle } ,
52- worker:: { InnerPortStatus , MOCK_PORT_NAME } ,
52+ port_status:: InnerPortStatus ,
53+ worker:: MOCK_PORT_NAME ,
5354 } ,
5455 settings:: { Behavior , PortSettings , Rendering , Settings } ,
5556 text_input:: TextInput ,
@@ -718,6 +719,12 @@ impl App {
718719 Event :: Crossterm ( CrosstermEvent :: RightClick ) => { }
719720
720721 Event :: Serial ( SerialEvent :: Connected ( reconnect) ) => {
722+ // Sync up the per-second tick for the "connected for" timer.
723+ self . carousel . add_repeating (
724+ "PerSecond" ,
725+ Tick :: PerSecond ,
726+ Duration :: from_secs ( 1 ) ,
727+ ) ?;
721728 if let Some ( reconnect_type) = & reconnect {
722729 info ! ( "Reconnected!" ) ;
723730 let text = match reconnect_type {
@@ -738,13 +745,13 @@ impl App {
738745 {
739746 let port_status_guard = self . serial . port_status . load ( ) ;
740747
741- if port_status_guard. current_port . is_none ( ) {
748+ if port_status_guard. current_port ( ) . is_none ( ) {
742749 error ! ( "Was told about a port connection but no current port exists!" ) ;
743750 panic ! ( "Was told about a port connection but no current port exists!" ) ;
744751 }
745752
746753 #[ cfg( feature = "logging" ) ]
747- if let Some ( current_port) = & port_status_guard. current_port {
754+ if let Some ( current_port) = port_status_guard. current_port ( ) {
748755 self . buffer
749756 . log_handle
750757 . log_port_connected ( current_port. to_owned ( ) , reconnect. clone ( ) ) ?;
@@ -850,7 +857,7 @@ impl App {
850857 return Ok ( ( ) ) ;
851858 }
852859
853- let port_status = & self . serial . port_status . load ( ) . inner ;
860+ let port_status = & self . serial . port_status . load ( ) . status ( ) ;
854861
855862 let reconnections_allowed =
856863 self . serial . port_settings . load ( ) . reconnections . allowed ( ) ;
@@ -1459,7 +1466,7 @@ impl App {
14591466 Ok ( ( ) )
14601467 }
14611468 fn send_crossterm_event_to_port ( & mut self , key_event : KeyEvent ) -> Result < ( ) > {
1462- let serial_healthy = self . serial . port_status . load ( ) . inner . is_connected ( ) ;
1469+ let serial_healthy = self . serial . port_status . load ( ) . status ( ) . is_connected ( ) ;
14631470
14641471 if let Ok ( event) =
14651472 terminput_crossterm:: to_terminput ( crossterm:: event:: Event :: Key ( key_event) )
@@ -1492,7 +1499,7 @@ impl App {
14921499 if actions. len ( ) == 1
14931500 && let Some ( action) = actions. first ( )
14941501 {
1495- let port_status = & self . serial . port_status . load ( ) . inner ;
1502+ let port_status = & self . serial . port_status . load ( ) . status ( ) ;
14961503
14971504 if action. requires_connection ( ) && !port_status. is_connected ( ) {
14981505 self . notifs . notify_str (
@@ -1581,11 +1588,11 @@ impl App {
15811588 }
15821589
15831590 // if action.requires_port_connection() {
1584- let port_status_guard = self . serial . port_status . load ( ) . inner ;
1591+ let port_status_guard = self . serial . port_status . load ( ) . status ( ) ;
15851592 match port_status_guard {
1586- InnerPortStatus :: Connected => ( ) ,
1593+ InnerPortStatus :: Connected { .. } => ( ) ,
15871594 #[ cfg( feature = "espflash" ) ]
1588- InnerPortStatus :: LentOut => {
1595+ InnerPortStatus :: LentOut { .. } => {
15891596 self . carousel . add_oneshot (
15901597 "ActionQueue" ,
15911598 Tick :: Action ,
@@ -1874,7 +1881,7 @@ impl App {
18741881 #[ cfg( feature = "logging" ) ]
18751882 A :: Logging ( LoggingAction :: Sync ) => {
18761883 let port_status_guard = self . serial . port_status . load ( ) ;
1877- let Some ( _) = & port_status_guard. current_port else {
1884+ let Some ( _) = port_status_guard. current_port ( ) else {
18781885 self . notifs . notify_str (
18791886 "Not (previously) connected to port? Unable to sync log." ,
18801887 Color :: Yellow ,
@@ -1983,8 +1990,8 @@ impl App {
19831990 // If user broke the connection intentionally, easy check
19841991 self . user_broke_connection ||
19851992 // Otherwise, only show if we're not connected or lending the port to espflash
1986- ( !port_status_guard. inner . is_connected ( )
1987- && !port_status_guard. inner . is_lent_out ( )
1993+ ( !port_status_guard. status ( ) . is_connected ( )
1994+ && !port_status_guard. status ( ) . is_lent_out ( )
19881995 // and if auto-reconnections is disabled.
19891996 // (when auto-reconns. are enabled, the normal Disconnect prompt
19901997 // is supposed to show to act as a pause for auto-reconnections)
@@ -2386,7 +2393,7 @@ impl App {
23862393 }
23872394 }
23882395 fn enter_pressed ( & mut self , ctrl_pressed : bool , shift_pressed : bool ) -> Result < ( ) > {
2389- let serial_healthy = self . serial . port_status . load ( ) . inner . is_connected ( ) ;
2396+ let serial_healthy = self . serial . port_status . load ( ) . status ( ) . is_connected ( ) ;
23902397 let popup_was_some = self . popup . is_some ( ) ;
23912398 // debug!("{:?}", self.menu);
23922399 match & self . popup {
@@ -3216,7 +3223,7 @@ impl App {
32163223 )
32173224 }
32183225 Popup :: DisconnectPrompt => {
3219- let port_state = { self . serial . port_status . load ( ) . inner } ;
3226+ let port_state = { self . serial . port_status . load ( ) . status ( ) } ;
32203227 let reconns_paused = if self . settings . serial . reconnections . allowed ( )
32213228 && port_state. is_premature_disconnect ( )
32223229 {
@@ -4251,7 +4258,7 @@ impl App {
42514258 let popup_shown = self . popup . is_some ( ) ;
42524259 let [ terminal_area, line_area, whole_input_area] = vertical ! [ *=1 , ==1 , ==1 ] . areas ( area) ;
42534260 let [ input_symbol_area, input_area] = horizontal ! [ ==1 , *=1 ] . areas ( whole_input_area) ;
4254-
4261+ let dark_gray = Style :: new ( ) . dark_gray ( ) ;
42554262 // let start = Instant::now();
42564263 if self . settings . rendering . hex_view {
42574264 self . buffer . render_hex ( terminal_area, frame. buffer_mut ( ) ) ;
@@ -4261,11 +4268,71 @@ impl App {
42614268 // debug!("1: {:?}", start.elapsed());
42624269 // let start = Instant::now();
42634270
4271+ // TODO toggle and layering options
4272+ let mut render_connection_timer =
4273+ |duration_opt : Option < Duration > , style : Style , lent_out_time : bool | {
4274+ let conn_stopwatch_string: Cow < ' _ , str > = if let Some ( duration) = duration_opt {
4275+ let secs = duration. as_secs ( ) ;
4276+ let day = secs / 86400 ;
4277+ let hour = ( secs % 86400 ) / 3600 ;
4278+ let min = ( secs % 3600 ) / 60 ;
4279+ let sec = secs % 60 ;
4280+
4281+ let output = if day > 0 {
4282+ format ! ( "{day:02}:{hour:02}:{min:02}:{sec:02}" )
4283+ } else {
4284+ format ! ( "{hour:02}:{min:02}:{sec:02}" )
4285+ } ;
4286+
4287+ let output = if lent_out_time {
4288+ format ! ( "({output})" )
4289+ } else {
4290+ output
4291+ } ;
4292+
4293+ output. into ( )
4294+ } else {
4295+ "XX:XX:XX" . into ( )
4296+ } ;
4297+
4298+ let [ top_line] = vertical ! [ ==1 ] . areas ( area. inner ( Margin {
4299+ horizontal : 1 ,
4300+ vertical : lent_out_time as u16 ,
4301+ } ) ) ;
4302+
4303+ let line = Line :: from ( Span :: styled ( conn_stopwatch_string, style) ) . right_aligned ( ) ;
4304+
4305+ frame. render_widget ( line, top_line) ;
4306+ } ;
4307+
42644308 let ( port_state, serial_signals, port_text) = {
42654309 let port_status_guard = self . serial . port_status . load ( ) ;
4266- let port_state = port_status_guard. inner ;
4310+ let port_state = port_status_guard. status ( ) ;
42674311
4268- let port_text = match & port_status_guard. current_port {
4312+ match port_state {
4313+ InnerPortStatus :: Connected { connected_at } => {
4314+ render_connection_timer ( Some ( connected_at. elapsed ( ) ) , dark_gray, false )
4315+ }
4316+ #[ cfg( feature = "espflash" ) ]
4317+ InnerPortStatus :: LentOut {
4318+ initial_connection_at,
4319+ lent_out_at,
4320+ } => {
4321+ render_connection_timer (
4322+ Some ( initial_connection_at. elapsed ( ) ) ,
4323+ dark_gray,
4324+ false ,
4325+ ) ;
4326+ render_connection_timer (
4327+ Some ( lent_out_at. elapsed ( ) ) ,
4328+ Color :: Yellow . into ( ) ,
4329+ true ,
4330+ ) ;
4331+ }
4332+ _ => render_connection_timer ( None , dark_gray, false ) ,
4333+ }
4334+
4335+ let port_text = match & port_status_guard. current_port ( ) {
42694336 Some ( port_info) => {
42704337 if port_state. is_connected ( ) || port_state. is_lent_out ( ) {
42714338 let baud_rate = self . serial . port_settings . load ( ) . baud_rate ;
@@ -4282,7 +4349,7 @@ impl App {
42824349 }
42834350 } ;
42844351
4285- ( port_state, port_status_guard. signals . clone ( ) , port_text)
4352+ ( port_state, port_status_guard. signals ( ) . clone ( ) , port_text)
42864353 } ;
42874354
42884355 repeating_pattern_widget ( frame, line_area, self . repeating_line_flip , port_state) ;
@@ -4413,7 +4480,7 @@ impl App {
44134480 . collect ( ) ,
44144481 )
44154482 } ;
4416- let dark_gray = Style :: new ( ) . dark_gray ( ) ;
4483+
44174484 let line = line ! [ span!( dark_gray; "Last sent: " ) , span!( dark_gray; value) ] ;
44184485
44194486 frame. render_widget ( line, whole_input_area) ;
@@ -5085,9 +5152,9 @@ pub fn repeating_pattern_widget(
50855152
50865153 let pattern_widget = ratatui:: widgets:: Paragraph :: new ( pattern) ;
50875154 let pattern_widget = match port_state {
5088- InnerPortStatus :: Connected => pattern_widget. green ( ) ,
5155+ InnerPortStatus :: Connected { .. } => pattern_widget. green ( ) ,
50895156 #[ cfg( feature = "espflash" ) ]
5090- InnerPortStatus :: LentOut => pattern_widget. yellow ( ) ,
5157+ InnerPortStatus :: LentOut { .. } => pattern_widget. yellow ( ) ,
50915158 InnerPortStatus :: PrematureDisconnect => pattern_widget. red ( ) ,
50925159 InnerPortStatus :: Idle => pattern_widget. red ( ) ,
50935160 } ;
0 commit comments