@@ -364,22 +364,6 @@ pub fn draw_dashboard(area: Rect, f: &mut Frame, state: &UiState) {
364364 let lost = udp_sent. saturating_sub ( safe_received) ;
365365 let pending = safe_total. saturating_sub ( udp_sent) ;
366366
367- let bar_width = udp_inner. width . saturating_sub ( 70 ) as usize ;
368- let bar_width = bar_width. max ( 10 ) ;
369-
370- // Ensure any loss shows at least one red segment
371- let lost_units = if lost > 0 {
372- ( ( lost as f64 / safe_total as f64 ) * bar_width as f64 ) . ceil ( ) . max ( 1.0 ) as usize
373- } else {
374- 0
375- } ;
376- let recv_units = ( ( safe_received as f64 / safe_total as f64 ) * bar_width as f64 ) . floor ( ) as usize ;
377- let pending_units = bar_width. saturating_sub ( recv_units + lost_units) ;
378-
379- let bar_recv = "█" . repeat ( recv_units) ;
380- let bar_lost = "█" . repeat ( lost_units) ;
381- let bar_pending = "░" . repeat ( pending_units) ;
382-
383367 let rtt_str = udp_latest_rtt
384368 . map ( |v| format ! ( "{:.0}ms" , v) )
385369 . unwrap_or_else ( || "-" . to_string ( ) ) ;
@@ -398,6 +382,58 @@ pub fn draw_dashboard(area: Rect, f: &mut Frame, state: &UiState) {
398382 } )
399383 . unwrap_or ( ( "" , String :: new ( ) , String :: new ( ) , String :: new ( ) ) ) ;
400384
385+ // Calculate text width before the bar
386+ let mut pre_bar_width: usize = 0 ;
387+ pre_bar_width += udp_status. len ( ) + 1 ; // status + space
388+ if !quality_label. is_empty ( ) {
389+ pre_bar_width += quality_label. len ( ) ;
390+ if !mos_str. is_empty ( ) {
391+ pre_bar_width += 2 + mos_str. len ( ) + 2 ; // " (" + mos + ") "
392+ } else {
393+ pre_bar_width += 1 ; // space
394+ }
395+ }
396+ let loss_str = format ! ( "loss {:.1}%" , udp_loss_pct) ;
397+ let rtt_display = format ! ( "rtt {}" , rtt_str) ;
398+ pre_bar_width += loss_str. len ( ) + 1 + rtt_display. len ( ) ; // loss + space + rtt
399+ if !jitter_str. is_empty ( ) {
400+ pre_bar_width += 1 + jitter_str. len ( ) ;
401+ }
402+ if !reorder_str. is_empty ( ) && state. phase != crate :: model:: Phase :: PacketLoss {
403+ pre_bar_width += 1 + reorder_str. len ( ) ;
404+ }
405+ pre_bar_width += 2 ; // " " before bar
406+
407+ // Calculate text width after the bar
408+ let ok_str = format ! ( "ok {}" , safe_received) ;
409+ let lost_str = format ! ( "lost {}" , lost) ;
410+ let mut post_bar_width: usize = 2 + ok_str. len ( ) + 1 + lost_str. len ( ) ; // " " + ok + " " + lost
411+ if pending > 0 {
412+ post_bar_width += format ! ( " pending {}" , pending) . len ( ) ;
413+ }
414+
415+ // Calculate bar width from remaining space
416+ let total_text_width = pre_bar_width + post_bar_width;
417+ let available_width = udp_inner. width as usize ;
418+ let bar_width = if available_width > total_text_width + 5 {
419+ available_width - total_text_width
420+ } else {
421+ 10 // minimum bar width
422+ } ;
423+
424+ // Ensure any loss shows at least one red segment
425+ let lost_units = if lost > 0 {
426+ ( ( lost as f64 / safe_total as f64 ) * bar_width as f64 ) . ceil ( ) . max ( 1.0 ) as usize
427+ } else {
428+ 0
429+ } ;
430+ let recv_units = ( ( safe_received as f64 / safe_total as f64 ) * bar_width as f64 ) . floor ( ) as usize ;
431+ let pending_units = bar_width. saturating_sub ( recv_units + lost_units) ;
432+
433+ let bar_recv = "█" . repeat ( recv_units) ;
434+ let bar_lost = "█" . repeat ( lost_units) ;
435+ let bar_pending = "░" . repeat ( pending_units) ;
436+
401437 let mut spans = vec ! [
402438 Span :: styled( udp_status, Style :: default ( ) . fg( Color :: Yellow ) ) ,
403439 Span :: raw( " " ) ,
@@ -409,7 +445,7 @@ pub fn draw_dashboard(area: Rect, f: &mut Frame, state: &UiState) {
409445 spans. push ( Span :: styled ( quality_label, Style :: default ( ) . fg ( label_color) ) ) ;
410446 if !mos_str. is_empty ( ) {
411447 spans. push ( Span :: raw ( " (" ) ) ;
412- spans. push ( Span :: styled ( mos_str, Style :: default ( ) . fg ( label_color) ) ) ;
448+ spans. push ( Span :: styled ( & mos_str, Style :: default ( ) . fg ( label_color) ) ) ;
413449 spans. push ( Span :: raw ( ") " ) ) ;
414450 } else {
415451 spans. push ( Span :: raw ( " " ) ) ;
@@ -418,21 +454,21 @@ pub fn draw_dashboard(area: Rect, f: &mut Frame, state: &UiState) {
418454
419455 spans. extend ( vec ! [
420456 Span :: styled(
421- format! ( "loss {:.1}%" , udp_loss_pct ) ,
457+ loss_str ,
422458 Style :: default ( ) . fg( if udp_loss_pct == 0.0 { Color :: Green } else if udp_loss_pct < 2.5 { Color :: Yellow } else { Color :: Red } ) ,
423459 ) ,
424460 Span :: raw( " " ) ,
425- Span :: styled( format! ( "rtt {}" , rtt_str ) , Style :: default ( ) . fg( Color :: Gray ) ) ,
461+ Span :: styled( rtt_display , Style :: default ( ) . fg( Color :: Gray ) ) ,
426462 ] ) ;
427463
428464 // Add jitter and reorder when available
429465 if !jitter_str. is_empty ( ) {
430466 spans. push ( Span :: raw ( " " ) ) ;
431- spans. push ( Span :: styled ( jitter_str, Style :: default ( ) . fg ( Color :: Gray ) ) ) ;
467+ spans. push ( Span :: styled ( & jitter_str, Style :: default ( ) . fg ( Color :: Gray ) ) ) ;
432468 }
433469 if !reorder_str. is_empty ( ) && state. phase != crate :: model:: Phase :: PacketLoss {
434470 spans. push ( Span :: raw ( " " ) ) ;
435- spans. push ( Span :: styled ( reorder_str, Style :: default ( ) . fg ( Color :: Gray ) ) ) ;
471+ spans. push ( Span :: styled ( & reorder_str, Style :: default ( ) . fg ( Color :: Gray ) ) ) ;
436472 }
437473
438474 spans. extend ( vec ! [
@@ -441,9 +477,9 @@ pub fn draw_dashboard(area: Rect, f: &mut Frame, state: &UiState) {
441477 Span :: styled( bar_lost, Style :: default ( ) . fg( Color :: Red ) ) ,
442478 Span :: styled( bar_pending, Style :: default ( ) . fg( Color :: DarkGray ) ) ,
443479 Span :: raw( " " ) ,
444- Span :: styled( format! ( "ok {}" , safe_received ) , Style :: default ( ) . fg( Color :: Green ) ) ,
480+ Span :: styled( ok_str , Style :: default ( ) . fg( Color :: Green ) ) ,
445481 Span :: raw( " " ) ,
446- Span :: styled( format! ( "lost {}" , lost ) , Style :: default ( ) . fg( Color :: Red ) ) ,
482+ Span :: styled( lost_str , Style :: default ( ) . fg( Color :: Red ) ) ,
447483 ] ) ;
448484
449485 if pending > 0 {
0 commit comments