Improved tauri events type safety

This commit is contained in:
2026-03-07 14:48:19 +08:00
parent f372e86457
commit f65d837841
20 changed files with 215 additions and 141 deletions

View File

@@ -41,4 +41,4 @@ pub struct DollDto {
pub configuration: DollConfigurationDto,
pub created_at: String,
pub updated_at: String,
}
}

View File

@@ -0,0 +1,79 @@
use serde::{Deserialize, Serialize};
use ts_rs::TS;
use super::dolls::DollDto;
use super::friends::UserBasicDto;
use crate::services::presence_modules::models::PresenceStatus;
#[derive(Clone, Serialize, Deserialize, Debug, TS)]
#[serde(rename_all = "lowercase")]
#[ts(export)]
pub enum UserStatusState {
Idle,
Resting,
}
#[derive(Clone, Serialize, Deserialize, Debug, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct UserStatusPayload {
pub presence_status: PresenceStatus,
pub state: UserStatusState,
}
#[derive(Clone, Serialize, Deserialize, Debug, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct FriendUserStatusPayload {
pub user_id: String,
pub status: UserStatusPayload,
}
#[derive(Clone, Serialize, Deserialize, Debug, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct FriendDisconnectedPayload {
pub user_id: String,
}
#[derive(Clone, Serialize, Deserialize, Debug, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct FriendActiveDollChangedPayload {
pub friend_id: String,
pub doll: Option<DollDto>,
}
#[derive(Clone, Serialize, Deserialize, Debug, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct FriendRequestReceivedPayload {
pub id: String,
pub sender: UserBasicDto,
pub created_at: String,
}
#[derive(Clone, Serialize, Deserialize, Debug, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct FriendRequestAcceptedPayload {
pub id: String,
pub friend: UserBasicDto,
pub accepted_at: String,
}
#[derive(Clone, Serialize, Deserialize, Debug, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct FriendRequestDeniedPayload {
pub id: String,
pub denier: UserBasicDto,
pub denied_at: String,
}
#[derive(Clone, Serialize, Deserialize, Debug, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct UnfriendedPayload {
pub friend_id: String,
}

View File

@@ -25,4 +25,4 @@ pub enum HealthError {
NonOkStatus(String),
#[error("health response decode failed: {0}")]
Decode(reqwest::Error),
}
}

View File

@@ -1,7 +1,8 @@
pub mod app_data;
pub mod remote_error;
pub mod dolls;
pub mod event_payloads;
pub mod friends;
pub mod health;
pub mod interaction;
pub mod remote_error;
pub mod user;

View File

@@ -3,7 +3,8 @@ use std::{path::Path, thread, time::Duration};
use tokio::runtime::Runtime;
use tracing::{error, info, warn};
use crate::services::ws::user_status::{report_user_status, UserStatusPayload};
use crate::models::event_payloads::{UserStatusPayload, UserStatusState};
use crate::services::ws::user_status::report_user_status;
use crate::services::ws::{ws_emit_soft, WS_EVENT};
use super::models::PresenceStatus;
@@ -45,7 +46,7 @@ impl UserData for Engine {
async fn update_status(status: PresenceStatus) {
let user_status = UserStatusPayload {
presence_status: status,
state: String::from("idle"),
state: UserStatusState::Idle,
};
report_user_status(user_status).await;
}
@@ -53,7 +54,7 @@ async fn update_status(status: PresenceStatus) {
async fn update_status_async(status: PresenceStatus) {
let payload = UserStatusPayload {
presence_status: status,
state: String::from("idle"),
state: UserStatusState::Idle,
};
if let Err(e) = ws_emit_soft(WS_EVENT::CLIENT_REPORT_USER_STATUS, payload).await {
warn!("User status report failed: {}", e);

View File

@@ -1,6 +1,11 @@
use rust_socketio::{Payload, RawClient};
use tracing::info;
use crate::models::event_payloads::{
FriendActiveDollChangedPayload, FriendDisconnectedPayload, FriendRequestAcceptedPayload,
FriendRequestDeniedPayload, FriendRequestReceivedPayload, FriendUserStatusPayload,
UnfriendedPayload,
};
use crate::services::app_events::AppEvents;
use crate::services::cursor::{normalized_to_absolute, CursorPositions};
use crate::state::AppDataRefreshScope;
@@ -13,30 +18,36 @@ use super::{
/// Handler for friend-request-received event
pub fn on_friend_request_received(payload: Payload, _socket: RawClient) {
if let Ok(value) = utils::extract_text_value(payload, "friend-request-received") {
emitter::emit_to_frontend(AppEvents::FriendRequestReceived.as_str(), value);
if let Ok(data) =
utils::extract_and_parse::<FriendRequestReceivedPayload>(payload, "friend-request-received")
{
emitter::emit_to_frontend(AppEvents::FriendRequestReceived.as_str(), data);
}
}
/// Handler for friend-request-accepted event
pub fn on_friend_request_accepted(payload: Payload, _socket: RawClient) {
if let Ok(value) = utils::extract_text_value(payload, "friend-request-accepted") {
emitter::emit_to_frontend(AppEvents::FriendRequestAccepted.as_str(), value);
if let Ok(data) =
utils::extract_and_parse::<FriendRequestAcceptedPayload>(payload, "friend-request-accepted")
{
emitter::emit_to_frontend(AppEvents::FriendRequestAccepted.as_str(), data);
refresh::refresh_app_data(AppDataRefreshScope::Friends);
}
}
/// Handler for friend-request-denied event
pub fn on_friend_request_denied(payload: Payload, _socket: RawClient) {
if let Ok(value) = utils::extract_text_value(payload, "friend-request-denied") {
emitter::emit_to_frontend(AppEvents::FriendRequestDenied.as_str(), value);
if let Ok(data) =
utils::extract_and_parse::<FriendRequestDeniedPayload>(payload, "friend-request-denied")
{
emitter::emit_to_frontend(AppEvents::FriendRequestDenied.as_str(), data);
}
}
/// Handler for unfriended event
pub fn on_unfriended(payload: Payload, _socket: RawClient) {
if let Ok(value) = utils::extract_text_value(payload, "unfriended") {
emitter::emit_to_frontend(AppEvents::Unfriended.as_str(), value);
if let Ok(data) = utils::extract_and_parse::<UnfriendedPayload>(payload, "unfriended") {
emitter::emit_to_frontend(AppEvents::Unfriended.as_str(), data);
refresh::refresh_app_data(AppDataRefreshScope::Friends);
}
}
@@ -63,8 +74,10 @@ pub fn on_friend_cursor_position(payload: Payload, _socket: RawClient) {
/// Handler for friend-disconnected event
pub fn on_friend_disconnected(payload: Payload, _socket: RawClient) {
if let Ok(value) = utils::extract_text_value(payload, "friend-disconnected") {
emitter::emit_to_frontend(AppEvents::FriendDisconnected.as_str(), value);
if let Ok(data) =
utils::extract_and_parse::<FriendDisconnectedPayload>(payload, "friend-disconnected")
{
emitter::emit_to_frontend(AppEvents::FriendDisconnected.as_str(), data);
}
}
@@ -93,15 +106,20 @@ fn handle_friend_doll_change(event_name: &str, payload: Payload) {
/// Handler for friend-active-doll-changed event
pub fn on_friend_active_doll_changed(payload: Payload, _socket: RawClient) {
if let Ok(value) = utils::extract_text_value(payload, "friend-active-doll-changed") {
emitter::emit_to_frontend(AppEvents::FriendActiveDollChanged.as_str(), value);
if let Ok(data) = utils::extract_and_parse::<FriendActiveDollChangedPayload>(
payload,
"friend-active-doll-changed",
) {
emitter::emit_to_frontend(AppEvents::FriendActiveDollChanged.as_str(), data);
refresh::refresh_app_data(AppDataRefreshScope::Friends);
}
}
/// Handler for friend-user-status event
pub fn on_friend_user_status(payload: Payload, _socket: RawClient) {
if let Ok(value) = utils::extract_text_value(payload, "friend-user-status") {
emitter::emit_to_frontend(AppEvents::FriendUserStatus.as_str(), value);
if let Ok(data) =
utils::extract_and_parse::<FriendUserStatusPayload>(payload, "friend-user-status")
{
emitter::emit_to_frontend(AppEvents::FriendUserStatus.as_str(), data);
}
}

View File

@@ -1,24 +1,15 @@
use once_cell::sync::Lazy;
use serde::Serialize;
use tauri::async_runtime::{self, JoinHandle};
use tokio::sync::Mutex;
use tokio::time::Duration;
use tracing::warn;
use crate::services::presence_modules::models::PresenceStatus;
use crate::models::event_payloads::UserStatusPayload;
use crate::services::app_events::AppEvents;
use super::{emitter, types::WS_EVENT};
/// User status payload sent to WebSocket server
#[derive(Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UserStatusPayload {
pub presence_status: PresenceStatus,
pub state: String,
}
/// Debouncer for user status reports
static USER_STATUS_REPORT_DEBOUNCE: Lazy<Mutex<Option<JoinHandle<()>>>> =
Lazy::new(|| Mutex::new(None));