diff --git a/src/app/page.tsx b/src/app/page.tsx index 0ac69eb..eb9cef3 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -52,6 +52,32 @@ export default function Page() { const init = useSessionStore((s) => s.init); const loading = useSessionStore((s) => s.loading); + // Auto-recover from stale-bundle chunk errors (a tab open across a redeploy + // requests JS chunks that no longer exist → "page couldn't load"). Reload once + // to fetch the fresh bundle; clear the guard after a healthy run. + useEffect(() => { + const isChunkErr = (m: string) => + /ChunkLoadError|Loading chunk|Failed to fetch dynamically imported|error loading dynamically imported|importing a module script failed/i.test(m); + const onErr = (e: ErrorEvent | PromiseRejectionEvent) => { + const msg = + ((e as ErrorEvent).message ?? "") + + " " + + (((e as PromiseRejectionEvent).reason as { message?: string })?.message ?? ""); + if (isChunkErr(msg) && !sessionStorage.getItem("hokm.chunkReload")) { + sessionStorage.setItem("hokm.chunkReload", "1"); + window.location.reload(); + } + }; + window.addEventListener("error", onErr); + window.addEventListener("unhandledrejection", onErr); + const clear = setTimeout(() => sessionStorage.removeItem("hokm.chunkReload"), 5000); + return () => { + window.removeEventListener("error", onErr); + window.removeEventListener("unhandledrejection", onErr); + clearTimeout(clear); + }; + }, []); + useEffect(() => { init(); diff --git a/src/components/GameTable.tsx b/src/components/GameTable.tsx index 312249f..a33d8bc 100644 --- a/src/components/GameTable.tsx +++ b/src/components/GameTable.tsx @@ -822,7 +822,7 @@ function Reactions() { initial={{ opacity: 0, y: 12, scale: 0.95 }} animate={{ opacity: 1, y: 0, scale: 1 }} exit={{ opacity: 0, y: 12, scale: 0.95 }} - className="absolute bottom-20 ltr:right-4 rtl:left-4 z-50 glass rounded-2xl p-2 w-[270px]" + className="absolute bottom-20 ltr:right-4 rtl:left-4 z-50 glass rounded-2xl p-2 w-[min(270px,86vw)]" >