@nethesis/chat-island 0.1.16 → 0.1.17

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
@@ -565,14 +565,14 @@ var D = /* @__PURE__ */ y(((e) => {
565
565
  e && this.write(e), this.write = function() {};
566
566
  }
567
567
  };
568
- })), M = D(), N = /* @__PURE__ */ x(O(), 1), P = /* @__PURE__ */ x(k(), 1), F = A(), ee = /* @__PURE__ */ x(j(), 1), te = class extends Error {
568
+ })), M = D(), N = /* @__PURE__ */ x(O(), 1), P = /* @__PURE__ */ x(k(), 1), F = A(), ee = /* @__PURE__ */ x(j(), 1), I = class extends Error {
569
569
  constructor(e) {
570
570
  super(e), this.name = "TimeoutError";
571
571
  }
572
572
  };
573
573
  //#endregion
574
574
  //#region node_modules/@xmpp/events/lib/delay.js
575
- function ne(e) {
575
+ function te(e) {
576
576
  let t, n = new Promise((n) => {
577
577
  t = setTimeout(n, e);
578
578
  });
@@ -580,32 +580,32 @@ function ne(e) {
580
580
  }
581
581
  //#endregion
582
582
  //#region node_modules/@xmpp/events/lib/timeout.js
583
- function re(e, t) {
584
- let n = ne(t);
583
+ function ne(e, t) {
584
+ let n = te(t);
585
585
  function r() {
586
586
  clearTimeout(n.timeout);
587
587
  }
588
- let i = new te();
588
+ let i = new I();
589
589
  return Promise.race([e.finally(r), n.then(() => {
590
590
  throw i;
591
591
  })]);
592
592
  }
593
593
  //#endregion
594
594
  //#region node_modules/@xmpp/events/lib/onoff.js
595
- var ie = /* @__PURE__ */ new WeakMap();
596
- function I(e) {
597
- let t = ie.get(e);
595
+ var re = /* @__PURE__ */ new WeakMap();
596
+ function ie(e) {
597
+ let t = re.get(e);
598
598
  return t || (t = {
599
599
  on: (e.addEventListener ?? e.addListener).bind(e),
600
600
  off: (e.removeEventListener ?? e.removeListener).bind(e),
601
601
  once: (e.once ?? ((t, n) => e.addEventListener(t, n, { once: !0 }))).bind(e)
602
- }, ie.set(e, t)), t;
602
+ }, re.set(e, t)), t;
603
603
  }
604
604
  //#endregion
605
605
  //#region node_modules/@xmpp/events/lib/promise.js
606
606
  function L(e, t, n = "error", r) {
607
607
  return new Promise((i, a) => {
608
- let o, { off: s, once: c } = I(e), l = () => {
608
+ let o, { off: s, once: c } = ie(e), l = () => {
609
609
  clearTimeout(o), s(t, d), s(n, u);
610
610
  };
611
611
  function u(e) {
@@ -615,7 +615,7 @@ function L(e, t, n = "error", r) {
615
615
  i(e), l();
616
616
  }
617
617
  if (c(t, d), n && c(n, u), r) {
618
- let e = new te();
618
+ let e = new I();
619
619
  o = setTimeout(() => {
620
620
  l(), a(e);
621
621
  }, r);
@@ -654,11 +654,11 @@ function oe(e, t = null, n) {
654
654
  function se(e) {
655
655
  return {
656
656
  subscribe(t) {
657
- let { on: n } = I(t);
657
+ let { on: n } = ie(t);
658
658
  for (let [t, r] of Object.entries(e)) n(t, r);
659
659
  },
660
660
  unsubscribe(t) {
661
- let { off: n } = I(t);
661
+ let { off: n } = ie(t);
662
662
  for (let [t, r] of Object.entries(e)) n(t, r);
663
663
  }
664
664
  };
@@ -1345,7 +1345,7 @@ var qe = class {
1345
1345
  let n = new ae();
1346
1346
  this.handlers.set(e.attrs.id, n);
1347
1347
  try {
1348
- await this.entity.send(e), await re(n.promise, t);
1348
+ await this.entity.send(e), await ne(n.promise, t);
1349
1349
  } catch (t) {
1350
1350
  throw this.handlers.delete(e.attrs.id), t;
1351
1351
  }
@@ -2322,7 +2322,8 @@ var hn = "chat.internal", W = {
2322
2322
  ping: "urn:xmpp:ping",
2323
2323
  reactions: "urn:xmpp:reactions:0",
2324
2324
  reply: "urn:xmpp:reply:0",
2325
- fallback: "urn:xmpp:fallback:0"
2325
+ fallback: "urn:xmpp:fallback:0",
2326
+ markers: "urn:xmpp:chat-markers:0"
2326
2327
  }, gn = 3e4, _n = class {
2327
2328
  xmpp;
2328
2329
  me;
@@ -2331,6 +2332,7 @@ var hn = "chat.internal", W = {
2331
2332
  uploadService;
2332
2333
  mamQueries = /* @__PURE__ */ new Map();
2333
2334
  mamReactions = /* @__PURE__ */ new Map();
2335
+ mamMarkers = /* @__PURE__ */ new Map();
2334
2336
  stopped = !1;
2335
2337
  attempt = 0;
2336
2338
  retryTimer;
@@ -2461,7 +2463,7 @@ var hn = "chat.internal", W = {
2461
2463
  room: e,
2462
2464
  nick: this.cfg.username,
2463
2465
  reply: r
2464
- }) : (s.push(R("active", { xmlns: W.chatstates })), await this.xmpp.send(R("message", {
2466
+ }) : (s.push(R("active", { xmlns: W.chatstates }), R("markable", { xmlns: W.markers })), await this.xmpp.send(R("message", {
2465
2467
  to: `${e}@${this.domain}`,
2466
2468
  type: "chat",
2467
2469
  id: i
@@ -2477,6 +2479,16 @@ var hn = "chat.internal", W = {
2477
2479
  reply: r
2478
2480
  });
2479
2481
  }
2482
+ async marker(e, t, n) {
2483
+ await this.xmpp.send(R("message", {
2484
+ to: `${e}@${this.domain}`,
2485
+ type: "chat",
2486
+ id: crypto.randomUUID()
2487
+ }, R(t, {
2488
+ xmlns: W.markers,
2489
+ id: n
2490
+ }), R("store", { xmlns: W.hints })));
2491
+ }
2480
2492
  async react(e, t, n) {
2481
2493
  let r = this.isGroup(e), i = R("reactions", {
2482
2494
  xmlns: W.reactions,
@@ -2519,7 +2531,7 @@ var hn = "chat.internal", W = {
2519
2531
  }
2520
2532
  async mam(e, t, n) {
2521
2533
  let r = crypto.randomUUID();
2522
- this.mamQueries.set(r, []), this.mamReactions.set(r, []);
2534
+ this.mamQueries.set(r, []), this.mamReactions.set(r, []), this.mamMarkers.set(r, []);
2523
2535
  let i = R("set", { xmlns: W.rsm }, R("max", {}, String(n)), R("before", {}, t ?? "")), a = [R("field", {
2524
2536
  var: "FORM_TYPE",
2525
2537
  type: "hidden"
@@ -2528,7 +2540,7 @@ var hn = "chat.internal", W = {
2528
2540
  let o = R("x", {
2529
2541
  xmlns: W.data,
2530
2542
  type: "submit"
2531
- }, ...a), s, c, l;
2543
+ }, ...a), s, c, l, u;
2532
2544
  try {
2533
2545
  s = await this.xmpp.iqCaller.request(R("iq", {
2534
2546
  type: "set",
@@ -2538,14 +2550,15 @@ var hn = "chat.internal", W = {
2538
2550
  queryid: r
2539
2551
  }, o, i)), 3e4);
2540
2552
  } finally {
2541
- c = this.mamQueries.get(r) ?? [], l = this.mamReactions.get(r) ?? [], this.mamQueries.delete(r), this.mamReactions.delete(r);
2553
+ c = this.mamQueries.get(r) ?? [], l = this.mamReactions.get(r) ?? [], u = this.mamMarkers.get(r) ?? [], this.mamQueries.delete(r), this.mamReactions.delete(r), this.mamMarkers.delete(r);
2542
2554
  }
2543
- let u = s.getChild("fin", W.mam), d = u?.getChild("set", W.rsm)?.getChildText("first") ?? void 0;
2555
+ let d = s.getChild("fin", W.mam), f = d?.getChild("set", W.rsm)?.getChildText("first") ?? void 0;
2544
2556
  return {
2545
2557
  messages: c,
2546
2558
  reactions: l,
2547
- complete: u?.attrs.complete === "true",
2548
- first: d
2559
+ markers: u,
2560
+ complete: d?.attrs.complete === "true",
2561
+ first: f
2549
2562
  };
2550
2563
  }
2551
2564
  async createGroup(e, t, n) {
@@ -2732,10 +2745,12 @@ var hn = "chat.internal", W = {
2732
2745
  if (!t) return;
2733
2746
  let e = n.getChild("forwarded", W.forward)?.getChild("message"), r = this.mamQueries.get(n.attrs.queryid);
2734
2747
  if (e && r) {
2735
- let t = this.reactionOf(e);
2736
- t && this.mamReactions.get(n.attrs.queryid)?.push(t);
2737
- let i = t ? void 0 : this.toMessage(e, n.attrs.id, bn(n.getChild("forwarded", W.forward)));
2738
- i && r.push(i);
2748
+ let t = bn(n.getChild("forwarded", W.forward)), i = this.markerOf(e, t);
2749
+ i && this.mamMarkers.get(n.attrs.queryid)?.push(i);
2750
+ let a = i ? void 0 : this.reactionOf(e);
2751
+ a && this.mamReactions.get(n.attrs.queryid)?.push(a);
2752
+ let o = a || i ? void 0 : this.toMessage(e, n.attrs.id, bn(n.getChild("forwarded", W.forward)));
2753
+ o && r.push(o);
2739
2754
  }
2740
2755
  return;
2741
2756
  }
@@ -2761,19 +2776,37 @@ var hn = "chat.internal", W = {
2761
2776
  this.deliver(e);
2762
2777
  }
2763
2778
  deliver(e) {
2764
- let t = this.reactionOf(e);
2779
+ let t = this.markerOf(e, bn(e));
2765
2780
  if (t) {
2766
- this.h.reaction(t);
2781
+ this.h.marker(t);
2767
2782
  return;
2768
2783
  }
2769
- let n = this.toMessage(e, e.getChild("stanza-id", W.sid)?.attrs.id, bn(e));
2784
+ let n = this.reactionOf(e);
2770
2785
  if (n) {
2771
- this.h.message(n);
2786
+ this.h.reaction(n);
2787
+ return;
2788
+ }
2789
+ let r = this.toMessage(e, e.getChild("stanza-id", W.sid)?.attrs.id, bn(e));
2790
+ if (r) {
2791
+ this.h.message(r);
2772
2792
  return;
2773
2793
  }
2774
2794
  if (e.attrs.type !== "chat") return;
2775
- let r = G(e.attrs.from), i = r === this.me ? G(e.attrs.to) : r, a = e.getChildByAttr("xmlns", W.chatstates);
2776
- !e.getChild("body") && a && this.h.typing(K(i), a.name === "composing");
2795
+ let i = G(e.attrs.from), a = i === this.me ? G(e.attrs.to) : i, o = e.getChildByAttr("xmlns", W.chatstates);
2796
+ !e.getChild("body") && o && this.h.typing(K(a), o.name === "composing");
2797
+ }
2798
+ markerOf(e, t) {
2799
+ if (e.attrs.type !== "chat") return;
2800
+ let n = e.getChild("received", W.markers) ?? e.getChild("displayed", W.markers);
2801
+ if (!n?.attrs.id) return;
2802
+ let r = G(e.attrs.from), i = r === this.me || !e.attrs.from, a = K(i ? G(e.attrs.to) : r);
2803
+ return a ? {
2804
+ peer: a,
2805
+ kind: n.name,
2806
+ id: n.attrs.id,
2807
+ ts: t,
2808
+ mine: i
2809
+ } : void 0;
2777
2810
  }
2778
2811
  reactionOf(e) {
2779
2812
  let t = e.getChild("event", W.pubsubEvent), n = e, r;
@@ -3088,6 +3121,33 @@ var An = (e) => {
3088
3121
  }
3089
3122
  } };
3090
3123
  }),
3124
+ applyMarkers: (t) => e((e) => {
3125
+ if (!t.length) return {};
3126
+ let n = { ...e.conversations };
3127
+ for (let e of t) {
3128
+ let t = n[e.peer];
3129
+ if (!t || t.kind !== "chat") continue;
3130
+ let r = t.messages.find((t) => t.mine !== e.mine && (t.oid === e.id || t.id === e.id))?.ts ?? e.ts;
3131
+ if (e.mine) {
3132
+ e.kind === "displayed" && (n[e.peer] = {
3133
+ ...t,
3134
+ myRead: Math.max(t.myRead ?? 0, r),
3135
+ unread: 0
3136
+ });
3137
+ continue;
3138
+ }
3139
+ let i = Math.max(t.delivered ?? 0, r);
3140
+ n[e.peer] = e.kind === "displayed" ? {
3141
+ ...t,
3142
+ delivered: i,
3143
+ read: Math.max(t.read ?? 0, r)
3144
+ } : {
3145
+ ...t,
3146
+ delivered: i
3147
+ };
3148
+ }
3149
+ return { conversations: n };
3150
+ }),
3091
3151
  applyReactions: (t) => e((e) => {
3092
3152
  if (!t.length) return {};
3093
3153
  let n = { ...e.conversations };
@@ -4136,33 +4196,33 @@ function xr({ reply: e, messages: t, mine: n, name: r }) {
4136
4196
  })]
4137
4197
  });
4138
4198
  }
4139
- function Sr({ messages: e, typing: t, onLoadOlder: n, hasOlder: r, group: a, reactions: o, me: l = "", onReact: u, onReply: p }) {
4140
- let m = Y((e) => e.contacts), h = s(null), g = s(!0), [_, v] = c(null), [y, b] = c(null), x = (e) => m[e]?.name ?? e;
4199
+ function Sr({ messages: e, typing: t, onLoadOlder: n, hasOlder: r, group: a, reactions: o, delivered: l = 0, read: u = 0, me: p = "", onReact: m, onReply: h }) {
4200
+ let g = Y((e) => e.contacts), _ = s(null), v = s(!0), [y, b] = c(null), [x, S] = c(null), C = (e) => g[e]?.name ?? e;
4141
4201
  i(() => {
4142
- let e = h.current;
4143
- e && g.current && (e.scrollTop = e.scrollHeight);
4202
+ let e = _.current;
4203
+ e && v.current && (e.scrollTop = e.scrollHeight);
4144
4204
  }, [
4145
4205
  e.length,
4146
4206
  t,
4147
4207
  o
4148
4208
  ]), i(() => {
4149
- if (!_) return;
4150
- let e = () => v(null), t = window.setTimeout(() => document.addEventListener("click", e, { once: !0 }), 0);
4209
+ if (!y) return;
4210
+ let e = () => b(null), t = window.setTimeout(() => document.addEventListener("click", e, { once: !0 }), 0);
4151
4211
  return () => {
4152
4212
  window.clearTimeout(t), document.removeEventListener("click", e);
4153
4213
  };
4154
- }, [_]);
4155
- let S = () => {
4156
- let e = h.current;
4157
- e && (g.current = e.scrollHeight - e.scrollTop - e.clientHeight < 40, e.scrollTop < 30 && r && n());
4158
- }, C = (e, t) => {
4159
- v(null), b(null), u?.(e, t);
4214
+ }, [y]);
4215
+ let w = () => {
4216
+ let e = _.current;
4217
+ e && (v.current = e.scrollHeight - e.scrollTop - e.clientHeight < 40, e.scrollTop < 30 && r && n());
4218
+ }, T = (e, t) => {
4219
+ b(null), S(null), m?.(e, t);
4160
4220
  };
4161
4221
  return /* @__PURE__ */ f("div", {
4162
4222
  className: "ci-relative ci-flex-1 ci-min-h-0 ci-flex ci-flex-col",
4163
4223
  children: [/* @__PURE__ */ f("div", {
4164
- ref: h,
4165
- onScroll: S,
4224
+ ref: _,
4225
+ onScroll: w,
4166
4226
  className: "ci-flex-1 ci-overflow-y-auto ci-px-4 ci-py-2 ci-space-y-1",
4167
4227
  children: [
4168
4228
  r && /* @__PURE__ */ d("div", {
@@ -4170,21 +4230,21 @@ function Sr({ messages: e, typing: t, onLoadOlder: n, hasOlder: r, group: a, rea
4170
4230
  children: "Scroll up for older messages"
4171
4231
  }),
4172
4232
  e.map((t, n) => {
4173
- let r = e[n - 1], i = !r || !pr(r.ts, t.ts), s = r && !i && r.mine === t.mine && r.nick === t.nick && t.ts - r.ts < 12e4, c = a && !t.mine && t.nick ? x(t.nick) : null, h = t.oid, g = !!u && !!h && !t.pending, y = g && /* @__PURE__ */ d("button", {
4233
+ let r = e[n - 1], i = !r || !pr(r.ts, t.ts), s = r && !i && r.mine === t.mine && r.nick === t.nick && t.ts - r.ts < 12e4, c = a && !t.mine && t.nick ? C(t.nick) : null, _ = t.oid, v = !!m && !!_ && !t.pending, x = v && /* @__PURE__ */ d("button", {
4174
4234
  type: "button",
4175
4235
  title: "React",
4176
4236
  "aria-label": "React to this message",
4177
4237
  onClick: (e) => {
4178
- e.stopPropagation(), v(_ === h ? null : h);
4238
+ e.stopPropagation(), b(y === _ ? null : _);
4179
4239
  },
4180
- className: `ci-self-center ci-h-7 ci-w-7 ci-shrink-0 ci-flex ci-items-center ci-justify-center ci-rounded-full ci-border-0 ci-bg-transparent ci-text-gray-500 dark:ci-text-gray-400 hover:ci-bg-gray-200 dark:hover:ci-bg-gray-800 focus:ci-opacity-100 ${_ === h ? "ci-opacity-100" : "ci-opacity-0 group-hover:ci-opacity-100"}`,
4240
+ className: `ci-self-center ci-h-7 ci-w-7 ci-shrink-0 ci-flex ci-items-center ci-justify-center ci-rounded-full ci-border-0 ci-bg-transparent ci-text-gray-500 dark:ci-text-gray-400 hover:ci-bg-gray-200 dark:hover:ci-bg-gray-800 focus:ci-opacity-100 ${y === _ ? "ci-opacity-100" : "ci-opacity-0 group-hover:ci-opacity-100"}`,
4181
4241
  children: $.react
4182
- }), S = !!p && !!h && !t.pending && /* @__PURE__ */ d("button", {
4242
+ }), w = !!h && !!_ && !t.pending && /* @__PURE__ */ d("button", {
4183
4243
  type: "button",
4184
4244
  title: "Reply",
4185
4245
  "aria-label": "Reply to this message",
4186
4246
  onClick: (e) => {
4187
- e.stopPropagation(), p(t);
4247
+ e.stopPropagation(), h(t);
4188
4248
  },
4189
4249
  className: "ci-self-center ci-h-7 ci-w-7 ci-shrink-0 ci-flex ci-items-center ci-justify-center ci-rounded-full ci-border-0 ci-bg-transparent ci-text-gray-500 dark:ci-text-gray-400 hover:ci-bg-gray-200 dark:hover:ci-bg-gray-800 focus:ci-opacity-100 ci-opacity-0 group-hover:ci-opacity-100",
4190
4250
  children: $.reply
@@ -4201,17 +4261,17 @@ function Sr({ messages: e, typing: t, onLoadOlder: n, hasOlder: r, group: a, rea
4201
4261
  className: "ci-w-7 ci-shrink-0",
4202
4262
  title: c,
4203
4263
  children: !s && /* @__PURE__ */ d(Kn, {
4204
- contact: m[t.nick],
4264
+ contact: g[t.nick],
4205
4265
  username: t.nick,
4206
4266
  size: 28
4207
4267
  })
4208
4268
  }),
4209
- t.mine && S,
4210
- t.mine && y,
4269
+ t.mine && w,
4270
+ t.mine && x,
4211
4271
  /* @__PURE__ */ f("div", {
4212
4272
  className: `ci-relative ci-flex ci-flex-col ci-max-w-[80%] ${t.mine ? "ci-items-end" : "ci-items-start"}`,
4213
4273
  children: [
4214
- _ === h && h && /* @__PURE__ */ f("div", {
4274
+ y === _ && _ && /* @__PURE__ */ f("div", {
4215
4275
  role: "menu",
4216
4276
  onClick: (e) => e.stopPropagation(),
4217
4277
  className: `ci-absolute ci-bottom-full ci-mb-1 ci-z-20 ci-flex ci-items-center ci-gap-0.5 ci-p-1 ci-rounded-full ci-bg-gray-50 dark:ci-bg-gray-950 ci-shadow-xl ci-border ci-border-solid ci-border-gray-300 dark:ci-border-gray-600 ${t.mine ? "ci-right-0" : "ci-left-0"}`,
@@ -4219,12 +4279,12 @@ function Sr({ messages: e, typing: t, onLoadOlder: n, hasOlder: r, group: a, rea
4219
4279
  type: "button",
4220
4280
  role: "menuitem",
4221
4281
  "aria-label": e,
4222
- onClick: () => C(h, e),
4282
+ onClick: () => T(_, e),
4223
4283
  style: {
4224
4284
  fontSize: 22,
4225
4285
  lineHeight: "32px"
4226
4286
  },
4227
- className: `ci-h-9 ci-w-9 ci-flex ci-items-center ci-justify-center ci-rounded-full ci-border-0 hover:ci-scale-125 ci-transition-transform ${o?.[h]?.[l]?.includes(e) ? "ci-bg-gray-200 dark:ci-bg-gray-800" : "ci-bg-transparent"}`,
4287
+ className: `ci-h-9 ci-w-9 ci-flex ci-items-center ci-justify-center ci-rounded-full ci-border-0 hover:ci-scale-125 ci-transition-transform ${o?.[_]?.[p]?.includes(e) ? "ci-bg-gray-200 dark:ci-bg-gray-800" : "ci-bg-transparent"}`,
4228
4288
  children: e
4229
4289
  }, e)), /* @__PURE__ */ d("button", {
4230
4290
  type: "button",
@@ -4232,7 +4292,7 @@ function Sr({ messages: e, typing: t, onLoadOlder: n, hasOlder: r, group: a, rea
4232
4292
  title: "More emojis",
4233
4293
  "aria-label": "More emojis",
4234
4294
  onClick: () => {
4235
- v(null), b(h);
4295
+ b(null), S(_);
4236
4296
  },
4237
4297
  className: "ci-h-8 ci-w-8 ci-flex ci-items-center ci-justify-center ci-rounded-full ci-border-0 ci-bg-gray-200 dark:ci-bg-gray-800 ci-text-gray-700 dark:ci-text-gray-200 ci-text-lg",
4238
4298
  children: "+"
@@ -4240,37 +4300,40 @@ function Sr({ messages: e, typing: t, onLoadOlder: n, hasOlder: r, group: a, rea
4240
4300
  }),
4241
4301
  /* @__PURE__ */ f("div", {
4242
4302
  title: dr(t.ts),
4243
- onDoubleClick: () => g && C(h, ar[0]),
4303
+ onDoubleClick: () => v && T(_, ar[0]),
4244
4304
  className: `ci-px-3.5 ci-py-2 ci-rounded-3xl ci-text-sm ci-select-text ci-cursor-text ${t.mine ? "ci-bg-gray-700 ci-text-gray-50 dark:ci-bg-gray-300 dark:ci-text-gray-900 ci-rounded-br-lg" : "ci-bg-elevationL2 ci-text-gray-900 dark:ci-bg-elevationL2Dark dark:ci-text-white ci-rounded-bl-lg"} ${t.pending ? "ci-opacity-60" : ""}`,
4245
4305
  children: [
4246
4306
  t.reply && /* @__PURE__ */ d(xr, {
4247
4307
  reply: t.reply,
4248
4308
  messages: e,
4249
4309
  mine: t.mine,
4250
- name: (e) => e === l ? "You" : x(e)
4310
+ name: (e) => e === p ? "You" : C(e)
4251
4311
  }),
4252
4312
  t.oob ? /* @__PURE__ */ d(hr, { url: t.oob }) : mr(t.body) ? /* @__PURE__ */ d(yr, { ...mr(t.body) }) : /* @__PURE__ */ d(vr, { text: t.body }),
4253
4313
  t.oob && t.body && t.body !== t.oob && t.body !== lr(t.oob) && /* @__PURE__ */ d("div", {
4254
4314
  className: "ci-text-xs ci-opacity-80 ci-mt-1",
4255
4315
  children: t.body
4256
4316
  }),
4257
- /* @__PURE__ */ d("span", {
4258
- className: "ci-block ci-text-right ci-text-[10px] ci-leading-none ci-opacity-60 ci-mt-1",
4259
- children: dr(t.ts)
4317
+ /* @__PURE__ */ f("span", {
4318
+ className: "ci-flex ci-items-center ci-justify-end ci-gap-1 ci-text-[10px] ci-leading-none ci-mt-1",
4319
+ children: [/* @__PURE__ */ d("span", {
4320
+ className: "ci-opacity-60",
4321
+ children: dr(t.ts)
4322
+ }), t.mine && !a && /* @__PURE__ */ d(wr, { state: t.pending ? "pending" : t.ts <= u ? "read" : t.ts <= l ? "delivered" : "sent" })]
4260
4323
  })
4261
4324
  ]
4262
4325
  }),
4263
- h && /* @__PURE__ */ d(br, {
4264
- forMsg: o?.[h],
4265
- me: l,
4326
+ _ && /* @__PURE__ */ d(br, {
4327
+ forMsg: o?.[_],
4328
+ me: p,
4266
4329
  mine: t.mine,
4267
- nameOf: x,
4268
- onReact: (e) => g && C(h, e)
4330
+ nameOf: C,
4331
+ onReact: (e) => v && T(_, e)
4269
4332
  })
4270
4333
  ]
4271
4334
  }),
4272
- !t.mine && y,
4273
- !t.mine && S
4335
+ !t.mine && x,
4336
+ !t.mine && w
4274
4337
  ]
4275
4338
  })]
4276
4339
  }, t.id);
@@ -4283,16 +4346,53 @@ function Sr({ messages: e, typing: t, onLoadOlder: n, hasOlder: r, group: a, rea
4283
4346
  })
4284
4347
  })
4285
4348
  ]
4286
- }), y && /* @__PURE__ */ d(or, {
4349
+ }), x && /* @__PURE__ */ d(or, {
4287
4350
  className: "ci-absolute ci-bottom-2 ci-left-1/2 ci--translate-x-1/2",
4288
- onPick: (e) => C(y, e),
4289
- onClose: () => b(null)
4351
+ onPick: (e) => T(x, e),
4352
+ onClose: () => S(null)
4290
4353
  })]
4291
4354
  });
4292
4355
  }
4356
+ var Cr = {
4357
+ pending: "Sending",
4358
+ sent: "Sent",
4359
+ delivered: "Delivered",
4360
+ read: "Read"
4361
+ };
4362
+ function wr({ state: e }) {
4363
+ return /* @__PURE__ */ d("span", {
4364
+ title: Cr[e],
4365
+ "aria-label": Cr[e],
4366
+ className: e === "read" ? "ci-text-phoneIslandCallDark dark:ci-text-phoneIslandCall" : "ci-opacity-60",
4367
+ children: e === "pending" ? /* @__PURE__ */ f("svg", {
4368
+ width: "12",
4369
+ height: "12",
4370
+ viewBox: "0 0 24 24",
4371
+ fill: "none",
4372
+ stroke: "currentColor",
4373
+ strokeWidth: "2.5",
4374
+ strokeLinecap: "round",
4375
+ children: [/* @__PURE__ */ d("circle", {
4376
+ cx: "12",
4377
+ cy: "12",
4378
+ r: "9"
4379
+ }), /* @__PURE__ */ d("path", { d: "M12 7v5l3 2" })]
4380
+ }) : /* @__PURE__ */ f("svg", {
4381
+ width: "16",
4382
+ height: "12",
4383
+ viewBox: "0 0 28 16",
4384
+ fill: "none",
4385
+ stroke: "currentColor",
4386
+ strokeWidth: "2.5",
4387
+ strokeLinecap: "round",
4388
+ strokeLinejoin: "round",
4389
+ children: [/* @__PURE__ */ d("path", { d: "M2 9l4 4 9-10" }), e !== "sent" && /* @__PURE__ */ d("path", { d: "M12 12l1 1 9-10" })]
4390
+ })
4391
+ });
4392
+ }
4293
4393
  //#endregion
4294
4394
  //#region src/ogg.ts
4295
- function Cr(e, t, n) {
4395
+ function Tr(e, t, n) {
4296
4396
  let r = e[t];
4297
4397
  if (r === void 0) return null;
4298
4398
  let i = 1;
@@ -4306,7 +4406,7 @@ function Cr(e, t, n) {
4306
4406
  unknown: !n && o
4307
4407
  };
4308
4408
  }
4309
- var wr = /* @__PURE__ */ new Set([
4409
+ var Er = /* @__PURE__ */ new Set([
4310
4410
  408125543,
4311
4411
  524531317,
4312
4412
  374648427,
@@ -4314,18 +4414,18 @@ var wr = /* @__PURE__ */ new Set([
4314
4414
  225,
4315
4415
  160
4316
4416
  ]);
4317
- function Tr(e) {
4417
+ function Dr(e) {
4318
4418
  let t = {
4319
4419
  channels: 1,
4320
4420
  packets: []
4321
4421
  }, n = 0;
4322
4422
  for (; n < e.length;) {
4323
- let r = Cr(e, n, !0);
4423
+ let r = Tr(e, n, !0);
4324
4424
  if (!r) break;
4325
- let i = Cr(e, n + r.len, !1);
4425
+ let i = Tr(e, n + r.len, !1);
4326
4426
  if (!i) break;
4327
4427
  let a = n + r.len + i.len;
4328
- if (wr.has(r.value)) {
4428
+ if (Er.has(r.value)) {
4329
4429
  n = a;
4330
4430
  continue;
4331
4431
  }
@@ -4334,14 +4434,14 @@ function Tr(e) {
4334
4434
  if (r.value === 25506) t.head = e.slice(a, o);
4335
4435
  else if (r.value === 159) t.channels = e[a] || 1;
4336
4436
  else if (r.value === 163 || r.value === 161) {
4337
- let n = Cr(e, a, !1);
4437
+ let n = Tr(e, a, !1);
4338
4438
  n && (e[a + n.len + 2] >> 1 & 3 || t.packets.push(e.slice(a + n.len + 3, o)));
4339
4439
  }
4340
4440
  n = o;
4341
4441
  }
4342
4442
  return t;
4343
4443
  }
4344
- function Er(e) {
4444
+ function Or(e) {
4345
4445
  if (!e.length) return 0;
4346
4446
  let t = e[0], n = t >> 3, r;
4347
4447
  r = n < 12 ? [
@@ -4358,7 +4458,7 @@ function Er(e) {
4358
4458
  let i = t & 3, a = i === 0 ? 1 : i === 3 ? (e[1] ?? 0) & 63 : 2;
4359
4459
  return Math.round(a * r * 48);
4360
4460
  }
4361
- var Dr = (() => {
4461
+ var kr = (() => {
4362
4462
  let e = /* @__PURE__ */ new Uint32Array(256);
4363
4463
  for (let t = 0; t < 256; t++) {
4364
4464
  let n = t << 24;
@@ -4367,12 +4467,12 @@ var Dr = (() => {
4367
4467
  }
4368
4468
  return e;
4369
4469
  })();
4370
- function Or(e) {
4470
+ function Ar(e) {
4371
4471
  let t = 0;
4372
- for (let n = 0; n < e.length; n++) t = (t << 8 ^ Dr[(t >>> 24 ^ e[n]) & 255]) >>> 0;
4472
+ for (let n = 0; n < e.length; n++) t = (t << 8 ^ kr[(t >>> 24 ^ e[n]) & 255]) >>> 0;
4373
4473
  return t;
4374
4474
  }
4375
- function kr(e, t, n, r, i) {
4475
+ function jr(e, t, n, r, i) {
4376
4476
  let a = [];
4377
4477
  for (let t of e) {
4378
4478
  let e = t.length;
@@ -4388,29 +4488,29 @@ function kr(e, t, n, r, i) {
4388
4488
  ], 0), s[5] = i, c.setUint32(6, t % 4294967296, !0), c.setUint32(10, Math.floor(t / 4294967296), !0), c.setUint32(14, n, !0), c.setUint32(18, r, !0), s[26] = a.length, s.set(a, 27);
4389
4489
  let l = 27 + a.length;
4390
4490
  for (let t of e) s.set(t, l), l += t.length;
4391
- return c.setUint32(22, Or(s), !0), s;
4491
+ return c.setUint32(22, Ar(s), !0), s;
4392
4492
  }
4393
- function Ar(e) {
4493
+ function Mr(e) {
4394
4494
  let t = /* @__PURE__ */ new Uint8Array(19), n = new DataView(t.buffer);
4395
4495
  return t.set(new TextEncoder().encode("OpusHead"), 0), t[8] = 1, t[9] = e, n.setUint16(10, 312, !0), n.setUint32(12, 48e3, !0), t;
4396
4496
  }
4397
- function jr() {
4497
+ function Nr() {
4398
4498
  let e = new TextEncoder().encode("chat-island"), t = new Uint8Array(12 + e.length + 4);
4399
4499
  return t.set(new TextEncoder().encode("OpusTags"), 0), new DataView(t.buffer).setUint32(8, e.length, !0), t.set(e, 12), t;
4400
4500
  }
4401
- function Mr(e) {
4402
- let { head: t, channels: n, packets: r } = Tr(e);
4501
+ function Pr(e) {
4502
+ let { head: t, channels: n, packets: r } = Dr(e);
4403
4503
  if (!r.length) return null;
4404
- let i = t && t.length >= 19 && new TextDecoder().decode(t.slice(0, 8)) === "OpusHead", a = Math.random() * 4294967295 >>> 0, o = [kr([i ? t : Ar(n)], 0, a, 0, 2), kr([jr()], 0, a, 1, 0)], s = 0, c = 2;
4504
+ let i = t && t.length >= 19 && new TextDecoder().decode(t.slice(0, 8)) === "OpusHead", a = Math.random() * 4294967295 >>> 0, o = [jr([i ? t : Mr(n)], 0, a, 0, 2), jr([Nr()], 0, a, 1, 0)], s = 0, c = 2;
4405
4505
  for (let e = 0; e < r.length;) {
4406
4506
  let t = [], n = 0;
4407
4507
  for (; e < r.length && t.length < 50;) {
4408
4508
  let i = Math.floor(r[e].length / 255) + 1;
4409
4509
  if (n + i > 255) break;
4410
- t.push(r[e]), n += i, s += Er(r[e]), e++;
4510
+ t.push(r[e]), n += i, s += Or(r[e]), e++;
4411
4511
  }
4412
4512
  if (!t.length) return null;
4413
- o.push(kr(t, s, a, c++, e >= r.length ? 4 : 0));
4513
+ o.push(jr(t, s, a, c++, e >= r.length ? 4 : 0));
4414
4514
  }
4415
4515
  let l = o.reduce((e, t) => e + t.length, 0), u = new Uint8Array(l), d = 0;
4416
4516
  for (let e of o) u.set(e, d), d += e.length;
@@ -4418,22 +4518,22 @@ function Mr(e) {
4418
4518
  }
4419
4519
  //#endregion
4420
4520
  //#region src/components/Composer.tsx
4421
- var Nr = [
4521
+ var Fr = [
4422
4522
  "audio/ogg;codecs=opus",
4423
4523
  "audio/webm;codecs=opus",
4424
4524
  "audio/mp4",
4425
4525
  "audio/webm"
4426
4526
  ];
4427
- async function Pr(e, t) {
4527
+ async function Ir(e, t) {
4428
4528
  let n = Date.now();
4429
4529
  if (/webm/.test(t) && /opus/.test(t)) try {
4430
- let t = Mr(new Uint8Array(await new Blob(e).arrayBuffer()));
4530
+ let t = Pr(new Uint8Array(await new Blob(e).arrayBuffer()));
4431
4531
  if (t) return new File([t], `voice-${n}.ogg`, { type: "audio/ogg" });
4432
4532
  } catch {}
4433
- return new File(e, `voice-${n}.${Fr(t)}`, { type: t.split(";")[0] });
4533
+ return new File(e, `voice-${n}.${Lr(t)}`, { type: t.split(";")[0] });
4434
4534
  }
4435
- var Fr = (e) => /mp4/.test(e) ? "m4a" : /ogg/.test(e) ? "ogg" : "webm", Ir = (e) => `${Math.floor(e / 6e4)}:${String(Math.floor(e % 6e4 / 1e3)).padStart(2, "0")}`;
4436
- function Lr({ onSend: e, onTyping: t, onFile: n, disabled: r, disabledText: o, focusKey: l }) {
4535
+ var Lr = (e) => /mp4/.test(e) ? "m4a" : /ogg/.test(e) ? "ogg" : "webm", Rr = (e) => `${Math.floor(e / 6e4)}:${String(Math.floor(e % 6e4 / 1e3)).padStart(2, "0")}`;
4536
+ function zr({ onSend: e, onTyping: t, onFile: n, disabled: r, disabledText: o, focusKey: l }) {
4437
4537
  let [u, p] = c(""), [m, h] = c(!1), g = s(null), _ = s(null), v = s(null), y = s(), b = s(!1), [x, S] = c(null), [C, w] = c(0), T = s(!1), E = s(!1), D = s(!1), O = s({});
4438
4538
  i(() => v.current?.focus(), []), i(() => () => {
4439
4539
  D.current = !0, T.current = !0, window.clearTimeout(y.current);
@@ -4474,9 +4574,9 @@ function Lr({ onSend: e, onTyping: t, onFile: n, disabled: r, disabledText: o, f
4474
4574
  t.getTracks().forEach((e) => e.stop());
4475
4575
  return;
4476
4576
  }
4477
- let r = Nr.find((e) => MediaRecorder.isTypeSupported(e)), i = new MediaRecorder(e, r ? { mimeType: r } : void 0), a = [];
4577
+ let r = Fr.find((e) => MediaRecorder.isTypeSupported(e)), i = new MediaRecorder(e, r ? { mimeType: r } : void 0), a = [];
4478
4578
  i.ondataavailable = (e) => e.data.size && a.push(e.data), i.onstop = () => {
4479
- t.getTracks().forEach((e) => e.stop()), O.current = {}, S(null), !T.current && a.length && Pr(a, i.mimeType || r || "").then(n);
4579
+ t.getTracks().forEach((e) => e.stop()), O.current = {}, S(null), !T.current && a.length && Ir(a, i.mimeType || r || "").then(n);
4480
4580
  }, T.current = !1, i.start(), O.current = {
4481
4581
  r: i,
4482
4582
  stream: t
@@ -4505,7 +4605,7 @@ function Lr({ onSend: e, onTyping: t, onFile: n, disabled: r, disabledText: o, f
4505
4605
  }),
4506
4606
  /* @__PURE__ */ f("div", {
4507
4607
  className: "ci-flex-1 ci-flex ci-items-center ci-gap-2 ci-px-4 ci-py-2.5 ci-rounded-3xl ci-bg-elevationL2 dark:ci-bg-elevationL2Dark ci-text-sm",
4508
- children: [/* @__PURE__ */ d("span", { className: "ci-w-2.5 ci-h-2.5 ci-rounded-full ci-bg-phoneIslandClose dark:ci-bg-phoneIslandCloseDark ci-animate-pulse" }), /* @__PURE__ */ f("span", { children: ["Recording ", Ir(C)] })]
4608
+ children: [/* @__PURE__ */ d("span", { className: "ci-w-2.5 ci-h-2.5 ci-rounded-full ci-bg-phoneIslandClose dark:ci-bg-phoneIslandCloseDark ci-animate-pulse" }), /* @__PURE__ */ f("span", { children: ["Recording ", Rr(C)] })]
4509
4609
  }),
4510
4610
  /* @__PURE__ */ d(Q, {
4511
4611
  variant: "green",
@@ -4585,14 +4685,14 @@ function Lr({ onSend: e, onTyping: t, onFile: n, disabled: r, disabledText: o, f
4585
4685
  }
4586
4686
  //#endregion
4587
4687
  //#region src/components/ChatWindow.tsx
4588
- var Rr = (e) => !!e && ![
4688
+ var Br = (e) => !!e && ![
4589
4689
  "offline",
4590
4690
  "dnd",
4591
4691
  "busy",
4592
4692
  "ringing",
4593
4693
  "onhold"
4594
4694
  ].includes(e);
4595
- function zr({ peer: e, actions: t, theme: n, onDragStart: r }) {
4695
+ function Vr({ peer: e, actions: t, theme: n, onDragStart: r }) {
4596
4696
  let { c: a, contacts: o, online: s, mobile: l, inactive: p, status: m, closeChat: h, openChat: g, markRead: _, order: v, me: y } = Y(w((t) => ({
4597
4697
  c: t.conversations[e],
4598
4698
  contacts: t.contacts,
@@ -4609,7 +4709,7 @@ function zr({ peer: e, actions: t, theme: n, onDragStart: r }) {
4609
4709
  i(() => {
4610
4710
  a && !a.loaded && t.loadOlder(e);
4611
4711
  }, [e, a?.loaded]), i(() => {
4612
- _(e);
4712
+ _(e), t.seen(e);
4613
4713
  }, [e, a?.messages.length]), i(() => {
4614
4714
  C(!1), E(!1), O(null);
4615
4715
  }, [e]);
@@ -4674,7 +4774,7 @@ function zr({ peer: e, actions: t, theme: n, onDragStart: r }) {
4674
4774
  children: F ? "No longer active" : m === "online" ? a.kind === "group" ? M.map(j).join(", ") : a.typing ? "typing…" : s[e] ? "online" : l[e] ? "Mobile" : "offline" : m
4675
4775
  })]
4676
4776
  }),
4677
- !F && a.kind !== "group" && x?.number && Rr(x.presence) && /* @__PURE__ */ d(Q, {
4777
+ !F && a.kind !== "group" && x?.number && Br(x.presence) && /* @__PURE__ */ d(Q, {
4678
4778
  variant: "call",
4679
4779
  title: `Call ${x.number}`,
4680
4780
  "aria-label": "Call",
@@ -4702,7 +4802,7 @@ function zr({ peer: e, actions: t, theme: n, onDragStart: r }) {
4702
4802
  ]
4703
4803
  }),
4704
4804
  /* @__PURE__ */ d("div", { className: "ci-border-t ci-border-gray-300 dark:ci-border-gray-700" }),
4705
- T && /* @__PURE__ */ d(Vr, {
4805
+ T && /* @__PURE__ */ d(Ur, {
4706
4806
  theme: n,
4707
4807
  onClose: () => E(!1)
4708
4808
  }),
@@ -4733,7 +4833,7 @@ function zr({ peer: e, actions: t, theme: n, onDragStart: r }) {
4733
4833
  "aria-label": "Chat",
4734
4834
  onClick: () => g(e),
4735
4835
  children: $.chat
4736
- }), o[e]?.number && Rr(o[e]?.presence) && /* @__PURE__ */ d(Q, {
4836
+ }), o[e]?.number && Br(o[e]?.presence) && /* @__PURE__ */ d(Q, {
4737
4837
  variant: "call",
4738
4838
  title: `Call ${o[e]?.number}`,
4739
4839
  "aria-label": "Call",
@@ -4756,6 +4856,8 @@ function zr({ peer: e, actions: t, theme: n, onDragStart: r }) {
4756
4856
  hasOlder: a.loaded && !a.complete,
4757
4857
  onLoadOlder: () => t.loadOlder(e),
4758
4858
  reactions: a.reactions,
4859
+ delivered: a.delivered,
4860
+ read: a.read,
4759
4861
  me: y,
4760
4862
  onReact: (n, r) => t.react(e, n, r),
4761
4863
  onReply: N
@@ -4779,7 +4881,7 @@ function zr({ peer: e, actions: t, theme: n, onDragStart: r }) {
4779
4881
  children: $.close
4780
4882
  })]
4781
4883
  }),
4782
- /* @__PURE__ */ d(Lr, {
4884
+ /* @__PURE__ */ d(zr, {
4783
4885
  focusKey: k,
4784
4886
  disabled: m !== "online" || F,
4785
4887
  disabledText: F ? "No longer active" : void 0,
@@ -4792,7 +4894,7 @@ function zr({ peer: e, actions: t, theme: n, onDragStart: r }) {
4792
4894
  ]
4793
4895
  });
4794
4896
  }
4795
- var Br = [
4897
+ var Hr = [
4796
4898
  {
4797
4899
  value: "light",
4798
4900
  label: "Light",
@@ -4809,7 +4911,7 @@ var Br = [
4809
4911
  icon: $.monitor
4810
4912
  }
4811
4913
  ];
4812
- function Vr({ theme: e, onClose: t }) {
4914
+ function Ur({ theme: e, onClose: t }) {
4813
4915
  let n = s(null);
4814
4916
  return i(() => {
4815
4917
  let e = (e) => n.current && !n.current.contains(e.target) && !e.target.closest("[aria-label=\"Menu\"]") && t();
@@ -4821,7 +4923,7 @@ function Vr({ theme: e, onClose: t }) {
4821
4923
  children: [/* @__PURE__ */ d("div", {
4822
4924
  className: "ci-px-4 ci-py-1 ci-font-semibold ci-text-gray-600 dark:ci-text-gray-50",
4823
4925
  children: "Theme"
4824
- }), Br.map((n) => /* @__PURE__ */ f("button", {
4926
+ }), Hr.map((n) => /* @__PURE__ */ f("button", {
4825
4927
  type: "button",
4826
4928
  role: "menuitemradio",
4827
4929
  "aria-checked": e === n.value,
@@ -4845,11 +4947,11 @@ function Vr({ theme: e, onClose: t }) {
4845
4947
  }
4846
4948
  //#endregion
4847
4949
  //#region src/components/NewChat.tsx
4848
- async function Hr(e) {
4950
+ async function Wr(e) {
4849
4951
  let t = await createImageBitmap(e), n = Math.min(t.width, t.height), r = document.createElement("canvas");
4850
4952
  return r.width = r.height = 128, r.getContext("2d")?.drawImage(t, (t.width - n) / 2, (t.height - n) / 2, n, n, 0, 0, 128, 128), r.toDataURL("image/jpeg", .8);
4851
4953
  }
4852
- function Ur({ onOpen: e, onCreateGroup: t, onDragStart: n }) {
4954
+ function Gr({ onOpen: e, onCreateGroup: t, onDragStart: n }) {
4853
4955
  let { contacts: r, online: i, mobile: a, setPicker: l } = Y(), [p, m] = c(""), [h, g] = c([]), [_, v] = c(""), [y, b] = c(!1), [x, S] = c(), C = s(null), w = o(() => {
4854
4956
  let e = Object.values(r), t = p.trim().toLowerCase();
4855
4957
  return t ? e.filter((e) => (e.name ?? "").toLowerCase().includes(t) || e.username.includes(t)) : e;
@@ -4958,7 +5060,7 @@ function Ur({ onOpen: e, onCreateGroup: t, onDragStart: n }) {
4958
5060
  type: "file",
4959
5061
  accept: "image/*",
4960
5062
  hidden: !0,
4961
- onChange: (e) => e.target.files?.[0] && Hr(e.target.files[0]).then(S).catch(() => {})
5063
+ onChange: (e) => e.target.files?.[0] && Wr(e.target.files[0]).then(S).catch(() => {})
4962
5064
  }),
4963
5065
  /* @__PURE__ */ d("button", {
4964
5066
  type: "button",
@@ -4993,22 +5095,22 @@ function Ur({ onOpen: e, onCreateGroup: t, onDragStart: n }) {
4993
5095
  }
4994
5096
  //#endregion
4995
5097
  //#region src/theme.ts
4996
- var Wr = "chat-island-theme", Gr = () => {
5098
+ var Kr = "chat-island-theme", qr = () => {
4997
5099
  try {
4998
- let e = localStorage.getItem(Wr);
5100
+ let e = localStorage.getItem(Kr);
4999
5101
  return e === "light" || e === "dark" || e === "system" ? e : void 0;
5000
5102
  } catch {
5001
5103
  return;
5002
5104
  }
5003
5105
  };
5004
- function Kr(e) {
5005
- let [t, n] = c(() => e ?? Gr()), [r, a] = c(!1);
5006
- return i(() => n(e ?? Gr()), [e]), i(() => {
5106
+ function Jr(e) {
5107
+ let [t, n] = c(() => e ?? qr()), [r, a] = c(!1);
5108
+ return i(() => n(e ?? qr()), [e]), i(() => {
5007
5109
  let e = (e) => {
5008
5110
  let t = e.detail?.theme;
5009
5111
  if (t === "light" || t === "dark" || t === "system") {
5010
5112
  try {
5011
- localStorage.setItem(Wr, t);
5113
+ localStorage.setItem(Kr, t);
5012
5114
  } catch {}
5013
5115
  n(t);
5014
5116
  }
@@ -5034,7 +5136,7 @@ function Kr(e) {
5034
5136
  }
5035
5137
  //#endregion
5036
5138
  //#region src/ChatIsland.tsx
5037
- function qr() {
5139
+ function Yr() {
5038
5140
  let e = Y.getState();
5039
5141
  return Object.values(e.conversations).map((t) => {
5040
5142
  let n = t.messages[t.messages.length - 1], r = e.contacts[t.peer];
@@ -5050,7 +5152,7 @@ function qr() {
5050
5152
  unread: t.unread,
5051
5153
  members: t.members,
5052
5154
  last: n ? {
5053
- body: Xr(n.body),
5155
+ body: Qr(n.body),
5054
5156
  ts: n.ts,
5055
5157
  mine: n.mine,
5056
5158
  oob: n.oob,
@@ -5059,7 +5161,7 @@ function qr() {
5059
5161
  };
5060
5162
  }).filter((e) => e.last || e.kind === "group").sort((e, t) => (t.last?.ts ?? 0) - (e.last?.ts ?? 0));
5061
5163
  }
5062
- var Jr = class extends t {
5164
+ var Xr = class extends t {
5063
5165
  state = { failed: !1 };
5064
5166
  failures = [];
5065
5167
  static getDerivedStateFromError() {
@@ -5077,7 +5179,7 @@ var Jr = class extends t {
5077
5179
  return this.state.failed ? null : this.props.children;
5078
5180
  }
5079
5181
  };
5080
- function Yr(e) {
5182
+ function Zr(e) {
5081
5183
  try {
5082
5184
  let [t, n, r] = atob(e).split(":");
5083
5185
  return t && n && r ? {
@@ -5089,8 +5191,8 @@ function Yr(e) {
5089
5191
  return null;
5090
5192
  }
5091
5193
  }
5092
- var Xr = (e) => (mr(e) ? "Attachment" : rr(e)).replace(/```[^\n]*\n?/g, "").replace(/(\*\*|__|~~|`)/g, "").replace(/(^|\s)[*_](\S[^*_]*)[*_]/g, "$1$2").replace(/\s+/g, " ").trim();
5093
- function Zr(e, t = !1) {
5194
+ var Qr = (e) => (mr(e) ? "Attachment" : rr(e)).replace(/```[^\n]*\n?/g, "").replace(/(\*\*|__|~~|`)/g, "").replace(/(^|\s)[*_](\S[^*_]*)[*_]/g, "$1$2").replace(/\s+/g, " ").trim();
5195
+ function $r(e, t = !1) {
5094
5196
  let [n, r] = c(e);
5095
5197
  return i(() => {
5096
5198
  if (e || t) return r(e);
@@ -5102,30 +5204,42 @@ function Zr(e, t = !1) {
5102
5204
  (t) => !e && t.target === t.currentTarget && r(e)
5103
5205
  ];
5104
5206
  }
5105
- function Qr({ dataConfig: e, position: t = "bottom-right", theme: n, serviceWorker: r, maxHeads: a = 5, newChatButton: l = !0, notifications: u = "click", sound: p = !0, drag: m = !0, onDragStart: h }) {
5106
- let g = o(() => Yr(e), [e]), [_, v] = Kr(n), y = s(g), b = s(p), x = s(u);
5107
- i(() => {
5108
- y.current = g, b.current = p, x.current = u;
5207
+ function ei({ dataConfig: e, position: t = "bottom-right", theme: n, serviceWorker: r, maxHeads: a = 5, newChatButton: l = !0, notifications: u = "click", sound: p = !0, drag: m = !0, onDragStart: h, headless: g = !1 }) {
5208
+ let _ = o(() => Zr(e), [e]), [v, y] = Jr(n), b = s(_), x = s(p), S = s(u), C = s(g);
5209
+ C.current = g, i(() => {
5210
+ b.current = _, x.current = p, S.current = u;
5109
5211
  }, [
5110
- g,
5212
+ _,
5111
5213
  p,
5112
5214
  u
5113
5215
  ]), i(() => Y.setState({
5114
5216
  maxHeads: a,
5115
5217
  newChatButton: l
5116
5218
  }), [a, l]);
5117
- let [S, C] = c(0);
5219
+ let [T, D] = c(0);
5118
5220
  i(() => {
5119
- let e = (e) => e.persisted && C((e) => e + 1);
5221
+ let e = (e) => e.persisted && D((e) => e + 1);
5120
5222
  return window.addEventListener("pageshow", e), () => window.removeEventListener("pageshow", e);
5121
5223
  }, []);
5122
- let T = s(null), D = s(/* @__PURE__ */ new Set()), O = s(!1), k = s(null), A = s(null), j = E(A, `chat-island-pos:${g?.host ?? ""}:${g?.username ?? ""}`), { open: M, picker: N, status: P } = Y(w((e) => ({
5224
+ let O = s(null), k = s(/* @__PURE__ */ new Set()), A = s(!1), j = s(null), M = s(null), N = E(M, `chat-island-pos:${_?.host ?? ""}:${_?.username ?? ""}`), { open: P, picker: F, status: ee } = Y(w((e) => ({
5123
5225
  open: e.open,
5124
5226
  picker: e.picker,
5125
5227
  status: e.status
5126
- }))), F = o(() => ({
5228
+ }))), I = o(() => ({
5229
+ seen: (e) => {
5230
+ let t = Y.getState().conversations[e];
5231
+ if (C.current || document.visibilityState !== "visible" || t?.kind !== "chat") return;
5232
+ let n = t.messages.findLast((e) => !e.mine && e.oid);
5233
+ !n || n.ts <= (t.myRead ?? 0) || (Y.setState((t) => ({ conversations: {
5234
+ ...t.conversations,
5235
+ [e]: {
5236
+ ...t.conversations[e],
5237
+ myRead: n.ts
5238
+ }
5239
+ } })), O.current?.marker(e, "displayed", n.oid).catch(() => {}));
5240
+ },
5127
5241
  send: async (e, t, n) => {
5128
- let r = T.current;
5242
+ let r = O.current;
5129
5243
  if (!r) throw Error("not connected");
5130
5244
  try {
5131
5245
  Y.getState().addMessage(e, await r.send(e, rr(t), void 0, n));
@@ -5136,9 +5250,9 @@ function Qr({ dataConfig: e, position: t = "bottom-right", theme: n, serviceWork
5136
5250
  }), e;
5137
5251
  }
5138
5252
  },
5139
- typing: (e, t) => Y.getState().online[e] && T.current?.typing(e, t).catch(() => {}),
5253
+ typing: (e, t) => Y.getState().online[e] && O.current?.typing(e, t).catch(() => {}),
5140
5254
  upload: async (e, t) => {
5141
- let n = T.current;
5255
+ let n = O.current;
5142
5256
  if (n) try {
5143
5257
  let r = await n.upload(t);
5144
5258
  Y.getState().addMessage(e, await n.send(e, t.name, r));
@@ -5150,7 +5264,7 @@ function Qr({ dataConfig: e, position: t = "bottom-right", theme: n, serviceWork
5150
5264
  }
5151
5265
  },
5152
5266
  createGroup: async (e, t, n) => {
5153
- let r = T.current, i = y.current;
5267
+ let r = O.current, i = b.current;
5154
5268
  if (r && i) try {
5155
5269
  let a = await r.createGroup(e, t, n), o = Y.getState();
5156
5270
  o.setGroup(a, e, [...t, i.username], n), o.openChat(a);
@@ -5162,7 +5276,7 @@ function Qr({ dataConfig: e, position: t = "bottom-right", theme: n, serviceWork
5162
5276
  }
5163
5277
  },
5164
5278
  remove: async (e) => {
5165
- let t = T.current, n = y.current;
5279
+ let t = O.current, n = b.current;
5166
5280
  if (!t || !n) return;
5167
5281
  let r = Y.getState().conversations[e];
5168
5282
  try {
@@ -5175,7 +5289,7 @@ function Qr({ dataConfig: e, position: t = "bottom-right", theme: n, serviceWork
5175
5289
  }
5176
5290
  },
5177
5291
  react: async (e, t, n) => {
5178
- let r = T.current, i = y.current?.username;
5292
+ let r = O.current, i = b.current?.username;
5179
5293
  if (!r || !i) return;
5180
5294
  let a = (Y.getState().conversations[e]?.reactions?.[t]?.[i] ?? []).includes(n) ? [] : [n];
5181
5295
  try {
@@ -5193,47 +5307,48 @@ function Qr({ dataConfig: e, position: t = "bottom-right", theme: n, serviceWork
5193
5307
  }
5194
5308
  },
5195
5309
  loadOlder: async (e) => {
5196
- let t = T.current, n = Y.getState().ensure(e);
5197
- if (!(!t || n.complete || D.current.has(e))) {
5198
- D.current.add(e);
5310
+ let t = O.current, n = Y.getState().ensure(e);
5311
+ if (!(!t || n.complete || k.current.has(e))) {
5312
+ k.current.add(e);
5199
5313
  try {
5200
5314
  let r = await t.history(e, n.oldest);
5201
- Y.getState().prependHistory(e, r.messages, r.complete, r.first), Y.getState().applyReactions(r.reactions);
5315
+ Y.getState().prependHistory(e, r.messages, r.complete, r.first), Y.getState().applyReactions(r.reactions), Y.getState().applyMarkers(r.markers);
5202
5316
  } catch (e) {
5203
5317
  X("chat-island-error", {
5204
5318
  scope: "history",
5205
5319
  message: e.message
5206
5320
  });
5207
5321
  } finally {
5208
- D.current.delete(e);
5322
+ k.current.delete(e);
5209
5323
  }
5210
5324
  }
5211
5325
  }
5212
5326
  }), []);
5213
5327
  i(() => {
5214
- if (!g) return;
5328
+ if (!_) return;
5215
5329
  let e = Y.getState();
5216
5330
  e.reset(), Y.setState({
5217
- me: g.username,
5331
+ me: _.username,
5218
5332
  mucHost: `conference.${hn}`,
5219
5333
  maxHeads: a,
5220
5334
  newChatButton: l
5221
5335
  });
5222
- let t = new _n(g, {
5336
+ let t = new _n(_, {
5223
5337
  status: (n, a) => {
5224
5338
  if (e.setStatus(n, a), X("chat-island-status", {
5225
5339
  status: n,
5226
5340
  error: a
5227
- }), n === "online" && r && !O.current && typeof Notification < "u") {
5341
+ }), n === "online" && r && !C.current && !A.current && typeof Notification < "u") {
5228
5342
  let e = Notification.permission;
5229
- (e === "granted" || x.current === "auto" && e === "default") && i();
5343
+ (e === "granted" || S.current === "auto" && e === "default") && i();
5230
5344
  }
5231
5345
  n === "online" && t.listGroups().then((t) => t.forEach((t) => e.setGroup(t.peer, t.name, t.members, t.avatar, t.owner))).catch(() => {}).then(() => t.recent()).then((e) => {
5232
- e && (Y.getState().seed(e.messages, g.username), Y.getState().applyReactions(e.reactions));
5346
+ e && (Y.getState().seed(e.messages, _.username), Y.getState().applyReactions(e.reactions), Y.getState().applyMarkers(e.markers));
5233
5347
  }).catch(() => {});
5234
5348
  },
5235
5349
  typing: (t, n) => e.setTyping(t, n),
5236
5350
  reaction: (t) => e.applyReactions([t]),
5351
+ marker: (t) => e.applyMarkers([t]),
5237
5352
  presence: (t, n) => e.setOnline(t, n),
5238
5353
  groupDestroyed: (t) => e.removeConversation(t),
5239
5354
  groupInvite: (n) => {
@@ -5248,13 +5363,13 @@ function Qr({ dataConfig: e, position: t = "bottom-right", theme: n, serviceWork
5248
5363
  r.room && !Y.getState().conversations[r.room]?.name && t.groupInfo(r.room).then((t) => e.setGroup(t.peer, t.name, t.members, t.avatar, t.owner)).catch(() => {}), e.addMessage(i, r, { live: !0 }), X("chat-island-message", {
5249
5364
  ...r,
5250
5365
  peer: i
5251
- }), X("chat-island-unread", { total: Y.getState().totalUnread() }), r.mine || n(i, r);
5366
+ }), X("chat-island-unread", { total: Y.getState().totalUnread() }), !r.mine && !r.room && r.oid && t.marker(i, "received", r.oid).catch(() => {}), !r.mine && !C.current && n(i, r);
5252
5367
  }
5253
5368
  }), n = (e, t) => {
5254
5369
  let n = Y.getState(), r = document.visibilityState === "visible";
5255
5370
  if (r && n.open === e) return;
5256
5371
  let i = n.conversations[e], a = i?.kind === "group" ? i.name ?? e : n.contacts[e]?.name ?? n.inactive[e] ?? e, o = t.oob ? "Attachment" : rr(t.body), s = i?.kind === "group", c = s && t.nick ? n.contacts[t.nick]?.name ?? t.nick : a, l = s && t.nick ? `${c}: ${o}` : o;
5257
- b.current && Cn();
5372
+ x.current && Cn();
5258
5373
  let u = s ? i?.avatar : n.contacts[e]?.avatar;
5259
5374
  if (X("chat-island-notify", {
5260
5375
  peer: e,
@@ -5276,18 +5391,18 @@ function Qr({ dataConfig: e, position: t = "bottom-right", theme: n, serviceWork
5276
5391
  };
5277
5392
  } catch {}
5278
5393
  };
5279
- T.current = t;
5394
+ O.current = t;
5280
5395
  let i = () => {
5281
- r && !O.current && (O.current = !0, Wn(g, r).then((e) => {
5396
+ r && !A.current && (A.current = !0, Wn(_, r).then((e) => {
5282
5397
  if (!e) {
5283
- O.current = !1, Y.setState({ push: Notification.permission === "denied" ? "denied" : "ask" });
5398
+ A.current = !1, Y.setState({ push: Notification.permission === "denied" ? "denied" : "ask" });
5284
5399
  return;
5285
5400
  }
5286
5401
  return t.enablePush(e.service, e.node).then(() => {
5287
- k.current = e, Y.setState({ push: "enabled" }), X("chat-island-push", { enabled: !0 });
5402
+ j.current = e, Y.setState({ push: "enabled" }), X("chat-island-push", { enabled: !0 });
5288
5403
  });
5289
5404
  }).catch((e) => {
5290
- O.current = !1, X("chat-island-error", {
5405
+ A.current = !1, X("chat-island-error", {
5291
5406
  scope: "push",
5292
5407
  message: e.message
5293
5408
  });
@@ -5300,75 +5415,81 @@ function Qr({ dataConfig: e, position: t = "bottom-right", theme: n, serviceWork
5300
5415
  let s = () => t.stop();
5301
5416
  window.addEventListener("pagehide", s), t.start();
5302
5417
  let c = () => {
5303
- Rn(g.host, g.token).then(e.setMobile).catch(() => {}), zn(g.host, g.token).then(e.setInactive).catch(() => {});
5418
+ Rn(_.host, _.token).then(e.setMobile).catch(() => {}), zn(_.host, _.token).then(e.setInactive).catch(() => {});
5304
5419
  };
5305
5420
  c();
5306
5421
  let u = window.setInterval(c, 12e4);
5307
- Ln(g.host, g.token, g.username, (e) => Y.setState({ myName: e })).then(e.setContacts).catch((e) => X("chat-island-error", {
5422
+ Ln(_.host, _.token, _.username, (e) => Y.setState({ myName: e })).then(e.setContacts).catch((e) => X("chat-island-error", {
5308
5423
  scope: "contacts",
5309
5424
  message: e.message
5310
5425
  }));
5311
- let d = Z("chat-island-open", ({ username: t }) => t && e.openChat(t)), f = Z("chat-island-close", () => e.closeChat()), p = Z("chat-island-new", () => e.setPicker(!0)), m = Z("chat-island-delete", ({ username: e }) => e && F.remove(e)), h = Z("chat-island-send", ({ username: e, text: t }) => e && t && F.send(e, t).catch(() => {})), _ = Z("chat-island-group-create", ({ name: e, members: t }) => e && t?.length && F.createGroup(e, t)), v = Z("chat-island-contacts", ({ contacts: t }) => t && e.setContacts(t)), y = Z("chat-island-conversations-request", () => X("chat-island-conversations", { conversations: qr() }));
5426
+ let d = Z("chat-island-open", ({ username: t }) => t && e.openChat(t)), f = Z("chat-island-close", () => e.closeChat()), p = Z("chat-island-new", () => e.setPicker(!0)), m = Z("chat-island-delete", ({ username: e }) => e && I.remove(e)), h = Z("chat-island-send", ({ username: e, text: t }) => e && t && I.send(e, t).catch(() => {})), g = Z("chat-island-group-create", ({ name: e, members: t }) => e && t?.length && I.createGroup(e, t)), v = Z("chat-island-contacts", ({ contacts: t }) => t && e.setContacts(t)), y = Z("chat-island-conversations-request", () => X("chat-island-conversations", { conversations: Yr() }));
5312
5427
  return () => {
5313
- window.removeEventListener("pagehide", s), window.clearInterval(u), y(), p(), m(), h(), _(), d(), f(), v(), k.current && t.disablePush(k.current.service, k.current.node).catch(() => {}), k.current = null, t.stop(), T.current = null, O.current = !1;
5428
+ window.removeEventListener("pagehide", s), window.clearInterval(u), y(), p(), m(), h(), g(), d(), f(), v(), j.current && t.disablePush(j.current.service, j.current.node).catch(() => {}), j.current = null, t.stop(), O.current = null, A.current = !1;
5314
5429
  };
5315
5430
  }, [
5316
- g,
5431
+ _,
5317
5432
  r,
5318
- S
5433
+ T
5319
5434
  ]);
5320
- let ee = Y((e) => Object.keys(e.contacts).join(","));
5435
+ let te = Y((e) => Object.keys(e.contacts).join(","));
5321
5436
  i(() => {
5322
- P === "online" && ee && T.current?.announce(ee.split(","));
5323
- }, [P, ee]);
5324
- let te = Y((e) => Object.values(e.conversations).map((e) => `${e.peer}:${e.kind}:${e.name ?? ""}:${(e.members ?? []).length}:${e.unread}:${e.messages[e.messages.length - 1]?.id ?? ""}`).join("|") + "#" + Object.keys(e.contacts).length + "#" + Object.values(e.online).filter(Boolean).length + "#" + Object.keys(e.inactive).length);
5325
- i(() => X("chat-island-conversations", { conversations: qr() }), [te]);
5326
- let ne = Y((e) => Object.values(e.conversations).reduce((e, t) => e + t.unread, 0));
5327
- i(() => X("chat-island-unread", { total: ne }), [ne]);
5328
- let re = s(null), ie = s(M), I = s(null), L = !N && !!M && M !== ie.current && !!re.current;
5329
- L && (I.current = re.current.offsetHeight), i(() => {
5330
- ie.current = M, M || (I.current = null);
5331
- }, [M]);
5332
- let [ae, oe, se] = Zr(M), [ce, le, R] = Zr(N, L);
5333
- if (!g) return null;
5334
- let ue = m && !h && j.anchor ? {
5335
- right: j.anchor.right,
5336
- bottom: j.anchor.bottom
5337
- } : void 0, de = ue ? "" : t === "bottom-left" ? "ci-left-4 ci-bottom-5" : "ci-right-4 ci-bottom-5";
5437
+ ee === "online" && te && O.current?.announce(te.split(","));
5438
+ }, [ee, te]);
5439
+ let ne = Y((e) => Object.values(e.conversations).map((e) => `${e.peer}:${e.kind}:${e.name ?? ""}:${(e.members ?? []).length}:${e.unread}:${e.messages[e.messages.length - 1]?.id ?? ""}`).join("|") + "#" + Object.keys(e.contacts).length + "#" + Object.values(e.online).filter(Boolean).length + "#" + Object.keys(e.inactive).length);
5440
+ i(() => X("chat-island-conversations", { conversations: Yr() }), [ne]);
5441
+ let re = Y((e) => Object.values(e.conversations).reduce((e, t) => e + t.unread, 0));
5442
+ i(() => X("chat-island-unread", { total: re }), [re]), i(() => {
5443
+ let e = () => {
5444
+ let e = Y.getState().open;
5445
+ document.visibilityState === "visible" && e && I.seen(e);
5446
+ };
5447
+ return document.addEventListener("visibilitychange", e), () => document.removeEventListener("visibilitychange", e);
5448
+ }, [I]);
5449
+ let ie = s(null), L = s(P), ae = s(null), oe = !F && !!P && P !== L.current && !!ie.current;
5450
+ oe && (ae.current = ie.current.offsetHeight), i(() => {
5451
+ L.current = P, P || (ae.current = null);
5452
+ }, [P]);
5453
+ let [se, ce, le] = $r(P), [R, ue, de] = $r(F, oe);
5454
+ if (!_ || g) return null;
5455
+ let fe = m && !h && N.anchor ? {
5456
+ right: N.anchor.right,
5457
+ bottom: N.anchor.bottom
5458
+ } : void 0, z = fe ? "" : t === "bottom-left" ? "ci-left-4 ci-bottom-5" : "ci-right-4 ci-bottom-5";
5338
5459
  return /* @__PURE__ */ d("div", {
5339
- ref: A,
5340
- style: ue,
5341
- onClickCapture: j.onClickCapture,
5342
- className: `chat-island-root ${_ ? "ci-dark" : ""} ci-fixed ${de} ci-z-[9999] ci-flex ci-items-end ci-gap-3 ci-font-sans ci-select-none`,
5343
- "data-status": P,
5344
- children: /* @__PURE__ */ f(Jr, { children: [
5345
- ae && /* @__PURE__ */ d("div", {
5346
- className: oe ? "ci-anim-close" : I.current ? "ci-anim-morph" : "ci-anim-open",
5347
- style: I.current ? { "--ci-from": `${I.current}px` } : void 0,
5348
- onAnimationEnd: se,
5349
- children: /* @__PURE__ */ d(zr, {
5350
- peer: ae,
5351
- actions: F,
5352
- theme: v,
5353
- onDragStart: h ?? (m ? j.start : void 0)
5460
+ ref: M,
5461
+ style: fe,
5462
+ onClickCapture: N.onClickCapture,
5463
+ className: `chat-island-root ${v ? "ci-dark" : ""} ci-fixed ${z} ci-z-[9999] ci-flex ci-items-end ci-gap-3 ci-font-sans ci-select-none`,
5464
+ "data-status": ee,
5465
+ children: /* @__PURE__ */ f(Xr, { children: [
5466
+ se && /* @__PURE__ */ d("div", {
5467
+ className: ce ? "ci-anim-close" : ae.current ? "ci-anim-morph" : "ci-anim-open",
5468
+ style: ae.current ? { "--ci-from": `${ae.current}px` } : void 0,
5469
+ onAnimationEnd: le,
5470
+ children: /* @__PURE__ */ d(Vr, {
5471
+ peer: se,
5472
+ actions: I,
5473
+ theme: y,
5474
+ onDragStart: h ?? (m ? N.start : void 0)
5354
5475
  })
5355
5476
  }),
5356
- ce && /* @__PURE__ */ d("div", {
5357
- ref: re,
5358
- className: le ? "ci-anim-close" : "ci-anim-open",
5359
- onAnimationEnd: R,
5360
- children: /* @__PURE__ */ d(Ur, {
5477
+ R && /* @__PURE__ */ d("div", {
5478
+ ref: ie,
5479
+ className: ue ? "ci-anim-close" : "ci-anim-open",
5480
+ onAnimationEnd: de,
5481
+ children: /* @__PURE__ */ d(Gr, {
5361
5482
  onOpen: (e) => Y.getState().openChat(e),
5362
- onCreateGroup: F.createGroup,
5363
- onDragStart: h ?? (m ? j.start : void 0)
5483
+ onCreateGroup: I.createGroup,
5484
+ onDragStart: h ?? (m ? N.start : void 0)
5364
5485
  })
5365
5486
  }),
5366
5487
  /* @__PURE__ */ d(Zn, {
5367
- onDragStart: h ?? (m ? j.start : void 0),
5488
+ onDragStart: h ?? (m ? N.start : void 0),
5368
5489
  pushButton: u !== "auto"
5369
5490
  })
5370
5491
  ] })
5371
5492
  });
5372
5493
  }
5373
5494
  //#endregion
5374
- export { Qr as ChatIsland, Fn as contactsFromOperators };
5495
+ export { ei as ChatIsland, Fn as contactsFromOperators };