This commit is contained in:
2026-04-02 16:51:28 +02:00
parent 945115527f
commit 9e14e41b36
15 changed files with 1740 additions and 492 deletions

200
src/rtc_state.rs Normal file
View File

@@ -0,0 +1,200 @@
// 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<String>,
pub peers: Vec<PeerInfo>,
pub logs: Vec<String>,
pub chat_messages: Vec<String>,
pub rtc_messages: Vec<String>,
pub rtc_status: String,
pub data_channel_open: bool,
pub active_remote_peer_id: Option<String>,
}
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<mpsc::UnboundedSender<RtcAction>>,
pub peer_connection: Option<Arc<RTCPeerConnection>>,
pub data_channel: Option<Arc<RTCDataChannel>>,
}
impl RtcRuntimeState {
pub fn new() -> Self {
Self {
signalling_tx: None,
peer_connection: None,
data_channel: None,
}
}
}
#[derive(Clone)]
pub struct RtcAppState {
pub ui: Arc<std::sync::Mutex<RtcUiState>>,
pub runtime: Arc<std::sync::Mutex<RtcRuntimeState>>,
}
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<RtcSnapshot, String> {
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<String>) {
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<PeerInfo>) {
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<String>) {
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;
}
}
}