Add chat gifts and relationship diary UI
Docker Image / Quality and Bundle Budgets (push) Successful in 3s
Docker Image / Build and Push Docker Image (push) Successful in 1m55s

This commit is contained in:
Codex
2026-07-21 17:41:18 +08:00
parent dd7d7d5dcf
commit cc9fb9f4fd
54 changed files with 1950 additions and 69 deletions
+39
View File
@@ -0,0 +1,39 @@
import type { TipOfferActionRequest } from "@/data/schemas/chat";
import { chatApi } from "@/data/services/api/chat_api";
const SESSION_KEY_PREFIX = "cozsweet.tipOffer.session";
export function getTipOfferSessionId(characterId: string): string {
const key = `${SESSION_KEY_PREFIX}.${characterId}`;
try {
const existing = globalThis.sessionStorage.getItem(key);
if (existing) return existing;
const created = createSessionId();
globalThis.sessionStorage.setItem(key, created);
return created;
} catch {
return createSessionId();
}
}
export function recordTipOfferAction(
characterId: string,
action: TipOfferActionRequest["action"],
triggerSource: TipOfferActionRequest["triggerSource"],
): void {
void chatApi
.recordTipOfferAction({
characterId,
sessionId: getTipOfferSessionId(characterId),
action,
triggerSource,
})
.catch(() => undefined);
}
function createSessionId(): string {
if (typeof globalThis.crypto?.randomUUID === "function") {
return globalThis.crypto.randomUUID();
}
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 14)}`;
}
@@ -1,6 +1,7 @@
"use client";
import {
createPendingChatPromotion as createPromotion,
NavigationStorage,
type PendingChatUnlock,
type PendingChatUnlockKind,
@@ -17,6 +18,13 @@ export type {
PendingChatUnlockStage,
};
export function createPendingChatPromotion(
promotionType: PendingChatPromotionType,
characterId: string,
): PendingChatPromotion {
return createPromotion(promotionType, characterId);
}
export async function savePendingChatUnlock(input: {
characterId: string;
displayMessageId?: string;