sbom_tools/tui/viewmodel/
status.rs1use std::time::{Duration, Instant};
7
8#[derive(Debug, Clone, Default)]
27pub struct StatusMessage {
28 message: Option<String>,
30 set_at: Option<Instant>,
32 auto_clear_after: Option<Duration>,
34}
35
36impl StatusMessage {
37 pub fn new() -> Self {
39 Self::default()
40 }
41
42 pub fn with_auto_clear(duration: Duration) -> Self {
44 Self {
45 message: None,
46 set_at: None,
47 auto_clear_after: Some(duration),
48 }
49 }
50
51 pub fn set(&mut self, msg: impl Into<String>) {
53 self.message = Some(msg.into());
54 self.set_at = Some(Instant::now());
55 }
56
57 pub fn clear(&mut self) {
59 self.message = None;
60 self.set_at = None;
61 }
62
63 pub fn message(&mut self) -> Option<&str> {
65 if let (Some(set_at), Some(duration)) = (self.set_at, self.auto_clear_after) {
67 if set_at.elapsed() >= duration {
68 self.message = None;
69 self.set_at = None;
70 }
71 }
72 self.message.as_deref()
73 }
74
75 pub fn peek(&self) -> Option<&str> {
79 self.message.as_deref()
80 }
81
82 pub fn has_message(&self) -> bool {
84 self.message.is_some()
85 }
86
87 pub fn as_option(&self) -> &Option<String> {
91 &self.message
92 }
93
94 pub fn take(&mut self) -> Option<String> {
96 self.set_at = None;
97 self.message.take()
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 use std::thread;
105
106 #[test]
107 fn test_status_message_set_clear() {
108 let mut status = StatusMessage::new();
109
110 assert!(!status.has_message());
111 assert!(status.peek().is_none());
112
113 status.set("Test message");
114 assert!(status.has_message());
115 assert_eq!(status.peek(), Some("Test message"));
116
117 status.clear();
118 assert!(!status.has_message());
119 assert!(status.peek().is_none());
120 }
121
122 #[test]
123 fn test_status_message_take() {
124 let mut status = StatusMessage::new();
125
126 status.set("Take me");
127 let taken = status.take();
128
129 assert_eq!(taken, Some("Take me".to_string()));
130 assert!(!status.has_message());
131 }
132
133 #[test]
134 fn test_status_message_auto_clear() {
135 let mut status = StatusMessage::with_auto_clear(Duration::from_millis(50));
136
137 status.set("Auto clear message");
138 assert!(status.message().is_some());
139
140 thread::sleep(Duration::from_millis(60));
142 assert!(status.message().is_none());
143 }
144
145 #[test]
146 fn test_status_message_no_auto_clear_default() {
147 let mut status = StatusMessage::new();
148
149 status.set("No auto clear");
150 thread::sleep(Duration::from_millis(10));
151 assert!(status.message().is_some()); }
153}