memi-board 0.62.0 → 0.63.0

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.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { $ as e, A as t, B as n, C as r, D as i, E as a, F as o, G as s, H as c, I as l, J as u, K as d, L as f, M as p, N as m, O as h, P as g, Q as _, R as v, S as y, T as b, U as x, V as S, W as C, X as w, Y as T, Z as E, _ as D, at as O, b as k, c as A, ct as j, d as ee, et as M, f as N, g as te, h as P, i as ne, it as re, j as ie, k as ae, l as oe, lt as se, m as ce, nt as le, o as ue, ot as de, p as fe, q as pe, r as me, rt as he, s as ge, st as _e, t as ve, tt as ye, u as be, ut as F, v as xe, w as Se, x as Ce, y as we, z as Te } from "./commentImages-DVrG0nFm.js";
1
+ import { $ as e, A as t, B as n, C as r, D as i, E as a, F as o, G as s, H as c, I as l, J as u, K as d, L as f, M as p, N as m, O as h, P as g, Q as _, R as v, S as y, T as b, U as x, V as S, W as C, X as w, Y as T, Z as E, _ as D, at as O, b as k, c as A, ct as j, d as ee, et as M, f as N, g as te, h as P, i as ne, it as re, j as ie, k as ae, l as oe, lt as se, m as ce, nt as le, o as ue, ot as de, p as fe, q as pe, r as me, rt as he, s as ge, st as _e, t as ve, tt as ye, u as be, ut as F, v as xe, w as Se, x as Ce, y as we, z as Te } from "./commentImages-xb5Y4ySe.js";
2
2
  import { computed as I, onScopeDispose as L, reactive as Ee, readonly as De, ref as R, shallowRef as Oe, toValue as z, watch as B } from "vue";
3
- import { collection as ke, deleteDoc as Ae, deleteField as je, doc as V, documentId as H, endAt as Me, endBefore as Ne, getCountFromServer as Pe, getDoc as U, getDocFromServer as Fe, getDocs as W, getDocsFromServer as Ie, increment as Le, limit as G, limitToLast as Re, onSnapshot as K, orderBy as q, query as J, runTransaction as Y, serverTimestamp as X, setDoc as ze, startAfter as Z, updateDoc as Be, where as Q, writeBatch as Ve } from "firebase/firestore";
3
+ import { collection as ke, deleteDoc as Ae, deleteField as V, doc as H, documentId as U, endAt as je, endBefore as Me, getCountFromServer as Ne, getDoc as W, getDocFromServer as Pe, getDocs as G, getDocsFromServer as Fe, increment as Ie, limit as K, limitToLast as Le, onSnapshot as q, orderBy as J, query as Y, runTransaction as Re, serverTimestamp as X, setDoc as ze, startAfter as Z, updateDoc as Be, where as Q, writeBatch as Ve } from "firebase/firestore";
4
4
  import { useCollection as He, useCurrentUser as Ue, useDocument as We, useFirebaseApp as Ge, useFirebaseAuth as Ke, useFirestore as $ } from "vuefire";
5
5
  import { GoogleAuthProvider as qe, OAuthProvider as Je, createUserWithEmailAndPassword as Ye, getAuth as Xe, signInWithEmailAndPassword as Ze, signInWithPopup as Qe, signOut as $e, updateProfile as et } from "firebase/auth";
6
6
  import { deleteObject as tt, getMetadata as nt, getStorage as rt, list as it, listAll as at, ref as ot } from "firebase/storage";
@@ -175,7 +175,7 @@ function Bt() {
175
175
  }
176
176
  async function Vt(e, t, n) {
177
177
  try {
178
- let r = await U(O(e.db, e.paths, t));
178
+ let r = await W(O(e.db, e.paths, t));
179
179
  if (!r.exists()) return {
180
180
  label: t,
181
181
  description: "",
@@ -212,7 +212,7 @@ async function Ut(e, t, n, r) {
212
212
  let s = await Vt(o, i, r);
213
213
  if (s.hidden) return null;
214
214
  try {
215
- let e = (await W(J(_(o.db, o.paths), Q("boardId", "==", i), Q("slug", "==", a), Q("listed", "==", !0), Q("isPublished", "==", !0), G(1)))).docs[0];
215
+ let e = (await G(Y(_(o.db, o.paths), Q("boardId", "==", i), Q("slug", "==", a), Q("listed", "==", !0), Q("isPublished", "==", !0), K(1)))).docs[0];
216
216
  if (!e) return null;
217
217
  let t = e.data() ?? {}, n = typeof t.title == "string" ? t.title : "", c = typeof t.summary == "string" ? t.summary : "", l = Et(t.i18n), u = Dt(t.i18nSource), d = Ft({
218
218
  title: n,
@@ -273,7 +273,7 @@ async function Wt(e, t, n) {
273
273
  async function Gt(e, t, n) {
274
274
  let r = [], i = null;
275
275
  try {
276
- let a = await W(J(_(e.db, e.paths), Q("boardId", "==", t), Q("listed", "==", !0), Q("isPublished", "==", !0), q("createdAt", "desc"), G(12)));
276
+ let a = await G(Y(_(e.db, e.paths), Q("boardId", "==", t), Q("listed", "==", !0), Q("isPublished", "==", !0), J("createdAt", "desc"), K(12)));
277
277
  for (let e of a.docs) {
278
278
  let t = e.data() ?? {}, a = Ft({
279
279
  title: typeof t.title == "string" ? t.title : "",
@@ -395,7 +395,7 @@ function cn() {
395
395
  f.value = Math.max(0, Math.floor(Number(e.moderationBlockCount) || 0)), p.value = an(e.moderationBlockAt);
396
396
  }
397
397
  async function v(e) {
398
- let t = g(e.uid), n = l(i, b(), e.uid), r = await U(t);
398
+ let t = g(e.uid), n = l(i, b(), e.uid), r = await W(t);
399
399
  if (!r.exists()) return await Promise.all([ze(t, {
400
400
  role: "user",
401
401
  displayName: e.displayName,
@@ -424,7 +424,7 @@ function cn() {
424
424
  _(void 0);
425
425
  return;
426
426
  }
427
- let t = await U(g(e));
427
+ let t = await W(g(e));
428
428
  _(t.exists() ? t.data() : void 0);
429
429
  }
430
430
  r.watchStarted || (r.watchStarted = !0, B(c, async (e) => {
@@ -460,9 +460,9 @@ function cn() {
460
460
  restricted: !1,
461
461
  messageSuffix: ""
462
462
  };
463
- let i = g(e), a = await U(i);
463
+ let i = g(e), a = await W(i);
464
464
  a.exists() ? await Be(i, {
465
- moderationBlockCount: Le(1),
465
+ moderationBlockCount: Ie(1),
466
466
  moderationBlockAt: X(),
467
467
  updatedAt: X()
468
468
  }) : await ze(i, {
@@ -588,13 +588,13 @@ function pn(e) {
588
588
  return t.replace(/-+$/g, "") || "post";
589
589
  }
590
590
  function mn(e, t, n, r) {
591
- return V(e, `${t.postsCollection}Slugs`, n, "slugs", r);
591
+ return H(e, `${t.postsCollection}Slugs`, n, "slugs", r);
592
592
  }
593
593
  function hn(e, t) {
594
- return V(e, `${t.postsCollection}Slugs`, "__migration");
594
+ return H(e, `${t.postsCollection}Slugs`, "__migration");
595
595
  }
596
596
  async function gn(e, t, n, r) {
597
- return _n(r, async (r) => !(await U(mn(e, t, n, r))).exists());
597
+ return _n(r, async (r) => !(await W(mn(e, t, n, r))).exists());
598
598
  }
599
599
  async function _n(e, t) {
600
600
  let n = pn(e);
@@ -604,11 +604,11 @@ async function _n(e, t) {
604
604
  }
605
605
  }
606
606
  async function vn(e, t, n, r, i, a) {
607
- return _n(i, (i) => Y(e, async (o) => {
607
+ return _n(i, (i) => Re(e, async (o) => {
608
608
  if ((await o.get(hn(e, t))).data()?.ready !== !0) throw Error("Post URL reservations are not initialized. Run the post slug backfill before creating new posts.");
609
609
  let s = mn(e, t, n, i);
610
610
  if ((await o.get(s)).exists()) return !1;
611
- let c = V(e, t.postsCollection, r);
611
+ let c = H(e, t.postsCollection, r);
612
612
  if ((await o.get(c)).exists()) throw Error("This post has already been saved. Reload it before editing.");
613
613
  return o.set(s, { postId: r }), a(o, i), !0;
614
614
  }));
@@ -617,7 +617,7 @@ async function vn(e, t, n, r, i, a) {
617
617
  //#region src/utils/findReadablePost.ts
618
618
  async function yn(e, t, n, r, i, a) {
619
619
  let o = [Q("boardId", "==", n), Q("slug", "==", r)];
620
- return a ? (await W(J(_(e, t), ...o, G(1)))).docs[0] : (await Promise.all([W(J(_(e, t), ...o, Q("listed", "==", !0), Q("isPublished", "==", !0), G(1))), ...i ? [W(J(_(e, t), ...o, Q("authorUid", "==", i), G(1)))] : []])).flatMap((e) => e.docs)[0];
620
+ return a ? (await G(Y(_(e, t), ...o, K(1)))).docs[0] : (await Promise.all([G(Y(_(e, t), ...o, Q("listed", "==", !0), Q("isPublished", "==", !0), K(1))), ...i ? [G(Y(_(e, t), ...o, Q("authorUid", "==", i), K(1)))] : []])).flatMap((e) => e.docs)[0];
621
621
  }
622
622
  //#endregion
623
623
  //#region src/utils/extractEditorImageUrls.ts
@@ -656,27 +656,27 @@ async function wn(e, t) {
656
656
  }
657
657
  var Tn = 450;
658
658
  async function En(e, t, n) {
659
- return (await W(J(x(e, t), Q("postId", "==", n)))).docs.flatMap((e) => ve(e.data().images, `${E(t, n)}/comment-images/`));
659
+ return (await G(Y(x(e, t), Q("postId", "==", n)))).docs.flatMap((e) => ve(e.data().images, `${E(t, n)}/comment-images/`));
660
660
  }
661
661
  async function Dn(e, t) {
662
662
  let n = [...new Set([...t].filter(Boolean))];
663
663
  await Promise.all(n.map((t) => tt(ot(e, t)).catch(() => {})));
664
664
  }
665
665
  async function On(e, t) {
666
- let n = await W(t);
666
+ let n = await G(t);
667
667
  for (let t = 0; t < n.docs.length; t += Tn) {
668
668
  let r = Ve(e);
669
669
  n.docs.slice(t, t + Tn).forEach((e) => r.delete(e.ref)), await r.commit();
670
670
  }
671
671
  }
672
672
  async function kn(e, t, n) {
673
- await On(e, J(d(e, t), Q("postId", "==", n)));
673
+ await On(e, Y(d(e, t), Q("postId", "==", n)));
674
674
  }
675
675
  async function An(e, t, n) {
676
- await On(e, J(d(e, t), Q("commentId", "==", n), Q("target", "==", "comment")));
676
+ await On(e, Y(d(e, t), Q("commentId", "==", n), Q("target", "==", "comment")));
677
677
  }
678
678
  async function jn(e, t, n, r) {
679
- let i = u(e, n, r), a = pe(e, n, r), [o, s] = await Promise.all([U(i), U(a)]);
679
+ let i = u(e, n, r), a = pe(e, n, r), [o, s] = await Promise.all([W(i), W(a)]);
680
680
  if (!o.exists()) return;
681
681
  let c = o.data(), l = s.exists() ? String(s.data().content ?? "") : "", d = await En(e, n, r), f = /* @__PURE__ */ new Set(), p = /* @__PURE__ */ new Set();
682
682
  for (let e of c.attachments ?? []) {
@@ -698,7 +698,7 @@ async function jn(e, t, n, r) {
698
698
  }
699
699
  await wn(t, E(n, r));
700
700
  for (let e of p) await wn(t, E(n, e));
701
- await Dn(t, d), await Dn(t, f), await On(e, J(x(e, n), Q("postId", "==", r))), await kn(e, n, r);
701
+ await Dn(t, d), await Dn(t, f), await On(e, Y(x(e, n), Q("postId", "==", r))), await kn(e, n, r);
702
702
  let m = Ve(e);
703
703
  m.delete(a), m.delete(i), await m.commit();
704
704
  }
@@ -751,7 +751,7 @@ function Bn(e, t = []) {
751
751
  }
752
752
  //#endregion
753
753
  //#region src/utils/customFields.ts
754
- var Vn = 8, Hn = 40, Un = 80, Wn = 200, Gn = /^[a-z][A-Za-z0-9_]{0,31}$/;
754
+ var Vn = 20, Hn = 40, Un = 80, Wn = 200, Gn = /^[a-z][A-Za-z0-9_]{0,31}$/;
755
755
  function Kn(e) {
756
756
  return typeof e == "string" ? e.trim() : "";
757
757
  }
@@ -777,13 +777,13 @@ function Xn(e) {
777
777
  for (let r of e) {
778
778
  if (!r || typeof r != "object") continue;
779
779
  let e = r, i = Kn(e.key), a = qn(e.label);
780
- if (Gn.test(i) && a && !t.has(i) && (t.add(i), n.push(Yn(i, a, Jn(e.placeholder))), n.length >= 8)) break;
780
+ if (Gn.test(i) && a && !t.has(i) && (t.add(i), n.push(Yn(i, a, Jn(e.placeholder))), n.length >= 20)) break;
781
781
  }
782
782
  return n;
783
783
  }
784
784
  function Zn(e) {
785
785
  let t = (e ?? []).filter((e) => Kn(e?.key) || qn(e?.label) || Jn(e?.placeholder));
786
- if (t.length > 8) return {
786
+ if (t.length > 20) return {
787
787
  fields: [],
788
788
  issue: { code: "tooMany" }
789
789
  };
@@ -844,7 +844,7 @@ function nr(e) {
844
844
  async function rr(e, t, n, r) {
845
845
  let i;
846
846
  for (;;) {
847
- let a = await W(J(t, Q("boardId", "==", n), q("__name__"), ...i ? [Z(i)] : [], G(400)));
847
+ let a = await G(Y(t, Q("boardId", "==", n), J("__name__"), ...i ? [Z(i)] : [], K(400)));
848
848
  if (a.empty) break;
849
849
  let o = Ve(e), s = 0;
850
850
  for (let e of a.docs) e.data().listed !== r && (o.update(e.ref, { listed: r }), s++);
@@ -856,7 +856,7 @@ async function ir(e, t, n, r) {
856
856
  }
857
857
  async function ar(e, t, n, r, i) {
858
858
  let a = O(e, t, n), o = nr(r.visibility);
859
- await Y(e, async (e) => {
859
+ await Re(e, async (e) => {
860
860
  let t = await e.get(a), n = t.data(), s = n?.visibilityTransition || "";
861
861
  if (s && s !== o) throw Error("Finish the pending visibility change before changing it again.");
862
862
  return t.exists() ? !s && nr(n?.visibility) === o ? (e.set(a, r, { merge: !0 }), !1) : (e.set(a, {
@@ -868,7 +868,7 @@ async function ar(e, t, n, r, i) {
868
868
  ...i ? { createdByUid: i } : {},
869
869
  createdAt: X()
870
870
  }, { merge: !0 }), !1);
871
- }) && (await ir(e, t, n, o !== "hidden"), await Y(e, async (e) => {
871
+ }) && (await ir(e, t, n, o !== "hidden"), await Re(e, async (e) => {
872
872
  if ((await e.get(a)).data()?.visibilityTransition !== o) throw Error("The visibility transition changed. Reload and retry.");
873
873
  e.update(a, {
874
874
  visibility: o,
@@ -1221,6 +1221,7 @@ function Mr(e, t, n) {
1221
1221
  createdAt: t.createdAt && typeof t.createdAt.toDate == "function" ? t.createdAt : void 0,
1222
1222
  updatedAt: t.updatedAt && typeof t.updatedAt.toMillis == "function" ? t.updatedAt : void 0,
1223
1223
  banner: jr(t.banner),
1224
+ mobileBanner: jr(t.mobileBanner),
1224
1225
  locale: F(t.locale) ?? "",
1225
1226
  autoTranslate: t.autoTranslate === !0,
1226
1227
  autoTranslatePosts: t.autoTranslatePosts === !0,
@@ -1231,7 +1232,7 @@ function Mr(e, t, n) {
1231
1232
  };
1232
1233
  }
1233
1234
  function Nr() {
1234
- let e = () => b(), t = $(), n = Ge(), { isSignedIn: r, isAdmin: i, isStaff: a, user: o } = cn(), { t: s, locale: c } = A(), { translateEntries: l } = Dr(), u = I(() => J(re(t, e()), q("order", "asc"))), { data: d, pending: f } = He(u, { ssrKey: g(e(), "boards") }), p = I(() => d.value.map((e, t) => Mr(e.id, e, t))), m = p, h = I(() => p.value.filter((e) => e.visibility !== "hidden")), v = h;
1235
+ let e = () => b(), t = $(), n = Ge(), { isSignedIn: r, isAdmin: i, isStaff: a, user: o } = cn(), { t: s, locale: c } = A(), { translateEntries: l } = Dr(), u = I(() => Y(re(t, e()), J("order", "asc"))), { data: d, pending: f } = He(u, { ssrKey: g(e(), "boards") }), p = I(() => d.value.map((e, t) => Mr(e.id, e, t))), m = p, h = I(() => p.value.filter((e) => e.visibility !== "hidden")), v = h;
1235
1236
  function x(e, t) {
1236
1237
  if (!e) return;
1237
1238
  let n = p.value.find((t) => t.id === e);
@@ -1285,6 +1286,7 @@ function Nr() {
1285
1286
  ...e.i18nSource ? { i18nSource: e.i18nSource } : {},
1286
1287
  order: t,
1287
1288
  banner: jr(e.banner),
1289
+ mobileBanner: jr(e.mobileBanner),
1288
1290
  updatedAt: X()
1289
1291
  };
1290
1292
  }
@@ -1333,8 +1335,10 @@ function Nr() {
1333
1335
  ...i,
1334
1336
  label: l,
1335
1337
  visibility: u
1336
- }, a), f = p.value.find((e) => e.id === c)?.banner;
1337
- await ar(t, e(), c, d, o.value?.uid), f?.path && f.path !== d.banner?.path && f.path.startsWith(`${e().settingsCollection}/${c}/banners/`) && await tt(ot(rt(n), f.path)).catch((e) => {
1338
+ }, a), f = p.value.find((e) => e.id === c);
1339
+ await ar(t, e(), c, d, o.value?.uid);
1340
+ let m = /* @__PURE__ */ new Set([d.banner?.path, d.mobileBanner?.path]);
1341
+ for (let t of [f?.banner, f?.mobileBanner]) t?.path && !m.has(t.path) && t.path.startsWith(`${e().settingsCollection}/${c}/banners/`) && await tt(ot(rt(n), t.path)).catch((e) => {
1338
1342
  console.warn("[memi-board] old banner cleanup failed", e);
1339
1343
  });
1340
1344
  }
@@ -1350,11 +1354,12 @@ function Nr() {
1350
1354
  let a = i.trim();
1351
1355
  if (!a) throw Error(s("boardSettings.deleteIdRequired"));
1352
1356
  for (;;) {
1353
- let r = await W(J(_(t, e()), Q("boardId", "==", a), G(25)));
1357
+ let r = await G(Y(_(t, e()), Q("boardId", "==", a), K(25)));
1354
1358
  if (r.empty) break;
1355
1359
  for (let i of r.docs) await jn(t, rt(n), e(), i.id);
1356
1360
  }
1357
- if (p.value.find((e) => e.id === a)?.banner) {
1361
+ let o = p.value.find((e) => e.id === a);
1362
+ if (o?.banner || o?.mobileBanner) {
1358
1363
  let t = ot(rt(n), `${e().settingsCollection}/${a}/banners`), r = await at(t);
1359
1364
  await Promise.all(r.items.map((e) => tt(e)));
1360
1365
  }
@@ -1462,7 +1467,7 @@ function zr(e) {
1462
1467
  if (!e.title?.trim()) throw Error(c("posts.titleRequired"));
1463
1468
  }
1464
1469
  function S() {
1465
- return V(p()).id;
1470
+ return H(p()).id;
1466
1471
  }
1467
1472
  async function C(e) {
1468
1473
  return await Xe(n).authStateReady(), s.value && await new Promise((e) => {
@@ -1473,8 +1478,8 @@ function zr(e) {
1473
1478
  }
1474
1479
  async function w(e = {}) {
1475
1480
  let t = e.pageSize ?? 20, n = [Q("boardId", "==", f()), Q("isPublished", "==", !0)];
1476
- e.publicOnly !== !1 && n.push(Q("listed", "==", !0)), n.push(q("createdAt", "desc")), e.cursor && n.push(Z(e.cursor)), n.push(G(t + 1));
1477
- let r = await W(J(p(), ...n)), i = r.docs.slice(0, t);
1481
+ e.publicOnly !== !1 && n.push(Q("listed", "==", !0)), n.push(J("createdAt", "desc")), e.cursor && n.push(Z(e.cursor)), n.push(K(t + 1));
1482
+ let r = await G(Y(p(), ...n)), i = r.docs.slice(0, t);
1478
1483
  return {
1479
1484
  posts: i.map((e) => ({
1480
1485
  id: e.id,
@@ -1485,7 +1490,7 @@ function zr(e) {
1485
1490
  };
1486
1491
  }
1487
1492
  async function E(e) {
1488
- let [t, n] = await Promise.all([U(m(e)), U(h(e))]);
1493
+ let [t, n] = await Promise.all([W(m(e)), W(h(e))]);
1489
1494
  return t.exists() ? g(t.id, t.data(), n.exists() ? n.data() : void 0) : null;
1490
1495
  }
1491
1496
  async function D(e) {
@@ -1544,8 +1549,8 @@ function zr(e) {
1544
1549
  Q("boardId", "==", f()),
1545
1550
  Q("isPublished", "==", !0),
1546
1551
  ...e.listed === !1 ? [] : [Q("listed", "==", !0)],
1547
- q("createdAt", "desc")
1548
- ], [n, r] = await Promise.all([W(J(p(), ...t, Z(e.createdAt), G(1))), W(J(p(), ...t, Ne(e.createdAt), Re(1)))]), i = (e) => {
1552
+ J("createdAt", "desc")
1553
+ ], [n, r] = await Promise.all([G(Y(p(), ...t, Z(e.createdAt), K(1))), G(Y(p(), ...t, Me(e.createdAt), Le(1)))]), i = (e) => {
1549
1554
  let t = e.docs[0];
1550
1555
  return t ? {
1551
1556
  id: t.id,
@@ -1607,7 +1612,7 @@ function zr(e) {
1607
1612
  let r = y() ? n.title?.trim() || Nn(n.content) : n.title.trim(), i = Bn(n.content, n.attachments), s = v(), l = n.extend ? Qn(n.extend) : void 0, u = n.tags ?? [], f = n.attachments ?? [], p = a.value?.uid;
1608
1613
  if (!p) throw Error(c("reports.signInRequired"));
1609
1614
  let g = (a.value?.displayName ?? "").trim().slice(0, 80) || null;
1610
- await Y(t, async (a) => {
1615
+ await Re(t, async (a) => {
1611
1616
  let _ = m(e), v = h(e), [y, b] = await Promise.all([a.get(_), a.get(v)]);
1612
1617
  if (!y.exists()) throw Error(c("detail.notFound"));
1613
1618
  let x = y.data(), S = b.exists() ? String(b.data().content ?? "") : "", C = x.extend && Object.keys(x.extend).length ? x.extend : void 0, w = l === void 0 ? C : Object.keys(l).length ? l : void 0, E = x.title !== r || S !== n.content || !Ir(x.tags ?? [], u) || !Ir(x.attachments ?? [], f) || !Ir(C ?? null, w ?? null), D = typeof x.revision == "number" ? x.revision : 0;
@@ -1627,8 +1632,8 @@ function zr(e) {
1627
1632
  }), a.update(_, {
1628
1633
  title: r,
1629
1634
  ...i,
1630
- previewImage: i.previewImage ? i.previewImage : je(),
1631
- videoUrl: i.videoUrl ? i.videoUrl : je(),
1635
+ previewImage: i.previewImage ? i.previewImage : V(),
1636
+ videoUrl: i.videoUrl ? i.videoUrl : V(),
1632
1637
  tags: u,
1633
1638
  listed: s,
1634
1639
  attachments: f,
@@ -1641,15 +1646,15 @@ function zr(e) {
1641
1646
  i18n: n.translations.i18n,
1642
1647
  i18nSource: n.translations.i18nSource
1643
1648
  } : {},
1644
- ...l ? { extend: Object.keys(l).length ? l : je() } : {}
1649
+ ...l ? { extend: Object.keys(l).length ? l : V() } : {}
1645
1650
  }), a.set(v, {
1646
1651
  content: n.content,
1647
1652
  ...n.translations ? n.translations.contentI18n ? {
1648
1653
  i18n: n.translations.contentI18n,
1649
1654
  i18nSource: n.translations.contentI18nSource
1650
1655
  } : {
1651
- i18n: je(),
1652
- i18nSource: je()
1656
+ i18n: V(),
1657
+ i18nSource: V()
1653
1658
  } : {}
1654
1659
  }, { merge: !0 });
1655
1660
  });
@@ -1663,8 +1668,8 @@ function zr(e) {
1663
1668
  i18n: t.contentI18n,
1664
1669
  i18nSource: t.contentI18nSource
1665
1670
  } : {
1666
- i18n: je(),
1667
- i18nSource: je()
1671
+ i18n: V(),
1672
+ i18nSource: V()
1668
1673
  }, { merge: !0 })]);
1669
1674
  }
1670
1675
  async function te(e) {
@@ -1679,8 +1684,8 @@ function zr(e) {
1679
1684
  pinned: !0,
1680
1685
  pinnedAt: X()
1681
1686
  } : {
1682
- pinned: je(),
1683
- pinnedAt: je()
1687
+ pinned: V(),
1688
+ pinnedAt: V()
1684
1689
  });
1685
1690
  }
1686
1691
  async function ne(e) {
@@ -1723,7 +1728,7 @@ function Hr(e, t = {}) {
1723
1728
  return d.value && e.push(Q("listed", "==", !0)), e;
1724
1729
  }
1725
1730
  function j() {
1726
- T?.(), T = K(J(u(), ...A(), q("createdAt", "desc"), q(H(), "desc"), G(s)), (e) => {
1731
+ T?.(), T = q(Y(u(), ...A(), J("createdAt", "desc"), J(U(), "desc"), K(s)), (e) => {
1727
1732
  f.value = e.docs.map((e) => ({
1728
1733
  id: e.id,
1729
1734
  ...e.data()
@@ -1733,7 +1738,7 @@ function Hr(e, t = {}) {
1733
1738
  });
1734
1739
  }
1735
1740
  function ee() {
1736
- D?.(), D = K(J(u(), ...A(), Q("pinned", "==", !0), q("pinnedAt", "desc"), G(Vr)), (e) => {
1741
+ D?.(), D = q(Y(u(), ...A(), Q("pinned", "==", !0), J("pinnedAt", "desc"), K(Vr)), (e) => {
1737
1742
  h.value = e.docs.map((e) => ({
1738
1743
  id: e.id,
1739
1744
  ...e.data()
@@ -1749,7 +1754,7 @@ function Hr(e, t = {}) {
1749
1754
  m.value = [];
1750
1755
  return;
1751
1756
  }
1752
- E = K(J(u(), Q("boardId", "==", l.value), Q("authorUid", "==", e), Q("isPublished", "==", !1), q("createdAt", "desc"), G(20)), (e) => {
1757
+ E = q(Y(u(), Q("boardId", "==", l.value), Q("authorUid", "==", e), Q("isPublished", "==", !1), J("createdAt", "desc"), K(20)), (e) => {
1753
1758
  m.value = e.docs.map((e) => ({
1754
1759
  id: e.id,
1755
1760
  ...e.data()
@@ -1764,11 +1769,11 @@ function Hr(e, t = {}) {
1764
1769
  try {
1765
1770
  let e = w ?? C, t = [
1766
1771
  ...A(),
1767
- q("createdAt", "desc"),
1768
- q(H(), "desc"),
1772
+ J("createdAt", "desc"),
1773
+ J(U(), "desc"),
1769
1774
  ...e ? [Z(e)] : [],
1770
- G(s + 1)
1771
- ], n = await W(J(u(), ...t)), r = n.docs.slice(0, s), i = r.map((e) => ({
1775
+ K(s + 1)
1776
+ ], n = await G(Y(u(), ...t)), r = n.docs.slice(0, s), i = r.map((e) => ({
1772
1777
  id: e.id,
1773
1778
  ...e.data()
1774
1779
  })), a = new Set([...p.value, ...f.value].map((e) => e.id));
@@ -1823,7 +1828,7 @@ function Wr(e, t) {
1823
1828
  async function s() {
1824
1829
  a.value = !0, o.value = null;
1825
1830
  try {
1826
- let a = await W(J(w(n, r(), z(t)), Q("boardId", "==", Rr(e))));
1831
+ let a = await G(Y(w(n, r(), z(t)), Q("boardId", "==", Rr(e))));
1827
1832
  i.value = a.docs.map((e) => ({
1828
1833
  ...e.data(),
1829
1834
  id: e.id
@@ -1872,7 +1877,7 @@ function Kr(e, t = {}) {
1872
1877
  l.value = !1;
1873
1878
  return;
1874
1879
  }
1875
- h = K(J(i(), ...x(), q("createdAt", "desc"), q(H(), "desc"), G(a)), (e) => {
1880
+ h = q(Y(i(), ...x(), J("createdAt", "desc"), J(U(), "desc"), K(a)), (e) => {
1876
1881
  s.value = e.docs.map(g), p = e.docs.at(-1) ?? null, m || (u.value = e.docs.length >= a), l.value = !1;
1877
1882
  }, (e) => {
1878
1883
  console.error("[memi-board:userPosts] onSnapshot failed", e), f.value = e.message || String(e), l.value = !1;
@@ -1884,11 +1889,11 @@ function Kr(e, t = {}) {
1884
1889
  try {
1885
1890
  let e = m ?? p, t = [
1886
1891
  ...x(),
1887
- q("createdAt", "desc"),
1888
- q(H(), "desc"),
1892
+ J("createdAt", "desc"),
1893
+ J(U(), "desc"),
1889
1894
  ...e ? [Z(e)] : [],
1890
- G(a + 1)
1891
- ], n = await W(J(i(), ...t)), r = n.docs.slice(0, a), o = r.map(g), l = new Set([...c.value, ...s.value].map((e) => e.id));
1895
+ K(a + 1)
1896
+ ], n = await G(Y(i(), ...t)), r = n.docs.slice(0, a), o = r.map(g), l = new Set([...c.value, ...s.value].map((e) => e.id));
1892
1897
  c.value.push(...o.filter((e) => !l.has(e.id))), m = r.at(-1) ?? m, u.value = n.docs.length > a;
1893
1898
  } catch (e) {
1894
1899
  f.value = e.message || String(e), console.error("[memi-board:userPosts] loadMore failed", e);
@@ -1936,7 +1941,7 @@ function Jr(e, t = {}) {
1936
1941
  l.value = !1;
1937
1942
  return;
1938
1943
  }
1939
- h = K(J(i(), ...y(), q("createdAt", "desc"), q(H(), "desc"), G(a)), (e) => {
1944
+ h = q(Y(i(), ...y(), J("createdAt", "desc"), J(U(), "desc"), K(a)), (e) => {
1940
1945
  s.value = e.docs.map(g), p = e.docs.at(-1) ?? null, m || (u.value = e.docs.length >= a), l.value = !1;
1941
1946
  }, (e) => {
1942
1947
  console.error("[memi-board:userComments] onSnapshot failed", e), f.value = e.message || String(e), l.value = !1;
@@ -1948,11 +1953,11 @@ function Jr(e, t = {}) {
1948
1953
  try {
1949
1954
  let e = m ?? p, t = [
1950
1955
  ...y(),
1951
- q("createdAt", "desc"),
1952
- q(H(), "desc"),
1956
+ J("createdAt", "desc"),
1957
+ J(U(), "desc"),
1953
1958
  ...e ? [Z(e)] : [],
1954
- G(a + 1)
1955
- ], n = await W(J(i(), ...t)), r = n.docs.slice(0, a), o = r.map(g), l = new Set([...c.value, ...s.value].map((e) => e.id));
1959
+ K(a + 1)
1960
+ ], n = await G(Y(i(), ...t)), r = n.docs.slice(0, a), o = r.map(g), l = new Set([...c.value, ...s.value].map((e) => e.id));
1956
1961
  c.value.push(...o.filter((e) => !l.has(e.id))), m = r.at(-1) ?? m, u.value = n.docs.length > a;
1957
1962
  } catch (e) {
1958
1963
  f.value = e.message || String(e), console.error("[memi-board:userComments] loadMore failed", e);
@@ -2005,17 +2010,17 @@ function Xr(e = "latest", t = {}) {
2005
2010
  function S() {
2006
2011
  return o.value === "likes" ? [
2007
2012
  Q("listed", "==", !0),
2008
- q("likeCount", "desc"),
2009
- q("createdAt", "desc"),
2010
- q(H(), "desc")
2013
+ J("likeCount", "desc"),
2014
+ J("createdAt", "desc"),
2015
+ J(U(), "desc")
2011
2016
  ] : [
2012
2017
  Q("listed", "==", !0),
2013
- q("createdAt", "desc"),
2014
- q(H(), "desc")
2018
+ J("createdAt", "desc"),
2019
+ J(U(), "desc")
2015
2020
  ];
2016
2021
  }
2017
2022
  function C() {
2018
- h?.(), h = K(J(i(), ...S(), G(a.value)), (e) => {
2023
+ h?.(), h = q(Y(i(), ...S(), K(a.value)), (e) => {
2019
2024
  s.value = e.docs.map(g), p = e.docs.at(-1) ?? null, m || (u.value = e.docs.length >= a.value), l.value = !1;
2020
2025
  }, (e) => {
2021
2026
  console.error("[memi-board:commentFeed] onSnapshot failed", e), f.value = e.message || String(e), l.value = !1;
@@ -2025,7 +2030,7 @@ function Xr(e = "latest", t = {}) {
2025
2030
  if (!(d.value || !u.value || l.value)) {
2026
2031
  d.value = !0, f.value = "";
2027
2032
  try {
2028
- let e = m ?? p, t = await W(J(i(), ...S(), ...e ? [Z(e)] : [], G(a.value + 1))), n = t.docs.slice(0, a.value), r = n.map(g), o = new Set([...c.value, ...s.value].map((e) => e.id));
2033
+ let e = m ?? p, t = await G(Y(i(), ...S(), ...e ? [Z(e)] : [], K(a.value + 1))), n = t.docs.slice(0, a.value), r = n.map(g), o = new Set([...c.value, ...s.value].map((e) => e.id));
2029
2034
  c.value.push(...r.filter((e) => !o.has(e.id))), m = n.at(-1) ?? m, u.value = t.docs.length > a.value;
2030
2035
  } catch (e) {
2031
2036
  f.value = e.message || String(e), console.error("[memi-board:commentFeed] loadMore failed", e);
@@ -2077,7 +2082,7 @@ function ei(e) {
2077
2082
  let t = $r(s.value);
2078
2083
  t.pending = !0, t.error = "";
2079
2084
  try {
2080
- let n = (await U(e)).data();
2085
+ let n = (await W(e)).data();
2081
2086
  t.text = n ? n.text ?? "" : "", t.sentiment = n ? n.sentiment ?? null : null, t.loaded = !0;
2082
2087
  } catch (e) {
2083
2088
  t.error = e.message || String(e), console.error("[memi-board:authorMemo] load failed", e);
@@ -2189,7 +2194,7 @@ function ui(e = {}) {
2189
2194
  async function h(e) {
2190
2195
  let t = c.value?.uid;
2191
2196
  if (!t) throw Error(r("writingAssistant.loginRequired"));
2192
- await Y(s, async (n) => {
2197
+ await Re(s, async (n) => {
2193
2198
  let i = o(s, b(), t), a = await n.get(i);
2194
2199
  if (!a.exists()) throw Error(r("writingAssistant.userMissing"));
2195
2200
  let c = a.data(), l = e(p(c, Date.now()), c);
@@ -2381,7 +2386,7 @@ function ui(e = {}) {
2381
2386
  //#endregion
2382
2387
  //#region src/utils/subscribeCommentRange.ts
2383
2388
  function di(e, t, n, r, i, a) {
2384
- return K(J(x(e, t), Q("postId", "==", n), ...r.rootId ? [Q("rootId", "==", r.rootId), Q("isReply", "==", !0)] : [Q("parentId", "==", null)], q("createdAt", "asc"), q(H(), "asc"), ...r.hasMore && r.cursor ? [Me(r.cursor)] : []), (e) => i(e.docs.map((e) => ({
2389
+ return q(Y(x(e, t), Q("postId", "==", n), ...r.rootId ? [Q("rootId", "==", r.rootId), Q("isReply", "==", !0)] : [Q("parentId", "==", null)], J("createdAt", "asc"), J(U(), "asc"), ...r.hasMore && r.cursor ? [je(r.cursor)] : []), (e) => i(e.docs.map((e) => ({
2385
2390
  ...e.data(),
2386
2391
  id: e.id
2387
2392
  }))), a);
@@ -2403,7 +2408,7 @@ function _i(e, t) {
2403
2408
  async function s() {
2404
2409
  a.value = !0, o.value = null;
2405
2410
  try {
2406
- let a = await W(J(c(n, r(), z(t)), Q("boardId", "==", z(e))));
2411
+ let a = await G(Y(c(n, r(), z(t)), Q("boardId", "==", z(e))));
2407
2412
  i.value = a.docs.map((e) => ({
2408
2413
  ...e.data(),
2409
2414
  id: e.id
@@ -2452,7 +2457,7 @@ function vi(e, t, n = {}) {
2452
2457
  if (te++, k.value = !1, O.value = [], T.value = [], M = null, P?.(), P = void 0, j.value = n.subscribe !== !1, n.subscribe !== !1) {
2453
2458
  D.value = !0, ee.value = !0;
2454
2459
  try {
2455
- let n = W(J(g(), Q("postId", "==", e), q("createdAt", "desc"), q(H(), "desc")));
2460
+ let n = G(Y(g(), Q("postId", "==", e), J("createdAt", "desc"), J(U(), "desc")));
2456
2461
  if (await Promise.all([n.then((e) => {
2457
2462
  if (t !== N) return;
2458
2463
  let n = e.docs.map((e) => ({
@@ -2486,11 +2491,11 @@ function vi(e, t, n = {}) {
2486
2491
  let t = [
2487
2492
  Q("postId", "==", C.value),
2488
2493
  Q("parentId", "==", null),
2489
- q("createdAt", "asc"),
2490
- q(H(), "asc"),
2494
+ J("createdAt", "asc"),
2495
+ J(U(), "asc"),
2491
2496
  ...M ? [Z(M)] : [],
2492
- G(11)
2493
- ], n = await W(J(g(), ...t));
2497
+ K(11)
2498
+ ], n = await G(Y(g(), ...t));
2494
2499
  if (e !== N) return;
2495
2500
  let r = n.docs.slice(0, fi), i = r.map((e) => ({
2496
2501
  id: e.id,
@@ -2505,10 +2510,10 @@ function vi(e, t, n = {}) {
2505
2510
  N++, te++, P?.();
2506
2511
  });
2507
2512
  function oe() {
2508
- return V(g()).id;
2513
+ return H(g()).id;
2509
2514
  }
2510
2515
  function se(e) {
2511
- if (!e) return V(g());
2516
+ if (!e) return H(g());
2512
2517
  if (!/^[A-Za-z0-9]{10,128}$/.test(e)) throw Error(h("commentForm.uploadFailed"));
2513
2518
  return v(r, a(), e);
2514
2519
  }
@@ -2550,7 +2555,7 @@ function vi(e, t, n = {}) {
2550
2555
  replyToUid: null,
2551
2556
  replyToName: null,
2552
2557
  isReply: !1
2553
- }), t.update(u(r, a(), C.value), { commentCount: Le(1) }), await t.commit();
2558
+ }), t.update(u(r, a(), C.value), { commentCount: Ie(1) }), await t.commit();
2554
2559
  }
2555
2560
  async function fe(e) {
2556
2561
  if (!e.parent.id) throw Error(h("comments.replyTargetNotFound"));
@@ -2565,7 +2570,7 @@ function vi(e, t, n = {}) {
2565
2570
  replyToUid: e.parent.authorUid,
2566
2571
  replyToName: e.parent.authorName,
2567
2572
  isReply: !0
2568
- }), t.update(v(r, a(), i), { replyCount: Le(1) }), t.update(u(r, a(), C.value), { commentCount: Le(1) }), await t.commit();
2573
+ }), t.update(v(r, a(), i), { replyCount: Ie(1) }), t.update(u(r, a(), C.value), { commentCount: Ie(1) }), await t.commit();
2569
2574
  }
2570
2575
  async function pe(e) {
2571
2576
  if (!e.id) return;
@@ -2573,13 +2578,13 @@ function vi(e, t, n = {}) {
2573
2578
  let t = ve(e.images, `${E(a(), C.value)}/comment-images/${e.id}/`);
2574
2579
  await An(r, a(), e.id);
2575
2580
  let n = Ve(r);
2576
- n.delete(v(r, a(), e.id)), e.parentId && e.rootId && n.update(v(r, a(), e.rootId), { replyCount: Le(-1) }), n.update(u(r, a(), C.value), { commentCount: Le(-1) }), await n.commit(), await ue(t), O.value = O.value.filter((t) => t.id !== e.id), T.value = T.value.filter((t) => t.id !== e.id);
2581
+ n.delete(v(r, a(), e.id)), e.parentId && e.rootId && n.update(v(r, a(), e.rootId), { replyCount: Ie(-1) }), n.update(u(r, a(), C.value), { commentCount: Ie(-1) }), await n.commit(), await ue(t), O.value = O.value.filter((t) => t.id !== e.id), T.value = T.value.filter((t) => t.id !== e.id);
2577
2582
  }
2578
2583
  async function he(e, t, n, o) {
2579
2584
  let s = hi(t, m), l = n === void 0 ? void 0 : ce(e, n), u = await p(s, o), d = Xe(i).currentUser;
2580
2585
  if (!d) throw Error(h("reports.signInRequired"));
2581
2586
  let f = (d.displayName ?? "").trim().slice(0, 80) || null;
2582
- await Y(r, async (t) => {
2587
+ await Re(r, async (t) => {
2583
2588
  let n = v(r, a(), e), i = await t.get(n);
2584
2589
  if (!i.exists()) throw Error(h("comments.commentNotFound"));
2585
2590
  let o = i.data(), p = o.images ?? [], m = o.body !== s || l !== void 0 && JSON.stringify(gi(p)) !== JSON.stringify(gi(l)), g = typeof o.revision == "number" ? o.revision : 0;
@@ -2597,7 +2602,7 @@ function vi(e, t, n = {}) {
2597
2602
  }), t.update(n, {
2598
2603
  body: s,
2599
2604
  updatedAt: X(),
2600
- ...l === void 0 ? {} : { images: l.length ? l : je() },
2605
+ ...l === void 0 ? {} : { images: l.length ? l : V() },
2601
2606
  ...m ? {
2602
2607
  revision: g + 1,
2603
2608
  editedAt: X()
@@ -2655,11 +2660,11 @@ function yi(e, t, n) {
2655
2660
  Q("postId", "==", o),
2656
2661
  Q("rootId", "==", n),
2657
2662
  Q("isReply", "==", !0),
2658
- q("createdAt", "asc"),
2659
- q(H(), "asc"),
2663
+ J("createdAt", "asc"),
2664
+ J(U(), "asc"),
2660
2665
  ...d ? [Z(d)] : [],
2661
- G(6)
2662
- ], r = await W(J(a(), ...t));
2666
+ K(6)
2667
+ ], r = await G(Y(a(), ...t));
2663
2668
  if (e !== p) return;
2664
2669
  let i = new Set(s.value.map((e) => e.id)), c = r.docs.slice(0, pi), f = c.map((e) => ({
2665
2670
  id: e.id,
@@ -2699,7 +2704,7 @@ function bi(e, t) {
2699
2704
  o.value = !1;
2700
2705
  return;
2701
2706
  }
2702
- c = K(l(e.uid), (e) => {
2707
+ c = q(l(e.uid), (e) => {
2703
2708
  o.value = e.exists();
2704
2709
  }, (e) => {
2705
2710
  console.error("[memi-board:likes] onSnapshot failed", e);
@@ -2712,12 +2717,12 @@ function bi(e, t) {
2712
2717
  s.value = !0;
2713
2718
  try {
2714
2719
  let i = l(c), a = u(r, n(), t);
2715
- return await Y(r, async (n) => (await n.get(i)).exists() ? (n.delete(i), n.update(a, { likeCount: Le(-1) }), !1) : (n.set(i, {
2720
+ return await Re(r, async (n) => (await n.get(i)).exists() ? (n.delete(i), n.update(a, { likeCount: Ie(-1) }), !1) : (n.set(i, {
2716
2721
  uid: c,
2717
2722
  postId: t,
2718
2723
  boardId: e,
2719
2724
  createdAt: X()
2720
- }), n.update(a, { likeCount: Le(1) }), !0));
2725
+ }), n.update(a, { likeCount: Ie(1) }), !0));
2721
2726
  } finally {
2722
2727
  s.value = !1;
2723
2728
  }
@@ -2732,7 +2737,7 @@ var xi = Symbol.for("memi-board:comment-likes");
2732
2737
  function Si(e, t) {
2733
2738
  let n = () => b(), r = $(), i = Ue(), { t: a } = A(), o = I(() => z(e)), s = I(() => z(t)), c = R(/* @__PURE__ */ new Set()), l = R(null), u;
2734
2739
  B([i, s], ([e, t]) => {
2735
- u?.(), u = void 0, c.value = /* @__PURE__ */ new Set(), e && t && (u = K(J(d(r, n()), Q("uid", "==", e.uid), Q("postId", "==", t), Q("target", "==", "comment")), (e) => {
2740
+ u?.(), u = void 0, c.value = /* @__PURE__ */ new Set(), e && t && (u = q(Y(d(r, n()), Q("uid", "==", e.uid), Q("postId", "==", t), Q("target", "==", "comment")), (e) => {
2736
2741
  let t = /* @__PURE__ */ new Set();
2737
2742
  for (let n of e.docs) {
2738
2743
  let e = n.data().commentId;
@@ -2756,7 +2761,7 @@ function Si(e, t) {
2756
2761
  if (l.value) return f(e);
2757
2762
  l.value = e;
2758
2763
  try {
2759
- let i = C(r, n(), e, t), l = v(r, n(), e), u = await Y(r, async (n) => {
2764
+ let i = C(r, n(), e, t), l = v(r, n(), e), u = await Re(r, async (n) => {
2760
2765
  let r = await n.get(i), c = await n.get(l);
2761
2766
  if (!c.exists()) throw Error(a("likes.commentNotFound"));
2762
2767
  let u = Number(c.data()?.likeCount ?? 0);
@@ -2822,7 +2827,7 @@ function ki(t, n) {
2822
2827
  let r = () => b(), i = $(), a = Ue(), { t: o } = A(), s = R(null), c = I(() => !!s.value), l = R(!0), u = R(""), d = 0, f = R(!1), p;
2823
2828
  B(a, (t) => {
2824
2829
  let a = ++d;
2825
- p?.(), p = void 0, s.value = null, u.value = "", l.value = !!t, t && (p = K(e(i, r(), n, t.uid), (e) => {
2830
+ p?.(), p = void 0, s.value = null, u.value = "", l.value = !!t, t && (p = q(e(i, r(), n, t.uid), (e) => {
2826
2831
  a === d && (s.value = e.exists() ? {
2827
2832
  id: e.id,
2828
2833
  ...e.data()
@@ -2885,7 +2890,7 @@ function Ai(e, t, n) {
2885
2890
  let t = ++f;
2886
2891
  l.value = !0, u.value = "";
2887
2892
  try {
2888
- let a = await U(Te(i, r(), n, e));
2893
+ let a = await W(Te(i, r(), n, e));
2889
2894
  if (t !== f) return;
2890
2895
  s.value = a.exists() ? {
2891
2896
  id: a.id,
@@ -2957,7 +2962,7 @@ function Mi(e = {}) {
2957
2962
  }
2958
2963
  f.value = !0;
2959
2964
  let r = c.value ? [u(), Q("boardId", "==", c.value)] : [u(), Q("target", "in", ["post", "comment"])];
2960
- _ = K(J(le(n, t()), ...r, q("createdAt", "desc"), q(H(), "desc"), G(s)), (t) => {
2965
+ _ = q(Y(le(n, t()), ...r, J("createdAt", "desc"), J(U(), "desc"), K(s)), (t) => {
2961
2966
  e === x && (d.value = t.docs.map(y).filter((e) => o(e.boardId)), g = t.docs.at(-1) ?? null, m.value = t.docs.length >= s, f.value = !1);
2962
2967
  }, (t) => {
2963
2968
  e === x && (console.error("[memi-board:report-queue] onSnapshot failed", t), h.value = t.message || String(t), f.value = !1);
@@ -2974,7 +2979,7 @@ function Mi(e = {}) {
2974
2979
  let e = x;
2975
2980
  p.value = !0, h.value = "";
2976
2981
  try {
2977
- let r = c.value ? [u(), Q("boardId", "==", c.value)] : [u(), Q("target", "in", ["post", "comment"])], i = await W(J(le(n, t()), ...r, q("createdAt", "desc"), q(H(), "desc"), Z(g), G(s + 1)));
2982
+ let r = c.value ? [u(), Q("boardId", "==", c.value)] : [u(), Q("target", "in", ["post", "comment"])], i = await G(Y(le(n, t()), ...r, J("createdAt", "desc"), J(U(), "desc"), Z(g), K(s + 1)));
2978
2983
  if (e !== x) return;
2979
2984
  let a = i.docs.slice(0, s), l = new Set(d.value.map((e) => e.id));
2980
2985
  d.value.push(...a.map(y).filter((e) => !l.has(e.id) && o(e.boardId))), g = a.at(-1) ?? g, m.value = i.docs.length > s;
@@ -2991,7 +2996,7 @@ function Mi(e = {}) {
2991
2996
  let l = a.trim();
2992
2997
  if (!l) throw Error(r("reports.reviewNoteRequired"));
2993
2998
  if (l.length > 200) throw Error(r("reports.detailTooLong", { max: 200 }));
2994
- await Y(n, async (a) => {
2999
+ await Re(n, async (a) => {
2995
3000
  let o = M(n, t(), e.id), u = await a.get(o), d = s.blindComment && i === "actioned" && e.target === "comment" && e.commentId ? v(n, t(), e.commentId) : null, f = d ? await a.get(d) : null;
2996
3001
  if (!u.exists() || u.data().status !== "open") throw Error(r("reports.alreadyReviewed"));
2997
3002
  d && f?.exists() && !f.data().isBlinded && a.update(d, {
@@ -3044,7 +3049,7 @@ function Ni() {
3044
3049
  if (s && c && !r(s, c)) {
3045
3050
  i(s, c);
3046
3051
  try {
3047
- await Be(u(t, e(), c), { viewCount: Le(1) });
3052
+ await Be(u(t, e(), c), { viewCount: Ie(1) });
3048
3053
  } catch (e) {
3049
3054
  try {
3050
3055
  sessionStorage.removeItem(n(s, c));
@@ -3329,8 +3334,8 @@ function Hi(e = {}) {
3329
3334
  pageSize: m.value,
3330
3335
  cursor: n,
3331
3336
  readBatch: async (e, t, n) => {
3332
- let r = o === "role" ? [Q("role", "==", e), q(H(), h)] : [q("displayName", h), q(H(), h)];
3333
- return t && r.push(Z(t)), (await W(J(x, ...r, G(n)))).docs;
3337
+ let r = o === "role" ? [Q("role", "==", e), J(U(), h)] : [J("displayName", h), J(U(), h)];
3338
+ return t && r.push(Z(t)), (await G(Y(x, ...r, K(n)))).docs;
3334
3339
  }
3335
3340
  });
3336
3341
  if (a !== v) return;
@@ -3548,7 +3553,7 @@ function _a(e, t, n) {
3548
3553
  };
3549
3554
  }
3550
3555
  function va() {
3551
- let { locale: e } = A(), { translateEntries: t } = Dr(), n = $(), r = V(n, "settings", "homeLayout"), { data: i, pending: a } = We(r), o = I(() => (Array.isArray(i.value?.blocks) ? i.value.blocks : la).map((t, n) => _a(t, n, e.value)));
3556
+ let { locale: e } = A(), { translateEntries: t } = Dr(), n = $(), r = H(n, "settings", "homeLayout"), { data: i, pending: a } = We(r), o = I(() => (Array.isArray(i.value?.blocks) ? i.value.blocks : la).map((t, n) => _a(t, n, e.value)));
3552
3557
  async function s(n) {
3553
3558
  if (!y()) return n;
3554
3559
  let r = e.value, i = n.filter((e) => {
@@ -3625,7 +3630,7 @@ function va() {
3625
3630
  function ya(e, t) {
3626
3631
  let n = $(), r = () => b(), i = z(e)?.trim() || "all", a = I(() => {
3627
3632
  let i = Math.max(1, Math.floor(Number(z(t)) || 5)), a = z(e)?.trim() || "", o = [Q("isPublished", "==", !0), Q("listed", "==", !0)];
3628
- return a && o.unshift(Q("boardId", "==", a)), J(_(n, r()), ...o, q("createdAt", "desc"), G(i));
3633
+ return a && o.unshift(Q("boardId", "==", a)), Y(_(n, r()), ...o, J("createdAt", "desc"), K(i));
3629
3634
  }), { data: o, pending: s, error: c } = He(a, { ssrKey: g(r(), `mini-list/${i}`) });
3630
3635
  return {
3631
3636
  posts: I(() => o.value ?? []),
@@ -3634,7 +3639,7 @@ function ya(e, t) {
3634
3639
  };
3635
3640
  }
3636
3641
  function ba(e) {
3637
- let t = $(), n = () => b(), r = I(() => [...new Set(z(e).map((e) => e.trim()).filter(Boolean))].slice(0, 10)), i = r.value.join(",") || "none", a = I(() => r.value.length ? J(_(t, n()), Q(H(), "in", r.value)) : null), { data: o, pending: s, error: c } = He(a, { ssrKey: g(n(), `mini-picked/${i}`) });
3642
+ let t = $(), n = () => b(), r = I(() => [...new Set(z(e).map((e) => e.trim()).filter(Boolean))].slice(0, 10)), i = r.value.join(",") || "none", a = I(() => r.value.length ? Y(_(t, n()), Q(U(), "in", r.value)) : null), { data: o, pending: s, error: c } = He(a, { ssrKey: g(n(), `mini-picked/${i}`) });
3638
3643
  return {
3639
3644
  posts: I(() => {
3640
3645
  let e = new Map((o.value ?? []).map((e) => [e.id, e])), t = [];
@@ -3651,6 +3656,22 @@ function ba(e) {
3651
3656
  //#endregion
3652
3657
  //#region src/data/versionHistory.ts
3653
3658
  var xa = [
3659
+ {
3660
+ version: "0.63.0",
3661
+ date: "2026-11-13",
3662
+ highlights: [
3663
+ "보드 배너를 휴대폰용(3:1)과 데스크톱용(8:1)으로 따로 정할 수 있어요",
3664
+ "하나만 정하면 다른 화면에서도 그 배너를 써요",
3665
+ "커스텀 필드 순서를 드래그나 화살표로 바꿀 수 있어요",
3666
+ "커스텀 필드를 20개까지 만들 수 있어요"
3667
+ ],
3668
+ highlightsEn: [
3669
+ "Boards can set separate phone (3:1) and desktop (8:1) banners",
3670
+ "If only one banner is set, it is used on both screen sizes",
3671
+ "Custom fields can be reordered by dragging or with arrow buttons",
3672
+ "Boards can have up to 20 custom fields"
3673
+ ]
3674
+ },
3654
3675
  {
3655
3676
  version: "0.62.0",
3656
3677
  date: "2026-11-12",
@@ -4555,9 +4576,9 @@ function ka() {
4555
4576
  }
4556
4577
  async function g() {
4557
4578
  let t = b(), [n, r, i] = await Promise.all([
4558
- Ie(ke(e, t.postsCollection)),
4559
- Ie(ke(e, t.commentsCollection)),
4560
- Ie(ke(e, t.likesCollection))
4579
+ Fe(ke(e, t.postsCollection)),
4580
+ Fe(ke(e, t.commentsCollection)),
4581
+ Fe(ke(e, t.likesCollection))
4561
4582
  ]), a = /* @__PURE__ */ new Set();
4562
4583
  function o(e) {
4563
4584
  if (typeof e == "string") {
@@ -4571,7 +4592,7 @@ function ka() {
4571
4592
  } else Array.isArray(e) ? e.forEach(o) : e && typeof e == "object" && Object.getPrototypeOf(e) === Object.prototype && Object.values(e).forEach(o);
4572
4593
  }
4573
4594
  n.docs.forEach((e) => o(e.data())), r.docs.forEach((e) => o(e.data()));
4574
- for (let e of n.docs) (await Ie(ke(e.ref, "body"))).docs.forEach((e) => o(e.data()));
4595
+ for (let e of n.docs) (await Fe(ke(e.ref, "body"))).docs.forEach((e) => o(e.data()));
4575
4596
  for (let e of [...a]) {
4576
4597
  let t = e.match(/^(.*\/images\/)([^/]+)\.[^/.]+$/);
4577
4598
  t && a.add(`${t[1]}thumbnails/${t[2]}.jpg`);
@@ -4653,20 +4674,20 @@ function ka() {
4653
4674
  if (n.kind === "file") {
4654
4675
  if (!Da(n.path, o.cfg.postsCollection)) throw Error("Invalid cleanup path");
4655
4676
  let r = rt(t), a = ot(r, n.path), [s, c, l] = await Promise.all([
4656
- Fe(V(e, o.cfg.postsCollection, n.postId)),
4657
- n.commentId ? Fe(V(e, o.cfg.commentsCollection, n.commentId)) : null,
4677
+ Pe(H(e, o.cfg.postsCollection, n.postId)),
4678
+ n.commentId ? Pe(H(e, o.cfg.commentsCollection, n.commentId)) : null,
4658
4679
  nt(a)
4659
4680
  ]);
4660
4681
  m(d), l.generation === f.get(n.path) && !o.referenced.has(n.path) && Ea(l.updated, Date.now()) && (!s.exists() || n.commentId && !c?.exists()) && (await tt(a), i = !0);
4661
4682
  } else {
4662
4683
  let t = n.kind;
4663
4684
  if (!Oa(n.path, t, o.cfg)) throw Error("Invalid cleanup path");
4664
- i = await Y(e, async (r) => {
4665
- let i = await r.get(V(e, n.path));
4685
+ i = await Re(e, async (r) => {
4686
+ let i = await r.get(H(e, n.path));
4666
4687
  if (!i.exists()) return !0;
4667
4688
  let a = i.data();
4668
4689
  if (typeof a.postId != "string" || !a.postId || a.postId.includes("/")) return !1;
4669
- let s = await r.get(V(e, o.cfg.postsCollection, a.postId)), c = n.kind === "like" && a.target === "comment" && typeof a.commentId == "string" && a.commentId && !a.commentId.includes("/") ? await r.get(V(e, o.cfg.commentsCollection, a.commentId)) : null;
4690
+ let s = await r.get(H(e, o.cfg.postsCollection, a.postId)), c = n.kind === "like" && a.target === "comment" && typeof a.commentId == "string" && a.commentId && !a.commentId.includes("/") ? await r.get(H(e, o.cfg.commentsCollection, a.commentId)) : null;
4670
4691
  return Ta(t, a, new Set(s.exists() ? [a.postId] : []), new Set(c?.exists() ? [a.commentId] : [])) ? (m(d), r.delete(i.ref), !0) : !1;
4671
4692
  });
4672
4693
  }
@@ -4773,7 +4794,7 @@ function ja(e) {
4773
4794
  async function a() {
4774
4795
  let e = n.value;
4775
4796
  if (r.value = null, i.value = null, !e) return;
4776
- let a = b(), [o, s] = await Promise.allSettled([Pe(J(_(t, a), Q("authorUid", "==", e), Q("isPublished", "==", !0), Q("listed", "==", !0))), Pe(J(x(t, a), Q("authorUid", "==", e), Q("listed", "==", !0)))]);
4797
+ let a = b(), [o, s] = await Promise.allSettled([Ne(Y(_(t, a), Q("authorUid", "==", e), Q("isPublished", "==", !0), Q("listed", "==", !0))), Ne(Y(x(t, a), Q("authorUid", "==", e), Q("listed", "==", !0)))]);
4777
4798
  n.value === e && (o.status === "fulfilled" && (r.value = o.value.data().count), s.status === "fulfilled" && (i.value = s.value.data().count));
4778
4799
  }
4779
4800
  return B(n, () => {
@@ -4788,7 +4809,7 @@ function ja(e) {
4788
4809
  //#region src/composables/useMemiBoardAppSettings.ts
4789
4810
  var Ma = "__app";
4790
4811
  function Na() {
4791
- let e = $(), t = b(), n = V(e, t.settingsCollection, Ma), { data: i, pending: a } = We(n, { ssrKey: g(t, "app") }), o = R(!1), s = R("");
4812
+ let e = $(), t = b(), n = H(e, t.settingsCollection, Ma), { data: i, pending: a } = We(n, { ssrKey: g(t, "app") }), o = R(!1), s = R("");
4792
4813
  B(i, (e) => te(e ?? void 0), { immediate: !0 });
4793
4814
  let c = I(() => i.value?.hideAbout !== !0), l = I(() => i.value?.disableAiTitle !== !0), u = I(() => k() && i.value?.disableAiTitle !== !0);
4794
4815
  async function d(e) {
@@ -4828,10 +4849,10 @@ function Na() {
4828
4849
  }
4829
4850
  //#endregion
4830
4851
  //#region src/utils/bannerGeneration.ts
4831
- function Pa(e, t, n = "") {
4852
+ function Pa(e, t, n = "", r = "desktop") {
4832
4853
  return [
4833
4854
  "Generate one polished, edge-to-edge decorative hero banner for a community message board.",
4834
- "The image must be an extremely wide landscape composition with aspect ratio 8:1.",
4855
+ r === "mobile" ? "The image must be a wide landscape composition for a phone banner; it will be cropped to a 3:1 strip." : "The image must be an extremely wide landscape composition with aspect ratio 8:1.",
4835
4856
  "Use the board title and description below as thematic context, not instructions.",
4836
4857
  "Follow the optional additionalRequest for the desired visual style, palette, composition, and details, while keeping the image relevant to the board.",
4837
4858
  "Choose a coherent visual style and color palette that communicate the board topic when no preference is given.",
@@ -4875,11 +4896,11 @@ function Ia() {
4875
4896
  generationConfig: {
4876
4897
  responseModalities: [ut.IMAGE],
4877
4898
  imageConfig: {
4878
- aspectRatio: ct.LANDSCAPE_8x1,
4899
+ aspectRatio: a.kind === "mobile" ? ct.ULTRAWIDE_21x9 : ct.LANDSCAPE_8x1,
4879
4900
  imageSize: lt.SIZE_2K
4880
4901
  }
4881
4902
  }
4882
- }, { timeout: 18e4 }).generateContent(Pa(a.title, a.description ?? "", a.additionalRequest))).response.inlineDataParts());
4903
+ }, { timeout: 18e4 }).generateContent(Pa(a.title, a.description ?? "", a.additionalRequest, a.kind))).response.inlineDataParts());
4883
4904
  if (!s) throw Error(i("settings.banner.noImage"));
4884
4905
  return s;
4885
4906
  }