1use crate::network::connection_state::SessionState::{LoggedIn, LoggedOut, LoginFailed};
13use crate::network::connection_state::{ConnectionState, SessionState};
14use crate::network::udp_client::MAX_CHANNEL;
15use crate::panels::terminal::TextFragment;
16use crate::panels::Tab;
17use common::logging::LogLevel;
18use common::logging::LogLevel::*;
19use common::networking::messages::{TcpClientMessage, TcpServerMessage};
20use common::networking::subscription_objects::{SubscribeTopic, TopicPayload};
21use common::r_log;
22use eframe::egui::Color32;
23use egui_dock::DockState;
24use std::fmt;
25use std::fmt::{Display, Formatter};
26use std::sync::mpsc::{Receiver, Sender};
27
28pub enum UiEvent {
33 SendTerminalCommand {
35 id: u32,
37 command: String,
39 },
40 LoginRequest {
42 password: String,
44 user_name: String,
46 user_role: common::networking::messages::UserRole,
48 },
49 SetConnectionState {
51 state: ConnectionState,
53 },
54 LogoutRequest,
56 DisconnectRequest,
58 SubscribeRequest {
60 topic: SubscribeTopic,
62 },
63}
64
65impl Display for UiEvent {
66 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
67 match self {
68 UiEvent::SendTerminalCommand { id, command } => {
69 write!(f, "SendTerminalCommand, id: {}, command: {}", id, command)
70 }
71 UiEvent::LoginRequest {
72 user_name,
73 password,
74 user_role,
75 } => write!(
76 f,
77 "LoginRequest, username: {},password: {}, role: {}",
78 user_name, password, user_role
79 ),
80 UiEvent::SetConnectionState { state } => write!(f, "SetConnectionState: {}", state),
81 UiEvent::LogoutRequest => write!(f, "LogoutRequest"),
82 UiEvent::DisconnectRequest => write!(f, "DisconnectRequest"),
83 UiEvent::SubscribeRequest { topic } => write!(f, "SubscribeRequest, topic: {}", topic),
84 }
85 }
86}
87
88pub(crate) fn handle_dmx_data(
95 dmx_receiver: &Receiver<(u8, [u8; MAX_CHANNEL])>,
96 tree: &mut DockState<Tab>,
97) {
98 while let Ok((universe_id, dmx_data)) = dmx_receiver.try_recv() {
99 for (_, tab) in tree.iter_all_tabs_mut() {
100 if let Tab::Universe(panel) = tab {
101 if panel.selected_universe - 1 == universe_id {
102 panel.dmx_data.copy_from_slice(&dmx_data);
103 }
104 }
105 }
106 }
107}
108
109pub fn send_ui_event(event: UiEvent) {
114 if let Ok(guard) = crate::UI_EVENT_SENDER.read() {
115 if let Some(sender) = guard.as_ref() {
116 let _ = sender.send(event);
117 }
118 }
119}
120
121fn process_terminal_command(
132 id: u32,
133 command: String,
134 tcp_sender: &Option<Sender<TcpClientMessage>>,
135 tree: &mut DockState<Tab>,
136) {
137 match command.as_str() {
138 "logout" => {
139 send_ui_event(UiEvent::LogoutRequest);
140 for (_, tab) in tree.iter_all_tabs_mut() {
141 if let Tab::Terminal(panel) = tab {
142 panel.add_fragments(vec![TextFragment {
143 text: "[SUCCESS] Logout successful, Terminal inactive!".to_string(),
144 color: log_level_to_color32(SuccessEvent),
145 }]);
146 };
147 }
148 }
149 _ => {
150 let msg = TcpClientMessage::ExecuteCommand {
151 response_id: id,
152 command,
153 };
154 if let Some(tcp_sender) = tcp_sender {
155 if let Err(e) = tcp_sender.send(msg) {
156 r_log!(Error, "Failed to send execute command: {}", e);
157 }
158 } else {
159 r_log!(
160 Error,
161 "Failed to send execute command: tcp sender doesn't exist"
162 );
163 }
164 }
165 }
166}
167
168pub fn log_level_to_color32(level: LogLevel) -> Color32 {
176 match level {
177 SuccessEvent => Color32::GREEN,
178 Info => Color32::BLUE,
179 Warning => Color32::YELLOW,
180 Error => Color32::RED,
181 UserError => Color32::GOLD,
182 UserSuccess => Color32::LIGHT_GREEN,
183 }
184}
185
186pub(crate) fn handle_incoming_network_data(
193 tcp_receiver: &mut Option<Receiver<TcpServerMessage>>,
194 tree: &mut DockState<Tab>,
195) {
196 if let Some(tcp_receiver) = tcp_receiver {
197 while let Ok(msg) = tcp_receiver.try_recv() {
198 match msg {
199 TcpServerMessage::CommandOutput {
200 answer,
201 response_id,
202 } => {
203 for (_, tab) in tree.iter_all_tabs_mut() {
204 if let Tab::Terminal(panel) = tab {
205 if panel.tab_id == response_id {
206 let (log_level, ref answer_string) = answer;
207 panel.add_fragments(vec![TextFragment {
208 text: format!("[{}]: {}", log_level, answer_string),
209 color: log_level_to_color32(log_level),
210 }]);
211 }
212 }
213 }
214 }
215 TcpServerMessage::LoginOk { token } => {
216 r_log!(UserSuccess, "Login Successful! Token: {}", token);
217 send_ui_event(UiEvent::SetConnectionState {
218 state: ConnectionState::Connected {
219 session_state: LoggedIn,
220 },
221 });
222 }
223 TcpServerMessage::LoginFailed { reason } => {
224 r_log!(UserError, "Login Failed: {}", reason);
225 send_ui_event(UiEvent::SetConnectionState {
226 state: ConnectionState::Connected {
227 session_state: LoginFailed(reason),
228 },
229 });
230 }
231 TcpServerMessage::LogoutOk => {
232 r_log!(UserSuccess, "Logout Successful");
233 send_ui_event(UiEvent::SetConnectionState {
234 state: ConnectionState::Connected {
235 session_state: LoggedOut,
236 },
237 });
238 }
239 TcpServerMessage::TopicUpdate { data } => match data {
240 TopicPayload::DMXConfiguration(dmx_config) => {
241 for (_, tab) in tree.iter_all_tabs_mut() {
242 if let Tab::Universe(panel) = tab {
243 panel.device_configuration = Some(dmx_config.clone());
244 }
245 }
246 }
247 },
248 TcpServerMessage::ShutdownAnnouncement => {
249 send_ui_event(UiEvent::SetConnectionState {
250 state: ConnectionState::Disconnected
251 });
252 },
253 TcpServerMessage::Unauthenticated => {
254 r_log!(UserError, "Server couldn't Unauthenticated");
255 }
256 TcpServerMessage::ReloginOk { .. } => {}
257 TcpServerMessage::ReloginFailed { .. } => {}
258 TcpServerMessage::Kicked { .. } => {}
259 TcpServerMessage::ImplicitCommandOutput { .. } => {}
260 TcpServerMessage::EditGranted { .. } => {}
261 TcpServerMessage::EditDenied { .. } => {}
262 TcpServerMessage::DropEditAck(_) => {}
263 }
264 }
265 }
266}
267
268pub(crate) fn handle_events(
279 ui_receiver: &Receiver<UiEvent>,
280 tcp_sender: &mut Option<Sender<TcpClientMessage>>,
281 connection_state: &mut ConnectionState,
282 tree: &mut DockState<Tab>,
283) {
284 while let Ok(event) = ui_receiver.try_recv() {
285 r_log!(Info, "UIEvent: {}" ,event);
286 match event {
287 UiEvent::SendTerminalCommand { id, command } => {
288 process_terminal_command(id, command, tcp_sender, tree);
289 }
290 UiEvent::LoginRequest {
291 password,
292 user_name,
293 user_role,
294 } => {
295 let msg = TcpClientMessage::Login {
296 password,
297 user_name,
298 user_role,
299 };
300 if let Some(tcp_sender) = tcp_sender {
301 if let Err(e) = tcp_sender.send(msg) {
302 r_log!(Error, "Failed to send login request: {}", e);
303 } else {
304 *connection_state = ConnectionState::Connected {
305 session_state: SessionState::LoginPending,
306 };
307 }
308 } else {
309 r_log!(
310 Error,
311 "Failed to send execute command: tcp sender doesn't exist"
312 );
313 }
314 }
315 UiEvent::SetConnectionState { state } => {
316 r_log!(Info, "New ConnectionState: {}", state);
317 for (_, tab) in tree.iter_all_tabs_mut() {
318 if state
319 == (ConnectionState::Connected {
320 session_state: LoggedIn,
321 })
322 {
323 tab.on_connect();
324 }
325 if let Tab::Terminal(panel) = tab {
326 panel.is_active = state
327 == (ConnectionState::Connected {
328 session_state: LoggedIn,
329 });
330 if state
331 == (ConnectionState::Connected {
332 session_state: LoggedIn,
333 })
334 {
335 panel.add_fragments(vec![TextFragment {
336 text: "[INFO] Logins successful, Terminal ready!".to_string(),
337 color: Color32::GREEN,
338 }]);
339 }
340 }
341 }
342 *connection_state = state;
343 }
344 UiEvent::LogoutRequest => {
345 let msg = TcpClientMessage::Logout;
346 if let Some(tcp_sender) = tcp_sender {
347 if let Err(e) = tcp_sender.send(msg) {
348 r_log!(Error, "Failed to send logout request: {}", e);
349 } else {
350 for (_, tab) in tree.iter_all_tabs_mut() {
351 if let Tab::Terminal(panel) = tab {
352 panel.is_active = false;
353 }
354 }
355 }
356 } else {
357 r_log!(
358 Error,
359 "Failed to send logout request: tcp sender doesn't exist"
360 );
361 }
362 }
363 UiEvent::DisconnectRequest => {
364 r_log!(Info, "Closing connection requested via UI");
365 *tcp_sender = None;
366 *connection_state = ConnectionState::Disconnected;
367 }
368 UiEvent::SubscribeRequest { topic } => {
369 let msg = TcpClientMessage::Subscribe {
370 topic: topic.clone(),
371 update_mode: common::networking::subscription_objects::UpdateMode::OnChange,
372 };
373 if let Some(tcp_sender) = tcp_sender {
374 if let Err(e) = tcp_sender.send(msg) {
375 r_log!(Error, "Failed to send subscribe request: {}", e);
376 }
377 }
378 }
379 }
380 }
381}