event broadcasting & nuking foreground app listener

This commit is contained in:
2026-02-16 12:38:30 +08:00
parent c76e436529
commit 279ac11c0e
22 changed files with 114 additions and 973 deletions

View File

@@ -1,13 +1,13 @@
import { listen, type UnlistenFn } from "@tauri-apps/api/event";
import { writable } from "svelte/store";
import type { AppMetadata } from "../types/bindings/AppMetadata";
import type { PresenceStatus } from "../types/bindings/PresenceStatus";
export type FriendUserStatus = {
appMetadata: AppMetadata;
export type UserStatus = {
presenceStatus: PresenceStatus;
state: "idle" | "resting";
};
export const friendsUserStatuses = writable<Record<string, FriendUserStatus>>({});
export const friendsUserStatuses = writable<Record<string, UserStatus>>({});
let unlistenStatus: UnlistenFn | null = null;
let unlistenFriendDisconnected: UnlistenFn | null = null;
@@ -29,52 +29,53 @@ export async function initUserStatusListeners() {
}
const userId = payload?.userId as string | undefined;
const status = payload?.status as FriendUserStatus | undefined;
const status = payload?.status as UserStatus | undefined;
if (!userId || !status) return;
if (!status.appMetadata) return;
if (!status.presenceStatus) return;
// Validate that appMetadata has at least one valid name
const hasValidName =
(typeof status.appMetadata.localized === "string" && status.appMetadata.localized.trim() !== "") ||
(typeof status.appMetadata.unlocalized === "string" && status.appMetadata.unlocalized.trim() !== "");
const hasValidName =
(typeof status.presenceStatus.title === "string" &&
status.presenceStatus.title.trim() !== "") ||
(typeof status.presenceStatus.subtitle === "string" &&
status.presenceStatus.subtitle.trim() !== "");
if (!hasValidName) return;
if (status.state !== "idle" && status.state !== "resting") return;
friendsUserStatuses.update((current) => ({
...current,
[userId]: {
appMetadata: status.appMetadata,
presenceStatus: status.presenceStatus,
state: status.state,
},
}));
});
unlistenFriendDisconnected = await listen<[{ userId: string }] | { userId: string } | string>(
"friend-disconnected",
(event) => {
let payload = event.payload as any;
if (typeof payload === "string") {
try {
payload = JSON.parse(payload);
} catch (error) {
console.error("Failed to parse friend-disconnected payload", error);
return;
}
unlistenFriendDisconnected = await listen<
[{ userId: string }] | { userId: string } | string
>("friend-disconnected", (event) => {
let payload = event.payload as any;
if (typeof payload === "string") {
try {
payload = JSON.parse(payload);
} catch (error) {
console.error("Failed to parse friend-disconnected payload", error);
return;
}
}
const data = Array.isArray(payload) ? payload[0] : payload;
const userId = data?.userId as string | undefined;
if (!userId) return;
const data = Array.isArray(payload) ? payload[0] : payload;
const userId = data?.userId as string | undefined;
if (!userId) return;
friendsUserStatuses.update((current) => {
const next = { ...current };
delete next[userId];
return next;
});
},
);
friendsUserStatuses.update((current) => {
const next = { ...current };
delete next[userId];
return next;
});
});
isListening = true;
} catch (error) {