p2p_chat/ui/log_mode/
render.rs1use super::super::UIState;
3use super::LogMode;
4use anyhow::Result;
5use crossterm::{
6 cursor, queue,
7 style::{Color, Print, ResetColor, SetForegroundColor},
8};
9use std::io::Write;
10use tracing::Level;
11
12impl LogMode {
13 pub fn render(
28 &self,
29 stdout: &mut impl Write,
30 state: &UIState,
31 area: (u16, u16, u16, u16),
32 ) -> Result<()> {
33 let (x, y, width, height) = area;
34
35 let filtered_logs = state.filtered_logs();
36 let total_logs = filtered_logs.len();
37 let visible_lines = height as usize;
38
39 let start_idx = if total_logs > visible_lines {
41 if state.log_scroll_offset >= total_logs {
42 0
43 } else {
44 total_logs.saturating_sub(visible_lines + state.log_scroll_offset)
45 }
46 } else {
47 0
48 };
49
50 let end_idx = (start_idx + visible_lines).min(total_logs);
51
52 for (line_idx, log_idx) in (start_idx..end_idx).enumerate() {
54 if let Some(log_entry) = filtered_logs.get(log_idx) {
55 queue!(stdout, cursor::MoveTo(x, y + line_idx as u16))?;
56
57 let timestamp = log_entry
58 .timestamp
59 .with_timezone(&chrono::Local)
60 .format("%H:%M:%S%.3f");
61
62 let level_color = match log_entry.level {
63 Level::ERROR => Color::Red,
64 Level::WARN => Color::Yellow,
65 Level::INFO => Color::Blue,
66 Level::DEBUG => Color::White,
67 Level::TRACE => Color::DarkGrey,
68 };
69
70 let log_line = format!(
71 "{} {:5} [{}] {}",
72 timestamp,
73 format!("{:?}", log_entry.level),
74 log_entry.module,
75 log_entry.message
76 );
77
78 let scrolled_line = if state.horizontal_scroll_offset < log_line.chars().count() {
80 log_line
81 .chars()
82 .skip(state.horizontal_scroll_offset)
83 .collect::<String>()
84 } else {
85 String::new()
86 };
87
88 let display_line = if scrolled_line.chars().count() > width as usize {
90 let truncated: String =
91 scrolled_line.chars().take(width as usize - 3).collect();
92 format!("{}...", truncated)
93 } else {
94 scrolled_line
95 };
96
97 queue!(
98 stdout,
99 SetForegroundColor(level_color),
100 Print(display_line),
101 ResetColor
102 )?;
103 }
104 }
105
106 if state.log_scroll_offset > 0 {
108 queue!(
109 stdout,
110 cursor::MoveTo(x + width - 15, y),
111 SetForegroundColor(Color::Yellow),
112 Print(format!("↑ +{} more logs", state.log_scroll_offset)),
113 ResetColor
114 )?;
115 }
116
117 if state.horizontal_scroll_offset > 0 {
119 queue!(
120 stdout,
121 cursor::MoveTo(x, y),
122 SetForegroundColor(Color::Yellow),
123 Print(format!("← +{}", state.horizontal_scroll_offset)),
124 ResetColor
125 )?;
126 }
127
128 Ok(())
129 }
130}