"use client"; import { useCallback, useEffect, useState } from "react"; import type { TFunction } from "i18next"; import { getLotteryEcho } from "@/lib/lottery-echo"; import { formatMinorAsCurrency } from "@/lib/money"; import type { JackpotBurstEvent } from "@/features/hall/jackpot-burst-overlay"; function notifyBrowser(event: JackpotBurstEvent, t: TFunction<"player">): void { if (typeof window === "undefined" || !("Notification" in window)) { return; } const currency = event.currency_code.toUpperCase(); const amount = formatMinorAsCurrency(event.total_payout_amount, currency); const title = t("hall.jackpotBurst.notificationTitle"); const body = t("hall.jackpotBurst.notificationBody", { drawNo: event.draw_no, amount, }); const push = () => { try { new Notification(title, { body, tag: `jackpot-burst-${event.draw_id}` }); } catch { // 浏览器通知失败不影响页面内爆池动画。 } }; if (Notification.permission === "granted") { push(); return; } if (Notification.permission === "default") { void Notification.requestPermission().then((permission) => { if (permission === "granted") { push(); } }); } } export function useJackpotBurstLive(t: TFunction<"player">) { const [event, setEvent] = useState(null); const handleBurst = useCallback( (payload: JackpotBurstEvent) => { setEvent(payload); notifyBrowser(payload, t); window.dispatchEvent(new Event("lottery-wallet-refresh")); window.dispatchEvent(new Event("lottery-hall-refresh")); }, [t], ); useEffect(() => { const echo = getLotteryEcho(); if (!echo) return; const channel = echo.channel("lottery-hall"); channel.listen(".jackpot.burst", handleBurst); return () => { channel.stopListening(".jackpot.burst"); }; }, [handleBurst]); return { burstEvent: event, clearBurstEvent: () => setEvent(null), }; }