Files
cozsweet-frontend-nextjs/src/lib/chat/chat_action_events.ts
T

101 lines
2.7 KiB
TypeScript

"use client";
import type {
ChatAction,
ChatActionEventType,
} from "@/data/schemas/chat";
import { chatApi } from "@/data/services/api";
const EVENT_PREFIX = "cozsweet:chat-action-event:v1";
const ARRIVAL_KEY = "cozsweet:chat-action-arrival:v1";
interface PendingChatActionArrival {
actionId: string;
characterId: string;
expectedPath: string;
}
export async function recordChatActionEvent(
action: ChatAction,
characterId: string,
eventType: ChatActionEventType,
): Promise<void> {
await recordChatActionEventById(action.actionId, characterId, eventType);
}
export async function recordChatActionEventById(
actionId: string,
characterId: string,
eventType: ChatActionEventType,
): Promise<void> {
await chatApi.recordActionEvent({
eventId: getOrCreateEventId(actionId, eventType),
actionId,
characterId,
eventType,
});
}
export function rememberChatActionArrival(
action: ChatAction,
characterId: string,
targetUrl: string,
): void {
if (typeof window === "undefined") return;
const target = new URL(targetUrl, window.location.origin);
if (target.origin !== window.location.origin) return;
const pending: PendingChatActionArrival = {
actionId: action.actionId,
characterId,
expectedPath: target.pathname,
};
window.sessionStorage.setItem(ARRIVAL_KEY, JSON.stringify(pending));
}
export function readPendingChatActionArrival(): PendingChatActionArrival | null {
if (typeof window === "undefined") return null;
try {
const raw = window.sessionStorage.getItem(ARRIVAL_KEY);
if (!raw) return null;
const parsed = JSON.parse(raw) as Partial<PendingChatActionArrival>;
if (!parsed.actionId || !parsed.characterId || !parsed.expectedPath) {
return null;
}
return parsed as PendingChatActionArrival;
} catch {
return null;
}
}
export function clearPendingChatActionArrival(): void {
if (typeof window === "undefined") return;
window.sessionStorage.removeItem(ARRIVAL_KEY);
}
function getOrCreateEventId(
actionId: string,
eventType: ChatActionEventType,
): string {
const key = `${EVENT_PREFIX}:${actionId}:${eventType}`;
if (typeof window !== "undefined") {
const existing = window.sessionStorage.getItem(key);
if (existing) return existing;
}
const eventId = createUuid();
if (typeof window !== "undefined") {
window.sessionStorage.setItem(key, eventId);
}
return eventId;
}
function createUuid(): string {
if (typeof globalThis.crypto?.randomUUID === "function") {
return globalThis.crypto.randomUUID();
}
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (value) => {
const random = Math.floor(Math.random() * 16);
const next = value === "x" ? random : (random & 0x3) | 0x8;
return next.toString(16);
});
}