flatland_play_loop/
chat.rs1use flatland_client_ui::{UiKeyCode, UiKeyEvent};
4
5#[derive(Debug, Clone, Default)]
6pub struct ChatSession {
7 pub active: bool,
8 pub whisper: bool,
9 pub buffer: String,
10}
11
12impl ChatSession {
13 pub const MAX_LEN: usize = 200;
14
15 pub fn open(&mut self, whisper: bool) {
16 self.active = true;
17 self.whisper = whisper;
18 self.buffer.clear();
19 }
20
21 pub fn close(&mut self) {
22 self.active = false;
23 self.buffer.clear();
24 }
25
26 pub fn handle_key(&mut self, key: UiKeyEvent) -> Option<String> {
28 match key.code {
29 UiKeyCode::Esc => {
30 self.close();
31 None
32 }
33 UiKeyCode::Enter => {
34 let text = self.buffer.trim().to_string();
35 self.close();
36 if text.is_empty() {
37 None
38 } else {
39 Some(text)
40 }
41 }
42 UiKeyCode::Backspace => {
43 self.buffer.pop();
44 None
45 }
46 UiKeyCode::Char(c) => {
47 if self.buffer.len() < Self::MAX_LEN {
48 self.buffer.push(c);
49 }
50 None
51 }
52 _ => None,
53 }
54 }
55
56 pub fn prompt_line(&self) -> String {
57 if !self.active {
58 return String::new();
59 }
60 let prefix = if self.whisper { "whisper> " } else { "say> " };
61 format!("{prefix}{}", self.buffer)
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use flatland_client_ui::{UiKeyEventKind, UiKeyModifiers};
69
70 fn char_key(c: char) -> UiKeyEvent {
71 UiKeyEvent {
72 kind: UiKeyEventKind::Press,
73 code: UiKeyCode::Char(c),
74 modifiers: UiKeyModifiers::default(),
75 }
76 }
77
78 #[test]
79 fn submit_trims_and_clears() {
80 let mut chat = ChatSession::default();
81 chat.open(false);
82 for c in " hello ".chars() {
83 assert!(chat.handle_key(char_key(c)).is_none());
84 }
85 let submitted = chat
86 .handle_key(UiKeyEvent {
87 kind: UiKeyEventKind::Press,
88 code: UiKeyCode::Enter,
89 modifiers: UiKeyModifiers::default(),
90 })
91 .expect("submit");
92 assert_eq!(submitted, "hello");
93 assert!(!chat.active);
94 }
95}