// file: src/rtc_state.rs use crate::rtc_types::{PeerInfo, RtcAction, RtcSnapshot}; use std::sync::Arc; use tokio::sync::mpsc; use webrtc::data_channel::RTCDataChannel; use webrtc::peer_connection::RTCPeerConnection; #[derive(Debug)] pub struct RtcUiState { pub signalling_connected: bool, pub server_url: String, pub display_name: String, pub my_peer_id: Option, pub peers: Vec, pub logs: Vec, pub chat_messages: Vec, pub rtc_messages: Vec, pub rtc_status: String, pub data_channel_open: bool, pub active_remote_peer_id: Option, } impl RtcUiState { pub fn new() -> Self { Self { signalling_connected: false, server_url: String::new(), display_name: String::new(), my_peer_id: None, peers: Vec::new(), logs: vec!["Ready.".to_string()], chat_messages: vec!["No messages yet.".to_string()], rtc_messages: vec!["No RTC messages yet.".to_string()], rtc_status: "Idle.".to_string(), data_channel_open: false, active_remote_peer_id: None, } } pub fn snapshot(&self) -> RtcSnapshot { RtcSnapshot { signalling_connected: self.signalling_connected, server_url: self.server_url.clone(), display_name: self.display_name.clone(), my_peer_id: self.my_peer_id.clone(), peers: self.peers.clone(), logs: self.logs.clone(), chat_messages: self.chat_messages.clone(), rtc_messages: self.rtc_messages.clone(), rtc_status: self.rtc_status.clone(), data_channel_open: self.data_channel_open, active_remote_peer_id: self.active_remote_peer_id.clone(), } } } pub struct RtcRuntimeState { pub signalling_tx: Option>, pub peer_connection: Option>, pub data_channel: Option>, } impl RtcRuntimeState { pub fn new() -> Self { Self { signalling_tx: None, peer_connection: None, data_channel: None, } } } #[derive(Clone)] pub struct RtcAppState { pub ui: Arc>, pub runtime: Arc>, } impl RtcAppState { pub fn new() -> Self { Self { ui: Arc::new(std::sync::Mutex::new(RtcUiState::new())), runtime: Arc::new(std::sync::Mutex::new(RtcRuntimeState::new())), } } pub fn snapshot(&self) -> Result { let lock_result = self.ui.lock(); match lock_result { Ok(guard) => Ok(guard.snapshot()), Err(_) => Err("rtc ui state lock poisoned".to_string()), } } pub fn push_log(&self, line: String) { let lock_result = self.ui.lock(); if let Ok(mut guard) = lock_result { guard.logs.push(line); if guard.logs.len() > 200 { let drain_len = guard.logs.len().saturating_sub(200); guard.logs.drain(0..drain_len); } } } pub fn push_chat_message(&self, line: String) { let lock_result = self.ui.lock(); if let Ok(mut guard) = lock_result { if guard.chat_messages.len() == 1 && guard.chat_messages[0] == "No messages yet." { guard.chat_messages.clear(); } guard.chat_messages.push(line); if guard.chat_messages.len() > 200 { let drain_len = guard.chat_messages.len().saturating_sub(200); guard.chat_messages.drain(0..drain_len); } } } pub fn push_rtc_message(&self, line: String) { let lock_result = self.ui.lock(); if let Ok(mut guard) = lock_result { if guard.rtc_messages.len() == 1 && guard.rtc_messages[0] == "No RTC messages yet." { guard.rtc_messages.clear(); } guard.rtc_messages.push(line); if guard.rtc_messages.len() > 200 { let drain_len = guard.rtc_messages.len().saturating_sub(200); guard.rtc_messages.drain(0..drain_len); } } } pub fn set_signalling_connected(&self, connected: bool) { let lock_result = self.ui.lock(); if let Ok(mut guard) = lock_result { guard.signalling_connected = connected; } } pub fn set_server_info(&self, server_url: String, display_name: String) { let lock_result = self.ui.lock(); if let Ok(mut guard) = lock_result { guard.server_url = server_url; guard.display_name = display_name; } } pub fn set_my_peer_id(&self, peer_id: Option) { let lock_result = self.ui.lock(); if let Ok(mut guard) = lock_result { guard.my_peer_id = peer_id; } } pub fn set_peers(&self, peers: Vec) { let lock_result = self.ui.lock(); if let Ok(mut guard) = lock_result { guard.peers = peers; } } pub fn set_rtc_status(&self, status: String) { let lock_result = self.ui.lock(); if let Ok(mut guard) = lock_result { guard.rtc_status = status; } } pub fn set_data_channel_open(&self, open: bool) { let lock_result = self.ui.lock(); if let Ok(mut guard) = lock_result { guard.data_channel_open = open; } } pub fn set_active_remote_peer_id(&self, peer_id: Option) { let lock_result = self.ui.lock(); if let Ok(mut guard) = lock_result { guard.active_remote_peer_id = peer_id; } } pub fn clear_after_disconnect(&self) { let lock_result = self.ui.lock(); if let Ok(mut guard) = lock_result { guard.signalling_connected = false; guard.my_peer_id = None; guard.peers.clear(); guard.rtc_status = "Idle.".to_string(); guard.data_channel_open = false; guard.active_remote_peer_id = None; } } }