rush_sync_server/output/
message.rs1use crate::core::prelude::*;
2use crate::input::keyboard::KeyAction;
3use crate::output::scroll::ScrollState;
4use unicode_segmentation::UnicodeSegmentation;
5
6pub struct Message {
7 pub content: String,
8 pub current_length: usize,
9 pub timestamp: Instant,
10}
11
12pub struct MessageManager<'a> {
13 pub messages: Vec<Message>,
14 config: &'a Config,
15 pub scroll_state: ScrollState,
16}
17
18impl<'a> MessageManager<'a> {
19 pub fn new(config: &'a Config) -> Self {
20 let scroll_state = ScrollState::new();
21 Self {
22 messages: Vec::with_capacity(config.max_messages),
23 config,
24 scroll_state,
25 }
26 }
27
28 pub fn clear_messages(&mut self) {
31 self.messages.clear();
32 self.scroll_state.force_auto_scroll();
33 }
34
35 pub fn get_content_height(&self) -> usize {
36 self.messages.len()
37 }
38
39 pub fn get_messages(&self) -> Vec<(&String, usize)> {
40 let (start, end) = self.scroll_state.get_visible_range();
41 let start = start.min(self.messages.len());
42 let end = end.min(self.messages.len());
43
44 if start >= end {
45 return Vec::new();
46 }
47
48 self.messages[start..end]
49 .iter()
50 .map(|msg| (&msg.content, msg.current_length))
51 .collect()
52 }
53
54 pub fn add_message(&mut self, content: String) {
55 if self.messages.len() >= self.config.max_messages {
56 self.messages.remove(0);
57 if self.scroll_state.offset > 0 {
58 self.scroll_state.offset = self.scroll_state.offset.saturating_sub(1);
59 }
60 }
61
62 self.messages.push(Message {
63 content,
64 current_length: 1,
65 timestamp: Instant::now(),
66 });
67
68 self.scroll_state.force_auto_scroll();
70
71 self.scroll_state
73 .update_dimensions(self.scroll_state.window_height, self.messages.len());
74 }
75
76 pub fn handle_scroll(&mut self, action: KeyAction, window_height: usize) {
77 self.scroll_state
79 .update_dimensions(window_height, self.messages.len());
80
81 match action {
82 KeyAction::ScrollUp => {
83 self.scroll_state.scroll_up(1);
84 }
85 KeyAction::ScrollDown => {
86 self.scroll_state.scroll_down(1);
87 }
88 KeyAction::PageUp => {
89 let scroll_amount = window_height.saturating_sub(1);
90 self.scroll_state.scroll_up(scroll_amount);
91 }
92 KeyAction::PageDown => {
93 let scroll_amount = window_height.saturating_sub(1);
94 self.scroll_state.scroll_down(scroll_amount);
95 }
96 _ => {}
97 }
98 }
99
100 pub fn get_visible_messages(&self) -> Vec<(&String, usize)> {
101 self.get_messages()
102 }
103
104 pub fn update_typewriter(&mut self) {
105 if let Some(last_message) = self.messages.last_mut() {
106 let total_length = last_message.content.graphemes(true).count();
107
108 if last_message.current_length < total_length
109 && last_message.timestamp.elapsed() >= self.config.typewriter_delay
110 {
111 last_message.current_length += 1;
112 last_message.timestamp = Instant::now();
113 }
114 }
115 }
116
117 pub fn log(&mut self, level: &str, message: &str) {
118 let log_message = format!("[{}] {}", level, message);
119 self.add_message(log_message);
120 }
121}