minor consolidation & handling of data from frontend to rust side

This commit is contained in:
2026-03-08 22:14:30 +08:00
parent 23c778a0bb
commit 2aa1d5f92f
26 changed files with 464 additions and 154 deletions

View File

@@ -3,10 +3,9 @@
import { SPRITE_SETS, SPRITE_SIZE } from "$lib/constants/pet-sprites";
import { getSpriteSheetUrl } from "$lib/utils/sprite-utils";
import PetSprite from "$lib/components/PetSprite.svelte";
import type { DollColorSchemeDto } from "$lib/bindings";
export let bodyColor: string;
export let outlineColor: string;
export let applyTexture: boolean = true;
export let dollColorScheme: DollColorSchemeDto;
let previewBase64: string | null = null;
let error: string | null = null;
@@ -21,11 +20,7 @@
function generatePreview() {
error = null;
getSpriteSheetUrl({
bodyColor,
outlineColor,
applyTexture,
})
getSpriteSheetUrl(dollColorScheme)
.then((url: string) => {
previewBase64 = url;
})
@@ -70,7 +65,7 @@
}, 3000);
}
$: if (bodyColor && outlineColor) {
$: if (dollColorScheme) {
debouncedGeneratePreview();
}
@@ -103,7 +98,10 @@
/>
</div>
{:else}
<div class="size-full skeleton" style:background-color={bodyColor}></div>
<div
class="size-full skeleton"
style:background-color={dollColorScheme.body}
></div>
{/if}
</div>
</div>

View File

@@ -43,10 +43,7 @@
class="flex flex-col w-full text-center py-6 gap-2 *:mx-auto hover:opacity-70 hover:cursor-pointer"
>
<div class="flex justify-center">
<DollPreview
bodyColor={doll.configuration.colorScheme.body}
outlineColor={doll.configuration.colorScheme.outline}
/>
<DollPreview dollColorScheme={doll.configuration.colorScheme} />
</div>
<p
style:background-color={doll.configuration.colorScheme.body}

View File

@@ -108,7 +108,9 @@
{:else}
<div class="h-full w-full p-4 gap-4 flex flex-col">
<div class="flex justify-center mt-4">
<DollPreview {bodyColor} {outlineColor} />
<DollPreview
dollColorScheme={{ body: bodyColor, outline: outlineColor }}
/>
</div>
<div class="form-control w-full">
<label class="label" for="name-input">

View File

@@ -1,22 +1,56 @@
<script lang="ts">
import { cursorPositionOnScreen } from "../../events/cursor";
import { friendsCursorPositions } from "../../events/friend-cursor";
import { sceneFriends } from "../../events/friend-cursor";
import { appData } from "../../events/app-data";
import { sceneInteractive } from "../../events/scene-interactive";
import {
friendsPresenceStates,
currentPresenceState,
} from "../../events/user-status";
import { commands } from "$lib/bindings";
import { commands, events, type SceneFriendNeko } from "$lib/bindings";
import { getSpriteSheetUrl } from "$lib/utils/sprite-utils";
import DebugBar from "./components/debug-bar.svelte";
import Neko from "./components/neko/neko.svelte";
let spriteUrl = $state("");
let userSpriteUrl = $state("");
let friendSpriteUrls = $state<Record<string, string>>({});
async function fetchUserSprite() {
try {
const doll = await commands.getUserActiveDoll();
const url = await getSpriteSheetUrl(doll?.configuration.colorScheme);
userSpriteUrl = url;
} catch {
const url = await getSpriteSheetUrl();
userSpriteUrl = url;
}
}
$effect(() => {
getSpriteSheetUrl().then((url) => {
spriteUrl = url;
fetchUserSprite();
events.userActiveDollUpdated.listen(() => {
fetchUserSprite();
});
});
$effect(() => {
const friends = $sceneFriends;
if (friends.length === 0) {
friendSpriteUrls = {};
return;
}
Promise.all(
friends.map(async (friend: SceneFriendNeko) => {
return [
friend.id,
await getSpriteSheetUrl(friend.activeDoll.configuration.colorScheme),
] as const;
}),
).then((entries) => {
friendSpriteUrls = Object.fromEntries(entries);
});
});
</script>
@@ -32,14 +66,23 @@
<Neko
targetX={$cursorPositionOnScreen.raw.x}
targetY={$cursorPositionOnScreen.raw.y}
{spriteUrl}
spriteUrl={userSpriteUrl}
/>
{#each $sceneFriends as friend (friend.id)}
<Neko
targetX={friend.position.raw.x}
targetY={friend.position.raw.y}
spriteUrl={friendSpriteUrls[friend.id] ?? ""}
/>
{/each}
<div id="debug-bar">
<DebugBar
isInteractive={$sceneInteractive}
cursorPosition={$cursorPositionOnScreen}
presenceStatus={$currentPresenceState?.presenceStatus ?? null}
friendsCursorPositions={$friendsCursorPositions}
friendsCursorPositions={Object.fromEntries(
$sceneFriends.map((friend) => [friend.id, friend.position]),
)}
friends={$appData?.friends ?? []}
friendsPresenceStates={$friendsPresenceStates}
/>

View File

@@ -1,5 +1,9 @@
<script lang="ts">
import type { PresenceStatus, UserStatusPayload } from "$lib/bindings";
import type {
CursorPositions,
PresenceStatus,
UserStatusPayload,
} from "$lib/bindings";
interface Friend {
friend?: {
@@ -10,9 +14,9 @@
interface Props {
isInteractive: boolean;
cursorPosition: { mapped: { x: number; y: number } };
cursorPosition: CursorPositions;
presenceStatus: PresenceStatus | null;
friendsCursorPositions: Record<string, { mapped: { x: number; y: number } }>;
friendsCursorPositions: Record<string, CursorPositions>;
friends: Friend[];
friendsPresenceStates: Record<string, UserStatusPayload>;
}

View File

@@ -98,7 +98,9 @@
<input
class="input input-bordered input-sm"
type="password"
autocomplete={useRegister ? "new-password" : "current-password"}
autocomplete={useRegister
? "new-password"
: "current-password"}
bind:value={form.password}
placeholder="••••••••"
/>
@@ -146,7 +148,9 @@
}
}}
>
{useRegister ? "Already have an account? Sign in" : "New here? Create an account"}
{useRegister
? "Already have an account? Sign in"
: "New here? Create an account"}
</button>
<button
class="btn btn-link p-0 btn-sm text-base-content w-max"
@@ -175,7 +179,7 @@
>
<div></div>
<div class="flex flex-col scale-200 origin-bottom-right">
<DollPreview bodyColor="b7f2ff" outlineColor="496065" />
<DollPreview dollColorScheme={{ body: "b7f2ff", outline: "496065" }} />
</div>
</div>
</div>