trivial enhancements to state management solution

This commit is contained in:
2025-12-24 16:25:48 +08:00
parent 83f145f490
commit 42f798c8b7
11 changed files with 400 additions and 178 deletions

View File

@@ -633,6 +633,15 @@ where
if let Err(e) = save_auth_pass(&auth_pass) {
error!("Failed to save auth pass: {}", e);
}
// Immediately refresh app data now that auth is available
tauri::async_runtime::spawn(async {
crate::state::init_app_data_scoped(
crate::state::AppDataRefreshScope::All,
)
.await;
});
on_success();
}
Err(e) => error!("Token exchange failed: {}", e),

View File

@@ -135,11 +135,8 @@ async fn init_cursor_tracking() -> Result<(), String> {
};
let mapped = absolute_to_normalized(&raw);
let positions = CursorPositions {
raw,
mapped,
};
let positions = CursorPositions { raw, mapped };
// Send to consumer channel (non-blocking)
if let Err(e) = tx.try_send(positions) {

View File

@@ -122,7 +122,7 @@ pub async fn open_doll_editor_window(doll_id: Option<String>) {
// macOS Specific: Focus Trap Listener ID
// We need to capture this to unlisten later.
let mut parent_focus_listener_id: Option<u32> = None;
if let Some(parent) = app_handle.get_webview_window(APP_MENU_WINDOW_LABEL) {

View File

@@ -7,7 +7,7 @@ use crate::{
get_app_handle, lock_r, lock_w,
models::app_config::AppConfig,
services::cursor::{normalized_to_absolute, CursorPosition, CursorPositions},
state::FDOLL,
state::{init_app_data_scoped, AppDataRefreshScope, FDOLL},
};
use serde::{Deserialize, Serialize};
@@ -59,7 +59,7 @@ fn on_initialized(payload: Payload, _socket: RawClient) {
Payload::Text(values) => {
if let Some(first_value) = values.first() {
info!("Received initialized event: {:?}", first_value);
// Mark WebSocket as initialized
let mut guard = lock_w!(FDOLL);
if let Some(clients) = guard.clients.as_mut() {
@@ -93,6 +93,11 @@ fn on_friend_request_accepted(payload: Payload, _socket: RawClient) {
if let Err(e) = get_app_handle().emit(WS_EVENT::FRIEND_REQUEST_ACCEPTED, str) {
error!("Failed to emit friend request accepted event: {:?}", e);
}
// Refresh friends list only (optimized - no need to fetch user profile)
tauri::async_runtime::spawn(async {
init_app_data_scoped(AppDataRefreshScope::Friends).await;
});
}
_ => error!("Received unexpected payload format for friend request accepted"),
}
@@ -117,6 +122,11 @@ fn on_unfriended(payload: Payload, _socket: RawClient) {
if let Err(e) = get_app_handle().emit(WS_EVENT::UNFRIENDED, str) {
error!("Failed to emit unfriended event: {:?}", e);
}
// Refresh friends list only (optimized - no need to fetch user profile)
tauri::async_runtime::spawn(async {
init_app_data_scoped(AppDataRefreshScope::Friends).await;
});
}
_ => error!("Received unexpected payload format for unfriended"),
}
@@ -232,6 +242,12 @@ fn on_friend_active_doll_changed(payload: Payload, _socket: RawClient) {
} else {
info!("Emitted friend-active-doll-changed to frontend");
}
// Refresh friends list only (optimized - friend's active doll is part of friends data)
// Deduplicate burst events inside init_app_data_scoped.
tauri::async_runtime::spawn(async {
init_app_data_scoped(AppDataRefreshScope::Friends).await;
});
} else {
info!("Received friend-active-doll-changed event with empty payload");
}
@@ -245,9 +261,11 @@ fn on_doll_created(payload: Payload, _socket: RawClient) {
Payload::Text(values) => {
if let Some(first_value) = values.first() {
info!("Received doll.created event: {:?}", first_value);
if let Err(e) = get_app_handle().emit(WS_EVENT::DOLL_CREATED, first_value) {
error!("Failed to emit doll.created event: {:?}", e);
}
// Refresh dolls list
tauri::async_runtime::spawn(async {
init_app_data_scoped(AppDataRefreshScope::Dolls).await;
});
} else {
info!("Received doll.created event with empty payload");
}
@@ -261,9 +279,31 @@ fn on_doll_updated(payload: Payload, _socket: RawClient) {
Payload::Text(values) => {
if let Some(first_value) = values.first() {
info!("Received doll.updated event: {:?}", first_value);
if let Err(e) = get_app_handle().emit(WS_EVENT::DOLL_UPDATED, first_value) {
error!("Failed to emit doll.updated event: {:?}", e);
}
// Try to extract doll ID to check if it's the active doll
let doll_id = first_value.get("id").and_then(|v| v.as_str());
let is_active_doll = if let Some(id) = doll_id {
let guard = lock_r!(FDOLL);
guard
.app_data
.user
.as_ref()
.and_then(|u| u.active_doll_id.as_ref())
.map(|active_id| active_id == id)
.unwrap_or(false)
} else {
false
};
// Refresh dolls + potentially User/Friends if active doll
tauri::async_runtime::spawn(async move {
init_app_data_scoped(AppDataRefreshScope::Dolls).await;
if is_active_doll {
init_app_data_scoped(AppDataRefreshScope::User).await;
init_app_data_scoped(AppDataRefreshScope::Friends).await;
}
});
} else {
info!("Received doll.updated event with empty payload");
}
@@ -277,9 +317,31 @@ fn on_doll_deleted(payload: Payload, _socket: RawClient) {
Payload::Text(values) => {
if let Some(first_value) = values.first() {
info!("Received doll.deleted event: {:?}", first_value);
if let Err(e) = get_app_handle().emit(WS_EVENT::DOLL_DELETED, first_value) {
error!("Failed to emit doll.deleted event: {:?}", e);
}
// Try to extract doll ID to check if it was the active doll
let doll_id = first_value.get("id").and_then(|v| v.as_str());
let is_active_doll = if let Some(id) = doll_id {
let guard = lock_r!(FDOLL);
guard
.app_data
.user
.as_ref()
.and_then(|u| u.active_doll_id.as_ref())
.map(|active_id| active_id == id)
.unwrap_or(false)
} else {
false
};
// Refresh dolls + User/Friends if the deleted doll was active
tauri::async_runtime::spawn(async move {
init_app_data_scoped(AppDataRefreshScope::Dolls).await;
if is_active_doll {
init_app_data_scoped(AppDataRefreshScope::User).await;
init_app_data_scoped(AppDataRefreshScope::Friends).await;
}
});
} else {
info!("Received doll.deleted event with empty payload");
}