//! 聊天相关命令 use tauri::{AppHandle, Emitter}; use crate::database::Database; use crate::models::{ChatMessage, event_names}; use crate::state::AppState; use crate::utils::{CommandError, CommandResult, HEARTBEAT_INTERVAL_MS}; use crate::websocket::{HeartbeatManager, WsClient, WsConnectionEvent, WsServer}; /// 启动 WebSocket 服务端 #[tauri::command] pub async fn start_websocket_server(app: AppHandle) -> CommandResult<()> { let state = AppState::get(); let local_device = state.local_device.read().clone(); // 创建并启动 WS 服务端 let mut server = WsServer::new( local_device.ws_port, local_device.device_id.clone(), state.connection_manager.clone(), ); server.start().await.map_err(|e| CommandError { code: "WS_SERVER_ERROR".to_string(), message: e.to_string(), })?; *state.ws_server.write() = Some(server); // 创建 WS 客户端 let client = WsClient::new( local_device.device_id.clone(), state.connection_manager.clone(), ); *state.ws_client.write() = Some(client); // 启动心跳管理 HeartbeatManager::start( state.connection_manager.clone(), local_device.device_id.clone(), HEARTBEAT_INTERVAL_MS, ); // 监听连接事件 let mut rx = state.connection_manager.subscribe(); let app_handle = app.clone(); tokio::spawn(async move { while let Ok(event) = rx.recv().await { match event { WsConnectionEvent::Connected { device_id } => { let _ = app_handle.emit(event_names::WEBSOCKET_CONNECTED, serde_json::json!({ "deviceId": device_id })); } WsConnectionEvent::Disconnected { device_id, reason } => { let _ = app_handle.emit(event_names::WEBSOCKET_DISCONNECTED, serde_json::json!({ "deviceId": device_id, "reason": reason })); } WsConnectionEvent::MessageReceived { message } => { let _ = app_handle.emit(event_names::MESSAGE_RECEIVED, &message); } } } }); log::info!("WebSocket server started on port {}", local_device.ws_port); Ok(()) } /// 停止 WebSocket 服务端 #[tauri::command] pub async fn stop_websocket_server() -> CommandResult<()> { let state = AppState::get(); // 关闭所有连接 state.connection_manager.close_all().await; // 停止服务端 if let Some(mut server) = state.ws_server.write().take() { server.stop(); } *state.ws_client.write() = None; log::info!("WebSocket server stopped"); Ok(()) } /// 连接到指定设备 #[tauri::command] pub async fn connect_to_peer(device_id: String) -> CommandResult<()> { let state = AppState::get(); // 获取设备信息 let device = state .device_manager .get_device(&device_id) .ok_or_else(|| CommandError { code: "DEVICE_NOT_FOUND".to_string(), message: format!("Device {} not found", device_id), })?; // 检查是否已连接 (同步检查,立即释放锁) { let client_guard = state.ws_client.read(); if let Some(client) = client_guard.as_ref() { if client.is_connected(&device_id) || state.connection_manager.is_connected(&device_id) { return Ok(()); } } else if state.connection_manager.is_connected(&device_id) { return Ok(()); } } // 克隆客户端引用以便异步使用 let ws_client = { let client_guard = state.ws_client.read(); client_guard.as_ref().cloned() }; let client = ws_client.ok_or_else(|| CommandError { code: "WS_NOT_STARTED".to_string(), message: "WebSocket client not started".to_string(), })?; client.connect(&device).await.map_err(|e| CommandError { code: "CONNECTION_ERROR".to_string(), message: e.to_string(), })?; // 更新设备在线状态 state.device_manager.set_device_online(&device_id, true); log::info!("Connected to device {}", device_id); Ok(()) } /// 断开与指定设备的连接 #[tauri::command] pub async fn disconnect_from_peer(device_id: String) -> CommandResult<()> { let state = AppState::get(); // 克隆客户端引用 let ws_client = { let client_guard = state.ws_client.read(); client_guard.as_ref().cloned() }; if let Some(client) = ws_client { client.disconnect(&device_id).await; } state.device_manager.set_device_online(&device_id, false); log::info!("Disconnected from device {}", device_id); Ok(()) } /// 发送聊天消息 #[tauri::command] pub async fn send_chat_message( device_id: String, content: String, message_type: Option, ) -> CommandResult { let state = AppState::get(); // 获取本地设备 ID (立即释放锁) let local_device_id = { let local_device = state.local_device.read(); local_device.device_id.clone() }; // 创建消息 let message = match message_type.as_deref() { Some("image") => ChatMessage::new_image( local_device_id, device_id.clone(), content, ), _ => ChatMessage::new_text( local_device_id, device_id.clone(), content, ), }; // 保存到数据库 Database::save_message(&message).map_err(|e| CommandError { code: "DB_ERROR".to_string(), message: e.to_string(), })?; // 获取客户端 (立即释放锁) let ws_client = { let client_guard = state.ws_client.read(); client_guard.as_ref().cloned() }; let mut sent = false; // 尝试通过客户端发送(主动连接的情况) if let Some(client) = &ws_client { if client.is_connected(&device_id) { client.send_to(&device_id, &message).await.map_err(|e| CommandError { code: "SEND_ERROR".to_string(), message: e, })?; sent = true; } } // 如果客户端没有发送,尝试通过服务端连接发送(被动连接的情况) if !sent { state .connection_manager .send_to(&device_id, &message) .await .map_err(|e| CommandError { code: "SEND_ERROR".to_string(), message: e, })?; } Ok(message) } /// 获取聊天历史 #[tauri::command] pub async fn get_chat_history( device_id: String, limit: Option, offset: Option, ) -> CommandResult> { let state = AppState::get(); let local_device = state.local_device.read(); let messages = Database::get_chat_history( &device_id, &local_device.device_id, limit.unwrap_or(50), offset.unwrap_or(0), ) .map_err(|e| CommandError { code: "DB_ERROR".to_string(), message: e.to_string(), })?; Ok(messages) } /// 删除聊天历史 #[tauri::command] pub async fn delete_chat_history(device_id: String) -> CommandResult { let state = AppState::get(); let local_device = state.local_device.read(); let count = Database::delete_chat_history(&device_id, &local_device.device_id) .map_err(|e| CommandError { code: "DB_ERROR".to_string(), message: e.to_string(), })?; Ok(count) }