move retrieval of sprite url from svelte to rust
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
lock_r,
|
lock_r,
|
||||||
models::{app_data::UserData, dolls::DollColorSchemeDto},
|
models::app_data::UserData,
|
||||||
services::presence_modules::models::ModuleMetadata,
|
services::{presence_modules::models::ModuleMetadata, sprite},
|
||||||
state::{init_app_data_scoped, AppDataRefreshScope, FDOLL},
|
state::{init_app_data_scoped, AppDataRefreshScope, FDOLL},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -29,24 +29,6 @@ pub fn get_modules() -> Result<Vec<ModuleMetadata>, String> {
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
#[specta::specta]
|
#[specta::specta]
|
||||||
pub fn get_active_doll_color_scheme() -> Result<Option<DollColorSchemeDto>, String> {
|
pub fn get_active_doll_sprite_base64() -> Result<Option<String>, String> {
|
||||||
let guard = lock_r!(FDOLL);
|
sprite::get_active_doll_sprite_base64()
|
||||||
let active_doll_id = guard
|
|
||||||
.user_data
|
|
||||||
.user
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|u| u.active_doll_id.as_deref());
|
|
||||||
|
|
||||||
match active_doll_id {
|
|
||||||
Some(active_doll_id) => {
|
|
||||||
let color_scheme = guard
|
|
||||||
.user_data
|
|
||||||
.dolls
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|dolls| dolls.iter().find(|d| d.id == active_doll_id))
|
|
||||||
.map(|d| d.configuration.color_scheme.clone());
|
|
||||||
Ok(color_scheme)
|
|
||||||
}
|
|
||||||
None => Ok(None),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ pub mod config;
|
|||||||
pub mod dolls;
|
pub mod dolls;
|
||||||
pub mod friends;
|
pub mod friends;
|
||||||
pub mod interaction;
|
pub mod interaction;
|
||||||
pub mod sprite;
|
|
||||||
pub mod petpet;
|
pub mod petpet;
|
||||||
|
pub mod sprite;
|
||||||
|
|
||||||
use crate::lock_r;
|
use crate::lock_r;
|
||||||
use crate::state::{init_app_data_scoped, AppDataRefreshScope, FDOLL};
|
use crate::state::{init_app_data_scoped, AppDataRefreshScope, FDOLL};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use commands::app::{quit_app, restart_app, retry_connection};
|
use commands::app::{quit_app, restart_app, retry_connection};
|
||||||
use commands::app_state::{get_app_data, get_active_doll_color_scheme, refresh_app_data};
|
use commands::app_state::{get_active_doll_sprite_base64, get_app_data, refresh_app_data};
|
||||||
use commands::auth::{change_password, login, logout_and_restart, register, reset_password};
|
use commands::auth::{change_password, login, logout_and_restart, register, reset_password};
|
||||||
use commands::config::{get_client_config, open_client_config_manager, save_client_config};
|
use commands::config::{get_client_config, open_client_config_manager, save_client_config};
|
||||||
use commands::dolls::{
|
use commands::dolls::{
|
||||||
@@ -17,18 +17,18 @@ use commands::friends::{
|
|||||||
search_users, send_friend_request, sent_friend_requests, unfriend,
|
search_users, send_friend_request, sent_friend_requests, unfriend,
|
||||||
};
|
};
|
||||||
use commands::interaction::send_interaction_cmd;
|
use commands::interaction::send_interaction_cmd;
|
||||||
use commands::sprite::recolor_gif_base64;
|
|
||||||
use commands::petpet::encode_pet_doll_gif_base64;
|
use commands::petpet::encode_pet_doll_gif_base64;
|
||||||
|
use commands::sprite::recolor_gif_base64;
|
||||||
use specta_typescript::Typescript;
|
use specta_typescript::Typescript;
|
||||||
use tauri::async_runtime;
|
use tauri::async_runtime;
|
||||||
use tauri_specta::{Builder as SpectaBuilder, ErrorHandlingMode, collect_commands, collect_events};
|
use tauri_specta::{collect_commands, collect_events, Builder as SpectaBuilder, ErrorHandlingMode};
|
||||||
|
|
||||||
use crate::services::app_events::{
|
use crate::services::app_events::{
|
||||||
AppDataRefreshed, CreateDoll, CursorMoved, EditDoll, FriendActiveDollChanged,
|
ActiveDollSpriteChanged, AppDataRefreshed, CreateDoll, CursorMoved, EditDoll,
|
||||||
FriendCursorPositionsUpdated, FriendDisconnected,
|
FriendActiveDollChanged, FriendCursorPositionsUpdated, FriendDisconnected,
|
||||||
FriendRequestAccepted, FriendRequestDenied, FriendRequestReceived,
|
FriendRequestAccepted, FriendRequestDenied, FriendRequestReceived, FriendUserStatusChanged,
|
||||||
FriendUserStatusChanged, InteractionDeliveryFailed, InteractionReceived,
|
InteractionDeliveryFailed, InteractionReceived, SceneInteractiveChanged, SetInteractionOverlay,
|
||||||
SceneInteractiveChanged, SetInteractionOverlay, Unfriended, UserStatusChanged,
|
Unfriended, UserStatusChanged,
|
||||||
};
|
};
|
||||||
|
|
||||||
static APP_HANDLE: std::sync::OnceLock<tauri::AppHandle<tauri::Wry>> = std::sync::OnceLock::new();
|
static APP_HANDLE: std::sync::OnceLock<tauri::AppHandle<tauri::Wry>> = std::sync::OnceLock::new();
|
||||||
@@ -65,7 +65,7 @@ pub fn run() {
|
|||||||
.error_handling(ErrorHandlingMode::Throw)
|
.error_handling(ErrorHandlingMode::Throw)
|
||||||
.commands(collect_commands![
|
.commands(collect_commands![
|
||||||
get_app_data,
|
get_app_data,
|
||||||
get_active_doll_color_scheme,
|
get_active_doll_sprite_base64,
|
||||||
refresh_app_data,
|
refresh_app_data,
|
||||||
list_friends,
|
list_friends,
|
||||||
search_users,
|
search_users,
|
||||||
@@ -106,6 +106,7 @@ pub fn run() {
|
|||||||
CursorMoved,
|
CursorMoved,
|
||||||
SceneInteractiveChanged,
|
SceneInteractiveChanged,
|
||||||
AppDataRefreshed,
|
AppDataRefreshed,
|
||||||
|
ActiveDollSpriteChanged,
|
||||||
SetInteractionOverlay,
|
SetInteractionOverlay,
|
||||||
EditDoll,
|
EditDoll,
|
||||||
CreateDoll,
|
CreateDoll,
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ pub struct SceneInteractiveChanged(pub bool);
|
|||||||
#[tauri_specta(event_name = "app-data-refreshed")]
|
#[tauri_specta(event_name = "app-data-refreshed")]
|
||||||
pub struct AppDataRefreshed(pub UserData);
|
pub struct AppDataRefreshed(pub UserData);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
|
||||||
|
#[tauri_specta(event_name = "active-doll-sprite-changed")]
|
||||||
|
pub struct ActiveDollSpriteChanged(pub Option<String>);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
|
||||||
#[tauri_specta(event_name = "set-interaction-overlay")]
|
#[tauri_specta(event_name = "set-interaction-overlay")]
|
||||||
pub struct SetInteractionOverlay(pub bool);
|
pub struct SetInteractionOverlay(pub bool);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ pub mod interaction;
|
|||||||
pub mod petpet;
|
pub mod petpet;
|
||||||
pub mod presence_modules;
|
pub mod presence_modules;
|
||||||
pub mod scene;
|
pub mod scene;
|
||||||
|
pub mod sprite;
|
||||||
pub mod sprite_recolor;
|
pub mod sprite_recolor;
|
||||||
pub mod welcome;
|
pub mod welcome;
|
||||||
pub mod ws;
|
pub mod ws;
|
||||||
|
|||||||
33
src-tauri/src/services/sprite.rs
Normal file
33
src-tauri/src/services/sprite.rs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
use crate::{lock_r, models::dolls::DollDto, state::FDOLL};
|
||||||
|
|
||||||
|
const APPLY_TEXTURE: bool = true;
|
||||||
|
|
||||||
|
pub fn get_active_doll() -> Option<DollDto> {
|
||||||
|
let guard = lock_r!(FDOLL);
|
||||||
|
let active_doll_id = guard
|
||||||
|
.user_data
|
||||||
|
.user
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|user| user.active_doll_id.as_deref())?;
|
||||||
|
|
||||||
|
guard
|
||||||
|
.user_data
|
||||||
|
.dolls
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|dolls| dolls.iter().find(|doll| doll.id == active_doll_id))
|
||||||
|
.cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_active_doll_sprite_base64() -> Result<Option<String>, String> {
|
||||||
|
get_active_doll()
|
||||||
|
.map(|doll| {
|
||||||
|
let color_scheme = doll.configuration.color_scheme;
|
||||||
|
super::sprite_recolor::recolor_gif_base64(
|
||||||
|
&color_scheme.body,
|
||||||
|
&color_scheme.outline,
|
||||||
|
APPLY_TEXTURE,
|
||||||
|
)
|
||||||
|
.map_err(|err| err.to_string())
|
||||||
|
})
|
||||||
|
.transpose()
|
||||||
|
}
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
get_app_handle, lock_r, lock_w,
|
get_app_handle, lock_r, lock_w,
|
||||||
remotes::{dolls::DollsRemote, friends::FriendRemote, user::UserRemote},
|
remotes::{dolls::DollsRemote, friends::FriendRemote, user::UserRemote},
|
||||||
services::{app_events::AppDataRefreshed, friend_cursor},
|
services::{
|
||||||
|
app_events::{ActiveDollSpriteChanged, AppDataRefreshed},
|
||||||
|
friend_cursor, sprite,
|
||||||
|
},
|
||||||
state::FDOLL,
|
state::FDOLL,
|
||||||
};
|
};
|
||||||
use std::{collections::HashSet, sync::LazyLock};
|
use std::{collections::HashSet, sync::LazyLock};
|
||||||
use tokio::sync::Mutex;
|
|
||||||
use tauri_specta::Event as _;
|
use tauri_specta::Event as _;
|
||||||
|
use tokio::sync::Mutex;
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
pub fn update_display_dimensions_for_scene_state() {
|
pub fn update_display_dimensions_for_scene_state() {
|
||||||
@@ -227,6 +230,26 @@ pub async fn init_app_data_scoped(scope: AppDataRefreshScope) {
|
|||||||
.kind(MessageDialogKind::Error)
|
.kind(MessageDialogKind::Error)
|
||||||
.show(|_| {});
|
.show(|_| {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if matches!(
|
||||||
|
scope,
|
||||||
|
AppDataRefreshScope::All
|
||||||
|
| AppDataRefreshScope::User
|
||||||
|
| AppDataRefreshScope::Dolls
|
||||||
|
) {
|
||||||
|
match sprite::get_active_doll_sprite_base64() {
|
||||||
|
Ok(sprite_b64) => {
|
||||||
|
if let Err(e) =
|
||||||
|
ActiveDollSpriteChanged(sprite_b64).emit(get_app_handle())
|
||||||
|
{
|
||||||
|
warn!("Failed to emit active-doll-sprite-changed event: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
warn!("Failed to generate active doll sprite: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
25
src/events/active-doll-sprite.ts
Normal file
25
src/events/active-doll-sprite.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { writable } from "svelte/store";
|
||||||
|
import onekoGif from "../assets/oneko/oneko.gif";
|
||||||
|
import { commands, events } from "$lib/bindings";
|
||||||
|
import { createEventSource } from "./listener-utils";
|
||||||
|
|
||||||
|
export const activeDollSpriteUrl = writable(onekoGif);
|
||||||
|
|
||||||
|
function toSpriteUrl(spriteBase64: string | null): string {
|
||||||
|
return spriteBase64 ? `data:image/gif;base64,${spriteBase64}` : onekoGif;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const {
|
||||||
|
start: startActiveDollSprite,
|
||||||
|
stop: stopActiveDollSprite,
|
||||||
|
} = createEventSource(async (addEventListener) => {
|
||||||
|
activeDollSpriteUrl.set(
|
||||||
|
toSpriteUrl(await commands.getActiveDollSpriteBase64()),
|
||||||
|
);
|
||||||
|
|
||||||
|
addEventListener(
|
||||||
|
await events.activeDollSpriteChanged.listen((event) => {
|
||||||
|
activeDollSpriteUrl.set(toSpriteUrl(event.payload));
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -8,8 +8,8 @@ export const commands = {
|
|||||||
async getAppData() : Promise<UserData> {
|
async getAppData() : Promise<UserData> {
|
||||||
return await TAURI_INVOKE("get_app_data");
|
return await TAURI_INVOKE("get_app_data");
|
||||||
},
|
},
|
||||||
async getActiveDollColorScheme() : Promise<DollColorSchemeDto | null> {
|
async getActiveDollSpriteBase64() : Promise<string | null> {
|
||||||
return await TAURI_INVOKE("get_active_doll_color_scheme");
|
return await TAURI_INVOKE("get_active_doll_sprite_base64");
|
||||||
},
|
},
|
||||||
async refreshAppData() : Promise<UserData> {
|
async refreshAppData() : Promise<UserData> {
|
||||||
return await TAURI_INVOKE("refresh_app_data");
|
return await TAURI_INVOKE("refresh_app_data");
|
||||||
@@ -128,6 +128,7 @@ async getModules() : Promise<ModuleMetadata[]> {
|
|||||||
|
|
||||||
|
|
||||||
export const events = __makeEvents__<{
|
export const events = __makeEvents__<{
|
||||||
|
activeDollSpriteChanged: ActiveDollSpriteChanged,
|
||||||
appDataRefreshed: AppDataRefreshed,
|
appDataRefreshed: AppDataRefreshed,
|
||||||
createDoll: CreateDoll,
|
createDoll: CreateDoll,
|
||||||
cursorMoved: CursorMoved,
|
cursorMoved: CursorMoved,
|
||||||
@@ -146,6 +147,7 @@ setInteractionOverlay: SetInteractionOverlay,
|
|||||||
unfriended: Unfriended,
|
unfriended: Unfriended,
|
||||||
userStatusChanged: UserStatusChanged
|
userStatusChanged: UserStatusChanged
|
||||||
}>({
|
}>({
|
||||||
|
activeDollSpriteChanged: "active-doll-sprite-changed",
|
||||||
appDataRefreshed: "app-data-refreshed",
|
appDataRefreshed: "app-data-refreshed",
|
||||||
createDoll: "create-doll",
|
createDoll: "create-doll",
|
||||||
cursorMoved: "cursor-moved",
|
cursorMoved: "cursor-moved",
|
||||||
@@ -171,6 +173,7 @@ userStatusChanged: "user-status-changed"
|
|||||||
|
|
||||||
/** user-defined types **/
|
/** user-defined types **/
|
||||||
|
|
||||||
|
export type ActiveDollSpriteChanged = string | null
|
||||||
export type AppConfig = { api_base_url: string | null }
|
export type AppConfig = { api_base_url: string | null }
|
||||||
export type AppDataRefreshed = UserData
|
export type AppDataRefreshed = UserData
|
||||||
export type CreateDoll = null
|
export type CreateDoll = null
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
startFriendCursorTracking,
|
startFriendCursorTracking,
|
||||||
stopFriendCursorTracking,
|
stopFriendCursorTracking,
|
||||||
} from "../events/friend-cursor";
|
} from "../events/friend-cursor";
|
||||||
|
import {
|
||||||
|
startActiveDollSprite,
|
||||||
|
stopActiveDollSprite,
|
||||||
|
} from "../events/active-doll-sprite";
|
||||||
import { startAppData } from "../events/app-data";
|
import { startAppData } from "../events/app-data";
|
||||||
import { startInteraction, stopInteraction } from "../events/interaction";
|
import { startInteraction, stopInteraction } from "../events/interaction";
|
||||||
import {
|
import {
|
||||||
@@ -19,6 +23,7 @@
|
|||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
try {
|
try {
|
||||||
await startAppData();
|
await startAppData();
|
||||||
|
await startActiveDollSprite();
|
||||||
await startCursorTracking();
|
await startCursorTracking();
|
||||||
await startFriendCursorTracking();
|
await startFriendCursorTracking();
|
||||||
await startSceneInteractive();
|
await startSceneInteractive();
|
||||||
@@ -32,6 +37,7 @@
|
|||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
stopCursorTracking();
|
stopCursorTracking();
|
||||||
stopFriendCursorTracking();
|
stopFriendCursorTracking();
|
||||||
|
stopActiveDollSprite();
|
||||||
stopSceneInteractive();
|
stopSceneInteractive();
|
||||||
stopInteraction();
|
stopInteraction();
|
||||||
stopUserStatus();
|
stopUserStatus();
|
||||||
|
|||||||
@@ -2,27 +2,15 @@
|
|||||||
import { cursorPositionOnScreen } from "../../events/cursor";
|
import { cursorPositionOnScreen } from "../../events/cursor";
|
||||||
import { friendsCursorPositions } from "../../events/friend-cursor";
|
import { friendsCursorPositions } from "../../events/friend-cursor";
|
||||||
import { appData } from "../../events/app-data";
|
import { appData } from "../../events/app-data";
|
||||||
|
import { activeDollSpriteUrl } from "../../events/active-doll-sprite";
|
||||||
import { sceneInteractive } from "../../events/scene-interactive";
|
import { sceneInteractive } from "../../events/scene-interactive";
|
||||||
import {
|
import {
|
||||||
friendsPresenceStates,
|
friendsPresenceStates,
|
||||||
currentPresenceState,
|
currentPresenceState,
|
||||||
} from "../../events/user-status";
|
} from "../../events/user-status";
|
||||||
import { commands } from "$lib/bindings";
|
import { commands } from "$lib/bindings";
|
||||||
import { getSpriteSheetUrl } from "$lib/utils/sprite-utils";
|
|
||||||
import DebugBar from "./components/debug-bar.svelte";
|
import DebugBar from "./components/debug-bar.svelte";
|
||||||
import Neko from "./components/neko/neko.svelte";
|
import Neko from "./components/neko/neko.svelte";
|
||||||
|
|
||||||
let spriteUrl = $state("");
|
|
||||||
|
|
||||||
$effect(() => {
|
|
||||||
$appData;
|
|
||||||
if (!$appData) return;
|
|
||||||
commands.getActiveDollColorScheme().then((colorScheme) => {
|
|
||||||
getSpriteSheetUrl(colorScheme ?? undefined).then((url) => {
|
|
||||||
spriteUrl = url;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-svw h-svh p-4 relative overflow-hidden">
|
<div class="w-svw h-svh p-4 relative overflow-hidden">
|
||||||
@@ -36,7 +24,7 @@
|
|||||||
<Neko
|
<Neko
|
||||||
targetX={$cursorPositionOnScreen.raw.x}
|
targetX={$cursorPositionOnScreen.raw.x}
|
||||||
targetY={$cursorPositionOnScreen.raw.y}
|
targetY={$cursorPositionOnScreen.raw.y}
|
||||||
{spriteUrl}
|
spriteUrl={$activeDollSpriteUrl}
|
||||||
/>
|
/>
|
||||||
<div id="debug-bar">
|
<div id="debug-bar">
|
||||||
<DebugBar
|
<DebugBar
|
||||||
|
|||||||
Reference in New Issue
Block a user