feat(遊戲化): 新增大廳、附身、時間流、後日談進度等遊戲化系統功能
新增角色大廳(lobby)邀約與通話、附身(possession)、時鐘(clock)抽象、 時間流與睡眠負債、後日談進度、行為選擇與旁觀反應等模組,並補齊對應冒煙 測試(R~V)與單元測試;同步調整 web/mobile 對應頁面與元件。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import { createContext, useCallback, useContext, useMemo, useState, type ReactNode } from "react";
|
||||
|
||||
interface UnreadContextValue {
|
||||
hasUnread: boolean; // 推播觸發的提示 或 任一房間有未讀,兩者只要有一個成立即為 true
|
||||
markUnread: () => void; // Q-4:收到推播時呼叫
|
||||
markRead: () => void; // Q-4:使用者切回聊天分頁時呼叫,只清推播提示,不動各房未讀數
|
||||
roomUnreadCounts: Record<string, number>; // T20-P2:各進行中房間的未讀數(來自大廳聚合查詢)
|
||||
setRoomUnreadCounts: (counts: Record<string, number>) => void;
|
||||
totalRoomUnread: number;
|
||||
}
|
||||
|
||||
const UnreadContext = createContext<UnreadContextValue | null>(null);
|
||||
|
||||
// Q-4:聊天分頁的未讀/推播提示紅點狀態,由根佈局的推播接收監聽器寫入,
|
||||
// 由聊天分頁在取得焦點時清除(見 app/(tabs)/index.tsx 的 useFocusEffect)。
|
||||
// T20-P2:擴充承接大廳多房未讀——分頁籤紅點現在同時反映「有推播尚未看」與「任一房間有未讀訊息」,
|
||||
// 兩個來源各自獨立更新,互不覆蓋(推播清除不會把房間未讀數也清空,反之亦然)。
|
||||
export function UnreadProvider({ children }: { children: ReactNode }) {
|
||||
const [pushUnread, setPushUnread] = useState(false);
|
||||
const [roomUnreadCounts, setRoomUnreadCounts] = useState<Record<string, number>>({});
|
||||
const markUnread = useCallback(() => setPushUnread(true), []);
|
||||
const markRead = useCallback(() => setPushUnread(false), []);
|
||||
const totalRoomUnread = useMemo(
|
||||
() => Object.values(roomUnreadCounts).reduce((sum, count) => sum + count, 0),
|
||||
[roomUnreadCounts],
|
||||
);
|
||||
const hasUnread = pushUnread || totalRoomUnread > 0;
|
||||
|
||||
return (
|
||||
<UnreadContext.Provider
|
||||
value={{ hasUnread, markUnread, markRead, roomUnreadCounts, setRoomUnreadCounts, totalRoomUnread }}
|
||||
>
|
||||
{children}
|
||||
</UnreadContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useUnread(): UnreadContextValue {
|
||||
const ctx = useContext(UnreadContext);
|
||||
if (!ctx) {
|
||||
throw new Error("useUnread 必須在 UnreadProvider 底下使用");
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
Reference in New Issue
Block a user