@hadoku/watchparty-ui 0.44.20 → 0.45.2

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 (29) hide show
  1. package/dist/chunks/{AdminPanel-CYbxabgY.js → AdminPanel-BGVD6Qlb.js} +4 -4
  2. package/dist/chunks/{AdminPanel-CYbxabgY.js.map → AdminPanel-BGVD6Qlb.js.map} +1 -1
  3. package/dist/chunks/{GameModule-Df1rYrJo.js → GameModule-Dx3GHtRk.js} +244 -247
  4. package/dist/chunks/GameModule-Dx3GHtRk.js.map +1 -0
  5. package/dist/chunks/{MapEditor-DgbOaCT2.js → MapEditor-yvJbXXgw.js} +319 -325
  6. package/dist/chunks/MapEditor-yvJbXXgw.js.map +1 -0
  7. package/dist/chunks/{MediaDrawer-Da6-fLeV.js → MediaDrawer-DLFj0-te.js} +293 -297
  8. package/dist/chunks/MediaDrawer-DLFj0-te.js.map +1 -0
  9. package/dist/chunks/{PlaylistPanel-fy0YV4nH.js → PlaylistPanel-B0SWGlFy.js} +124 -126
  10. package/dist/chunks/PlaylistPanel-B0SWGlFy.js.map +1 -0
  11. package/dist/chunks/Room-BVyJK3zM.js +6165 -0
  12. package/dist/chunks/Room-BVyJK3zM.js.map +1 -0
  13. package/dist/chunks/{index-B92W398r.js → index-DOLbMWw6.js} +1626 -1618
  14. package/dist/chunks/index-DOLbMWw6.js.map +1 -0
  15. package/dist/chunks/{submissionsApi-CHcpF-It.js → submissionsApi-CXZf_xlm.js} +2 -2
  16. package/dist/chunks/{submissionsApi-CHcpF-It.js.map → submissionsApi-CXZf_xlm.js.map} +1 -1
  17. package/dist/index.d.ts +11 -2
  18. package/dist/index.js +1 -1
  19. package/dist/room-chrome.js +3 -2
  20. package/dist/room-chrome.js.map +1 -1
  21. package/dist/watchparty-ui.css +1 -1
  22. package/package.json +2 -2
  23. package/dist/chunks/GameModule-Df1rYrJo.js.map +0 -1
  24. package/dist/chunks/MapEditor-DgbOaCT2.js.map +0 -1
  25. package/dist/chunks/MediaDrawer-Da6-fLeV.js.map +0 -1
  26. package/dist/chunks/PlaylistPanel-fy0YV4nH.js.map +0 -1
  27. package/dist/chunks/Room-Ci6DN1Oi.js +0 -6137
  28. package/dist/chunks/Room-Ci6DN1Oi.js.map +0 -1
  29. package/dist/chunks/index-B92W398r.js.map +0 -1
@@ -1,234 +1,234 @@
1
1
  import { jsxs as u, jsx as a, Fragment as j } from "react/jsx-runtime";
2
- import { useState as x, useEffect as D, useRef as ce, useMemo as ke, useCallback as Se } from "react";
3
- import { g as K, ay as Y, d as A, an as Fe, w as q, Y as Q, az as Be, aA as De, h as se, t as Oe, G as Ce, aB as Pe } from "./index-B92W398r.js";
4
- import { D as $e, a as ae, u as Ge, s as je, b as qe } from "./Room-Ci6DN1Oi.js";
5
- import { s as Ee, a as V, g as ue, f as He, b as pe, h as ze, u as Ve, c as We, e as Ye, d as Je, i as Ke, j as Qe, k as Xe } from "./submissionsApi-CHcpF-It.js";
6
- import { Icon as re } from "@wolffm/themes";
7
- import { b as Ze } from "./cover-AUIrlUMF.js";
8
- const ne = /* @__PURE__ */ new Map(), Z = /* @__PURE__ */ new Map(), et = 6e4;
9
- async function J(e = "") {
10
- const r = Date.now(), t = ne.get(e);
11
- if (t && r - t.ts < et) return t.data;
12
- const l = Z.get(e);
2
+ import { useState as x, useEffect as O, useRef as ue, useMemo as Se, useCallback as Ce } from "react";
3
+ import { g as X, ay as K, d as E, an as Be, w as q, Y as H, az as Oe, aA as De, h as ie, t as Pe, G as $e, aB as Ge } from "./index-DOLbMWw6.js";
4
+ import { D as Ee, a as re, u as je, s as qe, b as He } from "./Room-BVyJK3zM.js";
5
+ import { s as Ae, a as Y, g as pe, f as We, b as me, h as ze, u as Ve, c as Ye, e as Je, d as Ke, i as Qe, j as Xe, k as Ze } from "./submissionsApi-CXZf_xlm.js";
6
+ import { Icon as ne } from "@wolffm/themes";
7
+ import { b as et } from "./cover-AUIrlUMF.js";
8
+ const se = /* @__PURE__ */ new Map(), ee = /* @__PURE__ */ new Map(), tt = 6e4;
9
+ async function Q(e = "") {
10
+ const r = Date.now(), t = se.get(e);
11
+ if (t && r - t.ts < tt) return t.data;
12
+ const l = ee.get(e);
13
13
  if (l) return l;
14
14
  const o = (async () => {
15
- const p = `${K()}/api/catalog${e ? `?prefix=${encodeURIComponent(e)}` : ""}`, c = await fetch(p, { cache: "no-store" });
15
+ const g = `${X()}/api/catalog${e ? `?prefix=${encodeURIComponent(e)}` : ""}`, c = await fetch(g, { cache: "no-store" });
16
16
  if (!c.ok) throw new Error(`catalog_http_${c.status}`);
17
17
  const y = await c.json();
18
- return Y() && A("catalog", "Catalog fetched", { prefix: e, dirs: y.dirs?.length, files: y.files?.length }), ne.set(e, { ts: r, data: y }), y;
18
+ return K() && E("catalog", "Catalog fetched", { prefix: e, dirs: y.dirs?.length, files: y.files?.length }), se.set(e, { ts: r, data: y }), y;
19
19
  })();
20
- Z.set(e, o);
20
+ ee.set(e, o);
21
21
  try {
22
22
  return await o;
23
23
  } finally {
24
- Z.delete(e);
24
+ ee.delete(e);
25
25
  }
26
26
  }
27
- function tt(e) {
28
- ne.clear();
27
+ function at(e) {
28
+ se.clear();
29
29
  }
30
- async function at() {
31
- if (Y())
30
+ async function rt() {
31
+ if (K())
32
32
  try {
33
33
  const e = ["output/fmp4/anime", "output/fmp4/movie", "output/fmp4/tv"];
34
34
  for (const r of e) {
35
- const t = await J(r);
36
- A("catalog", "[probe] catalog " + r, { dirs: t.dirs.length, files: t.files.length });
35
+ const t = await Q(r);
36
+ E("catalog", "[probe] catalog " + r, { dirs: t.dirs.length, files: t.files.length });
37
37
  const l = t.files[0];
38
38
  if (l) {
39
- const o = rt(), i = `${o}/${l.id}/index.json`.replace(/\\/g, "/"), p = `${o}/${l.id}/${Fe}`.replace(/\\/g, "/");
40
- await me(i, "index"), await me(p, "fragment", { headers: { Range: "bytes=0-1023" } });
39
+ const o = nt(), s = `${o}/${l.id}/index.json`.replace(/\\/g, "/"), g = `${o}/${l.id}/${Be}`.replace(/\\/g, "/");
40
+ await ge(s, "index"), await ge(g, "fragment", { headers: { Range: "bytes=0-1023" } });
41
41
  }
42
42
  }
43
43
  } catch (e) {
44
44
  q("catalog", "[probe] error", { error: e instanceof Error ? e.message : String(e) });
45
45
  }
46
46
  }
47
- function rt() {
47
+ function nt() {
48
48
  return "/media";
49
49
  }
50
- async function me(e, r, t) {
51
- const l = performance.now(), o = await fetch(e, t), i = Math.round(performance.now() - l);
52
- return A("catalog", "[probe] " + r, { url: e, status: o.status, ms: i, bytes: o.headers.get("content-length") }), o;
50
+ async function ge(e, r, t) {
51
+ const l = performance.now(), o = await fetch(e, t), s = Math.round(performance.now() - l);
52
+ return E("catalog", "[probe] " + r, { url: e, status: o.status, ms: s, bytes: o.headers.get("content-length") }), o;
53
53
  }
54
- const nt = [
54
+ const st = [
55
55
  "yuuna",
56
56
  "gushingovermagicalgirls",
57
57
  "immoralguild",
58
58
  "ingokudanchi",
59
59
  "isekaionsenparadise"
60
- ], ge = (e) => e.toLowerCase().replace(/[^a-z0-9]/g, "");
61
- function st(e, r) {
62
- return new Set(r.map(ge)).has(ge(e));
60
+ ], fe = (e) => e.toLowerCase().replace(/[^a-z0-9]/g, "");
61
+ function it(e, r) {
62
+ return new Set(r.map(fe)).has(fe(e));
63
63
  }
64
- function it(e) {
65
- return st(e, nt);
64
+ function lt(e) {
65
+ return it(e, st);
66
66
  }
67
- function fe(e, r) {
67
+ function he(e, r) {
68
68
  const t = /* @__PURE__ */ new Map();
69
69
  for (const l of e) {
70
70
  const o = /* @__PURE__ */ new Map();
71
- for (const i of r(l))
72
- o.set(i.name, i.expanded === !0);
71
+ for (const s of r(l))
72
+ o.set(s.name, s.expanded === !0);
73
73
  t.set(l.name, { expanded: l.expanded === !0, children: o });
74
74
  }
75
75
  return t;
76
76
  }
77
- function he(e, r, t, l) {
77
+ function be(e, r, t, l) {
78
78
  return e.map((o) => {
79
- const i = r.get(o.name);
80
- if (!i) return o;
79
+ const s = r.get(o.name);
80
+ if (!s) return o;
81
81
  const c = t(o).map((v) => {
82
- const f = i.children.get(v.name);
83
- return f === void 0 ? v : { ...v, expanded: f };
82
+ const h = s.children.get(v.name);
83
+ return h === void 0 ? v : { ...v, expanded: h };
84
84
  });
85
- return l({ ...o, expanded: i.expanded }, c);
85
+ return l({ ...o, expanded: s.expanded }, c);
86
86
  });
87
87
  }
88
- const lt = "Anime";
89
- function W(e) {
90
- return e === lt;
88
+ const ot = "Anime";
89
+ function J(e) {
90
+ return e === ot;
91
91
  }
92
- function ot(e, r, t) {
92
+ function dt(e, r, t) {
93
93
  return e.map(
94
94
  (l) => t(
95
- { ...l, expanded: W(l.name) },
95
+ { ...l, expanded: J(l.name) },
96
96
  r(l).map((o) => ({ ...o, expanded: !1 }))
97
97
  )
98
98
  );
99
99
  }
100
- const be = "output/fmp4", xe = [
100
+ const xe = "output/fmp4", ye = [
101
101
  { key: "anime", label: "Anime" },
102
102
  { key: "movie", label: "Movie" },
103
103
  { key: "tv", label: "TV" }
104
104
  ];
105
- async function ee(e, r) {
105
+ async function te(e, r) {
106
106
  try {
107
107
  return await e(r);
108
108
  } catch (t) {
109
- return q("catalog", "Fetch failed", { prefix: r, ...Q(t) }), null;
109
+ return q("catalog", "Fetch failed", { prefix: r, ...H(t) }), null;
110
110
  }
111
111
  }
112
- async function ye(e) {
112
+ async function ve(e) {
113
113
  const [r, t] = await Promise.all([
114
- Promise.all(xe.map((c) => ee(e, `${be}/${c.key}`))),
115
- ee(e, `${be}/playlists`)
114
+ Promise.all(ye.map((c) => te(e, `${xe}/${c.key}`))),
115
+ te(e, `${xe}/playlists`)
116
116
  ]), l = await Promise.all(r.map((c) => Promise.all((c?.dirs ?? []).map(async (y) => {
117
- const f = ((await ee(e, y.path))?.files ?? []).map(($) => ({ type: "episode", name: $.title, mediaId: $.id }));
118
- return f.length ? { type: "series", name: y.name, episodes: f, expanded: !1 } : null;
119
- })))), o = [], i = [];
120
- xe.forEach((c, y) => {
117
+ const h = ((await te(e, y.path))?.files ?? []).map(($) => ({ type: "episode", name: $.title, mediaId: $.id }));
118
+ return h.length ? { type: "series", name: y.name, episodes: h, expanded: !1 } : null;
119
+ })))), o = [], s = [];
120
+ ye.forEach((c, y) => {
121
121
  const v = [];
122
- for (const f of l[y])
123
- f && (c.key === "anime" && it(f.name) ? i.push(f) : v.push(f));
124
- v.length && o.push({ type: "category", name: c.label, series: v, expanded: W(c.label) });
122
+ for (const h of l[y])
123
+ h && (c.key === "anime" && lt(h.name) ? s.push(h) : v.push(h));
124
+ v.length && o.push({ type: "category", name: c.label, series: v, expanded: J(c.label) });
125
125
  });
126
- const p = (t?.dirs ?? []).map((c) => ({ type: "playlist", name: c.name, playlistId: c.name }));
127
- return p.length && o.push({ type: "playlist_category", name: "Playlists", playlists: p, expanded: W("Playlists") }), i.length && o.push({ type: "category", name: "Ecchi", series: i, expanded: W("Ecchi") }), o;
126
+ const g = (t?.dirs ?? []).map((c) => ({ type: "playlist", name: c.name, playlistId: c.name }));
127
+ return g.length && o.push({ type: "playlist_category", name: "Playlists", playlists: g, expanded: J("Playlists") }), s.length && o.push({ type: "category", name: "Ecchi", series: s, expanded: J("Ecchi") }), o;
128
128
  }
129
- const dt = /^(?:https?|magnet):/i;
130
- function Ae(e) {
129
+ const ct = /^(?:https?|magnet):/i;
130
+ function Me(e) {
131
131
  const r = e.trim();
132
- return r.length >= Be && r.length <= De && !dt.test(r);
132
+ return r.length >= Oe && r.length <= De && !ct.test(r);
133
133
  }
134
- function ve(e) {
135
- return e ? `${K()}${e}` : null;
134
+ function we(e) {
135
+ return e ? `${X()}${e}` : null;
136
136
  }
137
- function ct(e) {
137
+ function ut(e) {
138
138
  if (e === null || !Number.isFinite(e) || e < 0) return "";
139
139
  const r = Math.floor(e % 60), t = Math.floor(e / 60) % 60, l = Math.floor(e / 3600), o = String(r).padStart(2, "0");
140
140
  return l > 0 ? `${l}:${String(t).padStart(2, "0")}:${o}` : `${t}:${o}`;
141
141
  }
142
- async function Me(e, r) {
142
+ async function Ie(e, r) {
143
143
  try {
144
- const t = await fetch(`${K()}${e}`, { signal: r });
144
+ const t = await fetch(`${X()}${e}`, { signal: r });
145
145
  return t.ok ? { ok: !0, value: await t.json() } : { ok: !1, status: t.status };
146
146
  } catch (t) {
147
- return r.aborted ? { ok: !1, status: "aborted" } : (q("search", "Search request threw", Q(t)), { ok: !1, status: "network" });
147
+ return r.aborted ? { ok: !1, status: "aborted" } : (q("search", "Search request threw", H(t)), { ok: !1, status: "network" });
148
148
  }
149
149
  }
150
- function ut(e, r) {
151
- return Me(`/api/search/shows?q=${encodeURIComponent(e.trim())}`, r);
152
- }
153
150
  function pt(e, r) {
154
- return Me(`/api/search/youtube?q=${encodeURIComponent(e.trim())}`, r);
151
+ return Ie(`/api/search/shows?q=${encodeURIComponent(e.trim())}`, r);
152
+ }
153
+ function mt(e, r) {
154
+ return Ie(`/api/search/youtube?q=${encodeURIComponent(e.trim())}`, r);
155
155
  }
156
- async function mt(e, r) {
156
+ async function gt(e, r) {
157
157
  try {
158
- const t = await fetch(`${K()}/api/watchlist`, {
158
+ const t = await fetch(`${X()}/api/watchlist`, {
159
159
  method: "POST",
160
160
  headers: { "Content-Type": "application/json" },
161
161
  body: JSON.stringify({ source: e, id: r })
162
162
  });
163
163
  if (t.status === 201) {
164
164
  const l = await t.json();
165
- return A("search", "Added to watch list", { source: e, id: r, series: l.series }), { ok: !0, value: l };
165
+ return E("search", "Added to watch list", { source: e, id: r, series: l.series }), { ok: !0, value: l };
166
166
  }
167
167
  return { ok: !1, code: t.status === 409 ? "exists" : "failed", status: t.status };
168
168
  } catch (t) {
169
- return q("search", "Watch-list add threw", Q(t)), { ok: !1, code: "failed", status: "network" };
169
+ return q("search", "Watch-list add threw", H(t)), { ok: !1, code: "failed", status: "network" };
170
170
  }
171
171
  }
172
- const gt = 350;
173
- function ft({ query: e, onSubmitted: r }) {
174
- const t = e.trim(), l = Ae(t), [o, i] = x(null), [p, c] = x(null), [y, v] = x({});
175
- if (D(() => {
172
+ const ft = 350;
173
+ function ht({ query: e, onSubmitted: r }) {
174
+ const t = e.trim(), l = Me(t), [o, s] = x(null), [g, c] = x(null), [y, v] = x({});
175
+ if (O(() => {
176
176
  if (!l) return;
177
177
  const d = new AbortController(), N = setTimeout(() => {
178
- ut(t, d.signal).then((m) => {
179
- d.signal.aborted || i({ q: t, outcome: m.ok ? { ok: !0, value: m.value.results } : m });
180
- }), pt(t, d.signal).then((m) => {
181
- d.signal.aborted || c({ q: t, outcome: m.ok ? { ok: !0, value: m.value.results } : m });
178
+ pt(t, d.signal).then((f) => {
179
+ d.signal.aborted || s({ q: t, outcome: f.ok ? { ok: !0, value: f.value.results } : f });
180
+ }), mt(t, d.signal).then((f) => {
181
+ d.signal.aborted || c({ q: t, outcome: f.ok ? { ok: !0, value: f.value.results } : f });
182
182
  });
183
- }, gt);
183
+ }, ft);
184
184
  return () => {
185
185
  clearTimeout(N), d.abort();
186
186
  };
187
187
  }, [t, l]), !l) return null;
188
- const f = o?.q === t ? o.outcome : null, $ = p?.q === t ? p.outcome : null;
189
- async function M(d) {
188
+ const h = o?.q === t ? o.outcome : null, $ = g?.q === t ? g.outcome : null;
189
+ async function A(d) {
190
190
  const N = `${d.source}:${d.id}`;
191
- v((S) => ({ ...S, [N]: "adding" }));
192
- const m = await mt(d.source, d.id);
193
- v((S) => ({ ...S, [N]: m.ok || m.code === "exists" ? "added" : `error ${m.status}` }));
191
+ v((k) => ({ ...k, [N]: "adding" }));
192
+ const f = await gt(d.source, d.id);
193
+ v((k) => ({ ...k, [N]: f.ok || f.code === "exists" ? "added" : `error ${f.status}` }));
194
194
  }
195
195
  async function R(d) {
196
196
  const N = `yt:${d.id}`;
197
- v((S) => ({ ...S, [N]: "adding" }));
198
- const m = await Ee(d.url, d.title);
199
- m.ok ? (v((S) => ({ ...S, [N]: "added" })), r(m.value)) : v((S) => ({ ...S, [N]: V(m.failure) }));
197
+ v((k) => ({ ...k, [N]: "adding" }));
198
+ const f = await Ae(d.url, d.title);
199
+ f.ok ? (v((k) => ({ ...k, [N]: "added" })), r(f.value)) : v((k) => ({ ...k, [N]: Y(f.failure) }));
200
200
  }
201
- const _ = f?.ok && $?.ok && f.value.length === 0 && $.value.length === 0;
201
+ const U = h?.ok && $?.ok && h.value.length === 0 && $.value.length === 0;
202
202
  return /* @__PURE__ */ u("div", { className: "border-b border-border", "data-testid": "media-search", children: [
203
- _ && /* @__PURE__ */ a("div", { className: "px-3 py-2 text-[11px] text-text-muted", children: "no results" }),
204
- /* @__PURE__ */ a(we, { label: "Shows", answer: f, testId: "search-shows", children: f?.ok && f.value.map((d) => {
205
- const N = `${d.source}:${d.id}`, m = d.onWatchlist ? "added" : y[N];
203
+ U && /* @__PURE__ */ a("div", { className: "px-3 py-2 text-[11px] text-text-muted", children: "no results" }),
204
+ /* @__PURE__ */ a(Ne, { label: "Shows", answer: h, testId: "search-shows", children: h?.ok && h.value.map((d) => {
205
+ const N = `${d.source}:${d.id}`, f = d.onWatchlist ? "added" : y[N];
206
206
  return /* @__PURE__ */ a(
207
- Ne,
207
+ ke,
208
208
  {
209
209
  testId: `show-${N}`,
210
- image: ve(d.poster),
210
+ image: we(d.poster),
211
211
  imageClass: "w-8 h-11",
212
212
  title: d.title,
213
213
  meta: [d.year, d.format, d.episodes ? `${d.episodes} ep` : null],
214
- state: m,
214
+ state: f,
215
215
  canAdd: d.addable,
216
216
  addLabel: `Add ${d.title} to watch list`,
217
217
  onAdd: () => {
218
- M(d);
218
+ A(d);
219
219
  }
220
220
  },
221
221
  N
222
222
  );
223
223
  }) }),
224
- /* @__PURE__ */ a(we, { label: "YouTube", answer: $, testId: "search-youtube", children: $?.ok && $.value.map((d) => /* @__PURE__ */ a(
225
- Ne,
224
+ /* @__PURE__ */ a(Ne, { label: "YouTube", answer: $, testId: "search-youtube", children: $?.ok && $.value.map((d) => /* @__PURE__ */ a(
225
+ ke,
226
226
  {
227
227
  testId: `video-${d.id}`,
228
- image: ve(d.thumb),
228
+ image: we(d.thumb),
229
229
  imageClass: "w-16 h-9",
230
230
  title: d.title,
231
- meta: [d.channel, ct(d.durationS)],
231
+ meta: [d.channel, ut(d.durationS)],
232
232
  state: y[`yt:${d.id}`],
233
233
  canAdd: !0,
234
234
  addLabel: `Request ${d.title}`,
@@ -240,7 +240,7 @@ function ft({ query: e, onSubmitted: r }) {
240
240
  )) })
241
241
  ] });
242
242
  }
243
- function we({ label: e, answer: r, testId: t, children: l }) {
243
+ function Ne({ label: e, answer: r, testId: t, children: l }) {
244
244
  if (r?.ok && r.value.length === 0) return null;
245
245
  const o = r && !r.ok && r.status !== "aborted";
246
246
  return /* @__PURE__ */ u("div", { "data-testid": t, "data-loaded": r ? "true" : "false", children: [
@@ -252,27 +252,27 @@ function we({ label: e, answer: r, testId: t, children: l }) {
252
252
  l
253
253
  ] });
254
254
  }
255
- function Ne({ testId: e, image: r, imageClass: t, title: l, meta: o, state: i, canAdd: p, addLabel: c, onAdd: y }) {
256
- const v = o.filter((f) => f !== null && f !== "").join(" · ");
257
- return /* @__PURE__ */ u("div", { className: "px-3 py-1 flex items-center gap-2", "data-testid": e, "data-state": i ?? "", children: [
255
+ function ke({ testId: e, image: r, imageClass: t, title: l, meta: o, state: s, canAdd: g, addLabel: c, onAdd: y }) {
256
+ const v = o.filter((h) => h !== null && h !== "").join(" · ");
257
+ return /* @__PURE__ */ u("div", { className: "px-3 py-1 flex items-center gap-2", "data-testid": e, "data-state": s ?? "", children: [
258
258
  r ? /* @__PURE__ */ a("img", { src: r, alt: "", loading: "lazy", className: `${t} object-cover rounded shrink-0 bg-bg-alt` }) : /* @__PURE__ */ a("div", { className: `${t} rounded shrink-0 bg-bg-alt` }),
259
259
  /* @__PURE__ */ u("div", { className: "flex-1 min-w-0", children: [
260
260
  /* @__PURE__ */ a("div", { className: "text-[11px] text-text truncate", title: l, children: l }),
261
261
  v && /* @__PURE__ */ a("div", { className: "text-[10px] text-text-muted truncate", children: v })
262
262
  ] }),
263
- i === "added" ? /* @__PURE__ */ a(re, { name: "check", variant: "tint", family: "success", round: !0, className: "shrink-0" }) : i && i !== "adding" ? /* @__PURE__ */ a("span", { className: "text-[10px] bg-danger-bg text-on-danger-bg px-1 rounded shrink-0", children: i }) : p && /* @__PURE__ */ a(
263
+ s === "added" ? /* @__PURE__ */ a(ne, { name: "check", variant: "tint", family: "success", round: !0, className: "shrink-0" }) : s && s !== "adding" ? /* @__PURE__ */ a("span", { className: "text-[10px] bg-danger-bg text-on-danger-bg px-1 rounded shrink-0", children: s }) : g && /* @__PURE__ */ a(
264
264
  "button",
265
265
  {
266
266
  onClick: y,
267
- disabled: i === "adding",
267
+ disabled: s === "adding",
268
268
  "aria-label": c,
269
269
  className: "drawer-btn shrink-0",
270
- children: /* @__PURE__ */ a(re, { name: "plus" })
270
+ children: /* @__PURE__ */ a(ne, { name: "plus" })
271
271
  }
272
272
  )
273
273
  ] });
274
274
  }
275
- const ht = 4e3, bt = {
275
+ const bt = 4e3, xt = {
276
276
  pending: "bg-neutral-bg text-on-neutral-bg",
277
277
  approved: "bg-primary-bg text-on-primary-bg",
278
278
  fetching: "bg-primary-bg text-on-primary-bg",
@@ -281,7 +281,7 @@ const ht = 4e3, bt = {
281
281
  rejected: "bg-danger-bg text-on-danger-bg",
282
282
  failed: "bg-danger-bg text-on-danger-bg"
283
283
  };
284
- function xt({ item: e }) {
284
+ function yt({ item: e }) {
285
285
  const r = e, t = e.title || e.source;
286
286
  return /* @__PURE__ */ u(
287
287
  "div",
@@ -294,106 +294,106 @@ function xt({ item: e }) {
294
294
  children: [
295
295
  /* @__PURE__ */ a("span", { className: "text-[10px] uppercase tracking-wider text-text-muted shrink-0", children: e.kind }),
296
296
  /* @__PURE__ */ a("span", { className: "text-[11px] text-text-tertiary truncate flex-1", title: e.source, children: r.series ? `${r.series} — ${t}` : t }),
297
- /* @__PURE__ */ a("span", { className: `text-[10px] uppercase tracking-wider px-1 rounded ${bt[e.state] ?? "text-text-muted"}`, children: e.state }),
297
+ /* @__PURE__ */ a("span", { className: `text-[10px] uppercase tracking-wider px-1 rounded ${xt[e.state] ?? "text-text-muted"}`, children: e.state }),
298
298
  e.error && /* @__PURE__ */ a("span", { className: "text-[10px] bg-danger-bg text-on-danger-bg px-1 rounded truncate max-w-[10rem]", children: e.error })
299
299
  ]
300
300
  }
301
301
  );
302
302
  }
303
- function yt({ open: e, onClose: r }) {
304
- const [t, l] = x(""), [o, i] = x(""), [p, c] = x(""), [y, v] = x(!1), [f, $] = x([]), [M, R] = x(!1), [_, d] = x(null), [N, m] = x(null), [S, H] = x(null), [L, z] = x(null), [T, O] = x(null), [U, n] = x(!1), [h, g] = x(null), [b, k] = x(null), E = ce(null), P = ce(!1), F = ke(() => ue(t), [t]) === "magnet" && t.trim().length > 0, ie = Ae(t), B = Se(async () => {
305
- const s = await He();
306
- P.current && (s.ok ? (m(s.value), H(null)) : H(s.failure));
307
- }, []);
308
- D(() => {
303
+ function vt({ open: e, onClose: r }) {
304
+ const [t, l] = x(""), [o, s] = x(""), [g, c] = x(""), [y, v] = x(!1), [h, $] = x([]), [A, R] = x(!1), [U, d] = x(null), [N, f] = x(null), [k, W] = x(null), [I, z] = x(null), [T, D] = x(null), [P, _] = x(!1), [V, n] = x(null), [p, m] = x(null), w = ue(null), S = ue(!1), L = Se(() => pe(t), [t]) === "magnet" && t.trim().length > 0, le = Me(t), B = Ce(() => We().then((i) => {
305
+ S.current && (i.ok ? (f(i.value), W(null)) : W(i.failure));
306
+ }), []);
307
+ O(() => {
309
308
  if (!e) return;
310
- P.current = !0, B();
311
- const s = setInterval(() => {
309
+ S.current = !0, B();
310
+ const i = setInterval(() => {
312
311
  B();
313
- }, ht);
312
+ }, bt);
314
313
  return () => {
315
- P.current = !1, clearInterval(s);
314
+ S.current = !1, clearInterval(i);
316
315
  };
317
- }, [e, B]), D(() => {
316
+ }, [e, B]), O(() => {
318
317
  if (!e) return;
319
- let s = !0;
320
- return pe().then((w) => {
321
- s && w.ok && z(w.value);
318
+ let i = !0;
319
+ return me().then((b) => {
320
+ i && b.ok && z(b.value);
322
321
  }), () => {
323
- s = !1;
322
+ i = !1;
324
323
  };
325
- }, [e]), D(() => {
324
+ }, [e]), O(() => {
326
325
  if (!e) return;
327
- let s = !0;
328
- return J("output/fmp4/anime").then((w) => {
329
- s && $(w.dirs.map((C) => C.name));
330
- }).catch(() => {
326
+ let i = !0;
327
+ return Q("output/fmp4/anime").then((b) => {
328
+ i && $(b.dirs.map((C) => C.name));
329
+ }).catch((b) => {
330
+ E("media", "series suggestions unavailable", H(b));
331
331
  }), () => {
332
- s = !1;
332
+ i = !1;
333
333
  };
334
334
  }, [e]);
335
- function Le(s) {
336
- if (l(s), ue(s) === "magnet" && s.trim().length > 0 && !y) {
337
- const C = Ye(s);
335
+ function Re(i) {
336
+ if (l(i), pe(i) === "magnet" && i.trim().length > 0 && !y) {
337
+ const C = Je(i);
338
338
  C && c(C);
339
339
  }
340
340
  }
341
- function Re() {
342
- l(""), i(""), c(""), v(!1);
341
+ function Te() {
342
+ l(""), s(""), c(""), v(!1);
343
343
  }
344
- const le = !F || o.trim().length > 0 && ze(p);
345
- async function oe() {
346
- const s = t.trim();
347
- if (!s || M || ie || F && !le) return;
344
+ const oe = !L || o.trim().length > 0 && ze(g);
345
+ async function de() {
346
+ const i = t.trim();
347
+ if (!i || A || le || L && !oe) return;
348
348
  R(!0), d(null);
349
- const w = F ? await Je(s, { title: p.trim() || void 0, series: o.trim() }) : await Ee(s);
350
- if (R(!1), !w.ok) {
351
- d(w.failure);
349
+ const b = L ? await Ke(i, { title: g.trim() || void 0, series: o.trim() }) : await Ae(i);
350
+ if (R(!1), !b.ok) {
351
+ d(b.failure);
352
352
  return;
353
353
  }
354
- A("submissions", "Submit accepted", { id: w.value.id, state: w.value.state }), Re(), m((C) => [w.value, ...(C ?? []).filter((I) => I.id !== w.value.id)]), B();
354
+ E("submissions", "Submit accepted", { id: b.value.id, state: b.value.state }), Te(), f((C) => [b.value, ...(C ?? []).filter((M) => M.id !== b.value.id)]), B();
355
355
  }
356
- function Te(s) {
357
- const w = s.target.files?.[0] ?? null;
358
- if (k(null), w && L && w.size > L.maxBytes) {
359
- O(null), k({ code: "too_large", maxBytes: L.maxBytes }), E.current && (E.current.value = "");
356
+ function _e(i) {
357
+ const b = i.target.files?.[0] ?? null;
358
+ if (m(null), b && I && b.size > I.maxBytes) {
359
+ D(null), m({ code: "too_large", maxBytes: I.maxBytes }), w.current && (w.current.value = "");
360
360
  return;
361
361
  }
362
- O(w);
362
+ D(b);
363
363
  }
364
- async function _e() {
365
- if (!T || U) return;
366
- n(!0), k(null);
367
- let s = L;
368
- if (!s) {
369
- const I = await pe();
370
- if (!I.ok) {
371
- n(!1), k(I.failure);
364
+ async function Ue() {
365
+ if (!T || P) return;
366
+ _(!0), m(null);
367
+ let i = I;
368
+ if (!i) {
369
+ const M = await me();
370
+ if (!M.ok) {
371
+ _(!1), m(M.failure);
372
372
  return;
373
373
  }
374
- s = I.value, z(s);
374
+ i = M.value, z(i);
375
375
  }
376
- if (T.size > s.maxBytes) {
377
- n(!1), k({ code: "too_large", maxBytes: s.maxBytes });
376
+ if (T.size > i.maxBytes) {
377
+ _(!1), m({ code: "too_large", maxBytes: i.maxBytes });
378
378
  return;
379
379
  }
380
- const w = await Ke(T, s, (I, X, Ue) => {
381
- g({ sent: I, total: X, phase: Ue });
380
+ const b = await Qe(T, i, (M, Z, Fe) => {
381
+ n({ sent: M, total: Z, phase: Fe });
382
382
  });
383
- if (!w.ok) {
384
- n(!1), g(null), k(w.failure);
383
+ if (!b.ok) {
384
+ _(!1), n(null), m(b.failure);
385
385
  return;
386
386
  }
387
- const C = await Qe(w.value.fileId, T.name);
388
- if (n(!1), g(null), !C.ok) {
389
- k(C.failure);
387
+ const C = await Xe(b.value.fileId, T.name);
388
+ if (_(!1), n(null), !C.ok) {
389
+ m(C.failure);
390
390
  return;
391
391
  }
392
- A("submissions", "Upload accepted", { id: C.value.id }), O(null), E.current && (E.current.value = ""), m((I) => [C.value, ...(I ?? []).filter((X) => X.id !== C.value.id)]), B();
392
+ E("submissions", "Upload accepted", { id: C.value.id }), D(null), w.current && (w.current.value = ""), f((M) => [C.value, ...(M ?? []).filter((Z) => Z.id !== C.value.id)]), B();
393
393
  }
394
- const de = b ? "maxBytes" in b || b.code === "target_unavailable" || b.code === "upload_failed" ? Ve(b) : V(b) : null;
394
+ const ce = p ? "maxBytes" in p || p.code === "target_unavailable" || p.code === "upload_failed" ? Ve(p) : Y(p) : null;
395
395
  return /* @__PURE__ */ u(
396
- $e,
396
+ Ee,
397
397
  {
398
398
  open: e,
399
399
  onClose: r,
@@ -406,8 +406,8 @@ function yt({ open: e, onClose: r }) {
406
406
  B();
407
407
  },
408
408
  "aria-label": "Refresh submissions",
409
- className: `${ae} ml-auto`,
410
- children: /* @__PURE__ */ a(re, { name: "refresh" })
409
+ className: `${re} ml-auto`,
410
+ children: /* @__PURE__ */ a(ne, { name: "refresh" })
411
411
  }
412
412
  )
413
413
  ] }),
@@ -417,34 +417,34 @@ function yt({ open: e, onClose: r }) {
417
417
  "input",
418
418
  {
419
419
  value: t,
420
- onChange: (s) => Le(s.target.value),
421
- onKeyDown: (s) => {
422
- s.key === "Enter" && !F && oe();
420
+ onChange: (i) => Re(i.target.value),
421
+ onKeyDown: (i) => {
422
+ i.key === "Enter" && !L && de();
423
423
  },
424
424
  "aria-label": "Media link",
425
425
  placeholder: "search, https:// or magnet:",
426
426
  className: "w-full bg-bg-alt border border-border focus:border-border-light outline-none px-2 py-1 rounded text-xs"
427
427
  }
428
428
  ),
429
- F && /* @__PURE__ */ u("div", { className: "flex flex-col gap-1.5", "data-testid": "magnet-fields", children: [
429
+ L && /* @__PURE__ */ u("div", { className: "flex flex-col gap-1.5", "data-testid": "magnet-fields", children: [
430
430
  /* @__PURE__ */ a(
431
431
  "input",
432
432
  {
433
433
  value: o,
434
- onChange: (s) => i(s.target.value),
434
+ onChange: (i) => s(i.target.value),
435
435
  list: "add-media-series-options",
436
436
  "aria-label": "Series",
437
437
  placeholder: "series",
438
438
  className: "w-full bg-bg-alt border border-border focus:border-border-light outline-none px-2 py-1 rounded text-xs"
439
439
  }
440
440
  ),
441
- /* @__PURE__ */ a("datalist", { id: "add-media-series-options", children: f.map((s) => /* @__PURE__ */ a("option", { value: s }, s)) }),
441
+ /* @__PURE__ */ a("datalist", { id: "add-media-series-options", children: h.map((i) => /* @__PURE__ */ a("option", { value: i }, i)) }),
442
442
  /* @__PURE__ */ a(
443
443
  "input",
444
444
  {
445
- value: p,
446
- onChange: (s) => {
447
- v(!0), c(s.target.value);
445
+ value: g,
446
+ onChange: (i) => {
447
+ v(!0), c(i.target.value);
448
448
  },
449
449
  "aria-label": "Title",
450
450
  placeholder: "title (SxxExx)",
@@ -457,22 +457,22 @@ function yt({ open: e, onClose: r }) {
457
457
  "button",
458
458
  {
459
459
  onClick: () => {
460
- oe();
460
+ de();
461
461
  },
462
- disabled: M || !t.trim() || ie || F && !le,
462
+ disabled: A || !t.trim() || le || L && !oe,
463
463
  "aria-label": "Submit media",
464
464
  className: "drawer-btn drawer-btn-primary",
465
- children: M ? "Submitting…" : "Submit"
465
+ children: A ? "Submitting…" : "Submit"
466
466
  }
467
467
  ),
468
- _ && /* @__PURE__ */ a("span", { "data-testid": "submit-failure", className: "text-[11px] bg-danger-bg text-on-danger-bg px-1.5 py-0.5 rounded", children: V(_) })
468
+ U && /* @__PURE__ */ a("span", { "data-testid": "submit-failure", className: "text-[11px] bg-danger-bg text-on-danger-bg px-1.5 py-0.5 rounded", children: Y(U) })
469
469
  ] })
470
470
  ] }),
471
471
  /* @__PURE__ */ a(
472
- ft,
472
+ ht,
473
473
  {
474
474
  query: t,
475
- onSubmitted: (s) => m((w) => [s, ...(w ?? []).filter((C) => C.id !== s.id)])
475
+ onSubmitted: (i) => f((b) => [i, ...(b ?? []).filter((C) => C.id !== i.id)])
476
476
  }
477
477
  ),
478
478
  /* @__PURE__ */ u("div", { className: "p-3 border-b border-border flex flex-col gap-2", children: [
@@ -480,9 +480,9 @@ function yt({ open: e, onClose: r }) {
480
480
  /* @__PURE__ */ a(
481
481
  "input",
482
482
  {
483
- ref: E,
483
+ ref: w,
484
484
  type: "file",
485
- onChange: Te,
485
+ onChange: _e,
486
486
  "aria-label": "Upload file",
487
487
  className: "text-[11px] flex-1 min-w-0"
488
488
  }
@@ -491,187 +491,183 @@ function yt({ open: e, onClose: r }) {
491
491
  "button",
492
492
  {
493
493
  onClick: () => {
494
- _e();
494
+ Ue();
495
495
  },
496
- disabled: !T || U,
496
+ disabled: !T || P,
497
497
  "aria-label": "Upload",
498
498
  className: "drawer-btn drawer-btn-primary",
499
- children: U ? h?.phase === "assembling" ? "Assembling…" : "Uploading…" : "Upload"
499
+ children: P ? V?.phase === "assembling" ? "Assembling…" : "Uploading…" : "Upload"
500
500
  }
501
501
  )
502
502
  ] }),
503
- /* @__PURE__ */ a("span", { className: "text-[10px] text-text-muted", "data-testid": "upload-cap", children: L ? `cap ${We(L.maxBytes)}` : "" }),
504
- de && /* @__PURE__ */ a("span", { "data-testid": "upload-failure", className: "text-[11px] bg-danger-bg text-on-danger-bg px-1.5 py-0.5 rounded", children: de })
503
+ /* @__PURE__ */ a("span", { className: "text-[10px] text-text-muted", "data-testid": "upload-cap", children: I ? `cap ${Ye(I.maxBytes)}` : "" }),
504
+ ce && /* @__PURE__ */ a("span", { "data-testid": "upload-failure", className: "text-[11px] bg-danger-bg text-on-danger-bg px-1.5 py-0.5 rounded", children: ce })
505
505
  ] }),
506
506
  /* @__PURE__ */ u("div", { className: "flex-1 overflow-auto", "data-testid": "my-submissions", children: [
507
- S && /* @__PURE__ */ a("div", { className: "mx-3 my-2 px-3 py-2 text-[11px] bg-danger-bg text-on-danger-bg rounded", children: V(S) }),
508
- N?.map((s) => /* @__PURE__ */ a(xt, { item: s }, s.id))
507
+ k && /* @__PURE__ */ a("div", { className: "mx-3 my-2 px-3 py-2 text-[11px] bg-danger-bg text-on-danger-bg rounded", children: Y(k) }),
508
+ N?.map((i) => /* @__PURE__ */ a(yt, { item: i }, i.id))
509
509
  ] })
510
510
  ]
511
511
  }
512
512
  );
513
513
  }
514
- const vt = { bomberman: Ze };
515
- function Ie() {
516
- Ce(null), A("game", "game_select", { gameId: null });
514
+ const wt = { bomberman: et };
515
+ function Le() {
516
+ $e(null), E("game", "game_select", { gameId: null });
517
517
  }
518
- function wt({ onDone: e }) {
519
- const r = se((i) => i.activeGameId), t = Oe();
520
- function l(i) {
521
- Ce(i), A("game", "game_select", { gameId: i }), e();
518
+ function Nt({ onDone: e }) {
519
+ const r = ie((s) => s.activeGameId), t = Pe();
520
+ function l(s) {
521
+ $e(s), E("game", "game_select", { gameId: s }), e();
522
522
  }
523
523
  function o() {
524
- Ie(), e();
524
+ Le(), e();
525
525
  }
526
- return /* @__PURE__ */ a("div", { className: "flex-1 overflow-auto p-3", children: /* @__PURE__ */ a("div", { className: "grid grid-cols-2 gap-3", children: t.map((i) => {
527
- const p = r === i.id, c = i.cover ?? vt[i.id];
526
+ return /* @__PURE__ */ a("div", { className: "flex-1 overflow-auto p-3", children: /* @__PURE__ */ a("div", { className: "grid grid-cols-2 gap-3", children: t.map((s) => {
527
+ const g = r === s.id, c = s.cover ?? wt[s.id];
528
528
  return /* @__PURE__ */ u(
529
529
  "button",
530
530
  {
531
- onClick: () => p ? o() : l(i.id),
532
- className: `group relative aspect-square overflow-hidden rounded-lg border-2 transition-all cursor-pointer ${p ? "border-primary shadow-lg shadow-primary/30" : "border-border hover:border-primary"}`,
533
- title: p ? `Stop ${i.name}` : `Start ${i.name}`,
531
+ onClick: () => g ? o() : l(s.id),
532
+ className: `group relative aspect-square overflow-hidden rounded-lg border-2 transition-all cursor-pointer ${g ? "border-primary shadow-lg shadow-primary/30" : "border-border hover:border-primary"}`,
533
+ title: g ? `Stop ${s.name}` : `Start ${s.name}`,
534
534
  children: [
535
535
  c ? /* @__PURE__ */ a(
536
536
  "img",
537
537
  {
538
538
  src: c,
539
- alt: i.name,
539
+ alt: s.name,
540
540
  className: "absolute inset-0 w-full h-full object-cover transition-transform group-hover:scale-105"
541
541
  }
542
542
  ) : /* @__PURE__ */ a("div", { className: "absolute inset-0 bg-bg-alt" }),
543
- /* @__PURE__ */ a("div", { className: "absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/85 via-black/40 to-transparent px-2 pt-6 pb-2", children: /* @__PURE__ */ a("div", { className: "text-sm font-medium text-white leading-tight", children: i.name }) }),
544
- p && /* @__PURE__ */ a("span", { className: "absolute top-2 left-2 px-1.5 py-0.5 bg-primary text-[10px] uppercase tracking-wide rounded text-white", children: "Active" })
543
+ /* @__PURE__ */ a("div", { className: "absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/85 via-black/40 to-transparent px-2 pt-6 pb-2", children: /* @__PURE__ */ a("div", { className: "text-sm font-medium text-white leading-tight", children: s.name }) }),
544
+ g && /* @__PURE__ */ a("span", { className: "absolute top-2 left-2 px-1.5 py-0.5 bg-primary text-[10px] uppercase tracking-wide rounded text-white", children: "Active" })
545
545
  ]
546
546
  },
547
- i.id
547
+ s.id
548
548
  );
549
549
  }) }) });
550
550
  }
551
- function Nt({ onDone: e }) {
552
- return se((t) => t.activeGameId) ? /* @__PURE__ */ a("button", { onClick: () => {
553
- Ie(), e();
551
+ function kt({ onDone: e }) {
552
+ return ie((t) => t.activeGameId) ? /* @__PURE__ */ a("button", { onClick: () => {
553
+ Le(), e();
554
554
  }, className: "drawer-btn drawer-btn-danger ml-auto", children: "Stop game" }) : null;
555
555
  }
556
- const G = (e) => e.type === "category" ? e.series : [], te = (e, r) => e.type === "category" ? { ...e, series: r } : e;
556
+ const G = (e) => e.type === "category" ? e.series : [], ae = (e, r) => e.type === "category" ? { ...e, series: r } : e;
557
557
  function Lt({ open: e, onClose: r }) {
558
- const [t, l] = x(!1), [o, i] = x(null), [p, c] = x([]), [y, v] = x(""), [f, $] = x(!1), [M, R] = x("watch"), _ = se((n) => n.snapshot.mediaId), d = Xe(), N = Se(async () => {
559
- l(!0), i(null);
560
- try {
561
- const n = await ye(J);
562
- c((h) => he(n, fe(h, G), G, te)), Y() && at();
563
- } catch (n) {
564
- i(n.message || "catalog_error");
565
- } finally {
566
- l(!1);
567
- }
568
- }, []), m = Ge();
569
- D(() => {
570
- if (!m) return;
558
+ const [t, l] = x(!1), [o, s] = x(null), [g, c] = x([]), [y, v] = x(""), [h, $] = x(!1), [A, R] = x("watch"), U = ie((n) => n.snapshot.mediaId), d = Ze(), N = Ce(() => ve(Q).then((n) => {
559
+ c((p) => be(n, he(p, G), G, ae)), K() && rt();
560
+ }).catch((n) => {
561
+ s(n instanceof Error && n.message || "catalog_error");
562
+ }).finally(() => l(!1)), []), f = je();
563
+ O(() => {
564
+ if (!f) return;
571
565
  let n = !0;
572
- return ye(J).then(
573
- (h) => {
574
- n && c((g) => he(h, fe(g, G), G, te));
566
+ return ve(Q).then(
567
+ (p) => {
568
+ n && c((m) => be(p, he(m, G), G, ae));
575
569
  },
576
- (h) => q("catalog", "Catalog prefetch failed", Q(h))
570
+ (p) => q("catalog", "Catalog prefetch failed", H(p))
577
571
  ), () => {
578
572
  n = !1;
579
573
  };
580
- }, [m]), D(() => {
581
- e && (R("watch"), c((n) => ot(n, G, te)), N());
574
+ }, [f]);
575
+ const [k, W] = x(!1);
576
+ e !== k && (W(e), e && (R("watch"), c((n) => dt(n, G, ae)), l(!0), s(null))), O(() => {
577
+ e && N();
582
578
  }, [e, N]);
583
- function S(n) {
584
- je(n), A("catalog", "control_load", { mediaId: n }), r();
579
+ function I(n) {
580
+ qe(n), E("catalog", "control_load", { mediaId: n }), r();
585
581
  }
586
- function H(n) {
587
- Pe(n), A("catalog", "playlist_load", { playlistId: n }), r();
582
+ function z(n) {
583
+ Ge(n), E("catalog", "playlist_load", { playlistId: n }), r();
588
584
  }
589
- function L() {
590
- qe(), A("controls", "Unload media clicked (media drawer)"), r();
585
+ function T() {
586
+ He(), E("controls", "Unload media clicked (media drawer)"), r();
591
587
  }
592
- function z(n, h) {
593
- c((g) => g.map((b, k) => k !== n || !("series" in b) ? b : { ...b, series: b.series.map((E, P) => P !== h ? E : { ...E, expanded: !E.expanded }) }));
588
+ function D(n, p) {
589
+ c((m) => m.map((w, S) => S !== n || !("series" in w) ? w : { ...w, series: w.series.map((F, L) => L !== p ? F : { ...F, expanded: !F.expanded }) }));
594
590
  }
595
- function T(n) {
596
- c((h) => h.map((g, b) => b !== n ? g : { ...g, expanded: !g.expanded }));
591
+ function P(n) {
592
+ c((p) => p.map((m, w) => w !== n ? m : { ...m, expanded: !m.expanded }));
597
593
  }
598
- function O() {
599
- tt(), N();
594
+ function _() {
595
+ at(), l(!0), s(null), N();
600
596
  }
601
- const U = ke(() => {
602
- if (!y.trim()) return p;
597
+ const V = Se(() => {
598
+ if (!y.trim()) return g;
603
599
  const n = y.toLowerCase();
604
- return p.map((h) => {
605
- if (h.type === "playlist_category") {
606
- const b = h.playlists.filter((k) => k.name.toLowerCase().includes(n));
607
- return b.length ? { ...h, playlists: b, expanded: !0 } : h.name.toLowerCase().includes(n) ? { ...h, expanded: !0 } : null;
600
+ return g.map((p) => {
601
+ if (p.type === "playlist_category") {
602
+ const w = p.playlists.filter((S) => S.name.toLowerCase().includes(n));
603
+ return w.length ? { ...p, playlists: w, expanded: !0 } : p.name.toLowerCase().includes(n) ? { ...p, expanded: !0 } : null;
608
604
  }
609
- const g = h.series.map((b) => {
610
- const k = b.episodes.filter((E) => E.name.toLowerCase().includes(n));
611
- return k.length ? { ...b, episodes: k, expanded: !0 } : b.name.toLowerCase().includes(n) ? { ...b, expanded: !0 } : null;
605
+ const m = p.series.map((w) => {
606
+ const S = w.episodes.filter((F) => F.name.toLowerCase().includes(n));
607
+ return S.length ? { ...w, episodes: S, expanded: !0 } : w.name.toLowerCase().includes(n) ? { ...w, expanded: !0 } : null;
612
608
  }).filter(Boolean);
613
- return g.length ? { ...h, series: g, expanded: !0 } : h.name.toLowerCase().includes(n) ? { ...h, expanded: !0 } : null;
609
+ return m.length ? { ...p, series: m, expanded: !0 } : p.name.toLowerCase().includes(n) ? { ...p, expanded: !0 } : null;
614
610
  }).filter(Boolean);
615
- }, [p, y]);
611
+ }, [g, y]);
616
612
  return /* @__PURE__ */ u(j, { children: [
617
- /* @__PURE__ */ a(yt, { open: f, onClose: () => $(!1) }),
613
+ /* @__PURE__ */ a(vt, { open: h, onClose: () => $(!1) }),
618
614
  /* @__PURE__ */ a(
619
- $e,
615
+ Ee,
620
616
  {
621
- open: e && !f,
617
+ open: e && !h,
622
618
  onClose: r,
623
619
  header: /* @__PURE__ */ u(j, { children: [
624
620
  /* @__PURE__ */ a("div", { className: "tl-tabs", role: "tablist", "aria-label": "Media drawer", children: ["watch", "play"].map((n) => /* @__PURE__ */ a(
625
621
  "button",
626
622
  {
627
623
  role: "tab",
628
- "aria-selected": M === n,
624
+ "aria-selected": A === n,
629
625
  onClick: () => R(n),
630
626
  className: "tl-tab",
631
627
  children: n === "watch" ? "Watch" : "Play"
632
628
  },
633
629
  n
634
630
  )) }),
635
- M === "play" && /* @__PURE__ */ a(Nt, { onDone: r }),
636
- M === "watch" && /* @__PURE__ */ u(j, { children: [
631
+ A === "play" && /* @__PURE__ */ a(kt, { onDone: r }),
632
+ A === "watch" && /* @__PURE__ */ u(j, { children: [
637
633
  d && /* @__PURE__ */ a(
638
634
  "button",
639
635
  {
640
636
  onClick: () => $(!0),
641
637
  "aria-label": "Add Media",
642
- className: ae,
638
+ className: re,
643
639
  children: "Add"
644
640
  }
645
641
  ),
646
- _ && /* @__PURE__ */ a(
642
+ U && /* @__PURE__ */ a(
647
643
  "button",
648
644
  {
649
- onClick: L,
645
+ onClick: T,
650
646
  title: "Unload the current media for everyone in the room",
651
647
  className: "drawer-btn drawer-btn-primary",
652
648
  children: "Unload"
653
649
  }
654
650
  ),
655
- /* @__PURE__ */ u("button", { onClick: O, disabled: t, className: `${ae} inline-flex items-center gap-1.5`, children: [
651
+ /* @__PURE__ */ u("button", { onClick: _, disabled: t, className: `${re} inline-flex items-center gap-1.5`, children: [
656
652
  t && /* @__PURE__ */ a("span", { className: "inline-block w-3 h-3 border-2 border-text-muted border-t-transparent rounded-full animate-spin" }),
657
653
  t ? "Reloading…" : "Reload"
658
654
  ] }),
659
655
  /* @__PURE__ */ a("input", { value: y, onChange: (n) => v(n.target.value), placeholder: "search", className: "ml-auto bg-bg-alt border border-border focus:border-border-light outline-none px-2 py-1 rounded text-xs" })
660
656
  ] })
661
657
  ] }),
662
- footer: Y() ? /* @__PURE__ */ a("div", { className: "p-2 text-[10px] text-text-muted border-t border-border flex justify-end", children: /* @__PURE__ */ a("span", { className: "opacity-70", children: "verbose" }) }) : void 0,
663
- children: M === "play" ? /* @__PURE__ */ a(wt, { onDone: r }) : /* @__PURE__ */ u(j, { children: [
664
- t && !p.length && /* @__PURE__ */ a("div", { className: "px-4 py-2 text-xs text-text-muted", children: "Loading catalog…" }),
658
+ footer: K() ? /* @__PURE__ */ a("div", { className: "p-2 text-[10px] text-text-muted border-t border-border flex justify-end", children: /* @__PURE__ */ a("span", { className: "opacity-70", children: "verbose" }) }) : void 0,
659
+ children: A === "play" ? /* @__PURE__ */ a(Nt, { onDone: r }) : /* @__PURE__ */ u(j, { children: [
660
+ t && !g.length && /* @__PURE__ */ a("div", { className: "px-4 py-2 text-xs text-text-muted", children: "Loading catalog…" }),
665
661
  o && /* @__PURE__ */ a("div", { className: "mx-3 px-3 py-2 text-xs bg-danger-bg text-on-danger-bg rounded", children: o }),
666
662
  /* @__PURE__ */ u("div", { className: "flex-1 overflow-auto text-sm py-2", children: [
667
- U.map((n, h) => /* @__PURE__ */ u("div", { className: "px-3 pb-3", children: [
663
+ V.map((n, p) => /* @__PURE__ */ u("div", { className: "px-3 pb-3", children: [
668
664
  /* @__PURE__ */ u(
669
665
  "div",
670
666
  {
671
667
  className: "flex items-center gap-2 cursor-pointer select-none group",
672
668
  "data-category": n.name,
673
669
  "data-expanded": n.expanded ? "true" : "false",
674
- onClick: () => T(h),
670
+ onClick: () => P(p),
675
671
  children: [
676
672
  /* @__PURE__ */ a("span", { className: "text-xs uppercase tracking-wider text-text-muted group-hover:text-text-secondary", children: n.name }),
677
673
  /* @__PURE__ */ a("span", { className: "text-[10px] opacity-50", children: n.expanded ? "−" : "+" })
@@ -679,30 +675,30 @@ function Lt({ open: e, onClose: r }) {
679
675
  }
680
676
  ),
681
677
  n.expanded && n.type === "playlist_category" && /* @__PURE__ */ u("div", { className: "mt-2 space-y-1", children: [
682
- n.playlists.map((g) => /* @__PURE__ */ u("button", { onClick: () => H(g.playlistId), className: "w-full text-left px-2 py-1 rounded hover:bg-bg-alt flex items-center gap-2 group", children: [
683
- /* @__PURE__ */ a("span", { className: "text-[11px] text-text-tertiary group-hover:text-text-secondary truncate", children: g.name }),
678
+ n.playlists.map((m) => /* @__PURE__ */ u("button", { onClick: () => z(m.playlistId), className: "w-full text-left px-2 py-1 rounded hover:bg-bg-alt flex items-center gap-2 group", children: [
679
+ /* @__PURE__ */ a("span", { className: "text-[11px] text-text-tertiary group-hover:text-text-secondary truncate", children: m.name }),
684
680
  /* @__PURE__ */ a("span", { className: "ml-auto text-[10px] text-text underline decoration-primary underline-offset-2 opacity-0 group-hover:opacity-100 transition-opacity", children: "Load" })
685
- ] }, g.playlistId)),
681
+ ] }, m.playlistId)),
686
682
  n.playlists.length === 0 && /* @__PURE__ */ a("div", { className: "text-[11px] text-text-muted italic", children: "(no playlists)" })
687
683
  ] }),
688
684
  n.expanded && n.type === "category" && /* @__PURE__ */ u("div", { className: "mt-2 space-y-2", children: [
689
- n.series.map((g, b) => /* @__PURE__ */ u("div", { children: [
690
- /* @__PURE__ */ u("div", { className: "flex items-center gap-2 cursor-pointer text-text-secondary hover:text-text", onClick: () => z(h, b), children: [
691
- /* @__PURE__ */ a("span", { className: "text-xs font-medium", children: g.name }),
692
- /* @__PURE__ */ a("span", { className: "text-[10px] opacity-40", children: g.expanded ? "−" : "+" })
685
+ n.series.map((m, w) => /* @__PURE__ */ u("div", { children: [
686
+ /* @__PURE__ */ u("div", { className: "flex items-center gap-2 cursor-pointer text-text-secondary hover:text-text", onClick: () => D(p, w), children: [
687
+ /* @__PURE__ */ a("span", { className: "text-xs font-medium", children: m.name }),
688
+ /* @__PURE__ */ a("span", { className: "text-[10px] opacity-40", children: m.expanded ? "−" : "+" })
693
689
  ] }),
694
- g.expanded && /* @__PURE__ */ u("div", { className: "mt-1 ml-3 border-l border-border pl-3 space-y-1", children: [
695
- g.episodes.map((k) => /* @__PURE__ */ u("button", { onClick: () => S(k.mediaId), className: "w-full text-left px-2 py-1 rounded hover:bg-bg-alt flex items-center gap-2 group", children: [
696
- /* @__PURE__ */ a("span", { className: "text-[11px] text-text-tertiary group-hover:text-text-secondary truncate", children: k.name }),
690
+ m.expanded && /* @__PURE__ */ u("div", { className: "mt-1 ml-3 border-l border-border pl-3 space-y-1", children: [
691
+ m.episodes.map((S) => /* @__PURE__ */ u("button", { onClick: () => I(S.mediaId), className: "w-full text-left px-2 py-1 rounded hover:bg-bg-alt flex items-center gap-2 group", children: [
692
+ /* @__PURE__ */ a("span", { className: "text-[11px] text-text-tertiary group-hover:text-text-secondary truncate", children: S.name }),
697
693
  /* @__PURE__ */ a("span", { className: "ml-auto text-[10px] text-text underline decoration-primary underline-offset-2 opacity-0 group-hover:opacity-100 transition-opacity", children: "Load" })
698
- ] }, k.mediaId)),
699
- g.episodes.length === 0 && /* @__PURE__ */ a("div", { className: "text-[11px] text-text-muted italic", children: "(no episodes)" })
694
+ ] }, S.mediaId)),
695
+ m.episodes.length === 0 && /* @__PURE__ */ a("div", { className: "text-[11px] text-text-muted italic", children: "(no episodes)" })
700
696
  ] })
701
- ] }, g.name)),
697
+ ] }, m.name)),
702
698
  n.series.length === 0 && /* @__PURE__ */ a("div", { className: "text-[11px] text-text-muted italic", children: "(empty)" })
703
699
  ] })
704
700
  ] }, n.name)),
705
- !t && !U.length && /* @__PURE__ */ a("div", { className: "px-4 py-6 text-center text-xs text-text-muted", children: "No matches" })
701
+ !t && !V.length && /* @__PURE__ */ a("div", { className: "px-4 py-6 text-center text-xs text-text-muted", children: "No matches" })
706
702
  ] })
707
703
  ] })
708
704
  }
@@ -712,4 +708,4 @@ function Lt({ open: e, onClose: r }) {
712
708
  export {
713
709
  Lt as default
714
710
  };
715
- //# sourceMappingURL=MediaDrawer-Da6-fLeV.js.map
711
+ //# sourceMappingURL=MediaDrawer-DLFj0-te.js.map