v0.5.2: offline report + tab UI + persist race fix
- New: Offline earnings report dialog (welcome back popup with gain/duration/rate/progress) - src/lib/game/offlineReport.ts: module-level store + custom event - src/components/game/OfflineReportDialog.tsx: Radix Dialog UI - gameStore.init: setPendingOfflineReport before set() - Fix: useGameLoop waits for persist.hasHydrated() before init - Root cause: Zustand persist rehydrate is async (Promise.resolve wrapper) - Before fix: init read INITIAL_STATE (lastTick=undefined), skipped offline branch - After fix: init waits for rehydrate, correctly reads saved lastTick - UI: Tab bar redesign with per-tab accent colors + flex-col layout - Version: v0.5 -> v0.5.2
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
// 回响星核 / Echo Nexus — 离线收益报告(v0.5.2)
|
||||
// 模块级存储 + 自定义事件通知 UI,不污染 GameState
|
||||
|
||||
export interface OfflineReport {
|
||||
elapsedSec: number; // 离线秒数(已 cap)
|
||||
rawElapsedSec: number; // 实际离线秒数(未 cap)
|
||||
gain: number; // 获得晶体
|
||||
rate: number; // 离线时产能 /s
|
||||
eff: number; // 离线效率 0-1
|
||||
capped: boolean; // 是否触达 8h 上限
|
||||
crystalsBefore: number; // 补发前晶体
|
||||
crystalsAfter: number; // 补发后晶体
|
||||
crystalCap: number; // 仓库上限
|
||||
}
|
||||
|
||||
let pending: OfflineReport | null = null;
|
||||
|
||||
export function setPendingOfflineReport(r: OfflineReport) {
|
||||
pending = r;
|
||||
if (typeof window !== "undefined") {
|
||||
window.dispatchEvent(new CustomEvent("echo-nexus-offline-report"));
|
||||
}
|
||||
}
|
||||
|
||||
export function getPendingOfflineReport(): OfflineReport | null {
|
||||
return pending;
|
||||
}
|
||||
|
||||
export function consumeOfflineReport(): OfflineReport | null {
|
||||
const r = pending;
|
||||
pending = null;
|
||||
return r;
|
||||
}
|
||||
|
||||
/** 格式化时长为中文 */
|
||||
export function formatDuration(sec: number): string {
|
||||
if (sec < 60) return `${Math.floor(sec)}秒`;
|
||||
const m = Math.floor(sec / 60);
|
||||
if (m < 60) return `${m}分钟`;
|
||||
const h = Math.floor(m / 60);
|
||||
const remM = m % 60;
|
||||
if (h < 24) return remM > 0 ? `${h}小时${remM}分` : `${h}小时`;
|
||||
const d = Math.floor(h / 24);
|
||||
const remH = h % 24;
|
||||
return remH > 0 ? `${d}天${remH}小时` : `${d}天`;
|
||||
}
|
||||
Reference in New Issue
Block a user