@hadoku/watchparty-ui 0.44.16 → 0.44.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. package/dist/chunks/{AdminPanel-CJtacvRu.js → AdminPanel-x_k_Hefb.js} +12 -12
  2. package/dist/chunks/{AdminPanel-CJtacvRu.js.map → AdminPanel-x_k_Hefb.js.map} +1 -1
  3. package/dist/chunks/{GameModule-BvqNQcVk.js → GameModule-D71uhFdW.js} +19 -19
  4. package/dist/chunks/{GameModule-BvqNQcVk.js.map → GameModule-D71uhFdW.js.map} +1 -1
  5. package/dist/chunks/{MapEditor-Bc0_hjZQ.js → MapEditor-gB0UYuFm.js} +2 -2
  6. package/dist/chunks/{MapEditor-Bc0_hjZQ.js.map → MapEditor-gB0UYuFm.js.map} +1 -1
  7. package/dist/chunks/{MediaDrawer-CgoGUHwV.js → MediaDrawer-DYNPH01V.js} +51 -51
  8. package/dist/chunks/{MediaDrawer-CgoGUHwV.js.map → MediaDrawer-DYNPH01V.js.map} +1 -1
  9. package/dist/chunks/{PlaylistPanel-BmKnGMqa.js → PlaylistPanel-CYNImBh_.js} +20 -20
  10. package/dist/chunks/{PlaylistPanel-BmKnGMqa.js.map → PlaylistPanel-CYNImBh_.js.map} +1 -1
  11. package/dist/chunks/{Room-CoE8L9aw.js → Room-C1DWAuT8.js} +464 -459
  12. package/dist/chunks/Room-C1DWAuT8.js.map +1 -0
  13. package/dist/chunks/{index-Buah62TP.js → index-DWgUNApo.js} +1295 -1319
  14. package/dist/chunks/index-DWgUNApo.js.map +1 -0
  15. package/dist/chunks/{submissionsApi-DXsG0ItW.js → submissionsApi-D9R81t17.js} +21 -21
  16. package/dist/chunks/{submissionsApi-DXsG0ItW.js.map → submissionsApi-D9R81t17.js.map} +1 -1
  17. package/dist/index.js +1 -1
  18. package/dist/room-chrome.css +1 -1
  19. package/dist/room-chrome.js +644 -658
  20. package/dist/room-chrome.js.map +1 -1
  21. package/package.json +4 -4
  22. package/dist/chunks/Room-CoE8L9aw.js.map +0 -1
  23. package/dist/chunks/index-Buah62TP.js.map +0 -1
@@ -1,15 +1,15 @@
1
1
  import { jsxs as n, jsx as t } from "react/jsx-runtime";
2
- import { h as R, aO as M, a1 as E } from "./index-Buah62TP.js";
3
- import { useState as f, useRef as A, useCallback as F, useEffect as I } from "react";
4
- import { l as $, a as w, m as P, n as B, r as O, o as T, p as C } from "./submissionsApi-DXsG0ItW.js";
5
- import { c as D, B as U } from "./Room-CoE8L9aw.js";
2
+ import { h as M, aM as R, $ as E } from "./index-DWgUNApo.js";
3
+ import { useState as f, useRef as $, useCallback as A, useEffect as F } from "react";
4
+ import { l as I, a as w, m as P, n as B, r as T, o as D, p as C } from "./submissionsApi-D9R81t17.js";
5
+ import { c as O, B as U } from "./Room-C1DWAuT8.js";
6
6
  const H = 5e3, q = 8e3;
7
7
  function K() {
8
- const [s, r] = f(null), [d, m] = f(null), [c, a] = f({}), [i, p] = f(null), [x, b] = f(null), [v, h] = f(""), [y, L] = f(() => Date.now()), g = A(!0), _ = F(async () => {
9
- const e = await $();
8
+ const [s, r] = f(null), [d, m] = f(null), [c, a] = f({}), [i, p] = f(null), [x, b] = f(null), [v, h] = f(""), [y, L] = f(() => Date.now()), g = $(!0), _ = A(async () => {
9
+ const e = await I();
10
10
  g.current && (L(Date.now()), e.ok ? (r(e.value), m(null)) : m(e.failure));
11
11
  }, []);
12
- I(() => {
12
+ F(() => {
13
13
  g.current = !0;
14
14
  const e = setTimeout(() => {
15
15
  _();
@@ -28,8 +28,8 @@ function K() {
28
28
  async function S(e, o) {
29
29
  if (i) return;
30
30
  p(e.id);
31
- const u = o === "approve" ? await B(e.id) : await O(e.id, v);
32
- p(null), g.current && (u.ok ? (b(null), h(""), r((l) => (l ?? []).filter((N) => N.id !== e.id)), j(e, u.value.state, "info")) : T(u.failure) ? (b(null), r((l) => (l ?? []).filter((N) => N.id !== e.id)), j(e, C(u.failure), "error")) : j(e, C(u.failure), "error"), _());
31
+ const u = o === "approve" ? await B(e.id) : await T(e.id, v);
32
+ p(null), g.current && (u.ok ? (b(null), h(""), r((l) => (l ?? []).filter((N) => N.id !== e.id)), j(e, u.value.state, "info")) : D(u.failure) ? (b(null), r((l) => (l ?? []).filter((N) => N.id !== e.id)), j(e, C(u.failure), "error")) : j(e, C(u.failure), "error"), _());
33
33
  }
34
34
  const k = [
35
35
  ...(s ?? []).map((e) => ({ row: e, note: c[e.id] })),
@@ -137,7 +137,7 @@ function K() {
137
137
  ] });
138
138
  }
139
139
  function Z() {
140
- const r = R((a) => a.healthSnapshot)?.clients ?? [], d = [...r].sort((a, i) => a.avg_download_rate_bps - i.avg_download_rate_bps), m = Q(d), c = M() ? /* @__PURE__ */ t(K, {}) : null;
140
+ const r = M((a) => a.healthSnapshot)?.clients ?? [], d = [...r].sort((a, i) => a.avg_download_rate_bps - i.avg_download_rate_bps), m = Q(d), c = R() ? /* @__PURE__ */ t(K, {}) : null;
141
141
  return r.length === 0 ? /* @__PURE__ */ n("div", { className: "flex-1 overflow-y-auto p-2 flex flex-col", children: [
142
142
  /* @__PURE__ */ t("div", { className: "flex-1 flex items-center justify-center p-4", children: /* @__PURE__ */ n("p", { className: "text-text-muted text-xs text-center", children: [
143
143
  "No health data yet.",
@@ -172,7 +172,7 @@ function Q(s) {
172
172
  return r;
173
173
  }
174
174
  function z({ client: s, initial: r }) {
175
- const m = (Math.round(s.avg_download_rate_bps / 1024) / 1024).toFixed(1), c = (s.buffered_ahead_ms / 1e3).toFixed(1), a = Math.round(s.rtt_ms), i = D(s), p = s.stale_ms !== void 0, x = p ? `Silent ${Math.round(s.stale_ms / 1e3)}s` : U[i], b = p || i === "critical" || i === "buffering", v = b ? "text-danger bg-danger/10" : i === "idle" ? "text-text-muted bg-bg-alt/40" : i === "warning" ? "text-on-neutral-bg bg-neutral/10" : "text-success bg-success/10", h = b ? "bg-danger" : i === "warning" ? "bg-neutral-bg" : "bg-success", y = Math.min(100, s.buffered_ahead_ms / E * 100);
175
+ const m = (Math.round(s.avg_download_rate_bps / 1024) / 1024).toFixed(1), c = (s.buffered_ahead_ms / 1e3).toFixed(1), a = Math.round(s.rtt_ms), i = O(s), p = s.stale_ms !== void 0, x = p ? `Silent ${Math.round(s.stale_ms / 1e3)}s` : U[i], b = p || i === "critical" || i === "buffering", v = b ? "text-danger bg-danger/10" : i === "idle" ? "text-text-muted bg-bg-alt/40" : i === "warning" ? "text-on-neutral-bg bg-neutral/10" : "text-success bg-success/10", h = b ? "bg-danger" : i === "warning" ? "bg-neutral-bg" : "bg-success", y = Math.min(100, s.buffered_ahead_ms / E * 100);
176
176
  return /* @__PURE__ */ n("div", { className: "rounded-lg border border-border/50 bg-bg-alt/20 p-2.5", "data-silent": p || void 0, children: [
177
177
  /* @__PURE__ */ n("div", { className: "flex items-center justify-between mb-2", children: [
178
178
  /* @__PURE__ */ n("div", { className: "flex items-center gap-2 min-w-0", children: [
@@ -224,4 +224,4 @@ function z({ client: s, initial: r }) {
224
224
  export {
225
225
  Z as default
226
226
  };
227
- //# sourceMappingURL=AdminPanel-CJtacvRu.js.map
227
+ //# sourceMappingURL=AdminPanel-x_k_Hefb.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AdminPanel-CJtacvRu.js","sources":["../../src/components/SubmissionQueue.tsx","../../src/components/AdminPanel.tsx"],"sourcesContent":["/**\n * The operator's moderation queue — every `pending` submission, with approve\n * and reject per row. Service tier only (the routes are `serviceAuth`; the\n * caller gates rendering on `isPrivileged()`, and a refusal is shown rather\n * than hidden if the gate and the server ever disagree).\n *\n * A row the server says has already moved (409, or 404 once it is gone) is not\n * an error in the click — a stale queue page is the ordinary way to meet it —\n * so it stays in place carrying the outcome, then drops off after\n * `NOTE_LINGER_MS`. Dropping it at once would make the click look like it did\n * nothing.\n *\n * Buttons carry real classes (`.drawer-btn`): the unlayered `button` reset\n * discards every Tailwind colour/font utility on a `<button>`.\n */\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { TSubmission } from '@watchparty/shared';\n/** `TSubmission` plus the `series` field the shared schema gains for magnets\n * (packages/shared/src/submissions.ts) — a cast rather than a schema edit,\n * since this file does not own that schema; harmless once the real field\n * lands, since the shapes agree. */\ntype SubmissionWithSeries = TSubmission & { series?: string };\nimport {\n approveSubmission,\n decisionFailureLabel,\n decisionMeansRowMoved,\n fetchPendingSubmissions,\n formatSubmissionAge,\n rejectSubmission,\n submissionFailureLabel,\n type SubmissionFailure,\n} from '../lib/submissionsApi';\n\nconst POLL_MS = 5000;\nconst NOTE_LINGER_MS = 8000;\n\ninterface Note { row: TSubmission; message: string; tone: 'info' | 'error' }\n\nexport default function SubmissionQueue() {\n const [rows, setRows] = useState<TSubmission[] | null>(null);\n const [listFailure, setListFailure] = useState<SubmissionFailure | null>(null);\n const [notes, setNotes] = useState<Record<string, Note>>({});\n const [busyId, setBusyId] = useState<string | null>(null);\n const [rejectingId, setRejectingId] = useState<string | null>(null);\n const [reason, setReason] = useState('');\n const [now, setNow] = useState(() => Date.now());\n const liveRef = useRef(true);\n\n const refresh = useCallback(async () => {\n const res = await fetchPendingSubmissions();\n if (!liveRef.current) return;\n setNow(Date.now());\n if (res.ok) { setRows(res.value); setListFailure(null); }\n else { setListFailure(res.failure); }\n }, []);\n\n useEffect(() => {\n liveRef.current = true;\n // Deferred a tick: the first read is a subscription callback, not a\n // synchronous setState in the effect body.\n const first = setTimeout(() => { void refresh(); }, 0);\n const timer = setInterval(() => { void refresh(); }, POLL_MS);\n return () => { liveRef.current = false; clearTimeout(first); clearInterval(timer); };\n }, [refresh]);\n\n function leaveNote(row: TSubmission, message: string, tone: Note['tone']) {\n setNotes(prev => ({ ...prev, [row.id]: { row, message, tone } }));\n setTimeout(() => {\n if (!liveRef.current) return;\n setNotes(prev => Object.fromEntries(Object.entries(prev).filter(([id]) => id !== row.id)));\n }, NOTE_LINGER_MS);\n }\n\n async function decide(row: TSubmission, verb: 'approve' | 'reject') {\n if (busyId) return;\n setBusyId(row.id);\n const res = verb === 'approve'\n ? await approveSubmission(row.id)\n : await rejectSubmission(row.id, reason);\n setBusyId(null);\n if (!liveRef.current) return;\n if (res.ok) {\n setRejectingId(null);\n setReason('');\n setRows(prev => (prev ?? []).filter(r => r.id !== row.id));\n leaveNote(row, res.value.state, 'info');\n } else if (decisionMeansRowMoved(res.failure)) {\n setRejectingId(null);\n setRows(prev => (prev ?? []).filter(r => r.id !== row.id));\n leaveNote(row, decisionFailureLabel(res.failure), 'error');\n } else {\n leaveNote(row, decisionFailureLabel(res.failure), 'error');\n }\n void refresh();\n }\n\n const shown = [\n ...(rows ?? []).map(r => ({ row: r, note: notes[r.id] })),\n ...Object.values(notes)\n .filter(n => !(rows ?? []).some(r => r.id === n.row.id))\n .map(n => ({ row: n.row, note: n })),\n ];\n\n // Nothing to moderate is shown as nothing — no header, no \"(none)\". A list\n // failure still renders, since that IS state the leader needs to see.\n if (!listFailure && shown.length === 0) return null;\n\n return (\n <section className=\"border-t border-border pt-2\" data-testid=\"submission-queue\">\n <div className=\"flex items-center px-1 pb-1\">\n <span className=\"text-[10px] uppercase tracking-wider text-text-muted\">Submissions</span>\n <span className=\"ml-1 text-[10px] text-text-muted\" data-testid=\"submission-queue-count\">\n {rows?.length ?? 0}\n </span>\n </div>\n {listFailure && (\n <div className=\"px-2 py-1 text-[11px] bg-danger-bg text-on-danger-bg rounded\">{submissionFailureLabel(listFailure)}</div>\n )}\n <ul className=\"list-none m-0 p-0\">\n {shown.map(({ row, note }) => {\n const decided = note && !(rows ?? []).some(r => r.id === row.id);\n return (\n <li\n key={row.id}\n className=\"px-1 py-1.5 border-b border-border/50 flex flex-col gap-1\"\n data-submission-id={row.id}\n data-submission-state={decided ? 'decided' : row.state}\n data-submission-kind={row.kind}\n data-submission-series={(row as SubmissionWithSeries).series ?? ''}\n >\n <div className=\"flex items-center gap-2 text-[11px] min-w-0\">\n <span className=\"text-[10px] uppercase tracking-wider text-text-muted shrink-0\">{row.kind}</span>\n <span className=\"text-text truncate flex-1\" title={row.source}>\n {(row as SubmissionWithSeries).series\n ? `${(row as SubmissionWithSeries).series} — ${row.title || row.source}`\n : (row.title || row.source)}\n </span>\n <span className=\"text-text-muted shrink-0\">{formatSubmissionAge(row.createdAt, now)}</span>\n </div>\n <div className=\"text-[10px] text-text-muted truncate\" title={row.ownerUserId}>{row.ownerUserId}</div>\n {note && (\n <div\n data-testid=\"submission-decision-note\"\n className={`text-[11px] px-1.5 py-0.5 rounded ${note.tone === 'error' ? 'bg-danger-bg text-on-danger-bg' : 'bg-success-bg text-on-success-bg'}`}\n >\n {note.message}\n </div>\n )}\n {!decided && rejectingId === row.id ? (\n <div className=\"flex items-center gap-1\">\n <input\n value={reason}\n onChange={e => setReason(e.target.value)}\n onKeyDown={e => { if (e.key === 'Enter') void decide(row, 'reject'); }}\n aria-label=\"Reject reason\"\n placeholder=\"reason\"\n className=\"flex-1 min-w-0 bg-bg-alt border border-border outline-none px-2 py-0.5 rounded text-[11px]\"\n />\n <button\n className=\"drawer-btn drawer-btn-danger\"\n aria-label=\"Confirm reject\"\n disabled={busyId === row.id}\n onClick={() => { void decide(row, 'reject'); }}\n >\n Reject\n </button>\n <button\n className=\"drawer-btn\"\n aria-label=\"Cancel reject\"\n onClick={() => { setRejectingId(null); setReason(''); }}\n >\n Cancel\n </button>\n </div>\n ) : !decided && (\n <div className=\"flex items-center gap-1\">\n <button\n className=\"drawer-btn drawer-btn-primary\"\n aria-label=\"Approve submission\"\n disabled={busyId === row.id}\n onClick={() => { void decide(row, 'approve'); }}\n >\n Approve\n </button>\n <button\n className=\"drawer-btn\"\n aria-label=\"Reject submission\"\n disabled={busyId === row.id}\n onClick={() => { setRejectingId(row.id); setReason(''); }}\n >\n Reject\n </button>\n </div>\n )}\n </li>\n );\n })}\n </ul>\n </section>\n );\n}\n","import { useAppStore } from '../lib/store';\nimport { BUFFER_AHEAD_MS, type TClientHealth } from '@watchparty/shared';\nimport { isPrivileged } from '../lib/auth';\nimport SubmissionQueue from './SubmissionQueue';\nimport { bufferHealthLevel, BUFFER_HEALTH_LABEL } from './bufferHealth';\n\n/**\n * Health monitor panel — renders as sidebar content (replaces chat when active).\n * Shows a card per connected client with live health metrics.\n */\nexport default function AdminPanel() {\n const healthSnapshot = useAppStore(s => s.healthSnapshot);\n\n const clients = healthSnapshot?.clients ?? [];\n // Slowest download first — easiest to spot struggling clients\n const sorted = [...clients].sort((a, b) => a.avg_download_rate_bps - b.avg_download_rate_bps);\n\n const initials = computeInitials(sorted);\n // Moderation is service tier, like the routes behind it.\n const queue = isPrivileged() ? <SubmissionQueue /> : null;\n\n if (clients.length === 0) {\n return (\n <div className=\"flex-1 overflow-y-auto p-2 flex flex-col\">\n <div className=\"flex-1 flex items-center justify-center p-4\">\n <p className=\"text-text-muted text-xs text-center\">\n No health data yet.<br />Clients report once media is loaded.\n </p>\n </div>\n {queue}\n </div>\n );\n }\n\n return (\n <div className=\"flex-1 overflow-y-auto p-2 space-y-2\">\n {sorted.map(c => <ClientCard key={c.client_id} client={c} initial={initials[c.client_id]} />)}\n {queue}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n\nfunction formatTime(ms: number): string {\n const totalSecs = Math.floor(ms / 1000);\n const mins = Math.floor(totalSecs / 60);\n const secs = totalSecs % 60;\n return `${mins}:${secs.toString().padStart(2, '0')}`;\n}\n\n// Initials are first alphanumeric of display name; on conflict, advance to next\n// unused alphanumeric letter in the same name. Stable across renders via client_id sort.\nfunction computeInitials(clients: TClientHealth[]): Record<string, string> {\n const out: Record<string, string> = {};\n const taken = new Set<string>();\n const ordered = [...clients].sort((a, b) => a.client_id.localeCompare(b.client_id));\n for (const c of ordered) {\n const name = c.name ?? '';\n let chosen = '?';\n for (const ch of name) {\n if (!/[\\p{L}\\p{N}]/u.test(ch)) continue;\n const up = ch.toUpperCase();\n if (!taken.has(up)) { chosen = up; taken.add(up); break; }\n }\n out[c.client_id] = chosen;\n }\n return out;\n}\n\nfunction ClientCard({ client, initial }: { client: TClientHealth; initial: string }) {\n const dlKbps = Math.round(client.avg_download_rate_bps / 1024);\n const dlMbps = (dlKbps / 1024).toFixed(1);\n const bufferS = (client.buffered_ahead_ms / 1000).toFixed(1);\n const rtt = Math.round(client.rtt_ms);\n\n // Idle: not playing, no meaningful position — don't alarm about \"Critical\".\n // Near end-of-stream is exempt from the buffered-ahead thresholds (see\n // bufferHealth.ts) so the final seconds of every episode don't false-Critical.\n const level = bufferHealthLevel(client);\n // A connected client whose reports stopped arriving: the figures below are\n // its last known state, and the silence itself is the status.\n const silent = client.stale_ms !== undefined;\n const statusLabel = silent ? `Silent ${Math.round(client.stale_ms! / 1000)}s` : BUFFER_HEALTH_LABEL[level];\n const isRed = silent || level === 'critical' || level === 'buffering';\n const statusClasses = isRed\n ? 'text-danger bg-danger/10'\n : level === 'idle'\n ? 'text-text-muted bg-bg-alt/40'\n : level === 'warning'\n ? 'text-on-neutral-bg bg-neutral/10'\n : 'text-success bg-success/10';\n\n const barColor = isRed ? 'bg-danger' : level === 'warning' ? 'bg-neutral-bg' : 'bg-success';\n const barPct = Math.min(100, (client.buffered_ahead_ms / BUFFER_AHEAD_MS) * 100);\n\n return (\n <div className=\"rounded-lg border border-border/50 bg-bg-alt/20 p-2.5\" data-silent={silent || undefined}>\n {/* Row 1: Name + Status */}\n <div className=\"flex items-center justify-between mb-2\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <div className=\"w-5 h-5 rounded-full bg-bg-alt flex items-center justify-center text-[9px] font-semibold shrink-0\">\n {initial}\n </div>\n <span className=\"text-sm font-medium text-text truncate\">{client.name}</span>\n </div>\n <span className={`inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium shrink-0 ${statusClasses}`}>\n {statusLabel}\n </span>\n </div>\n\n {/* Row 2: Stats grid */}\n <div className={`grid grid-cols-3 gap-x-2 gap-y-1 text-[11px] ${silent ? 'opacity-50' : ''}`}>\n <div>\n <span className=\"text-text-muted\">DL</span>\n <span className=\"ml-1 font-mono text-text\">{dlMbps}</span>\n <span className=\"text-text-muted ml-0.5\">Mbps</span>\n </div>\n <div>\n <span className=\"text-text-muted\">Ping</span>\n <span className=\"ml-1 font-mono text-text\">{rtt}</span>\n <span className=\"text-text-muted ml-0.5\">ms</span>\n </div>\n <div>\n <span className=\"text-text-muted\">Pos</span>\n <span className=\"ml-1 font-mono text-text-secondary\">{formatTime(client.playhead_ms)}</span>\n </div>\n\n {/* Buffer row spans full width */}\n <div className=\"col-span-2 flex items-center gap-1.5\">\n <span className=\"text-text-muted\">Buf</span>\n <span className=\"font-mono text-text\">{bufferS}s</span>\n <div className=\"flex-1 h-1 bg-bg-alt rounded-full overflow-hidden\">\n <div className={`h-full rounded-full transition-all ${barColor}`} style={{ width: `${barPct}%` }} />\n </div>\n </div>\n <div className=\"flex gap-1 font-mono justify-end\">\n <span className=\"bg-success-bg text-on-success-bg px-1 rounded\">{client.fragments_loaded}L</span>\n <span className=\"text-text-muted\">{client.fragments_pending}P</span>\n {client.fragments_error > 0 && <span className=\"bg-danger-bg text-on-danger-bg px-1 rounded\">{client.fragments_error}E</span>}\n </div>\n </div>\n </div>\n );\n}\n"],"names":["POLL_MS","NOTE_LINGER_MS","SubmissionQueue","rows","setRows","useState","listFailure","setListFailure","notes","setNotes","busyId","setBusyId","rejectingId","setRejectingId","reason","setReason","now","setNow","liveRef","useRef","refresh","useCallback","res","fetchPendingSubmissions","useEffect","first","timer","leaveNote","row","message","tone","prev","id","decide","verb","approveSubmission","rejectSubmission","r","decisionMeansRowMoved","decisionFailureLabel","shown","n","jsxs","jsx","submissionFailureLabel","note","decided","e","AdminPanel","clients","useAppStore","s","sorted","b","initials","computeInitials","queue","isPrivileged","c","ClientCard","formatTime","ms","totalSecs","mins","secs","out","taken","ordered","a","name","chosen","ch","up","client","initial","dlMbps","bufferS","rtt","level","bufferHealthLevel","silent","statusLabel","BUFFER_HEALTH_LABEL","isRed","statusClasses","barColor","barPct","BUFFER_AHEAD_MS"],"mappings":"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"}
1
+ {"version":3,"file":"AdminPanel-x_k_Hefb.js","sources":["../../src/components/SubmissionQueue.tsx","../../src/components/AdminPanel.tsx"],"sourcesContent":["/**\n * The operator's moderation queue — every `pending` submission, with approve\n * and reject per row. Service tier only (the routes are `serviceAuth`; the\n * caller gates rendering on `isPrivileged()`, and a refusal is shown rather\n * than hidden if the gate and the server ever disagree).\n *\n * A row the server says has already moved (409, or 404 once it is gone) is not\n * an error in the click — a stale queue page is the ordinary way to meet it —\n * so it stays in place carrying the outcome, then drops off after\n * `NOTE_LINGER_MS`. Dropping it at once would make the click look like it did\n * nothing.\n *\n * Buttons carry real classes (`.drawer-btn`): the unlayered `button` reset\n * discards every Tailwind colour/font utility on a `<button>`.\n */\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { TSubmission } from '@watchparty/shared';\n/** `TSubmission` plus the `series` field the shared schema gains for magnets\n * (packages/shared/src/submissions.ts) — a cast rather than a schema edit,\n * since this file does not own that schema; harmless once the real field\n * lands, since the shapes agree. */\ntype SubmissionWithSeries = TSubmission & { series?: string };\nimport {\n approveSubmission,\n decisionFailureLabel,\n decisionMeansRowMoved,\n fetchPendingSubmissions,\n formatSubmissionAge,\n rejectSubmission,\n submissionFailureLabel,\n type SubmissionFailure,\n} from '../lib/submissionsApi';\n\nconst POLL_MS = 5000;\nconst NOTE_LINGER_MS = 8000;\n\ninterface Note { row: TSubmission; message: string; tone: 'info' | 'error' }\n\nexport default function SubmissionQueue() {\n const [rows, setRows] = useState<TSubmission[] | null>(null);\n const [listFailure, setListFailure] = useState<SubmissionFailure | null>(null);\n const [notes, setNotes] = useState<Record<string, Note>>({});\n const [busyId, setBusyId] = useState<string | null>(null);\n const [rejectingId, setRejectingId] = useState<string | null>(null);\n const [reason, setReason] = useState('');\n const [now, setNow] = useState(() => Date.now());\n const liveRef = useRef(true);\n\n const refresh = useCallback(async () => {\n const res = await fetchPendingSubmissions();\n if (!liveRef.current) return;\n setNow(Date.now());\n if (res.ok) { setRows(res.value); setListFailure(null); }\n else { setListFailure(res.failure); }\n }, []);\n\n useEffect(() => {\n liveRef.current = true;\n // Deferred a tick: the first read is a subscription callback, not a\n // synchronous setState in the effect body.\n const first = setTimeout(() => { void refresh(); }, 0);\n const timer = setInterval(() => { void refresh(); }, POLL_MS);\n return () => { liveRef.current = false; clearTimeout(first); clearInterval(timer); };\n }, [refresh]);\n\n function leaveNote(row: TSubmission, message: string, tone: Note['tone']) {\n setNotes(prev => ({ ...prev, [row.id]: { row, message, tone } }));\n setTimeout(() => {\n if (!liveRef.current) return;\n setNotes(prev => Object.fromEntries(Object.entries(prev).filter(([id]) => id !== row.id)));\n }, NOTE_LINGER_MS);\n }\n\n async function decide(row: TSubmission, verb: 'approve' | 'reject') {\n if (busyId) return;\n setBusyId(row.id);\n const res = verb === 'approve'\n ? await approveSubmission(row.id)\n : await rejectSubmission(row.id, reason);\n setBusyId(null);\n if (!liveRef.current) return;\n if (res.ok) {\n setRejectingId(null);\n setReason('');\n setRows(prev => (prev ?? []).filter(r => r.id !== row.id));\n leaveNote(row, res.value.state, 'info');\n } else if (decisionMeansRowMoved(res.failure)) {\n setRejectingId(null);\n setRows(prev => (prev ?? []).filter(r => r.id !== row.id));\n leaveNote(row, decisionFailureLabel(res.failure), 'error');\n } else {\n leaveNote(row, decisionFailureLabel(res.failure), 'error');\n }\n void refresh();\n }\n\n const shown = [\n ...(rows ?? []).map(r => ({ row: r, note: notes[r.id] })),\n ...Object.values(notes)\n .filter(n => !(rows ?? []).some(r => r.id === n.row.id))\n .map(n => ({ row: n.row, note: n })),\n ];\n\n // Nothing to moderate is shown as nothing — no header, no \"(none)\". A list\n // failure still renders, since that IS state the leader needs to see.\n if (!listFailure && shown.length === 0) return null;\n\n return (\n <section className=\"border-t border-border pt-2\" data-testid=\"submission-queue\">\n <div className=\"flex items-center px-1 pb-1\">\n <span className=\"text-[10px] uppercase tracking-wider text-text-muted\">Submissions</span>\n <span className=\"ml-1 text-[10px] text-text-muted\" data-testid=\"submission-queue-count\">\n {rows?.length ?? 0}\n </span>\n </div>\n {listFailure && (\n <div className=\"px-2 py-1 text-[11px] bg-danger-bg text-on-danger-bg rounded\">{submissionFailureLabel(listFailure)}</div>\n )}\n <ul className=\"list-none m-0 p-0\">\n {shown.map(({ row, note }) => {\n const decided = note && !(rows ?? []).some(r => r.id === row.id);\n return (\n <li\n key={row.id}\n className=\"px-1 py-1.5 border-b border-border/50 flex flex-col gap-1\"\n data-submission-id={row.id}\n data-submission-state={decided ? 'decided' : row.state}\n data-submission-kind={row.kind}\n data-submission-series={(row as SubmissionWithSeries).series ?? ''}\n >\n <div className=\"flex items-center gap-2 text-[11px] min-w-0\">\n <span className=\"text-[10px] uppercase tracking-wider text-text-muted shrink-0\">{row.kind}</span>\n <span className=\"text-text truncate flex-1\" title={row.source}>\n {(row as SubmissionWithSeries).series\n ? `${(row as SubmissionWithSeries).series} — ${row.title || row.source}`\n : (row.title || row.source)}\n </span>\n <span className=\"text-text-muted shrink-0\">{formatSubmissionAge(row.createdAt, now)}</span>\n </div>\n <div className=\"text-[10px] text-text-muted truncate\" title={row.ownerUserId}>{row.ownerUserId}</div>\n {note && (\n <div\n data-testid=\"submission-decision-note\"\n className={`text-[11px] px-1.5 py-0.5 rounded ${note.tone === 'error' ? 'bg-danger-bg text-on-danger-bg' : 'bg-success-bg text-on-success-bg'}`}\n >\n {note.message}\n </div>\n )}\n {!decided && rejectingId === row.id ? (\n <div className=\"flex items-center gap-1\">\n <input\n value={reason}\n onChange={e => setReason(e.target.value)}\n onKeyDown={e => { if (e.key === 'Enter') void decide(row, 'reject'); }}\n aria-label=\"Reject reason\"\n placeholder=\"reason\"\n className=\"flex-1 min-w-0 bg-bg-alt border border-border outline-none px-2 py-0.5 rounded text-[11px]\"\n />\n <button\n className=\"drawer-btn drawer-btn-danger\"\n aria-label=\"Confirm reject\"\n disabled={busyId === row.id}\n onClick={() => { void decide(row, 'reject'); }}\n >\n Reject\n </button>\n <button\n className=\"drawer-btn\"\n aria-label=\"Cancel reject\"\n onClick={() => { setRejectingId(null); setReason(''); }}\n >\n Cancel\n </button>\n </div>\n ) : !decided && (\n <div className=\"flex items-center gap-1\">\n <button\n className=\"drawer-btn drawer-btn-primary\"\n aria-label=\"Approve submission\"\n disabled={busyId === row.id}\n onClick={() => { void decide(row, 'approve'); }}\n >\n Approve\n </button>\n <button\n className=\"drawer-btn\"\n aria-label=\"Reject submission\"\n disabled={busyId === row.id}\n onClick={() => { setRejectingId(row.id); setReason(''); }}\n >\n Reject\n </button>\n </div>\n )}\n </li>\n );\n })}\n </ul>\n </section>\n );\n}\n","import { useAppStore } from '../lib/store';\nimport { BUFFER_AHEAD_MS, type TClientHealth } from '@watchparty/shared';\nimport { isPrivileged } from '../lib/auth';\nimport SubmissionQueue from './SubmissionQueue';\nimport { bufferHealthLevel, BUFFER_HEALTH_LABEL } from './bufferHealth';\n\n/**\n * Health monitor panel — renders as sidebar content (replaces chat when active).\n * Shows a card per connected client with live health metrics.\n */\nexport default function AdminPanel() {\n const healthSnapshot = useAppStore(s => s.healthSnapshot);\n\n const clients = healthSnapshot?.clients ?? [];\n // Slowest download first — easiest to spot struggling clients\n const sorted = [...clients].sort((a, b) => a.avg_download_rate_bps - b.avg_download_rate_bps);\n\n const initials = computeInitials(sorted);\n // Moderation is service tier, like the routes behind it.\n const queue = isPrivileged() ? <SubmissionQueue /> : null;\n\n if (clients.length === 0) {\n return (\n <div className=\"flex-1 overflow-y-auto p-2 flex flex-col\">\n <div className=\"flex-1 flex items-center justify-center p-4\">\n <p className=\"text-text-muted text-xs text-center\">\n No health data yet.<br />Clients report once media is loaded.\n </p>\n </div>\n {queue}\n </div>\n );\n }\n\n return (\n <div className=\"flex-1 overflow-y-auto p-2 space-y-2\">\n {sorted.map(c => <ClientCard key={c.client_id} client={c} initial={initials[c.client_id]} />)}\n {queue}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n\nfunction formatTime(ms: number): string {\n const totalSecs = Math.floor(ms / 1000);\n const mins = Math.floor(totalSecs / 60);\n const secs = totalSecs % 60;\n return `${mins}:${secs.toString().padStart(2, '0')}`;\n}\n\n// Initials are first alphanumeric of display name; on conflict, advance to next\n// unused alphanumeric letter in the same name. Stable across renders via client_id sort.\nfunction computeInitials(clients: TClientHealth[]): Record<string, string> {\n const out: Record<string, string> = {};\n const taken = new Set<string>();\n const ordered = [...clients].sort((a, b) => a.client_id.localeCompare(b.client_id));\n for (const c of ordered) {\n const name = c.name ?? '';\n let chosen = '?';\n for (const ch of name) {\n if (!/[\\p{L}\\p{N}]/u.test(ch)) continue;\n const up = ch.toUpperCase();\n if (!taken.has(up)) { chosen = up; taken.add(up); break; }\n }\n out[c.client_id] = chosen;\n }\n return out;\n}\n\nfunction ClientCard({ client, initial }: { client: TClientHealth; initial: string }) {\n const dlKbps = Math.round(client.avg_download_rate_bps / 1024);\n const dlMbps = (dlKbps / 1024).toFixed(1);\n const bufferS = (client.buffered_ahead_ms / 1000).toFixed(1);\n const rtt = Math.round(client.rtt_ms);\n\n // Idle: not playing, no meaningful position — don't alarm about \"Critical\".\n // Near end-of-stream is exempt from the buffered-ahead thresholds (see\n // bufferHealth.ts) so the final seconds of every episode don't false-Critical.\n const level = bufferHealthLevel(client);\n // A connected client whose reports stopped arriving: the figures below are\n // its last known state, and the silence itself is the status.\n const silent = client.stale_ms !== undefined;\n const statusLabel = silent ? `Silent ${Math.round(client.stale_ms! / 1000)}s` : BUFFER_HEALTH_LABEL[level];\n const isRed = silent || level === 'critical' || level === 'buffering';\n const statusClasses = isRed\n ? 'text-danger bg-danger/10'\n : level === 'idle'\n ? 'text-text-muted bg-bg-alt/40'\n : level === 'warning'\n ? 'text-on-neutral-bg bg-neutral/10'\n : 'text-success bg-success/10';\n\n const barColor = isRed ? 'bg-danger' : level === 'warning' ? 'bg-neutral-bg' : 'bg-success';\n const barPct = Math.min(100, (client.buffered_ahead_ms / BUFFER_AHEAD_MS) * 100);\n\n return (\n <div className=\"rounded-lg border border-border/50 bg-bg-alt/20 p-2.5\" data-silent={silent || undefined}>\n {/* Row 1: Name + Status */}\n <div className=\"flex items-center justify-between mb-2\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <div className=\"w-5 h-5 rounded-full bg-bg-alt flex items-center justify-center text-[9px] font-semibold shrink-0\">\n {initial}\n </div>\n <span className=\"text-sm font-medium text-text truncate\">{client.name}</span>\n </div>\n <span className={`inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium shrink-0 ${statusClasses}`}>\n {statusLabel}\n </span>\n </div>\n\n {/* Row 2: Stats grid */}\n <div className={`grid grid-cols-3 gap-x-2 gap-y-1 text-[11px] ${silent ? 'opacity-50' : ''}`}>\n <div>\n <span className=\"text-text-muted\">DL</span>\n <span className=\"ml-1 font-mono text-text\">{dlMbps}</span>\n <span className=\"text-text-muted ml-0.5\">Mbps</span>\n </div>\n <div>\n <span className=\"text-text-muted\">Ping</span>\n <span className=\"ml-1 font-mono text-text\">{rtt}</span>\n <span className=\"text-text-muted ml-0.5\">ms</span>\n </div>\n <div>\n <span className=\"text-text-muted\">Pos</span>\n <span className=\"ml-1 font-mono text-text-secondary\">{formatTime(client.playhead_ms)}</span>\n </div>\n\n {/* Buffer row spans full width */}\n <div className=\"col-span-2 flex items-center gap-1.5\">\n <span className=\"text-text-muted\">Buf</span>\n <span className=\"font-mono text-text\">{bufferS}s</span>\n <div className=\"flex-1 h-1 bg-bg-alt rounded-full overflow-hidden\">\n <div className={`h-full rounded-full transition-all ${barColor}`} style={{ width: `${barPct}%` }} />\n </div>\n </div>\n <div className=\"flex gap-1 font-mono justify-end\">\n <span className=\"bg-success-bg text-on-success-bg px-1 rounded\">{client.fragments_loaded}L</span>\n <span className=\"text-text-muted\">{client.fragments_pending}P</span>\n {client.fragments_error > 0 && <span className=\"bg-danger-bg text-on-danger-bg px-1 rounded\">{client.fragments_error}E</span>}\n </div>\n </div>\n </div>\n );\n}\n"],"names":["POLL_MS","NOTE_LINGER_MS","SubmissionQueue","rows","setRows","useState","listFailure","setListFailure","notes","setNotes","busyId","setBusyId","rejectingId","setRejectingId","reason","setReason","now","setNow","liveRef","useRef","refresh","useCallback","res","fetchPendingSubmissions","useEffect","first","timer","leaveNote","row","message","tone","prev","id","decide","verb","approveSubmission","rejectSubmission","r","decisionMeansRowMoved","decisionFailureLabel","shown","n","jsxs","jsx","submissionFailureLabel","note","decided","e","AdminPanel","clients","useAppStore","s","sorted","b","initials","computeInitials","queue","isPrivileged","c","ClientCard","formatTime","ms","totalSecs","mins","secs","out","taken","ordered","a","name","chosen","ch","up","client","initial","dlMbps","bufferS","rtt","level","bufferHealthLevel","silent","statusLabel","BUFFER_HEALTH_LABEL","isRed","statusClasses","barColor","barPct","BUFFER_AHEAD_MS"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import { jsx as A, jsxs as o } from "react/jsx-runtime";
2
2
  import { useState as v, useEffect as w, useMemo as G, useRef as Y } from "react";
3
- import { d as g, w as V, j as H, R as Oe, s as ce, h as J, aE as Ze, aF as Ge, $ as De, aG as y, a0 as Ce, aH as xe, I as se, aI as ye, aJ as Ne, aK as Me, aL as Le, aM as Ke, g as Re, aN as Je } from "./index-Buah62TP.js";
3
+ import { d as g, w as V, j as H, P as Oe, s as ce, h as J, aC as Ze, aD as Ge, Z as De, aE as y, _ as Ce, aF as xe, G as se, aG as ye, aH as Ne, aI as Le, aJ as Me, aK as Ke, g as Re, aL as Je } from "./index-DWgUNApo.js";
4
4
  import { b as He } from "./cover-AUIrlUMF.js";
5
5
  import { createPortal as We } from "react-dom";
6
- import { S as Xe } from "./Room-CoE8L9aw.js";
6
+ import { S as Xe } from "./Room-C1DWAuT8.js";
7
7
  import { Icon as Ye } from "@wolffm/themes";
8
8
  const Ve = "data:image/png;base64,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", Fe = 700, je = -1, _e = -2, $e = { endMatch: !1, rejectedStale: !1 };
9
9
  function eA(e, n, r) {
@@ -795,7 +795,7 @@ function Qe() {
795
795
  }
796
796
  function gA() {
797
797
  const e = `${Re()}/game/`, n = e.includes("?") ? "&" : "?";
798
- return `${e}${n}net=1&v=${encodeURIComponent("0.44.16")}`;
798
+ return `${e}${n}net=1&v=${encodeURIComponent("0.44.19")}`;
799
799
  }
800
800
  function NA() {
801
801
  const e = Y(null), n = Y(null), r = J((t) => t.snapshot.leaderId), a = J((t) => t.me.clientId), s = !!r && r === a, f = J((t) => t.roster), h = G(() => Object.values(f), [f]), Q = J((t) => t.gameSessionWins), c = J((t) => t.gameBotCount), C = G(() => {
@@ -809,7 +809,7 @@ function NA() {
809
809
  for (const [b, x] of Object.entries(Q))
810
810
  x <= 0 || (x > l ? (t = b, l = x, u = !1) : x === l && (u = !0));
811
811
  return u ? null : t;
812
- }, [Q]), T = G(gA, []), [N, j] = v(Qe), [p, K] = v("pre-start"), [M, _] = v(te), [$, ee] = v(!1), [Ue, Ae] = v(!1), [D, ze] = v(!1), [L, fe] = v("loading"), Ie = L === "ready", m = G(() => {
812
+ }, [Q]), T = G(gA, []), [N, j] = v(Qe), [p, K] = v("pre-start"), [L, _] = v(te), [$, ee] = v(!1), [Ue, Ae] = v(!1), [D, ze] = v(!1), [M, fe] = v("loading"), Ie = M === "ready", m = G(() => {
813
813
  try {
814
814
  return new URL(T, window.location.href).origin;
815
815
  } catch {
@@ -821,13 +821,13 @@ function NA() {
821
821
  }
822
822
  w(() => {
823
823
  if (p !== "countdown") return;
824
- if (M <= 0) {
825
- s && Me("bomberman");
824
+ if (L <= 0) {
825
+ s && Le("bomberman");
826
826
  return;
827
827
  }
828
828
  const t = setTimeout(() => _((l) => l - 1), 1e3);
829
829
  return () => clearTimeout(t);
830
- }, [p, M, s]);
830
+ }, [p, L, s]);
831
831
  const oe = Y(null);
832
832
  w(() => {
833
833
  if (p === "countdown" && !(N <= 0))
@@ -836,13 +836,13 @@ function NA() {
836
836
  const R = window.AudioContext || window.webkitAudioContext;
837
837
  oe.current = new R();
838
838
  }
839
- const t = oe.current, l = M <= 0, u = l ? 660 : 880, b = l ? 0.35 : 0.15, x = ie(N) * 0.35, P = t.createOscillator(), U = t.createGain();
839
+ const t = oe.current, l = L <= 0, u = l ? 660 : 880, b = l ? 0.35 : 0.15, x = ie(N) * 0.35, P = t.createOscillator(), U = t.createGain();
840
840
  P.type = "sine", P.frequency.value = u;
841
841
  const k = t.currentTime;
842
842
  U.gain.setValueAtTime(0, k), U.gain.linearRampToValueAtTime(x, k + 0.01), U.gain.exponentialRampToValueAtTime(1e-4, k + b), P.connect(U).connect(t.destination), P.start(k), P.stop(k + b + 0.01);
843
843
  } catch {
844
844
  }
845
- }, [p, M, N]), w(() => {
845
+ }, [p, L, N]), w(() => {
846
846
  let t = !1;
847
847
  const l = () => {
848
848
  if (t) return;
@@ -873,14 +873,14 @@ function NA() {
873
873
  }, bA);
874
874
  return () => clearTimeout(t);
875
875
  }, [p, s, $]), w(() => {
876
- Le();
876
+ Me();
877
877
  }, []), w(() => {
878
- if (L !== "loading") return;
878
+ if (M !== "loading") return;
879
879
  const t = setTimeout(() => {
880
880
  V("game", "world_built never arrived (30s) — escalating to error"), fe("error");
881
881
  }, 3e4);
882
882
  return () => clearTimeout(t);
883
- }, [L]), w(() => {
883
+ }, [M]), w(() => {
884
884
  if (!D) return;
885
885
  const t = n.current;
886
886
  t && (g("game", "replaying game_active preview after iframeReady"), e.current?.contentWindow?.postMessage(
@@ -1447,11 +1447,11 @@ function NA() {
1447
1447
  WebkitTextStroke: "6px #000",
1448
1448
  textShadow: "-3px -3px 0 #000, 3px -3px 0 #000, -3px 3px 0 #000, 3px 3px 0 #000, 0 8px 32px rgba(0,0,0,0.7)"
1449
1449
  },
1450
- children: M > 0 ? M : "GO!"
1450
+ children: L > 0 ? L : "GO!"
1451
1451
  },
1452
- M
1452
+ L
1453
1453
  ) }),
1454
- L === "loading" && (p === "pre-start" || p === "countdown") && /* @__PURE__ */ o(
1454
+ M === "loading" && (p === "pre-start" || p === "countdown") && /* @__PURE__ */ o(
1455
1455
  "div",
1456
1456
  {
1457
1457
  className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-20 px-6 py-3 rounded bg-black/60 backdrop-blur text-text-secondary text-sm pointer-events-none flex items-center gap-2",
@@ -1461,7 +1461,7 @@ function NA() {
1461
1461
  ]
1462
1462
  }
1463
1463
  ),
1464
- L === "error" && (p === "pre-start" || p === "countdown") && /* @__PURE__ */ o("div", { className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-20 px-6 py-4 rounded bg-black/80 backdrop-blur text-text text-sm flex flex-col items-center gap-3 pointer-events-auto", children: [
1464
+ M === "error" && (p === "pre-start" || p === "countdown") && /* @__PURE__ */ o("div", { className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-20 px-6 py-4 rounded bg-black/80 backdrop-blur text-text text-sm flex flex-col items-center gap-3 pointer-events-auto", children: [
1465
1465
  /* @__PURE__ */ A("span", { className: "bg-danger-bg text-on-danger-bg px-2 py-0.5 rounded font-semibold", children: "Game failed to load" }),
1466
1466
  /* @__PURE__ */ A("span", { className: "text-text-secondary text-xs", children: "Bevy didn't report ready within 30s." }),
1467
1467
  /* @__PURE__ */ A(
@@ -1474,7 +1474,7 @@ function NA() {
1474
1474
  }
1475
1475
  )
1476
1476
  ] }),
1477
- s && p === "pre-start" && L === "ready" && /* @__PURE__ */ A(
1477
+ s && p === "pre-start" && M === "ready" && /* @__PURE__ */ A(
1478
1478
  "button",
1479
1479
  {
1480
1480
  type: "button",
@@ -1496,7 +1496,7 @@ function NA() {
1496
1496
  children: "Start Game"
1497
1497
  }
1498
1498
  ),
1499
- !s && p === "pre-start" && L === "ready" && /* @__PURE__ */ A("div", { className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-20 px-6 py-3 rounded bg-black/60 backdrop-blur text-text-secondary text-sm pointer-events-none", children: "Waiting for the host to start the game…" })
1499
+ !s && p === "pre-start" && M === "ready" && /* @__PURE__ */ A("div", { className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-20 px-6 py-3 rounded bg-black/60 backdrop-blur text-text-secondary text-sm pointer-events-none", children: "Waiting for the host to start the game…" })
1500
1500
  ]
1501
1501
  }
1502
1502
  ),
@@ -1512,4 +1512,4 @@ function NA() {
1512
1512
  export {
1513
1513
  NA as default
1514
1514
  };
1515
- //# sourceMappingURL=GameModule-BvqNQcVk.js.map
1515
+ //# sourceMappingURL=GameModule-D71uhFdW.js.map