182 lines
5.7 KiB
Rust
182 lines
5.7 KiB
Rust
use rust_socketio::{ClientBuilder, Payload, RawClient};
|
|
use serde_json::json;
|
|
use tauri::{async_runtime, Emitter};
|
|
use tracing::{error, info};
|
|
|
|
use crate::{
|
|
get_app_handle, lock_r, lock_w, models::app_config::AppConfig,
|
|
services::cursor::CursorPosition, state::FDOLL,
|
|
};
|
|
|
|
#[allow(non_camel_case_types)] // pretend to be a const like in js
|
|
pub struct WS_EVENT;
|
|
|
|
impl WS_EVENT {
|
|
pub const CURSOR_REPORT_POSITION: &str = "cursor-report-position";
|
|
pub const FRIEND_REQUEST_RECEIVED: &str = "friend-request-received";
|
|
pub const FRIEND_REQUEST_ACCEPTED: &str = "friend-request-accepted";
|
|
pub const FRIEND_REQUEST_DENIED: &str = "friend-request-denied";
|
|
pub const UNFRIENDED: &str = "unfriended";
|
|
pub const FRIEND_CURSOR_POSITION: &str = "friend-cursor-position";
|
|
pub const FRIEND_DISCONNECTED: &str = "friend-disconnected";
|
|
}
|
|
|
|
fn on_friend_request_received(payload: Payload, _socket: RawClient) {
|
|
match payload {
|
|
Payload::Text(str) => {
|
|
println!("Received friend request: {:?}", str);
|
|
get_app_handle()
|
|
.emit(WS_EVENT::FRIEND_REQUEST_RECEIVED, str)
|
|
.unwrap();
|
|
}
|
|
_ => error!("Received unexpected payload format for friend request received"),
|
|
}
|
|
}
|
|
|
|
fn on_friend_request_accepted(payload: Payload, _socket: RawClient) {
|
|
match payload {
|
|
Payload::Text(str) => {
|
|
println!("Received friend request accepted: {:?}", str);
|
|
get_app_handle()
|
|
.emit(WS_EVENT::FRIEND_REQUEST_ACCEPTED, str)
|
|
.unwrap();
|
|
}
|
|
_ => error!("Received unexpected payload format for friend request accepted"),
|
|
}
|
|
}
|
|
|
|
fn on_friend_request_denied(payload: Payload, _socket: RawClient) {
|
|
match payload {
|
|
Payload::Text(str) => {
|
|
println!("Received friend request denied: {:?}", str);
|
|
get_app_handle()
|
|
.emit(WS_EVENT::FRIEND_REQUEST_DENIED, str)
|
|
.unwrap();
|
|
}
|
|
_ => error!("Received unexpected payload format for friend request denied"),
|
|
}
|
|
}
|
|
|
|
fn on_unfriended(payload: Payload, _socket: RawClient) {
|
|
match payload {
|
|
Payload::Text(str) => {
|
|
println!("Received unfriended: {:?}", str);
|
|
get_app_handle().emit(WS_EVENT::UNFRIENDED, str).unwrap();
|
|
}
|
|
_ => error!("Received unexpected payload format for unfriended"),
|
|
}
|
|
}
|
|
|
|
fn on_friend_cursor_position(payload: Payload, _socket: RawClient) {
|
|
match payload {
|
|
Payload::Text(str) => {
|
|
get_app_handle()
|
|
.emit(WS_EVENT::FRIEND_CURSOR_POSITION, str)
|
|
.unwrap();
|
|
}
|
|
_ => error!("Received unexpected payload format for friend cursor position"),
|
|
}
|
|
}
|
|
|
|
fn on_friend_disconnected(payload: Payload, _socket: RawClient) {
|
|
match payload {
|
|
Payload::Text(str) => {
|
|
println!("Received friend disconnected: {:?}", str);
|
|
get_app_handle()
|
|
.emit(WS_EVENT::FRIEND_DISCONNECTED, str)
|
|
.unwrap();
|
|
}
|
|
_ => error!("Received unexpected payload format for friend disconnected"),
|
|
}
|
|
}
|
|
|
|
pub async fn report_cursor_data(cursor_position: CursorPosition) {
|
|
let client = {
|
|
let guard = lock_r!(FDOLL);
|
|
guard
|
|
.clients
|
|
.as_ref()
|
|
.expect("Clients are initialized")
|
|
.ws_client
|
|
.as_ref()
|
|
.expect("WebSocket client is initialized")
|
|
.clone()
|
|
};
|
|
|
|
match async_runtime::spawn_blocking(move || {
|
|
client.emit(
|
|
WS_EVENT::CURSOR_REPORT_POSITION,
|
|
Payload::Text(vec![json!(cursor_position)]),
|
|
)
|
|
})
|
|
.await
|
|
{
|
|
Ok(Ok(_)) => (),
|
|
Ok(Err(e)) => error!("Failed to emit ping: {}", e),
|
|
Err(e) => error!("Failed to execute blocking task: {}", e),
|
|
}
|
|
}
|
|
|
|
pub async fn init_ws_client() {
|
|
let app_config = {
|
|
let guard = lock_r!(FDOLL);
|
|
guard.app_config.clone()
|
|
};
|
|
|
|
let ws_client = build_ws_client(&app_config).await;
|
|
|
|
let mut guard = lock_w!(FDOLL);
|
|
if let Some(clients) = guard.clients.as_mut() {
|
|
clients.ws_client = Some(ws_client);
|
|
}
|
|
info!("WebSocket client initialized after authentication");
|
|
}
|
|
|
|
pub async fn build_ws_client(app_config: &AppConfig) -> rust_socketio::client::Client {
|
|
let token = crate::services::auth::get_access_token()
|
|
.await
|
|
.expect("No access token available for WebSocket connection");
|
|
|
|
info!("Building WebSocket client with authentication");
|
|
|
|
let api_base_url = app_config
|
|
.api_base_url
|
|
.clone()
|
|
.expect("Missing API base URL");
|
|
|
|
let client = async_runtime::spawn_blocking(move || {
|
|
ClientBuilder::new(api_base_url)
|
|
.namespace("/")
|
|
.on(
|
|
WS_EVENT::FRIEND_REQUEST_RECEIVED,
|
|
on_friend_request_received,
|
|
)
|
|
.on(
|
|
WS_EVENT::FRIEND_REQUEST_ACCEPTED,
|
|
on_friend_request_accepted,
|
|
)
|
|
.on(WS_EVENT::FRIEND_REQUEST_DENIED, on_friend_request_denied)
|
|
.on(WS_EVENT::UNFRIENDED, on_unfriended)
|
|
.on(WS_EVENT::FRIEND_CURSOR_POSITION, on_friend_cursor_position)
|
|
.on(WS_EVENT::FRIEND_DISCONNECTED, on_friend_disconnected)
|
|
.auth(json!({ "token": token }))
|
|
.connect()
|
|
})
|
|
.await
|
|
.expect("Failed to spawn blocking task");
|
|
|
|
match client {
|
|
Ok(c) => {
|
|
info!("WebSocket client connected successfully");
|
|
c
|
|
}
|
|
Err(e) => {
|
|
error!("Failed to connect WebSocket: {:?}", e);
|
|
panic!(
|
|
"TODO: better error handling for WebSocket connection - {}",
|
|
e
|
|
);
|
|
}
|
|
}
|
|
}
|