consolidation & handling of data from backend pt 2
This commit is contained in:
@@ -1,34 +1,34 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug, Type)]
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug, Type, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DollColorSchemeDto {
|
||||
pub outline: String,
|
||||
pub body: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug, Type)]
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug, Type, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DollConfigurationDto {
|
||||
pub color_scheme: DollColorSchemeDto,
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug, Type)]
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug, Type, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CreateDollDto {
|
||||
pub name: String,
|
||||
pub configuration: Option<DollConfigurationDto>,
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug, Type)]
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug, Type, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UpdateDollDto {
|
||||
pub name: Option<String>,
|
||||
pub configuration: Option<DollConfigurationDto>,
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug, Type)]
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug, Type, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DollDto {
|
||||
pub id: String,
|
||||
|
||||
@@ -5,14 +5,14 @@ use super::dolls::DollDto;
|
||||
use super::friends::UserBasicDto;
|
||||
use crate::services::presence_modules::models::PresenceStatus;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, Type)]
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, Type, PartialEq, Eq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum UserStatusState {
|
||||
Idle,
|
||||
Resting,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, Type)]
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, Type, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UserStatusPayload {
|
||||
pub presence_status: PresenceStatus,
|
||||
|
||||
@@ -15,14 +15,14 @@ use crate::{
|
||||
};
|
||||
use tauri_specta::Event as _;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Type)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Type, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CursorPosition {
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Type)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Type, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CursorPositions {
|
||||
pub raw: CursorPosition,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Type)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Type, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PresenceStatus {
|
||||
pub title: Option<String>,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use crate::{
|
||||
get_app_handle, lock_r, lock_w, models::event_payloads::UserStatusPayload,
|
||||
services::app_events::PresenceStateUpdated, state::FDOLL,
|
||||
get_app_handle, lock_r, lock_w,
|
||||
models::event_payloads::UserStatusPayload,
|
||||
services::app_events::PresenceStateUpdated,
|
||||
state::{get_known_friend_ids, FDOLL},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
@@ -22,44 +24,44 @@ pub fn get_presence_state_snapshot() -> PresenceStateSnapshot {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_current_presence(status: UserStatusPayload) {
|
||||
pub fn set_current_presence(status: UserStatusPayload) -> bool {
|
||||
let mut guard = lock_w!(FDOLL);
|
||||
|
||||
if guard.presence.current.as_ref() == Some(&status) {
|
||||
return false;
|
||||
}
|
||||
|
||||
guard.presence.current = Some(status);
|
||||
true
|
||||
}
|
||||
|
||||
pub fn set_friend_presence(friend_id: String, status: UserStatusPayload) {
|
||||
pub fn set_friend_presence(friend_id: String, status: UserStatusPayload) -> bool {
|
||||
let mut guard = lock_w!(FDOLL);
|
||||
|
||||
if guard.presence.friends.get(&friend_id) == Some(&status) {
|
||||
return false;
|
||||
}
|
||||
|
||||
guard.presence.friends.insert(friend_id, status);
|
||||
true
|
||||
}
|
||||
|
||||
pub fn remove_friend_presence(friend_id: &str) {
|
||||
pub fn remove_friend_presence(friend_id: &str) -> bool {
|
||||
let mut guard = lock_w!(FDOLL);
|
||||
guard.presence.friends.remove(friend_id);
|
||||
guard.presence.friends.remove(friend_id).is_some()
|
||||
}
|
||||
|
||||
pub fn clear_missing_friends_from_presence_state() {
|
||||
let friend_ids = {
|
||||
let guard = lock_r!(FDOLL);
|
||||
guard
|
||||
.user_data
|
||||
.friends
|
||||
.as_ref()
|
||||
.map(|friends| {
|
||||
friends
|
||||
.iter()
|
||||
.filter_map(|friendship| {
|
||||
friendship.friend.as_ref().map(|friend| friend.id.clone())
|
||||
})
|
||||
.collect::<std::collections::HashSet<_>>()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
};
|
||||
pub fn clear_missing_friends_from_presence_state() -> bool {
|
||||
let friend_ids = get_known_friend_ids();
|
||||
|
||||
let mut guard = lock_w!(FDOLL);
|
||||
let initial_count = guard.presence.friends.len();
|
||||
guard
|
||||
.presence
|
||||
.friends
|
||||
.retain(|friend_id, _| friend_ids.contains(friend_id));
|
||||
|
||||
guard.presence.friends.len() != initial_count
|
||||
}
|
||||
|
||||
pub fn emit_presence_state_updated() {
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::{
|
||||
get_app_handle, lock_r, lock_w,
|
||||
models::{dolls::DollDto, scene::SceneFriendNeko},
|
||||
services::{app_events::SceneFriendsUpdated, cursor::CursorPositions},
|
||||
state::FDOLL,
|
||||
state::{get_known_friend_ids, FDOLL},
|
||||
};
|
||||
use tauri_specta::Event as _;
|
||||
use tracing::error;
|
||||
@@ -34,44 +34,49 @@ pub fn get_scene_friends_snapshot() -> Vec<SceneFriendNeko> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn set_friend_cursor_position(friend_id: String, position: CursorPositions) {
|
||||
pub fn set_friend_cursor_position(friend_id: String, position: CursorPositions) -> bool {
|
||||
let mut guard = lock_w!(FDOLL);
|
||||
|
||||
if guard.friend_scene.cursor_positions.get(&friend_id) == Some(&position) {
|
||||
return false;
|
||||
}
|
||||
|
||||
guard
|
||||
.friend_scene
|
||||
.cursor_positions
|
||||
.insert(friend_id, position);
|
||||
true
|
||||
}
|
||||
|
||||
pub fn set_friend_active_doll(friend_id: String, doll: Option<DollDto>) {
|
||||
pub fn set_friend_active_doll(friend_id: String, doll: Option<DollDto>) -> bool {
|
||||
let mut guard = lock_w!(FDOLL);
|
||||
|
||||
if guard.friend_scene.active_dolls.get(&friend_id) == Some(&doll) {
|
||||
return false;
|
||||
}
|
||||
|
||||
guard.friend_scene.active_dolls.insert(friend_id, doll);
|
||||
true
|
||||
}
|
||||
|
||||
pub fn remove_friend(friend_id: &str) {
|
||||
pub fn remove_friend(friend_id: &str) -> bool {
|
||||
let mut guard = lock_w!(FDOLL);
|
||||
guard.friend_scene.cursor_positions.remove(friend_id);
|
||||
guard.friend_scene.active_dolls.remove(friend_id);
|
||||
let removed_cursor = guard
|
||||
.friend_scene
|
||||
.cursor_positions
|
||||
.remove(friend_id)
|
||||
.is_some();
|
||||
let removed_doll = guard.friend_scene.active_dolls.remove(friend_id).is_some();
|
||||
|
||||
removed_cursor || removed_doll
|
||||
}
|
||||
|
||||
pub fn clear_missing_friends_from_runtime_state() {
|
||||
let friend_ids = {
|
||||
let guard = lock_r!(FDOLL);
|
||||
guard
|
||||
.user_data
|
||||
.friends
|
||||
.as_ref()
|
||||
.map(|friends| {
|
||||
friends
|
||||
.iter()
|
||||
.filter_map(|friendship| {
|
||||
friendship.friend.as_ref().map(|friend| friend.id.clone())
|
||||
})
|
||||
.collect::<std::collections::HashSet<_>>()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
};
|
||||
pub fn clear_missing_friends_from_runtime_state() -> bool {
|
||||
let friend_ids = get_known_friend_ids();
|
||||
|
||||
let mut guard = lock_w!(FDOLL);
|
||||
let initial_cursor_count = guard.friend_scene.cursor_positions.len();
|
||||
let initial_active_doll_count = guard.friend_scene.active_dolls.len();
|
||||
guard
|
||||
.friend_scene
|
||||
.cursor_positions
|
||||
@@ -80,6 +85,9 @@ pub fn clear_missing_friends_from_runtime_state() {
|
||||
.friend_scene
|
||||
.active_dolls
|
||||
.retain(|friend_id, _| friend_ids.contains(friend_id));
|
||||
|
||||
guard.friend_scene.cursor_positions.len() != initial_cursor_count
|
||||
|| guard.friend_scene.active_dolls.len() != initial_active_doll_count
|
||||
}
|
||||
|
||||
pub fn emit_scene_friends_updated() {
|
||||
|
||||
@@ -75,13 +75,15 @@ pub fn on_friend_cursor_position(payload: Payload, _socket: RawClient) {
|
||||
},
|
||||
};
|
||||
|
||||
scene_friends::set_friend_cursor_position(
|
||||
let scene_friends_changed = scene_friends::set_friend_cursor_position(
|
||||
outgoing_payload.user_id.clone(),
|
||||
outgoing_payload.position.clone(),
|
||||
);
|
||||
|
||||
emitter::emit_to_frontend_typed(&FriendCursorPositionUpdated(outgoing_payload));
|
||||
scene_friends::emit_scene_friends_updated();
|
||||
if scene_friends_changed {
|
||||
scene_friends::emit_scene_friends_updated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,11 +92,15 @@ pub fn on_friend_disconnected(payload: Payload, _socket: RawClient) {
|
||||
if let Ok(data) =
|
||||
utils::extract_and_parse::<FriendDisconnectedPayload>(payload, "friend-disconnected")
|
||||
{
|
||||
scene_friends::remove_friend(&data.user_id);
|
||||
presence_state::remove_friend_presence(&data.user_id);
|
||||
let scene_friends_changed = scene_friends::remove_friend(&data.user_id);
|
||||
let presence_changed = presence_state::remove_friend_presence(&data.user_id);
|
||||
emitter::emit_to_frontend_typed(&FriendDisconnected(data));
|
||||
scene_friends::emit_scene_friends_updated();
|
||||
presence_state::emit_presence_state_updated();
|
||||
if scene_friends_changed {
|
||||
scene_friends::emit_scene_friends_updated();
|
||||
}
|
||||
if presence_changed {
|
||||
presence_state::emit_presence_state_updated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +135,6 @@ pub fn on_friend_active_doll_changed(payload: Payload, _socket: RawClient) {
|
||||
) {
|
||||
scene_friends::set_friend_active_doll(data.friend_id.clone(), data.doll.clone());
|
||||
emitter::emit_to_frontend_typed(&FriendActiveDollChanged(data));
|
||||
scene_friends::emit_scene_friends_updated();
|
||||
refresh::refresh_app_data(AppDataRefreshScope::Friends);
|
||||
}
|
||||
}
|
||||
@@ -139,8 +144,11 @@ pub fn on_friend_user_status(payload: Payload, _socket: RawClient) {
|
||||
if let Ok(data) =
|
||||
utils::extract_and_parse::<FriendUserStatusPayload>(payload, "friend-user-status")
|
||||
{
|
||||
presence_state::set_friend_presence(data.user_id.clone(), data.status.clone());
|
||||
let presence_changed =
|
||||
presence_state::set_friend_presence(data.user_id.clone(), data.status.clone());
|
||||
emitter::emit_to_frontend_typed(&FriendUserStatusChanged(data));
|
||||
presence_state::emit_presence_state_updated();
|
||||
if presence_changed {
|
||||
presence_state::emit_presence_state_updated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,9 @@ pub async fn report_user_status(status: UserStatusPayload) {
|
||||
warn!("Failed to emit user-status-changed event: {e}");
|
||||
}
|
||||
|
||||
presence_state::set_current_presence(status.clone());
|
||||
presence_state::emit_presence_state_updated();
|
||||
if presence_state::set_current_presence(status.clone()) {
|
||||
presence_state::emit_presence_state_updated();
|
||||
}
|
||||
|
||||
// Schedule new report after 500ms
|
||||
let handle = async_runtime::spawn(async move {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// in app-core/src/state.rs
|
||||
use crate::{
|
||||
lock_r,
|
||||
lock_w,
|
||||
models::{app_data::UserData, dolls::DollDto},
|
||||
services::{
|
||||
@@ -7,7 +8,7 @@ use crate::{
|
||||
presence_modules::models::ModuleMetadata,
|
||||
},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::{Arc, LazyLock, RwLock};
|
||||
use tauri::tray::TrayIcon;
|
||||
use tracing::info;
|
||||
@@ -55,6 +56,22 @@ pub struct AppState {
|
||||
pub static FDOLL: LazyLock<Arc<RwLock<AppState>>> =
|
||||
LazyLock::new(|| Arc::new(RwLock::new(AppState::default())));
|
||||
|
||||
pub fn get_known_friend_ids() -> HashSet<String> {
|
||||
let guard = lock_r!(FDOLL);
|
||||
|
||||
guard
|
||||
.user_data
|
||||
.friends
|
||||
.as_ref()
|
||||
.map(|friends| {
|
||||
friends
|
||||
.iter()
|
||||
.filter_map(|friendship| friendship.friend.as_ref().map(|friend| friend.id.clone()))
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Populate app state with initial
|
||||
/// values and necesary client instances.
|
||||
pub fn init_app_state() {
|
||||
|
||||
@@ -211,8 +211,14 @@ pub async fn init_app_data_scoped(scope: AppDataRefreshScope) {
|
||||
let app_data_clone = guard.user_data.clone();
|
||||
drop(guard); // Drop lock before emitting to prevent potential deadlocks
|
||||
|
||||
scene_friends::clear_missing_friends_from_runtime_state();
|
||||
presence_state::clear_missing_friends_from_presence_state();
|
||||
let refreshes_friend_runtime = matches!(
|
||||
scope,
|
||||
AppDataRefreshScope::All | AppDataRefreshScope::Friends
|
||||
);
|
||||
if refreshes_friend_runtime {
|
||||
scene_friends::clear_missing_friends_from_runtime_state();
|
||||
presence_state::clear_missing_friends_from_presence_state();
|
||||
}
|
||||
|
||||
if let Err(e) = AppDataRefreshed(app_data_clone).emit(get_app_handle()) {
|
||||
warn!("Failed to emit app-data-refreshed event: {}", e);
|
||||
@@ -229,8 +235,12 @@ pub async fn init_app_data_scoped(scope: AppDataRefreshScope) {
|
||||
.show(|_| {});
|
||||
}
|
||||
|
||||
scene_friends::emit_scene_friends_updated();
|
||||
presence_state::emit_presence_state_updated();
|
||||
if refreshes_friend_runtime {
|
||||
scene_friends::emit_scene_friends_updated();
|
||||
}
|
||||
if refreshes_friend_runtime {
|
||||
presence_state::emit_presence_state_updated();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user