refactored frontend events for code conciseness
This commit is contained in:
@@ -1,32 +1,16 @@
|
|||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
import { commands, events, type UserData } from "$lib/bindings";
|
import { commands, events, type UserData } from "$lib/bindings";
|
||||||
import { createListenersSubscription, setupHmrCleanup } from "./listener-utils";
|
import { createEventSource } from "./listener-utils";
|
||||||
|
|
||||||
export const appData = writable<UserData | null>(null);
|
export const appData = writable<UserData | null>(null);
|
||||||
|
|
||||||
const subscription = createListenersSubscription();
|
export const { start: startAppData, stop: stopAppData } = createEventSource(
|
||||||
|
async (addEventListener) => {
|
||||||
/**
|
|
||||||
* Starts listening for app data refresh events.
|
|
||||||
* Initializes app data from the backend.
|
|
||||||
*/
|
|
||||||
export async function startAppData() {
|
|
||||||
try {
|
|
||||||
if (subscription.isListening()) return;
|
|
||||||
appData.set(await commands.getAppData());
|
appData.set(await commands.getAppData());
|
||||||
const unlisten = await events.appDataRefreshed.listen((event) => {
|
addEventListener(
|
||||||
|
await events.appDataRefreshed.listen((event) => {
|
||||||
appData.set(event.payload);
|
appData.set(event.payload);
|
||||||
});
|
}),
|
||||||
subscription.addUnlisten(unlisten);
|
);
|
||||||
subscription.setListening(true);
|
},
|
||||||
} catch (error) {
|
);
|
||||||
console.error(error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stopAppData() {
|
|
||||||
subscription.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
setupHmrCleanup(stopAppData);
|
|
||||||
|
|||||||
@@ -1,35 +1,17 @@
|
|||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
import { events, type CursorPositions } from "$lib/bindings";
|
import { events, type CursorPositions } from "$lib/bindings";
|
||||||
import { createListenersSubscription, setupHmrCleanup } from "./listener-utils";
|
import { createEventSource } from "./listener-utils";
|
||||||
|
|
||||||
export const cursorPositionOnScreen = writable<CursorPositions>({
|
export const cursorPositionOnScreen = writable<CursorPositions>({
|
||||||
raw: { x: 0, y: 0 },
|
raw: { x: 0, y: 0 },
|
||||||
mapped: { x: 0, y: 0 },
|
mapped: { x: 0, y: 0 },
|
||||||
});
|
});
|
||||||
|
|
||||||
const subscription = createListenersSubscription();
|
export const { start: startCursorTracking, stop: stopCursorTracking } =
|
||||||
|
createEventSource(async (addEventListener) => {
|
||||||
/**
|
addEventListener(
|
||||||
* Starts tracking the local cursor position.
|
await events.cursorMoved.listen((event) => {
|
||||||
* Initializes cursor position from the backend and listens for updates.
|
|
||||||
*/
|
|
||||||
export async function startCursorTracking() {
|
|
||||||
if (subscription.isListening()) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const unlisten = await events.cursorMoved.listen((event) => {
|
|
||||||
cursorPositionOnScreen.set(event.payload);
|
cursorPositionOnScreen.set(event.payload);
|
||||||
|
}),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
subscription.addUnlisten(unlisten);
|
|
||||||
subscription.setListening(true);
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Failed to initialize cursor tracking:", err);
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stopCursorTracking() {
|
|
||||||
subscription.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
setupHmrCleanup(stopCursorTracking);
|
|
||||||
|
|||||||
@@ -5,11 +5,7 @@ import {
|
|||||||
type DollDto,
|
type DollDto,
|
||||||
type OutgoingFriendCursorPayload,
|
type OutgoingFriendCursorPayload,
|
||||||
} from "$lib/bindings";
|
} from "$lib/bindings";
|
||||||
import {
|
import { createEventSource, removeFromStore } from "./listener-utils";
|
||||||
createListenersSubscription,
|
|
||||||
removeFromStore,
|
|
||||||
setupHmrCleanup,
|
|
||||||
} from "./listener-utils";
|
|
||||||
|
|
||||||
type FriendCursorData = {
|
type FriendCursorData = {
|
||||||
position: CursorPositions;
|
position: CursorPositions;
|
||||||
@@ -21,21 +17,12 @@ export const friendsCursorPositions = writable<Record<string, CursorPositions>>(
|
|||||||
);
|
);
|
||||||
export const friendsActiveDolls = writable<Record<string, DollDto | null>>({});
|
export const friendsActiveDolls = writable<Record<string, DollDto | null>>({});
|
||||||
|
|
||||||
const subscription = createListenersSubscription();
|
export const {
|
||||||
|
start: startFriendCursorTracking,
|
||||||
|
stop: stopFriendCursorTracking,
|
||||||
|
} = createEventSource(async (addEventListener) => {
|
||||||
let friendCursorState: Record<string, FriendCursorData> = {};
|
let friendCursorState: Record<string, FriendCursorData> = {};
|
||||||
|
addEventListener(
|
||||||
/**
|
|
||||||
* Starts listening for friend cursor position and active doll changes.
|
|
||||||
* Also handles friend disconnection events.
|
|
||||||
*/
|
|
||||||
export async function startFriendCursorTracking() {
|
|
||||||
if (subscription.isListening()) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// TODO: Add initial sync for existing friends' cursors and dolls if needed
|
|
||||||
|
|
||||||
const unlistenFriendCursor =
|
|
||||||
await events.friendCursorPositionUpdated.listen((event) => {
|
await events.friendCursorPositionUpdated.listen((event) => {
|
||||||
const data: OutgoingFriendCursorPayload = event.payload;
|
const data: OutgoingFriendCursorPayload = event.payload;
|
||||||
|
|
||||||
@@ -50,11 +37,11 @@ export async function startFriendCursorTracking() {
|
|||||||
[data.userId]: data.position,
|
[data.userId]: data.position,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
});
|
}),
|
||||||
subscription.addUnlisten(unlistenFriendCursor);
|
);
|
||||||
|
|
||||||
const unlistenFriendDisconnected = await events.friendDisconnected.listen(
|
addEventListener(
|
||||||
(event) => {
|
await events.friendDisconnected.listen((event) => {
|
||||||
const data = event.payload;
|
const data = event.payload;
|
||||||
|
|
||||||
if (friendCursorState[data.userId]) {
|
if (friendCursorState[data.userId]) {
|
||||||
@@ -64,11 +51,10 @@ export async function startFriendCursorTracking() {
|
|||||||
friendsCursorPositions.update((current) =>
|
friendsCursorPositions.update((current) =>
|
||||||
removeFromStore(current, data.userId),
|
removeFromStore(current, data.userId),
|
||||||
);
|
);
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
subscription.addUnlisten(unlistenFriendDisconnected);
|
|
||||||
|
|
||||||
const unlistenFriendActiveDollChanged =
|
addEventListener(
|
||||||
await events.friendActiveDollChanged.listen((event) => {
|
await events.friendActiveDollChanged.listen((event) => {
|
||||||
const payload = event.payload;
|
const payload = event.payload;
|
||||||
|
|
||||||
@@ -90,18 +76,6 @@ export async function startFriendCursorTracking() {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
subscription.addUnlisten(unlistenFriendActiveDollChanged);
|
|
||||||
|
|
||||||
subscription.setListening(true);
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Failed to initialize friend cursor tracking:", err);
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stopFriendCursorTracking() {
|
|
||||||
subscription.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
setupHmrCleanup(stopFriendCursorTracking);
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
import { events, type InteractionPayloadDto } from "$lib/bindings";
|
import { events, type InteractionPayloadDto } from "$lib/bindings";
|
||||||
import { createListenersSubscription, setupHmrCleanup } from "./listener-utils";
|
import { createEventSource } from "./listener-utils";
|
||||||
|
|
||||||
export const receivedInteractions = writable<
|
export const receivedInteractions = writable<
|
||||||
Map<string, InteractionPayloadDto>
|
Map<string, InteractionPayloadDto>
|
||||||
@@ -22,40 +22,20 @@ export function clearInteraction(userId: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const subscription = createListenersSubscription();
|
export const { start: startInteraction, stop: stopInteraction } =
|
||||||
|
createEventSource(async (addEventListener) => {
|
||||||
/**
|
addEventListener(
|
||||||
* Starts listening for interaction events (received and delivery failed).
|
await events.interactionReceived.listen((event) => {
|
||||||
*/
|
|
||||||
export async function startInteraction() {
|
|
||||||
if (subscription.isListening()) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const unlistenReceived = await events.interactionReceived.listen(
|
|
||||||
(event) => {
|
|
||||||
addInteraction(event.payload);
|
addInteraction(event.payload);
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
subscription.addUnlisten(unlistenReceived);
|
|
||||||
|
|
||||||
const unlistenFailed = await events.interactionDeliveryFailed.listen(
|
addEventListener(
|
||||||
(event) => {
|
await events.interactionDeliveryFailed.listen((event) => {
|
||||||
console.error("Interaction delivery failed:", event.payload);
|
console.error("Interaction delivery failed:", event.payload);
|
||||||
alert(
|
alert(
|
||||||
`Failed to send message to user ${event.payload.recipientUserId}: ${event.payload.reason}`,
|
`Failed to send message to user ${event.payload.recipientUserId}: ${event.payload.reason}`,
|
||||||
);
|
);
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
subscription.addUnlisten(unlistenFailed);
|
});
|
||||||
subscription.setListening(true);
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Failed to initialize interaction listeners:", err);
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stopInteraction() {
|
|
||||||
subscription.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
setupHmrCleanup(stopInteraction);
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export type ListenerSubscription = {
|
|||||||
stop: () => void;
|
stop: () => void;
|
||||||
isListening: () => boolean;
|
isListening: () => boolean;
|
||||||
setListening: (value: boolean) => void;
|
setListening: (value: boolean) => void;
|
||||||
addUnlisten: (unlisten: UnlistenFn | null) => void;
|
addEventListener: (unlisten: UnlistenFn | null) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function createListenersSubscription(
|
export function createListenersSubscription(
|
||||||
@@ -26,7 +26,7 @@ export function createListenersSubscription(
|
|||||||
setListening: (value) => {
|
setListening: (value) => {
|
||||||
listening = value;
|
listening = value;
|
||||||
},
|
},
|
||||||
addUnlisten: (unlisten) => {
|
addEventListener: (unlisten) => {
|
||||||
if (unlisten) {
|
if (unlisten) {
|
||||||
unlistens.push(unlisten);
|
unlistens.push(unlisten);
|
||||||
}
|
}
|
||||||
@@ -34,14 +34,41 @@ export function createListenersSubscription(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setupHmrCleanup(cleanup: () => void) {
|
export type EventSource = {
|
||||||
if (import.meta.hot) {
|
start: () => Promise<void>;
|
||||||
import.meta.hot.dispose(() => {
|
stop: () => void;
|
||||||
cleanup();
|
isListening: () => boolean;
|
||||||
});
|
};
|
||||||
|
|
||||||
|
export function createEventSource(
|
||||||
|
setup: (addEventListener: (unlisten: UnlistenFn) => void) => Promise<void>,
|
||||||
|
stopFn: () => void = () => {},
|
||||||
|
): EventSource {
|
||||||
|
const subscription = createListenersSubscription(stopFn);
|
||||||
|
|
||||||
|
async function start() {
|
||||||
|
if (subscription.isListening()) return;
|
||||||
|
try {
|
||||||
|
await setup((unlisten) => subscription.addEventListener(unlisten));
|
||||||
|
subscription.setListening(true);
|
||||||
|
} catch (err) {
|
||||||
|
subscription.stop();
|
||||||
|
console.error(`Failed to start:`, err);
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stop() {
|
||||||
|
subscription.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (import.meta.hot) {
|
||||||
|
import.meta.hot.dispose(() => stop());
|
||||||
|
}
|
||||||
|
|
||||||
|
return { start, stop, isListening: () => subscription.isListening() };
|
||||||
|
}
|
||||||
|
|
||||||
export function removeFromStore<T>(
|
export function removeFromStore<T>(
|
||||||
current: Record<string, T>,
|
current: Record<string, T>,
|
||||||
key: string,
|
key: string,
|
||||||
|
|||||||
@@ -1,33 +1,15 @@
|
|||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
import { commands, events } from "$lib/bindings";
|
import { commands, events } from "$lib/bindings";
|
||||||
import { createListenersSubscription, setupHmrCleanup } from "./listener-utils";
|
import { createEventSource } from "./listener-utils";
|
||||||
|
|
||||||
export const sceneInteractive = writable<boolean>(false);
|
export const sceneInteractive = writable<boolean>(false);
|
||||||
|
|
||||||
const subscription = createListenersSubscription();
|
export const { start: startSceneInteractive, stop: stopSceneInteractive } =
|
||||||
|
createEventSource(async (addEventListener) => {
|
||||||
/**
|
|
||||||
* Starts listening for scene interactive state changes.
|
|
||||||
* Initializes the scene interactive state from the backend.
|
|
||||||
*/
|
|
||||||
export async function startSceneInteractive() {
|
|
||||||
if (subscription.isListening()) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
sceneInteractive.set(await commands.getSceneInteractive());
|
sceneInteractive.set(await commands.getSceneInteractive());
|
||||||
const unlisten = await events.sceneInteractiveChanged.listen((event) => {
|
addEventListener(
|
||||||
|
await events.sceneInteractiveChanged.listen((event) => {
|
||||||
sceneInteractive.set(Boolean(event.payload));
|
sceneInteractive.set(Boolean(event.payload));
|
||||||
|
}),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
subscription.addUnlisten(unlisten);
|
|
||||||
subscription.setListening(true);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Failed to initialize scene interactive listener:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stopSceneInteractive() {
|
|
||||||
subscription.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
setupHmrCleanup(stopSceneInteractive);
|
|
||||||
|
|||||||
@@ -1,27 +1,16 @@
|
|||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
import { events, type UserStatusPayload } from "$lib/bindings";
|
import { events, type UserStatusPayload } from "$lib/bindings";
|
||||||
import {
|
import { createEventSource, removeFromStore } from "./listener-utils";
|
||||||
createListenersSubscription,
|
|
||||||
removeFromStore,
|
|
||||||
setupHmrCleanup,
|
|
||||||
} from "./listener-utils";
|
|
||||||
|
|
||||||
export const friendsPresenceStates = writable<
|
export const friendsPresenceStates = writable<
|
||||||
Record<string, UserStatusPayload>
|
Record<string, UserStatusPayload>
|
||||||
>({});
|
>({});
|
||||||
export const currentPresenceState = writable<UserStatusPayload | null>(null);
|
export const currentPresenceState = writable<UserStatusPayload | null>(null);
|
||||||
|
|
||||||
const subscription = createListenersSubscription();
|
export const { start: startUserStatus, stop: stopUserStatus } =
|
||||||
|
createEventSource(async (addEventListener) => {
|
||||||
/**
|
addEventListener(
|
||||||
* Starts listening for user status changes and friend status updates.
|
await events.friendUserStatusChanged.listen((event) => {
|
||||||
*/
|
|
||||||
export async function startUserStatus() {
|
|
||||||
if (subscription.isListening()) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const unlistenStatus = await events.friendUserStatusChanged.listen(
|
|
||||||
(event) => {
|
|
||||||
const { userId, status } = event.payload;
|
const { userId, status } = event.payload;
|
||||||
|
|
||||||
const hasValidName =
|
const hasValidName =
|
||||||
@@ -35,36 +24,21 @@ export async function startUserStatus() {
|
|||||||
...current,
|
...current,
|
||||||
[userId]: status,
|
[userId]: status,
|
||||||
}));
|
}));
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
subscription.addUnlisten(unlistenStatus);
|
|
||||||
|
|
||||||
const unlistenUserStatusChanged = await events.userStatusChanged.listen(
|
addEventListener(
|
||||||
(event) => {
|
await events.userStatusChanged.listen((event) => {
|
||||||
currentPresenceState.set(event.payload);
|
currentPresenceState.set(event.payload);
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
subscription.addUnlisten(unlistenUserStatusChanged);
|
|
||||||
|
|
||||||
const unlistenFriendDisconnected = await events.friendDisconnected.listen(
|
addEventListener(
|
||||||
(event) => {
|
await events.friendDisconnected.listen((event) => {
|
||||||
const { userId } = event.payload;
|
const { userId } = event.payload;
|
||||||
friendsPresenceStates.update((current) =>
|
friendsPresenceStates.update((current) =>
|
||||||
removeFromStore(current, userId),
|
removeFromStore(current, userId),
|
||||||
);
|
);
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
subscription.addUnlisten(unlistenFriendDisconnected);
|
});
|
||||||
|
|
||||||
subscription.setListening(true);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Failed to initialize user status listeners", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stopUserStatus() {
|
|
||||||
subscription.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
setupHmrCleanup(stopUserStatus);
|
|
||||||
|
|||||||
Reference in New Issue
Block a user