@linktr.ee/messaging-react 1.12.2-rc-1765340127 → 1.12.2-rc-1765342563
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 +61 -58
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/MessagingShell/index.tsx +3 -0
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import k from "classnames";
|
|
|
3
3
|
import O, { createContext as Ue, useContext as Pe, useCallback as _, useState as E, useRef as z, useEffect as $ } from "react";
|
|
4
4
|
import { StreamChatService as je } from "@linktr.ee/messaging-core";
|
|
5
5
|
import { Chat as Ae, ChannelList as ze, useMessageComposer as Be, useStateStore as Ge, MessageInput as $e, useMessageInputContext as He, useMessageComposerHasSendableData as Ve, SimpleAttachmentSelector as We, QuotedMessagePreview as Ze, AttachmentPreviewList as qe, TextareaComposer as Ye, MessageTimestamp as Je, Channel as Qe, useChannelStateContext as ve, Window as Xe, MessageList as Ke } from "stream-chat-react";
|
|
6
|
-
import { XIcon as
|
|
6
|
+
import { XIcon as me, ArrowUpIcon as es, ArrowLeftIcon as fe, DotsThreeIcon as ge, SpinnerGapIcon as re, SignOutIcon as ss, ProhibitInsetIcon as xe, FlagIcon as ts, MagnifyingGlassIcon as ns, ChatCircleDotsIcon as Ne } from "@phosphor-icons/react";
|
|
7
7
|
import { LinkPreviewsManager as Ce } from "stream-chat";
|
|
8
8
|
const ye = Ue({
|
|
9
9
|
service: null,
|
|
@@ -15,7 +15,7 @@ const ye = Ue({
|
|
|
15
15
|
refreshConnection: async () => {
|
|
16
16
|
},
|
|
17
17
|
debug: !1
|
|
18
|
-
}),
|
|
18
|
+
}), ae = () => Pe(ye), _s = ({
|
|
19
19
|
children: t,
|
|
20
20
|
user: s,
|
|
21
21
|
serviceConfig: n,
|
|
@@ -216,7 +216,7 @@ const ye = Ue({
|
|
|
216
216
|
children: t
|
|
217
217
|
}
|
|
218
218
|
) : t });
|
|
219
|
-
}, rs = () =>
|
|
219
|
+
}, rs = () => ae(), ls = (t, s) => {
|
|
220
220
|
const n = new Date(
|
|
221
221
|
Date.UTC(t.getUTCFullYear(), t.getUTCMonth(), t.getUTCDate())
|
|
222
222
|
), o = new Date(
|
|
@@ -396,7 +396,7 @@ const Ie = O.memo(
|
|
|
396
396
|
}) => {
|
|
397
397
|
const d = O.useRef(0);
|
|
398
398
|
d.current++;
|
|
399
|
-
const { debug: l = !1 } =
|
|
399
|
+
const { debug: l = !1 } = ae();
|
|
400
400
|
l && console.log("📺 [ChannelList] 🔄 RENDER START", {
|
|
401
401
|
renderCount: d.current,
|
|
402
402
|
selectedChannelId: s == null ? void 0 : s.id,
|
|
@@ -474,7 +474,7 @@ function Se({ label: t, className: s, children: n, ...r }) {
|
|
|
474
474
|
);
|
|
475
475
|
}
|
|
476
476
|
function pe({ onClick: t }) {
|
|
477
|
-
return /* @__PURE__ */ e(Se, { label: "Close", onClick: t, className: "p-1", children: /* @__PURE__ */ e(
|
|
477
|
+
return /* @__PURE__ */ e(Se, { label: "Close", onClick: t, className: "p-1", children: /* @__PURE__ */ e(me, { className: "h-5 w-5 text-stone", weight: "bold" }) });
|
|
478
478
|
}
|
|
479
479
|
const cs = (t) => ({
|
|
480
480
|
linkPreviews: Array.from(t.previews.values()).filter(
|
|
@@ -510,7 +510,7 @@ const cs = (t) => ({
|
|
|
510
510
|
},
|
|
511
511
|
className: "absolute right-4 top-4 flex size-6 items-center justify-center rounded-full border border-white/40 bg-white/70 backdrop-blur-2xl",
|
|
512
512
|
"aria-label": "Close link preview",
|
|
513
|
-
children: /* @__PURE__ */ e(
|
|
513
|
+
children: /* @__PURE__ */ e(me, { className: "size-4 text-black/90" })
|
|
514
514
|
}
|
|
515
515
|
),
|
|
516
516
|
/* @__PURE__ */ i("div", { className: "p-2", children: [
|
|
@@ -624,11 +624,11 @@ const cs = (t) => ({
|
|
|
624
624
|
s && /* @__PURE__ */ e("span", { className: "text-stone", children: s })
|
|
625
625
|
]
|
|
626
626
|
}
|
|
627
|
-
),
|
|
627
|
+
), oe = O.memo(() => (console.log("[LoadingState] render - showing loading spinner"), /* @__PURE__ */ e("div", { className: "messaging-loading-state flex items-center justify-center h-full", children: /* @__PURE__ */ i("div", { className: "flex items-center", children: [
|
|
628
628
|
/* @__PURE__ */ e(xs, { className: "w-6 h-6" }),
|
|
629
629
|
/* @__PURE__ */ e("span", { className: "text-sm text-stone", children: "Loading messages" })
|
|
630
630
|
] }) })));
|
|
631
|
-
|
|
631
|
+
oe.displayName = "LoadingState";
|
|
632
632
|
const Ns = ({ onBack: t, showBackButton: s, onShowInfo: n, canShowInfo: r }) => {
|
|
633
633
|
var h, g, v, f, S;
|
|
634
634
|
const { channel: o } = ve(), d = O.useMemo(() => Object.values(o.state.members || {}).find(
|
|
@@ -726,8 +726,8 @@ const Ns = ({ onBack: t, showBackButton: s, onShowInfo: n, canShowInfo: r }) =>
|
|
|
726
726
|
onBlockParticipantClick: g,
|
|
727
727
|
onReportParticipantClick: v
|
|
728
728
|
}) => {
|
|
729
|
-
var Q, X,
|
|
730
|
-
const { service: f, debug: S } =
|
|
729
|
+
var Q, X, ce, U, H, V, G;
|
|
730
|
+
const { service: f, debug: S } = ae(), [R, w] = E(!1), [c, x] = E(!1), [y, I] = E(!1), M = _(async () => {
|
|
731
731
|
var D;
|
|
732
732
|
if (!(!f || !((D = n == null ? void 0 : n.user) != null && D.id)))
|
|
733
733
|
try {
|
|
@@ -738,10 +738,10 @@ const Ns = ({ onBack: t, showBackButton: s, onShowInfo: n, canShowInfo: r }) =>
|
|
|
738
738
|
}
|
|
739
739
|
);
|
|
740
740
|
w(A);
|
|
741
|
-
} catch (
|
|
741
|
+
} catch (F) {
|
|
742
742
|
console.error(
|
|
743
743
|
"[ChannelInfoDialog] Failed to check blocked status:",
|
|
744
|
-
|
|
744
|
+
F
|
|
745
745
|
);
|
|
746
746
|
}
|
|
747
747
|
}, [f, (Q = n == null ? void 0 : n.user) == null ? void 0 : Q.id]);
|
|
@@ -753,20 +753,20 @@ const Ns = ({ onBack: t, showBackButton: s, onShowInfo: n, canShowInfo: r }) =>
|
|
|
753
753
|
if (!c) {
|
|
754
754
|
h == null || h(), S && console.log("[ChannelInfoDialog] Leave conversation", r.cid), x(!0);
|
|
755
755
|
try {
|
|
756
|
-
const
|
|
757
|
-
await r.hide(
|
|
758
|
-
} catch (
|
|
759
|
-
console.error("[ChannelInfoDialog] Failed to leave conversation",
|
|
756
|
+
const F = ((D = r._client) == null ? void 0 : D.userID) ?? null;
|
|
757
|
+
await r.hide(F, !1), d && await d(r), s();
|
|
758
|
+
} catch (F) {
|
|
759
|
+
console.error("[ChannelInfoDialog] Failed to leave conversation", F);
|
|
760
760
|
} finally {
|
|
761
761
|
x(!1);
|
|
762
762
|
}
|
|
763
763
|
}
|
|
764
764
|
}, p = async () => {
|
|
765
|
-
var D,
|
|
765
|
+
var D, F, A;
|
|
766
766
|
if (!(y || !f)) {
|
|
767
767
|
g == null || g(), S && console.log("[ChannelInfoDialog] Block member", (D = n == null ? void 0 : n.user) == null ? void 0 : D.id), I(!0);
|
|
768
768
|
try {
|
|
769
|
-
await f.blockUser((
|
|
769
|
+
await f.blockUser((F = n == null ? void 0 : n.user) == null ? void 0 : F.id), l && await l((A = n == null ? void 0 : n.user) == null ? void 0 : A.id), s();
|
|
770
770
|
} catch (W) {
|
|
771
771
|
console.error("[ChannelInfoDialog] Failed to block member", W);
|
|
772
772
|
} finally {
|
|
@@ -774,11 +774,11 @@ const Ns = ({ onBack: t, showBackButton: s, onShowInfo: n, canShowInfo: r }) =>
|
|
|
774
774
|
}
|
|
775
775
|
}
|
|
776
776
|
}, a = async () => {
|
|
777
|
-
var D,
|
|
777
|
+
var D, F, A;
|
|
778
778
|
if (!(y || !f)) {
|
|
779
779
|
g == null || g(), S && console.log("[ChannelInfoDialog] Unblock member", (D = n == null ? void 0 : n.user) == null ? void 0 : D.id), I(!0);
|
|
780
780
|
try {
|
|
781
|
-
await f.unBlockUser((
|
|
781
|
+
await f.unBlockUser((F = n == null ? void 0 : n.user) == null ? void 0 : F.id), l && await l((A = n == null ? void 0 : n.user) == null ? void 0 : A.id), s();
|
|
782
782
|
} catch (W) {
|
|
783
783
|
console.error("[ChannelInfoDialog] Failed to unblock member", W);
|
|
784
784
|
} finally {
|
|
@@ -793,7 +793,7 @@ const Ns = ({ onBack: t, showBackButton: s, onShowInfo: n, canShowInfo: r }) =>
|
|
|
793
793
|
);
|
|
794
794
|
};
|
|
795
795
|
if (!n) return null;
|
|
796
|
-
const C = ((X = n.user) == null ? void 0 : X.name) || ((
|
|
796
|
+
const C = ((X = n.user) == null ? void 0 : X.name) || ((ce = n.user) == null ? void 0 : ce.id) || "Unknown member", B = (U = n.user) == null ? void 0 : U.image, j = (H = n.user) == null ? void 0 : H.email, Z = (V = n.user) == null ? void 0 : V.username, J = j || (Z ? `linktr.ee/${Z}` : void 0), ie = ((G = n.user) == null ? void 0 : G.id) || "unknown";
|
|
797
797
|
return (
|
|
798
798
|
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions
|
|
799
799
|
/* @__PURE__ */ e(
|
|
@@ -820,7 +820,7 @@ const Ns = ({ onBack: t, showBackButton: s, onShowInfo: n, canShowInfo: r }) =>
|
|
|
820
820
|
/* @__PURE__ */ e(
|
|
821
821
|
Y,
|
|
822
822
|
{
|
|
823
|
-
id:
|
|
823
|
+
id: ie,
|
|
824
824
|
name: C,
|
|
825
825
|
image: B,
|
|
826
826
|
size: 88,
|
|
@@ -999,7 +999,7 @@ const Ns = ({ onBack: t, showBackButton: s, onShowInfo: n, canShowInfo: r }) =>
|
|
|
999
999
|
channel: t,
|
|
1000
1000
|
MessageSystem: fs,
|
|
1001
1001
|
EmptyStateIndicator: m,
|
|
1002
|
-
LoadingIndicator:
|
|
1002
|
+
LoadingIndicator: oe,
|
|
1003
1003
|
children: /* @__PURE__ */ e(
|
|
1004
1004
|
bs,
|
|
1005
1005
|
{
|
|
@@ -1056,7 +1056,7 @@ function ws({
|
|
|
1056
1056
|
s(""), (o = r.current) == null || o.focus();
|
|
1057
1057
|
},
|
|
1058
1058
|
className: "absolute right-3 top-1/2 -translate-y-1/2 p-1 text-stone hover:text-charcoal",
|
|
1059
|
-
children: /* @__PURE__ */ e(
|
|
1059
|
+
children: /* @__PURE__ */ e(me, { className: "h-4 w-4", weight: "bold" })
|
|
1060
1060
|
}
|
|
1061
1061
|
)
|
|
1062
1062
|
] });
|
|
@@ -1070,7 +1070,7 @@ const vs = ({
|
|
|
1070
1070
|
searchPlaceholder: d = "Search participants...",
|
|
1071
1071
|
className: l
|
|
1072
1072
|
}) => {
|
|
1073
|
-
const { debug: m } =
|
|
1073
|
+
const { debug: m } = ae(), [h, g] = E(""), [v, f] = E([]), [S, R] = E(!1), [w, c] = E(null), [x, y] = E(
|
|
1074
1074
|
null
|
|
1075
1075
|
), I = z(!1);
|
|
1076
1076
|
$(() => {
|
|
@@ -1357,7 +1357,7 @@ const le = O.memo(({ message: t, onBack: s }) => /* @__PURE__ */ e("div", { clas
|
|
|
1357
1357
|
)
|
|
1358
1358
|
] }) }));
|
|
1359
1359
|
le.displayName = "ErrorState";
|
|
1360
|
-
const
|
|
1360
|
+
const Ts = ({
|
|
1361
1361
|
capabilities: t = {},
|
|
1362
1362
|
className: s,
|
|
1363
1363
|
renderMessageInputActions: n,
|
|
@@ -1381,8 +1381,8 @@ const Fs = ({
|
|
|
1381
1381
|
error: I,
|
|
1382
1382
|
refreshConnection: M,
|
|
1383
1383
|
debug: N
|
|
1384
|
-
} = rs(), [p, a] = E(null), [u, C] = E(!1), [B, j] = E(!1), [Z, J] = E(!1), [
|
|
1385
|
-
participantSource:
|
|
1384
|
+
} = rs(), [p, a] = E(null), [u, C] = E(!1), [B, j] = E(!1), [Z, J] = E(!1), [ie, Q] = E(/* @__PURE__ */ new Set()), [X, ce] = E(0), [U, H] = E(!1), [V, G] = E(null), D = z(null), {
|
|
1385
|
+
participantSource: F,
|
|
1386
1386
|
participantLabel: A = "participants",
|
|
1387
1387
|
showDeleteConversation: W = !0
|
|
1388
1388
|
} = t, K = O.useMemo(() => {
|
|
@@ -1411,17 +1411,17 @@ const Fs = ({
|
|
|
1411
1411
|
},
|
|
1412
1412
|
{},
|
|
1413
1413
|
{ limit: 100 }
|
|
1414
|
-
),
|
|
1414
|
+
), T = /* @__PURE__ */ new Set();
|
|
1415
1415
|
P.forEach((L) => {
|
|
1416
|
-
const
|
|
1417
|
-
Object.values(
|
|
1416
|
+
const de = L.state.members;
|
|
1417
|
+
Object.values(de).forEach((Oe) => {
|
|
1418
1418
|
var he;
|
|
1419
|
-
const
|
|
1420
|
-
|
|
1419
|
+
const ue = (he = Oe.user) == null ? void 0 : he.id;
|
|
1420
|
+
ue && ue !== b && T.add(ue);
|
|
1421
1421
|
});
|
|
1422
|
-
}), Q((L) => L.size ===
|
|
1422
|
+
}), Q((L) => L.size === T.size && [...L].every((de) => T.has(de)) ? L : T), C(P.length > 0), j(!0), ee.current = b, N && console.log("[MessagingShell] Channels synced successfully:", {
|
|
1423
1423
|
channelCount: P.length,
|
|
1424
|
-
memberCount:
|
|
1424
|
+
memberCount: T.size
|
|
1425
1425
|
});
|
|
1426
1426
|
} catch (P) {
|
|
1427
1427
|
console.error("[MessagingShell] Failed to sync channels:", P);
|
|
@@ -1441,7 +1441,7 @@ const Fs = ({
|
|
|
1441
1441
|
"[MessagingShell] Loading initial conversation with:",
|
|
1442
1442
|
d
|
|
1443
1443
|
);
|
|
1444
|
-
const
|
|
1444
|
+
const T = await c.queryChannels(
|
|
1445
1445
|
{
|
|
1446
1446
|
type: "messaging",
|
|
1447
1447
|
members: { $eq: [P, d] }
|
|
@@ -1449,10 +1449,10 @@ const Fs = ({
|
|
|
1449
1449
|
{},
|
|
1450
1450
|
{ limit: 1 }
|
|
1451
1451
|
);
|
|
1452
|
-
if (
|
|
1453
|
-
a(
|
|
1452
|
+
if (T.length > 0)
|
|
1453
|
+
a(T[0]), H(!0), G(null), r && r(T[0]), N && console.log(
|
|
1454
1454
|
"[MessagingShell] Initial conversation loaded:",
|
|
1455
|
-
|
|
1455
|
+
T[0].id
|
|
1456
1456
|
);
|
|
1457
1457
|
else if (l && w) {
|
|
1458
1458
|
N && console.log(
|
|
@@ -1483,10 +1483,10 @@ const Fs = ({
|
|
|
1483
1483
|
"[MessagingShell] No conversation found for:",
|
|
1484
1484
|
d
|
|
1485
1485
|
);
|
|
1486
|
-
} catch (
|
|
1486
|
+
} catch (T) {
|
|
1487
1487
|
console.error(
|
|
1488
1488
|
"[MessagingShell] Failed to load initial conversation:",
|
|
1489
|
-
|
|
1489
|
+
T
|
|
1490
1490
|
), G("Failed to load conversation");
|
|
1491
1491
|
}
|
|
1492
1492
|
})();
|
|
@@ -1515,32 +1515,32 @@ const Fs = ({
|
|
|
1515
1515
|
"[MessagingShell] Starting conversation with:",
|
|
1516
1516
|
b.id
|
|
1517
1517
|
);
|
|
1518
|
-
const
|
|
1518
|
+
const T = await w.startChannelWithParticipant({
|
|
1519
1519
|
id: b.id,
|
|
1520
1520
|
name: b.name,
|
|
1521
1521
|
email: b.email,
|
|
1522
1522
|
phone: b.phone
|
|
1523
1523
|
});
|
|
1524
1524
|
try {
|
|
1525
|
-
await
|
|
1525
|
+
await T.show();
|
|
1526
1526
|
} catch (L) {
|
|
1527
1527
|
console.warn("[MessagingShell] Failed to unhide channel:", L);
|
|
1528
1528
|
}
|
|
1529
|
-
a(
|
|
1530
|
-
} catch (
|
|
1531
|
-
console.error("[MessagingShell] Failed to start conversation:",
|
|
1529
|
+
a(T), J(!1), (P = D.current) == null || P.close(), o == null || o(b);
|
|
1530
|
+
} catch (T) {
|
|
1531
|
+
console.error("[MessagingShell] Failed to start conversation:", T);
|
|
1532
1532
|
}
|
|
1533
1533
|
},
|
|
1534
1534
|
[w, o, N]
|
|
1535
1535
|
), se = _(() => {
|
|
1536
1536
|
var b;
|
|
1537
1537
|
J(!1), (b = D.current) == null || b.close();
|
|
1538
|
-
}, []),
|
|
1538
|
+
}, []), Te = _(
|
|
1539
1539
|
(b) => {
|
|
1540
1540
|
b.target === D.current && se();
|
|
1541
1541
|
},
|
|
1542
1542
|
[se]
|
|
1543
|
-
),
|
|
1543
|
+
), Fe = _(
|
|
1544
1544
|
async (b) => {
|
|
1545
1545
|
N && console.log("[MessagingShell] Leaving conversation:", b.id), a(null), H(!1), ee.current = null, await q();
|
|
1546
1546
|
},
|
|
@@ -1559,7 +1559,7 @@ const Fs = ({
|
|
|
1559
1559
|
directConversationError: V,
|
|
1560
1560
|
selectedChannelId: p == null ? void 0 : p.id,
|
|
1561
1561
|
directConversationMode: U
|
|
1562
|
-
}), y ? (console.log("[MessagingShell] showing LOADING state"), /* @__PURE__ */ e("div", { className: k("h-full", s), children: /* @__PURE__ */ e(
|
|
1562
|
+
}), y ? (console.log("[MessagingShell] showing LOADING state"), /* @__PURE__ */ e("div", { className: k("h-full", s), children: /* @__PURE__ */ e(oe, {}) })) : I ? (console.log("[MessagingShell] showing ERROR state:", I), /* @__PURE__ */ e("div", { className: k("h-full", s), children: /* @__PURE__ */ e(le, { message: I, onBack: M }) })) : !x || !c ? (console.log("[MessagingShell] showing NOT CONNECTED state"), /* @__PURE__ */ e("div", { className: k("h-full", s), children: /* @__PURE__ */ e(
|
|
1563
1563
|
le,
|
|
1564
1564
|
{
|
|
1565
1565
|
message: "Not connected to messaging service",
|
|
@@ -1617,7 +1617,7 @@ const Fs = ({
|
|
|
1617
1617
|
onBack: De,
|
|
1618
1618
|
showBackButton: !U,
|
|
1619
1619
|
renderMessageInputActions: n,
|
|
1620
|
-
onLeaveConversation:
|
|
1620
|
+
onLeaveConversation: Fe,
|
|
1621
1621
|
onBlockParticipant: Le,
|
|
1622
1622
|
CustomChannelEmptyState: m,
|
|
1623
1623
|
showDeleteConversation: W,
|
|
@@ -1626,7 +1626,10 @@ const Fs = ({
|
|
|
1626
1626
|
onReportParticipantClick: R
|
|
1627
1627
|
},
|
|
1628
1628
|
p.id
|
|
1629
|
-
) }) :
|
|
1629
|
+
) }) : d ? (
|
|
1630
|
+
// Show loading while creating/loading direct conversation channel
|
|
1631
|
+
/* @__PURE__ */ e(oe, {})
|
|
1632
|
+
) : /* @__PURE__ */ e(
|
|
1630
1633
|
Re,
|
|
1631
1634
|
{
|
|
1632
1635
|
hasChannels: u,
|
|
@@ -1636,21 +1639,21 @@ const Fs = ({
|
|
|
1636
1639
|
}
|
|
1637
1640
|
)
|
|
1638
1641
|
] }),
|
|
1639
|
-
|
|
1642
|
+
F && // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions
|
|
1640
1643
|
/* @__PURE__ */ e(
|
|
1641
1644
|
"dialog",
|
|
1642
1645
|
{
|
|
1643
1646
|
ref: D,
|
|
1644
1647
|
className: "mes-dialog",
|
|
1645
|
-
onClick:
|
|
1648
|
+
onClick: Te,
|
|
1646
1649
|
onClose: se,
|
|
1647
1650
|
children: /* @__PURE__ */ e("div", { className: "h-full w-full bg-white shadow-max-elevation-light", children: /* @__PURE__ */ e(
|
|
1648
1651
|
vs,
|
|
1649
1652
|
{
|
|
1650
|
-
participantSource:
|
|
1653
|
+
participantSource: F,
|
|
1651
1654
|
onSelectParticipant: _e,
|
|
1652
1655
|
onClose: se,
|
|
1653
|
-
existingParticipantIds:
|
|
1656
|
+
existingParticipantIds: ie,
|
|
1654
1657
|
participantLabel: A,
|
|
1655
1658
|
searchPlaceholder: `Search ${A}...`
|
|
1656
1659
|
},
|
|
@@ -1683,7 +1686,7 @@ const Fs = ({
|
|
|
1683
1686
|
),
|
|
1684
1687
|
children: t
|
|
1685
1688
|
}
|
|
1686
|
-
),
|
|
1689
|
+
), Fs = ({
|
|
1687
1690
|
faqs: t,
|
|
1688
1691
|
onFaqClick: s,
|
|
1689
1692
|
loadingFaqId: n,
|
|
@@ -1770,10 +1773,10 @@ export {
|
|
|
1770
1773
|
gs as ChannelEmptyState,
|
|
1771
1774
|
Ie as ChannelList,
|
|
1772
1775
|
ke as ChannelView,
|
|
1773
|
-
|
|
1776
|
+
Fs as FaqList,
|
|
1774
1777
|
Es as FaqListItem,
|
|
1775
1778
|
_s as MessagingProvider,
|
|
1776
|
-
|
|
1779
|
+
Ts as MessagingShell,
|
|
1777
1780
|
vs as ParticipantPicker,
|
|
1778
1781
|
os as formatRelativeTime,
|
|
1779
1782
|
rs as useMessaging,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/providers/MessagingProvider.tsx","../src/hooks/useMessaging.ts","../src/utils/formatRelativeTime.ts","../src/components/Avatar/getAvatarEmoji.ts","../src/components/Avatar/index.tsx","../src/components/ChannelList/CustomChannelPreview.tsx","../src/components/ChannelList/index.tsx","../src/components/ActionButton/index.tsx","../src/components/IconButton/index.tsx","../src/components/CloseButton/index.tsx","../src/components/CustomLinkPreviewList/index.tsx","../src/components/CustomMessageInput/index.tsx","../src/components/CustomSystemMessage/index.tsx","../src/components/MessagingShell/ChannelEmptyState.tsx","../src/components/Loading/index.tsx","../src/components/MessagingShell/LoadingState.tsx","../src/components/ChannelView.tsx","../src/components/SearchInput/index.tsx","../src/components/ParticipantPicker/index.tsx","../src/components/MessagingShell/EmptyState.tsx","../src/components/MessagingShell/ErrorState.tsx","../src/components/MessagingShell/index.tsx","../src/components/FaqList/FaqListItem.tsx","../src/components/FaqList/index.tsx","../src/hooks/useParticipants.ts"],"sourcesContent":["import { StreamChatService } from '@linktr.ee/messaging-core'\nimport React, {\n createContext,\n useContext,\n useEffect,\n useState,\n useRef,\n useCallback,\n} from 'react'\nimport type { StreamChat } from 'stream-chat'\nimport { Chat } from 'stream-chat-react'\n\nimport type { MessagingProviderProps, MessagingCapabilities } from '../types'\n\n/**\n * Context value for messaging state and service\n */\nexport interface MessagingContextValue {\n service: StreamChatService | null\n client: StreamChat | null // Stream Chat client\n isConnected: boolean\n isLoading: boolean\n error: string | null\n capabilities: MessagingCapabilities\n refreshConnection: () => Promise<void>\n debug: boolean\n}\n\nconst MessagingContext = createContext<MessagingContextValue>({\n service: null,\n client: null,\n isConnected: false,\n isLoading: false,\n error: null,\n capabilities: {},\n refreshConnection: async () => {},\n debug: false,\n})\n\n/**\n * Hook to access messaging context\n */\nexport const useMessagingContext = () => useContext(MessagingContext)\n\n/**\n * Provider component that wraps messaging-core with React state management\n */\nexport const MessagingProvider: React.FC<MessagingProviderProps> = ({\n children,\n user,\n serviceConfig,\n apiKey,\n capabilities = {},\n debug = false,\n}) => {\n // Create debug logger that respects the debug prop\n const debugLog = useCallback(\n (message: string, ...args: unknown[]) => {\n if (debug) {\n console.log(`🔥 [MessagingProvider] ${message}`, ...args)\n }\n },\n [debug]\n )\n\n debugLog('🔄 RENDER START', {\n userId: user?.id,\n apiKey: apiKey?.substring(0, 8) + '...',\n serviceConfig: !!serviceConfig,\n capabilities: Object.keys(capabilities),\n })\n\n const [service, setService] = useState<StreamChatService | null>(null)\n const [client, setClient] = useState<StreamChat | null>(null)\n const [isConnected, setIsConnected] = useState(false)\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n // Prevent multiple concurrent connection attempts\n const connectingRef = useRef(false)\n\n // Track renders and prop changes\n const prevPropsRef = useRef({\n userId: user?.id,\n apiKey,\n serviceConfig,\n capabilities,\n })\n const renderCountRef = useRef(0)\n renderCountRef.current++\n\n debugLog('📊 RENDER INFO', {\n renderCount: renderCountRef.current,\n currentProps: { userId: user?.id, apiKey: apiKey?.substring(0, 8) + '...' },\n propChanges: {\n userChanged: prevPropsRef.current.userId !== user?.id,\n apiKeyChanged: prevPropsRef.current.apiKey !== apiKey,\n serviceConfigChanged:\n prevPropsRef.current.serviceConfig !== serviceConfig,\n capabilitiesChanged: prevPropsRef.current.capabilities !== capabilities,\n },\n })\n\n prevPropsRef.current = {\n userId: user?.id,\n apiKey,\n serviceConfig,\n capabilities,\n }\n\n // Initialize service when config changes\n useEffect(() => {\n const currentRender = renderCountRef.current\n debugLog('🔧 SERVICE INIT EFFECT TRIGGERED', {\n renderCount: currentRender,\n apiKey: !!apiKey,\n serviceConfig: !!serviceConfig,\n dependencies: {\n apiKey: apiKey?.substring(0, 8) + '...',\n serviceConfigRef: serviceConfig,\n serviceConfigStable:\n prevPropsRef.current.serviceConfig === serviceConfig,\n apiKeyStable: prevPropsRef.current.apiKey === apiKey,\n },\n })\n\n if (!apiKey || !serviceConfig) {\n debugLog('⚠️ SERVICE INIT SKIPPED', {\n renderCount: currentRender,\n reason: 'Missing apiKey or serviceConfig',\n })\n return\n }\n\n debugLog('🚀 CREATING NEW SERVICE', {\n renderCount: currentRender,\n apiKey: apiKey?.substring(0, 8) + '...',\n serviceConfigChanged:\n prevPropsRef.current.serviceConfig !== serviceConfig,\n })\n\n const newService = new StreamChatService({\n ...serviceConfig,\n apiKey,\n debug,\n })\n\n setService(newService)\n debugLog('✅ SERVICE SET', {\n renderCount: currentRender,\n serviceInstance: !!newService,\n })\n\n return () => {\n debugLog('🧹 SERVICE CLEANUP', {\n renderCount: currentRender,\n reason: 'Effect cleanup',\n })\n newService.disconnectUser().catch(console.error)\n }\n }, [apiKey, serviceConfig, debug, debugLog]) // Use serviceConfig object directly, not individual properties\n\n // Track if we've already connected this user with this service to prevent duplicate connections\n const connectedUserRef = useRef<{\n serviceId: StreamChatService\n userId: string\n } | null>(null)\n\n // Connect user when service and user are available\n useEffect(() => {\n debugLog('🔗 USER CONNECTION EFFECT TRIGGERED', {\n hasService: !!service,\n hasUser: !!user,\n userId: user?.id,\n isConnecting: connectingRef.current,\n isConnected: isConnected,\n dependencies: { service: !!service, userId: user?.id },\n })\n\n if (!service || !user) {\n debugLog('⚠️ USER CONNECTION SKIPPED', 'Missing service or user')\n return\n }\n\n if (connectingRef.current) {\n debugLog('⚠️ USER CONNECTION SKIPPED', 'Already connecting')\n return\n }\n\n // Check if we've already connected this exact user with this exact service instance\n if (\n connectedUserRef.current?.serviceId === service &&\n connectedUserRef.current?.userId === user.id\n ) {\n debugLog(\n '⚠️ USER CONNECTION SKIPPED',\n 'Already connected this user with this service'\n )\n return\n }\n\n const connectUser = async () => {\n debugLog('🚀 STARTING USER CONNECTION', { userId: user.id })\n connectingRef.current = true\n setIsLoading(true)\n setError(null)\n\n try {\n debugLog('📞 CALLING SERVICE.CONNECTUSER', { userId: user.id })\n const streamClient = await service.connectUser(user)\n setClient(streamClient)\n setIsConnected(true)\n connectedUserRef.current = { serviceId: service, userId: user.id } // Mark as connected\n debugLog('✅ USER CONNECTION SUCCESS', {\n userId: user.id,\n clientId: streamClient.userID,\n })\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : 'Connection failed'\n setError(errorMessage)\n debugLog('❌ USER CONNECTION ERROR', {\n userId: user.id,\n error: errorMessage,\n })\n } finally {\n setIsLoading(false)\n connectingRef.current = false\n debugLog('🔄 USER CONNECTION FINISHED', {\n userId: user.id,\n isConnected,\n })\n }\n }\n\n connectUser()\n }, [service, user, debugLog, isConnected]) // Remove isConnected to prevent circular dependency\n\n // Disconnect when user is removed (cleanup effect)\n useEffect(() => {\n debugLog('🔌 CLEANUP EFFECT REGISTERED', {\n hasService: !!service,\n isConnected,\n })\n return () => {\n if (service && isConnected) {\n debugLog(\n '🧹 CLEANUP EFFECT TRIGGERED',\n 'Cleaning up connection on unmount'\n )\n connectedUserRef.current = null // Reset connection tracking\n service.disconnectUser().catch(console.error)\n } else {\n debugLog('🔇 CLEANUP EFFECT SKIPPED', {\n hasService: !!service,\n isConnected,\n })\n }\n }\n }, [service, isConnected, debugLog])\n\n const refreshConnection = useCallback(async () => {\n debugLog('🔄 REFRESH CONNECTION CALLED', {\n hasService: !!service,\n hasUser: !!user,\n })\n\n if (!service || !user) {\n debugLog('⚠️ REFRESH CONNECTION SKIPPED', 'Missing service or user')\n return\n }\n\n debugLog('🚀 STARTING CONNECTION REFRESH', { userId: user.id })\n setIsLoading(true)\n try {\n debugLog('🔌 DISCONNECTING FOR REFRESH')\n await service.disconnectUser()\n debugLog('📞 RECONNECTING FOR REFRESH')\n const streamClient = await service.connectUser(user)\n setClient(streamClient)\n setIsConnected(true)\n setError(null)\n debugLog('✅ CONNECTION REFRESH SUCCESS', { userId: user.id })\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Refresh failed'\n setError(errorMessage)\n debugLog('❌ CONNECTION REFRESH ERROR', {\n userId: user.id,\n error: errorMessage,\n })\n } finally {\n setIsLoading(false)\n debugLog('🔄 CONNECTION REFRESH FINISHED', { userId: user.id })\n }\n }, [service, user, debugLog])\n\n // Memoize context value to prevent unnecessary re-renders\n const contextValue: MessagingContextValue = React.useMemo(() => {\n debugLog('💫 CONTEXT VALUE MEMOIZATION', {\n hasService: !!service,\n hasClient: !!client,\n isConnected,\n isLoading,\n hasError: !!error,\n capabilitiesKeys: Object.keys(capabilities),\n })\n\n return {\n service,\n client,\n isConnected,\n isLoading,\n error,\n capabilities,\n refreshConnection,\n debug,\n }\n }, [\n service,\n client,\n isConnected,\n isLoading,\n error,\n capabilities,\n refreshConnection,\n debug,\n debugLog,\n ])\n\n debugLog('🔄 RENDER END', {\n renderCount: renderCountRef.current,\n willRenderChat: !!(client && isConnected),\n contextValueReady: !!contextValue,\n })\n\n return (\n <MessagingContext.Provider value={contextValue}>\n {client && isConnected ? (\n <Chat\n client={client}\n customClasses={{\n channelList:\n 'str-chat__channel-list str-chat__channel-list-react bg-transparent lg:border-r-2 border-r-0 border-[#0000000A]',\n }}\n >\n {children}\n </Chat>\n ) : (\n children\n )}\n </MessagingContext.Provider>\n )\n}\n","import { useMessagingContext } from '../providers/MessagingProvider';\nimport type { MessagingContextValue } from '../providers/MessagingProvider';\n\n/**\n * Hook to access messaging service and state\n */\nexport const useMessaging = (): MessagingContextValue => {\n return useMessagingContext();\n};\n","/**\n * Get the number of days between two dates (calendar days in UTC, not 24-hour periods)\n * Uses UTC to ensure consistent day calculations globally since messages are stored in UTC\n */\nconst getDaysDifference = (date1: Date, date2: Date): number => {\n const d1 = new Date(\n Date.UTC(date1.getUTCFullYear(), date1.getUTCMonth(), date1.getUTCDate())\n )\n const d2 = new Date(\n Date.UTC(date2.getUTCFullYear(), date2.getUTCMonth(), date2.getUTCDate())\n )\n const diffTime = d2.getTime() - d1.getTime()\n return Math.floor(diffTime / (1000 * 60 * 60 * 24))\n}\n\n/**\n * Format a date - shows time for today, relative time for older messages\n * (e.g., \"Just now\", \"2:08 PM\" for today, \"Yesterday\" for yesterday, \"2d\" for 2 days ago)\n */\nexport const formatRelativeTime = (date: Date): string => {\n const now = new Date()\n const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000)\n\n // Less than 1 minute\n if (diffInSeconds < 60) {\n return 'Just now'\n }\n\n // Check if it's today (same calendar day)\n const daysDiff = getDaysDifference(date, now)\n\n // If today, show the time (e.g., \"2:08 PM\")\n if (daysDiff === 0) {\n return date.toLocaleTimeString([], {\n hour: 'numeric',\n minute: '2-digit',\n })\n }\n\n // Yesterday\n if (daysDiff === 1) {\n return 'Yesterday'\n }\n\n // Less than 7 days - show days\n if (daysDiff < 7) {\n return `${daysDiff}d`\n }\n\n // Less than 4 weeks - show weeks\n if (daysDiff < 28) {\n const weeks = Math.floor(daysDiff / 7)\n return `${weeks}w`\n }\n\n // More than 4 weeks - show date as MM/DD/YY\n return date.toLocaleDateString('en-US', {\n month: 'numeric',\n day: 'numeric',\n year: '2-digit',\n })\n}\n","/**\n * Generate a fruit emoji based on a string id\n * Returns a consistent fruit emoji for the same id\n */\nconst EMOJIS = [\n '🍎', // Apple\n '🍌', // Banana\n '🍇', // Grape\n '🍊', // Orange\n '🍓', // Strawberry\n '🥥', // Coconut\n '🍒', // Cherry\n '🥭', // Mango\n '🍉', // Watermelon\n '🍋', // Lemon\n '🥝', // Kiwi\n '🫒', // Olive\n '🍈', // Melon\n]\n\n/**\n * Simple hash function to convert string to number\n */\nfunction hashString(str: string): number {\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32-bit integer\n }\n return Math.abs(hash)\n}\n\n/**\n * Get a fruit emoji based on an id string\n * @param id - The string id to generate emoji from\n * @returns A fruit emoji string\n */\nexport function getAvatarEmoji(id: string): string {\n const hash = hashString(id)\n const index = hash % EMOJIS.length\n return EMOJIS[index]\n}\n\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport { getAvatarEmoji } from './getAvatarEmoji'\n\nexport interface AvatarProps {\n id: string\n name: string\n image?: string\n size?: number\n className?: string\n shape?: 'squircle' | 'circle'\n}\n\n/**\n * Avatar component that displays a user image or colored initial fallback\n */\nexport const Avatar: React.FC<AvatarProps> = ({\n id,\n image,\n size = 40,\n className,\n shape = 'squircle',\n}) => {\n const emoji = getAvatarEmoji(id)\n\n // Determine font size based on avatar size\n const getFontSizeClass = () => {\n if (size < 32) return 'text-xs'\n if (size < 56) return 'text-sm'\n return 'text-lg'\n }\n\n const fontSizeClass = getFontSizeClass()\n\n const borderStyle =\n shape === 'circle'\n ? { borderRadius: '50%' }\n : {\n borderRadius: '33%',\n 'corner-shape': 'superellipse(1.3)',\n }\n\n return (\n <div\n className={classNames('flex-shrink-0 overflow-hidden', className)}\n style={{\n width: `${size}px`,\n height: `${size}px`,\n ...borderStyle,\n }}\n >\n {image ? (\n <img\n src={image}\n alt=\"\"\n className=\"h-full w-full object-cover aspect-square\"\n />\n ) : (\n <div\n aria-hidden=\"true\"\n className={classNames(\n 'avatar-fallback flex h-full w-full items-center justify-center font-semibold bg-[#E6E5E3] select-none transition-colors',\n fontSizeClass\n )}\n >\n {emoji}\n </div>\n )}\n </div>\n )\n}\n","import classNames from 'classnames'\nimport React from 'react'\nimport { Channel } from 'stream-chat'\nimport { ChannelPreviewUIComponentProps } from 'stream-chat-react'\n\nimport { formatRelativeTime } from '../../utils/formatRelativeTime'\nimport { Avatar } from '../Avatar'\n\ntype CustomChannelPreviewProps = ChannelPreviewUIComponentProps & {\n selectedChannel?: Channel | null\n onChannelSelect: (channel: Channel) => void\n debug?: boolean\n}\n\n/**\n * Custom channel preview that handles selection\n */\nconst CustomChannelPreview = React.memo<CustomChannelPreviewProps>(\n ({ channel, selectedChannel, onChannelSelect, debug = false, unread }) => {\n const isSelected = selectedChannel?.id === channel?.id\n\n const handleClick = () => {\n if (channel) {\n onChannelSelect(channel)\n }\n }\n\n // Get participant info\n const members = Object.values(channel?.state?.members || {})\n const participant = members.find(\n (member) => member.user?.id && member.user.id !== channel?._client?.userID\n )\n const participantName = participant?.user?.name || 'Conversation'\n const participantImage = participant?.user?.image\n\n // Get last message and format timestamp\n const lastMessage =\n channel?.state?.messages?.[channel.state.messages.length - 1]\n\n // Fallback order: text -> attachment URL -> \"No messages yet\"\n const getLastMessageText = () => {\n if (lastMessage?.text) return lastMessage.text\n\n const attachment = lastMessage?.attachments?.[0]\n if (attachment?.asset_url) return attachment.asset_url\n if (attachment?.image_url) return attachment.image_url\n if (attachment?.og_scrape_url) return attachment.og_scrape_url\n if (attachment?.thumb_url) return attachment.thumb_url\n\n return 'No messages yet'\n }\n\n const lastMessageText = getLastMessageText()\n const lastMessageTime = lastMessage?.created_at\n ? formatRelativeTime(new Date(lastMessage.created_at))\n : ''\n\n // Use the unread prop passed by Stream Chat (reactive and updates automatically)\n const unreadCount = unread ?? 0\n\n if (debug) {\n console.log('📺 [ChannelList] 📋 CHANNEL PREVIEW RENDER', {\n channelId: channel?.id,\n isSelected,\n participantName,\n unreadCount,\n hasTimestamp: !!lastMessageTime,\n })\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n className={classNames(\n 'group w-full px-4 py-3 transition-colors text-left max-w-full overflow-hidden focus-ring',\n {\n 'bg-primary-alt/10 border-l-4 border-l-primary': isSelected,\n 'hover:bg-sand': !isSelected,\n }\n )}\n >\n <div className=\"flex items-start gap-3\">\n {/* Avatar */}\n <Avatar\n id={participant?.user?.id || channel.id || 'unknown'}\n name={participantName}\n image={participantImage}\n size={44}\n className=\"[&_.avatar-fallback]:group-hover:bg-[#eeeeee]\"\n />\n\n {/* Content column */}\n <div className=\"flex-1 min-w-0 flex flex-col gap-1\">\n {/* Name and timestamp row */}\n <div className=\"flex items-center justify-between gap-2\">\n <h3\n className={classNames(\n 'text-sm font-medium truncate',\n isSelected ? 'text-primary' : 'text-charcoal'\n )}\n >\n {participantName}\n </h3>\n {lastMessageTime && (\n <span className=\"text-xs text-stone flex-shrink-0\">\n {lastMessageTime}\n </span>\n )}\n </div>\n\n {/* Message and unread badge row */}\n <div className=\"flex items-center justify-between gap-2 min-w-0\">\n <p className=\"text-xs text-stone mr-2 flex-1 line-clamp-2\">\n {lastMessageText}\n </p>\n {unreadCount > 0 && (\n <span className=\"bg-[#7f22fe] text-white text-xs px-2 py-0.5 rounded-full min-w-[20px] text-center flex-shrink-0\">\n {unreadCount > 99 ? '99+' : unreadCount}\n </span>\n )}\n </div>\n </div>\n </div>\n </button>\n )\n }\n)\n\nexport default CustomChannelPreview\nCustomChannelPreview.displayName = 'CustomChannelPreview'\n","import classNames from 'classnames'\nimport React from 'react'\nimport type { ChannelPreviewUIComponentProps } from 'stream-chat-react'\nimport { ChannelList as StreamChannelList } from 'stream-chat-react'\n\nimport { useMessagingContext } from '../../providers/MessagingProvider'\nimport type { ChannelListProps } from '../../types'\n\nimport CustomChannelPreview from './CustomChannelPreview'\n\n/**\n * Channel list component with customizable header and actions\n */\nexport const ChannelList = React.memo<ChannelListProps>(\n ({\n onChannelSelect,\n selectedChannel,\n filters,\n className,\n customEmptyStateIndicator,\n }) => {\n // Track renders\n const renderCountRef = React.useRef(0)\n renderCountRef.current++\n\n // Get debug flag from context\n const { debug = false } = useMessagingContext()\n\n if (debug) {\n console.log('📺 [ChannelList] 🔄 RENDER START', {\n renderCount: renderCountRef.current,\n selectedChannelId: selectedChannel?.id,\n filters,\n })\n }\n\n // Memoize Preview component to prevent re-renders\n const PreviewComponent = React.useMemo(() => {\n const Preview = (props: ChannelPreviewUIComponentProps) => (\n <CustomChannelPreview\n {...props}\n selectedChannel={selectedChannel}\n onChannelSelect={onChannelSelect}\n debug={debug}\n />\n )\n return Preview\n }, [selectedChannel, onChannelSelect, debug])\n\n return (\n <div\n className={classNames(\n 'messaging-channel-list h-full flex flex-col min-w-0 overflow-hidden',\n className\n )}\n >\n {/* Channel List */}\n <div className=\"flex-1 overflow-hidden min-w-0\">\n <StreamChannelList\n key={JSON.stringify(filters)}\n filters={filters}\n sort={{ last_message_at: -1 }}\n options={{ limit: 30 }}\n Preview={PreviewComponent}\n EmptyStateIndicator={customEmptyStateIndicator}\n />\n </div>\n </div>\n )\n }\n)\nChannelList.displayName = 'ChannelList'\n","import classNames from \"classnames\";\nimport React from \"react\";\n\ninterface ActionButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: \"default\" | \"danger\";\n}\n\nconst ActionButton = ({\n variant = \"default\",\n className,\n children,\n ...rest\n}: ActionButtonProps) => {\n const isDanger = variant === \"danger\";\n return (\n <button\n type=\"button\"\n className={classNames(\n \"flex w-full items-center gap-3 rounded-lg px-4 py-3 text-left text-sm transition-colors focus-ring disabled:cursor-not-allowed disabled:opacity-60\",\n isDanger\n ? \"text-danger hover:bg-danger/50\"\n : \"text-charcoal hover:bg-sand\",\n className,\n )}\n {...rest}\n >\n {children}\n </button>\n );\n};\n\nexport default ActionButton;\n","import classNames from \"classnames\";\nimport React from \"react\";\n\ninterface IconButtonProps\n extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n \"type\" | \"children\"\n > {\n label: string;\n children: React.ReactNode;\n className?: string;\n}\n\nexport function IconButton({ label, className, children, ...rest }: IconButtonProps) {\n return (\n <button\n type=\"button\"\n className={classNames(\n \"rounded-full p-2 transition-colors focus-ring\",\n {\n \"cursor-not-allowed opacity-50\": rest.disabled,\n \"hover:bg-sand\": !rest.disabled,\n },\n className,\n )}\n {...rest}\n >\n <span className=\"sr-only\">{label}</span>\n {children}\n </button>\n );\n}","import { XIcon } from '@phosphor-icons/react'\n\nimport { IconButton } from '../IconButton'\n\ninterface CloseButtonProps {\n onClick: () => void\n}\n\nexport function CloseButton({ onClick }: CloseButtonProps) {\n return (\n <IconButton label=\"Close\" onClick={onClick} className=\"p-1\">\n <XIcon className=\"h-5 w-5 text-stone\" weight=\"bold\" />\n </IconButton>\n )\n}\n","import { XIcon } from '@phosphor-icons/react'\nimport React from 'react'\nimport {\n LinkPreview,\n LinkPreviewsManager,\n LinkPreviewsManagerState,\n} from 'stream-chat'\nimport { useMessageComposer, useStateStore } from 'stream-chat-react'\n\nconst linkPreviewsManagerStateSelector = (state: LinkPreviewsManagerState) => ({\n linkPreviews: Array.from(state.previews.values()).filter(\n (preview) =>\n LinkPreviewsManager.previewIsLoaded(preview) ||\n LinkPreviewsManager.previewIsLoading(preview)\n ),\n})\n\ninterface CustomLinkPreviewCardProps {\n link: LinkPreview\n onDismiss: (url: string) => void\n}\n\nconst CustomLinkPreviewCard: React.FC<CustomLinkPreviewCardProps> = ({\n link,\n onDismiss,\n}) => {\n const { og_scrape_url, title, image_url } = link\n\n const handleDismissLink = (e: React.MouseEvent) => {\n e.preventDefault()\n onDismiss(og_scrape_url)\n }\n\n return (\n <a\n href={og_scrape_url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"relative w-full block rounded-[24px] bg-[#121110] p-2 no-underline transition-opacity hover:opacity-90\"\n >\n {image_url && (\n <img\n src={image_url}\n alt={title || ''}\n className=\"h-[148px] w-full rounded-[20px] object-cover\"\n />\n )}\n <button\n type=\"button\"\n onClick={handleDismissLink}\n className=\"absolute right-4 top-4 flex size-6 items-center justify-center rounded-full border border-white/40 bg-white/70 backdrop-blur-2xl\"\n aria-label=\"Close link preview\"\n >\n <XIcon className=\"size-4 text-black/90\" />\n </button>\n <div className=\"p-2\">\n {title && (\n <div className=\"text-[14px] font-medium leading-5 text-white\">\n {title}\n </div>\n )}\n <div className=\"text-[12px] leading-4 text-white/55\">\n {og_scrape_url}\n </div>\n </div>\n </a>\n )\n}\n\nexport const CustomLinkPreviewList = () => {\n const { linkPreviewsManager } = useMessageComposer()\n\n const { linkPreviews: stateLinkPreviews } = useStateStore(\n linkPreviewsManager.state,\n linkPreviewsManagerStateSelector\n )\n\n const handleDismiss = (url: string) => {\n linkPreviewsManager.dismissPreview(url)\n }\n\n const showLinkPreviews = stateLinkPreviews.length > 0\n\n if (!showLinkPreviews) return null\n\n return (\n <div className=\"str-chat__link-preview-list p-0 gap-2 mb-4\">\n {stateLinkPreviews.map((linkPreview) => (\n <CustomLinkPreviewCard\n key={linkPreview.og_scrape_url}\n link={linkPreview}\n onDismiss={handleDismiss}\n />\n ))}\n </div>\n )\n}\n","import { ArrowUpIcon } from '@phosphor-icons/react'\nimport React from 'react'\nimport {\n AttachmentPreviewList,\n MessageInput,\n QuotedMessagePreview,\n SimpleAttachmentSelector,\n TextareaComposer,\n useMessageComposerHasSendableData,\n useMessageInputContext,\n} from 'stream-chat-react'\n\nimport { CustomLinkPreviewList } from '../CustomLinkPreviewList'\n\nconst CustomMessageInputInner: React.FC = () => {\n const { handleSubmit } = useMessageInputContext()\n const hasSendableData = useMessageComposerHasSendableData()\n\n return (\n <>\n <div className=\"left-container\">\n <SimpleAttachmentSelector />\n </div>\n <div className=\"central-container min-w-0 w-full p-2 bg-white rounded-[1.5rem] shadow-[0_4px_16px_0_rgba(0,0,0,0.08),0_1px_2px_0_rgba(0,0,0,0.04),0_0_0_1px_rgba(0,0,0,0.04)]\">\n <QuotedMessagePreview />\n <CustomLinkPreviewList />\n <AttachmentPreviewList />\n <div className=\"flex\">\n <div className=\"w-full ml-2 mr-4 self-center leading-[0]\">\n <TextareaComposer\n className=\"w-full resize-none outline-none leading-6\"\n maxRows={4}\n />\n </div>\n <button\n aria-label=\"Send\"\n className=\"str-chat__send-button mt-auto flex justify-center items-center flex-shrink-0 rounded-full size-8 bg-[#121110] disabled:bg-[#F1F0EE] disabled:text-black/20 text-white\"\n data-testid=\"send-button\"\n disabled={!hasSendableData}\n onClick={handleSubmit}\n type=\"button\"\n >\n <ArrowUpIcon className=\"size-4\" />\n </button>\n </div>\n </div>\n </>\n )\n}\n\nexport interface CustomMessageInputProps {\n renderActions?: () => React.ReactNode\n}\n\nexport const CustomMessageInput: React.FC<CustomMessageInputProps> = ({\n renderActions,\n}) => (\n <div className=\"message-input flex items-center gap-2 p-4\">\n {renderActions && renderActions?.()}\n <MessageInput Input={CustomMessageInputInner} />\n </div>\n)\n","import { MessageTimestamp, type EventComponentProps } from 'stream-chat-react'\n\nexport const CustomSystemMessage: React.FC<EventComponentProps> = (props) => {\n const isDateHidden = props.message.hide_date === true\n\n return (\n <div className=\"str-chat__message--system\" data-testid=\"message-system\">\n <div className=\"str-chat__message--system__text\">\n <div className=\"str-chat__message--system__line\"></div>\n <p>{props.message.text}</p>\n <div className=\"str-chat__message--system__line\"></div>\n </div>\n {!isDateHidden && <MessageTimestamp message={props.message} />}\n </div>\n )\n}\n","import React from 'react'\n\n/**\n * Empty state component shown when a channel has no messages\n * Returns null to show nothing - the LoadingIndicator handles the loading state\n */\nexport const ChannelEmptyState: React.FC = () => {\n console.log('[ChannelEmptyState] render - returning NULL')\n return null\n}\n","import classNames from 'classnames'\n\ntype LoadingProps = {\n className?: string\n message?: string\n}\n\nconst Loading = ({ className, message }: LoadingProps) => (\n <div\n className={classNames('flex items-center justify-center h-full', className)}\n >\n <svg viewBox=\"0 0 100 100\" className=\"size-8 fill-pebble\" stroke=\"none\">\n <circle cx=\"6\" cy=\"50\" r=\"6\">\n <animateTransform\n attributeName=\"transform\"\n dur=\"1s\"\n type=\"translate\"\n values=\"0 15 ; 0 -15; 0 15\"\n repeatCount=\"indefinite\"\n begin=\"0.1\"\n />\n </circle>\n <circle cx=\"30\" cy=\"50\" r=\"6\">\n <animateTransform\n attributeName=\"transform\"\n dur=\"1s\"\n type=\"translate\"\n values=\"0 10 ; 0 -10; 0 10\"\n repeatCount=\"indefinite\"\n begin=\"0.2\"\n />\n </circle>\n <circle cx=\"54\" cy=\"50\" r=\"6\">\n <animateTransform\n attributeName=\"transform\"\n dur=\"1s\"\n type=\"translate\"\n values=\"0 5 ; 0 -5; 0 5\"\n repeatCount=\"indefinite\"\n begin=\"0.3\"\n />\n </circle>\n </svg>\n {message && <span className=\"text-stone\">{message}</span>}\n </div>\n)\n\nexport default Loading\n","import React from 'react'\n\nimport Loading from '../Loading'\n\n/**\n * Loading state component\n */\nexport const LoadingState = React.memo(() => {\n console.log('[LoadingState] render - showing loading spinner')\n return (\n <div className=\"messaging-loading-state flex items-center justify-center h-full\">\n <div className=\"flex items-center\">\n <Loading className=\"w-6 h-6\" />\n <span className=\"text-sm text-stone\">Loading messages</span>\n </div>\n </div>\n )\n})\nLoadingState.displayName = 'LoadingState'\n","import {\n ArrowLeftIcon,\n DotsThreeIcon,\n FlagIcon,\n ProhibitInsetIcon,\n SignOutIcon,\n SpinnerGapIcon,\n} from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React, { useState, useCallback, useRef, useEffect } from 'react'\nimport { Channel as ChannelType, ChannelMemberResponse } from 'stream-chat'\nimport {\n Channel,\n Window,\n MessageList,\n useChannelStateContext,\n} from 'stream-chat-react'\n\nimport { useMessagingContext } from '../providers/MessagingProvider'\nimport type { ChannelViewProps } from '../types'\n\nimport ActionButton from './ActionButton'\nimport { Avatar } from './Avatar'\nimport { CloseButton } from './CloseButton'\nimport { CustomMessageInput } from './CustomMessageInput'\nimport { CustomSystemMessage } from './CustomSystemMessage'\nimport { ChannelEmptyState } from './MessagingShell/ChannelEmptyState'\nimport { LoadingState } from './MessagingShell/LoadingState'\n\n// Custom user type with email and username\ntype CustomUser = {\n email?: string\n username?: string\n}\n\n// Blocked user from Stream Chat API\ntype BlockedUser = {\n blocked_user_id: string\n}\n\n/**\n * Custom channel header component\n */\nconst CustomChannelHeader: React.FC<{\n onBack?: () => void\n showBackButton: boolean\n onShowInfo: () => void\n canShowInfo: boolean\n}> = ({ onBack, showBackButton, onShowInfo, canShowInfo }) => {\n const { channel } = useChannelStateContext()\n\n // Get participant info (excluding current user)\n const participant = React.useMemo(() => {\n const members = Object.values(channel.state.members || {})\n return members.find(\n (member) => member.user?.id && member.user.id !== channel._client.userID\n )\n }, [channel._client.userID, channel.state.members])\n\n const participantName =\n participant?.user?.name || participant?.user?.id || 'Unknown member'\n const participantImage = participant?.user?.image\n\n return (\n <div className=\"@container\">\n <div className=\"flex justify-between items-center @lg:hidden\">\n <button\n className={classNames(\n 'size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center',\n !showBackButton && 'invisible'\n )}\n onClick={onBack || (() => {})}\n type=\"button\"\n aria-label=\"Back to conversations\"\n >\n <ArrowLeftIcon className=\"size-5 text-black/90\" />\n </button>\n <div className=\"flex flex-col gap-1 items-center\">\n <Avatar\n id={participant?.user?.id || channel.id || 'unknown'}\n name={participantName}\n image={participantImage}\n size={40}\n />\n <h1 className=\"text-xs font-medium text-black/90\">\n {participantName}\n </h1>\n </div>\n <button\n className={classNames(\n 'size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center'\n )}\n onClick={onShowInfo}\n type=\"button\"\n aria-label=\"Show info\"\n >\n <DotsThreeIcon className=\"size-5 text-black/90\" />\n </button>\n </div>\n <div className=\"hidden @lg:flex items-center justify-between gap-3 min-h-12\">\n <div className=\"flex items-center gap-4 min-w-0\">\n {showBackButton && onBack && (\n <button\n type=\"button\"\n onClick={onBack}\n className=\"size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center\"\n aria-label=\"Back to conversations\"\n >\n <ArrowLeftIcon className=\"size-5 text-black/90\" />\n </button>\n )}\n {/* Avatar */}\n <Avatar\n id={participant?.user?.id || channel.id || 'unknown'}\n name={participantName}\n image={participantImage}\n size={40}\n />\n <div className=\"min-w-0\">\n <h1 className=\"font-medium text-black/90 truncate\">\n {participantName}\n </h1>\n </div>\n </div>\n {canShowInfo && onShowInfo && (\n <button\n className={classNames(\n 'size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center'\n )}\n onClick={onShowInfo}\n >\n <DotsThreeIcon className=\"size-5 text-black/90\" />\n </button>\n )}\n </div>\n </div>\n )\n}\n\n/**\n * Channel info dialog (matching original implementation)\n */\nconst ChannelInfoDialog: React.FC<{\n dialogRef: React.RefObject<HTMLDialogElement>\n onClose: () => void\n participant: ChannelMemberResponse | undefined\n channel: ChannelType\n followerStatusLabel?: string\n onLeaveConversation?: (channel: ChannelType) => void\n onBlockParticipant?: (participantId?: string) => void\n showDeleteConversation?: boolean\n onDeleteConversationClick?: () => void\n onBlockParticipantClick?: () => void\n onReportParticipantClick?: () => void\n}> = ({\n dialogRef,\n onClose,\n participant,\n channel,\n followerStatusLabel,\n onLeaveConversation,\n onBlockParticipant,\n showDeleteConversation = true,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n}) => {\n const { service, debug } = useMessagingContext()\n const [isParticipantBlocked, setIsParticipantBlocked] = useState(false)\n const [isLeaving, setIsLeaving] = useState(false)\n const [isUpdatingBlockStatus, setIsUpdatingBlockStatus] = useState(false)\n\n // Check if participant is blocked when participant changes\n const checkIsParticipantBlocked = useCallback(async () => {\n if (!service || !participant?.user?.id) return\n\n try {\n const blockedUsers = await service.getBlockedUsers()\n const isBlocked = blockedUsers.some(\n (user: BlockedUser) => user.blocked_user_id === participant?.user?.id\n )\n setIsParticipantBlocked(isBlocked)\n } catch (error) {\n console.error(\n '[ChannelInfoDialog] Failed to check blocked status:',\n error\n )\n }\n }, [service, participant?.user?.id])\n\n useEffect(() => {\n checkIsParticipantBlocked()\n }, [checkIsParticipantBlocked])\n\n const handleLeaveConversation = async () => {\n if (isLeaving) return\n\n // Fire analytics callback before action\n onDeleteConversationClick?.()\n\n if (debug) {\n console.log('[ChannelInfoDialog] Leave conversation', channel.cid)\n }\n setIsLeaving(true)\n\n try {\n const actingUserId = channel._client?.userID ?? null\n await channel.hide(actingUserId, false)\n\n if (onLeaveConversation) {\n await onLeaveConversation(channel)\n }\n\n onClose()\n } catch (error) {\n console.error('[ChannelInfoDialog] Failed to leave conversation', error)\n } finally {\n setIsLeaving(false)\n }\n }\n\n const handleBlockUser = async () => {\n if (isUpdatingBlockStatus || !service) return\n\n // Fire analytics callback before action\n onBlockParticipantClick?.()\n\n if (debug) {\n console.log('[ChannelInfoDialog] Block member', participant?.user?.id)\n }\n setIsUpdatingBlockStatus(true)\n\n try {\n await service.blockUser(participant?.user?.id)\n\n if (onBlockParticipant) {\n await onBlockParticipant(participant?.user?.id)\n }\n\n onClose()\n } catch (error) {\n console.error('[ChannelInfoDialog] Failed to block member', error)\n } finally {\n setIsUpdatingBlockStatus(false)\n }\n }\n\n const handleUnblockUser = async () => {\n if (isUpdatingBlockStatus || !service) return\n\n // Fire analytics callback before action\n onBlockParticipantClick?.()\n\n if (debug) {\n console.log('[ChannelInfoDialog] Unblock member', participant?.user?.id)\n }\n setIsUpdatingBlockStatus(true)\n\n try {\n await service.unBlockUser(participant?.user?.id)\n\n if (onBlockParticipant) {\n await onBlockParticipant(participant?.user?.id)\n }\n\n onClose()\n } catch (error) {\n console.error('[ChannelInfoDialog] Failed to unblock member', error)\n } finally {\n setIsUpdatingBlockStatus(false)\n }\n }\n\n const handleReportUser = () => {\n // Fire analytics callback before action\n onReportParticipantClick?.()\n\n onClose()\n window.open(\n 'https://linktr.ee/s/about/trust-center/report',\n '_blank',\n 'noopener,noreferrer'\n )\n }\n\n if (!participant) return null\n\n const participantName =\n participant.user?.name || participant.user?.id || 'Unknown member'\n const participantImage = participant.user?.image\n const participantEmail = (participant.user as CustomUser)?.email\n const participantUsername = (participant.user as CustomUser)?.username\n const participantSecondary = participantEmail\n ? participantEmail\n : participantUsername\n ? `linktr.ee/${participantUsername}`\n : undefined\n const participantId = participant.user?.id || 'unknown'\n\n return (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions\n <dialog\n ref={dialogRef}\n className=\"mes-dialog group\"\n onClose={onClose}\n onClick={(e) => {\n if (e.target === dialogRef.current) {\n onClose()\n }\n }}\n >\n <div className=\"ml-auto flex h-full w-full flex-col bg-white shadow-none transition-shadow duration-200 group-open:shadow-max-elevation-light\">\n <div className=\"flex items-center justify-between border-b border-sand px-4 py-3\">\n <h2 className=\"text-base font-semibold text-charcoal\">Chat info</h2>\n <CloseButton onClick={onClose} />\n </div>\n\n <div className=\"flex-1 px-2 overflow-y-auto w-full\">\n <div\n className=\"flex flex-col items-center gap-3 self-stretch px-4 py-2 mt-6 rounded-lg border border-black/[0.04]\"\n style={{ backgroundColor: '#FBFAF9' }}\n >\n <div className=\"flex items-center gap-3 w-full\">\n <Avatar\n id={participantId}\n name={participantName}\n image={participantImage}\n size={88}\n shape=\"circle\"\n />\n <div className=\"flex flex-col min-w-0 flex-1\">\n <p className=\"truncate text-base font-semibold text-charcoal\">\n {participantName}\n </p>\n {participantSecondary && (\n <p className=\"truncate text-sm text-[#00000055]\">\n {participantSecondary}\n </p>\n )}\n {followerStatusLabel && (\n <span\n className=\"mt-1 rounded-full text-xs font-normal w-fit\"\n style={{\n padding: '4px 8px',\n backgroundColor:\n followerStatusLabel === 'Subscribed to you'\n ? '#DCFCE7'\n : '#F5F5F4',\n color:\n followerStatusLabel === 'Subscribed to you'\n ? '#008236'\n : '#78716C',\n lineHeight: '133.333%',\n letterSpacing: '0.21px',\n }}\n >\n {followerStatusLabel}\n </span>\n )}\n </div>\n </div>\n </div>\n\n <ul className=\"flex flex-col gap-2 mt-2\">\n {showDeleteConversation && (\n <li>\n <ActionButton\n onClick={handleLeaveConversation}\n disabled={isLeaving}\n aria-busy={isLeaving}\n >\n {isLeaving ? (\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n ) : (\n <SignOutIcon className=\"h-5 w-5\" />\n )}\n <span>Delete Conversation</span>\n </ActionButton>\n </li>\n )}\n <li>\n {isParticipantBlocked ? (\n <ActionButton\n onClick={handleUnblockUser}\n disabled={isUpdatingBlockStatus}\n aria-busy={isUpdatingBlockStatus}\n >\n {isUpdatingBlockStatus ? (\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n ) : (\n <ProhibitInsetIcon className=\"h-5 w-5\" />\n )}\n <span>Unblock</span>\n </ActionButton>\n ) : (\n <ActionButton\n onClick={handleBlockUser}\n disabled={isUpdatingBlockStatus}\n aria-busy={isUpdatingBlockStatus}\n >\n {isUpdatingBlockStatus ? (\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n ) : (\n <ProhibitInsetIcon className=\"h-5 w-5\" />\n )}\n <span>Block</span>\n </ActionButton>\n )}\n </li>\n <li>\n <ActionButton variant=\"danger\" onClick={handleReportUser}>\n <FlagIcon className=\"h-5 w-5\" />\n <span>Report</span>\n </ActionButton>\n </li>\n </ul>\n </div>\n </div>\n </dialog>\n )\n}\n\n/**\n * Inner component that has access to channel context\n */\nconst ChannelViewInner: React.FC<{\n onBack?: () => void\n showBackButton: boolean\n renderMessageInputActions?: (channel: ChannelType) => React.ReactNode\n onLeaveConversation?: (channel: ChannelType) => void\n onBlockParticipant?: (participantId?: string) => void\n CustomChannelEmptyState?: React.ComponentType\n showDeleteConversation?: boolean\n onDeleteConversationClick?: () => void\n onBlockParticipantClick?: () => void\n onReportParticipantClick?: () => void\n}> = ({\n onBack,\n showBackButton,\n renderMessageInputActions,\n onLeaveConversation,\n onBlockParticipant,\n showDeleteConversation = true,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n}) => {\n const { channel } = useChannelStateContext()\n const infoDialogRef = useRef<HTMLDialogElement>(null)\n\n // Get participant info for info dialog\n const participant = React.useMemo(() => {\n const members = Object.values(channel.state.members || {})\n return members.find(\n (member) => member.user?.id && member.user.id !== channel._client.userID\n )\n }, [channel._client.userID, channel.state.members])\n\n // Get follower status label from channel data\n const followerStatusLabel = React.useMemo(() => {\n const channelExtraData = (channel.data ?? {}) as {\n followerStatus?: string\n isFollower?: boolean\n }\n\n // If explicit followerStatus is provided, use it\n if (channelExtraData.followerStatus) {\n return String(channelExtraData.followerStatus)\n }\n // If isFollower is explicitly defined, use it to determine status\n if (channelExtraData.isFollower !== undefined) {\n return channelExtraData.isFollower\n ? 'Subscribed to you'\n : 'Not subscribed'\n }\n // Otherwise, don't show any status\n return undefined\n }, [channel.data])\n\n const handleShowInfo = useCallback(() => {\n infoDialogRef.current?.showModal()\n }, [])\n\n const handleCloseInfo = useCallback(() => {\n infoDialogRef.current?.close()\n }, [])\n\n return (\n <>\n <Window>\n {/* Custom Channel Header */}\n <div className=\"p-4\">\n <CustomChannelHeader\n onBack={onBack}\n showBackButton={showBackButton}\n onShowInfo={handleShowInfo}\n canShowInfo={Boolean(participant)}\n />\n </div>\n\n {/* Message List */}\n <div className=\"flex-1 overflow-hidden relative\">\n <MessageList\n hideDeletedMessages\n hideNewMessageSeparator={false}\n messageActions={[]}\n />\n </div>\n\n {/* Message Input */}\n <CustomMessageInput\n renderActions={() => renderMessageInputActions?.(channel)}\n />\n </Window>\n\n {/* Channel Info Dialog */}\n <ChannelInfoDialog\n dialogRef={infoDialogRef}\n onClose={handleCloseInfo}\n participant={participant}\n channel={channel}\n followerStatusLabel={followerStatusLabel}\n onLeaveConversation={onLeaveConversation}\n onBlockParticipant={onBlockParticipant}\n showDeleteConversation={showDeleteConversation}\n onDeleteConversationClick={onDeleteConversationClick}\n onBlockParticipantClick={onBlockParticipantClick}\n onReportParticipantClick={onReportParticipantClick}\n />\n </>\n )\n}\n\n/**\n * Channel view component with message list and input\n */\nexport const ChannelView = React.memo<ChannelViewProps>(\n ({\n channel,\n onBack,\n showBackButton = false,\n renderMessageInputActions,\n onLeaveConversation,\n onBlockParticipant,\n className,\n CustomChannelEmptyState = ChannelEmptyState,\n showDeleteConversation = true,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n }) => {\n console.log('[ChannelView] render', {\n channelId: channel.id,\n channelInitialized: channel.initialized,\n messageCount: channel.state?.messages?.length\n })\n return (\n <div\n className={classNames(\n 'messaging-channel-view h-full flex flex-col',\n className\n )}\n >\n <Channel\n channel={channel}\n MessageSystem={CustomSystemMessage}\n EmptyStateIndicator={CustomChannelEmptyState}\n LoadingIndicator={LoadingState}\n >\n <ChannelViewInner\n onBack={onBack}\n showBackButton={showBackButton}\n renderMessageInputActions={renderMessageInputActions}\n onLeaveConversation={onLeaveConversation}\n onBlockParticipant={onBlockParticipant}\n CustomChannelEmptyState={CustomChannelEmptyState}\n showDeleteConversation={showDeleteConversation}\n onDeleteConversationClick={onDeleteConversationClick}\n onBlockParticipantClick={onBlockParticipantClick}\n onReportParticipantClick={onReportParticipantClick}\n />\n </Channel>\n </div>\n )\n }\n)\nChannelView.displayName = 'ChannelView'\n","import { MagnifyingGlassIcon, XIcon } from '@phosphor-icons/react'\nimport { useRef } from 'react'\n\nimport { IconButton } from '../IconButton'\n\ninterface SearchInputProps {\n searchQuery: string\n setSearchQuery: (value: string) => void\n placeholder: string\n}\n\nexport function SearchInput({\n searchQuery,\n setSearchQuery,\n placeholder,\n}: SearchInputProps) {\n const searchInputRef = useRef<HTMLInputElement>(null)\n\n return (\n <div className=\"relative\">\n <MagnifyingGlassIcon\n className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone\"\n weight=\"bold\"\n />\n\n <input\n ref={searchInputRef}\n type=\"text\"\n placeholder={placeholder}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full pl-10 pr-10 py-3 text-sm border border-sand rounded-xl focus:outline-none focus:ring-2 focus:ring-black focus:border-transparent\"\n />\n\n {searchQuery && (\n <IconButton\n label=\"Clear search\"\n onClick={() => {\n setSearchQuery('')\n searchInputRef.current?.focus()\n }}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 p-1 text-stone hover:text-charcoal\"\n >\n <XIcon className=\"h-4 w-4\" weight=\"bold\" />\n </IconButton>\n )}\n </div>\n )\n}\n","import { ChatCircleDotsIcon, SpinnerGapIcon } from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React, { useCallback, useEffect, useState, useRef } from 'react'\n\nimport { useMessagingContext } from '../../providers/MessagingProvider'\nimport type { ParticipantPickerProps, Participant } from '../../types'\nimport { Avatar } from '../Avatar'\nimport { CloseButton } from '../CloseButton'\nimport { SearchInput } from '../SearchInput'\n\n/**\n * Generic participant picker component for starting conversations\n */\nexport const ParticipantPicker: React.FC<ParticipantPickerProps> = ({\n participantSource,\n onSelectParticipant,\n onClose,\n existingParticipantIds = new Set(),\n participantLabel = 'participants',\n searchPlaceholder = 'Search participants...',\n className,\n}) => {\n const { debug } = useMessagingContext()\n const [searchQuery, setSearchQuery] = useState('')\n const [participants, setParticipants] = useState<Participant[]>([])\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [startingChatWithId, setStartingChatWithId] = useState<string | null>(\n null\n )\n\n // Track if we've already loaded participants to prevent repeated loading\n const loadedRef = useRef(false)\n\n // Load participants initially - wait for participantSource to finish loading first\n useEffect(() => {\n // Wait for the participantSource to finish loading before we try to load participants\n if (participantSource.loading) {\n if (debug) {\n console.log(\n '[ParticipantPicker] Waiting for participant source to finish loading...'\n )\n }\n return\n }\n\n if (loadedRef.current) return // Prevent multiple loads\n\n const loadInitialParticipants = async () => {\n if (debug) {\n console.log('[ParticipantPicker] Loading initial participants...')\n }\n setLoading(true)\n setError(null)\n\n try {\n const result = await participantSource.loadParticipants({\n search: '', // Load all participants initially\n limit: 100,\n })\n setParticipants(result.participants)\n loadedRef.current = true // Mark as loaded\n if (debug) {\n console.log(\n '[ParticipantPicker] Participants loaded successfully:',\n result.participants.length\n )\n }\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : 'Failed to load participants'\n setError(errorMessage)\n console.error('[ParticipantPicker] Failed to load participants:', err)\n // Don't mark as loaded on error, allow retry\n } finally {\n setLoading(false)\n }\n }\n\n loadInitialParticipants()\n }, [participantSource.loading, debug]) // Re-run when loading state changes\n\n // Filter participants by search query and existing participants\n const availableParticipants = participants\n .filter((participant) => !existingParticipantIds.has(participant.id))\n .filter((participant) => {\n if (!searchQuery) return true\n const searchLower = searchQuery.toLowerCase()\n return (\n participant.name.toLowerCase().includes(searchLower) ||\n participant.email?.toLowerCase().includes(searchLower) ||\n false\n )\n })\n\n const handleSelectParticipant = useCallback(\n async (participant: Participant) => {\n if (startingChatWithId) return // Prevent multiple clicks\n\n setStartingChatWithId(participant.id)\n try {\n await onSelectParticipant(participant)\n } catch (error) {\n console.error('[ParticipantPicker] Failed to start chat:', error)\n // Reset the loading state on error\n setStartingChatWithId(null)\n }\n // Note: Don't reset startingChatWithId on success because the dialog will close\n },\n [onSelectParticipant, startingChatWithId]\n )\n\n const handleKeyDown = (\n event: React.KeyboardEvent,\n participant: Participant\n ) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n handleSelectParticipant(participant)\n }\n }\n\n return (\n <div className={classNames('flex flex-col h-full', className)}>\n {/* Header */}\n <div className=\"px-4 py-4 border-b border-sand bg-chalk\">\n <div className=\"flex items-center justify-between mb-3\">\n <h2 className=\"text-lg font-semibold text-charcoal\">\n Start a new Conversation\n </h2>\n <CloseButton onClick={onClose} />\n </div>\n\n <p className=\"text-xs text-stone mb-3\">\n Select a {participantLabel.slice(0, -1)} to start messaging (\n {availableParticipants.length} available)\n {participantSource.totalCount !== undefined &&\n ` • ${participantSource.totalCount} ${participantLabel} total`}\n </p>\n\n <SearchInput\n searchQuery={searchQuery}\n setSearchQuery={setSearchQuery}\n placeholder={searchPlaceholder}\n />\n </div>\n\n {/* Error State */}\n {error && (\n <div className=\"p-4 text-sm text-danger bg-danger-alt\">\n Error loading {participantLabel}: {error}\n </div>\n )}\n\n {/* Participants List */}\n <div className=\"flex-1 overflow-auto\">\n {loading && availableParticipants.length === 0 ? (\n <div className=\"h-32 flex items-center justify-center\">\n <div className=\"flex items-center space-x-2\">\n <div className=\"w-4 h-4 animate-spin rounded-full border-2 border-primary border-t-transparent\"></div>\n <span className=\"text-sm text-stone\">\n Loading {participantLabel}...\n </span>\n </div>\n </div>\n ) : availableParticipants.length === 0 ? (\n <div className=\"p-6 text-center\">\n <div className=\"mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-sand\">\n <ChatCircleDotsIcon className=\"h-8 w-8 text-charcoal\" />\n </div>\n <h3 className=\"text-sm font-semibold text-charcoal mb-2\">\n {searchQuery\n ? `No ${participantLabel} found`\n : participants.length > 0\n ? `Already chatting with all ${participantLabel}`\n : `No ${participantLabel} yet`}\n </h3>\n <p className=\"text-xs text-stone\">\n {searchQuery\n ? 'Try a different search term'\n : participants.length > 0\n ? `You have existing conversations with all your ${participantLabel}`\n : `${participantLabel.charAt(0).toUpperCase() + participantLabel.slice(1)} will appear here`}\n </p>\n </div>\n ) : (\n <ul className=\"space-y-0\">\n {availableParticipants.map((participant) => {\n const displayName =\n participant.name || participant.email || participant.id\n const displaySecondary =\n participant.email && participant.name\n ? participant.email\n : participant.phone\n\n return (\n <li key={participant.id}>\n <button\n type=\"button\"\n onClick={() => handleSelectParticipant(participant)}\n onKeyDown={(e) => handleKeyDown(e, participant)}\n className=\"w-full px-4 py-3 hover:bg-sand transition-colors border-b border-sand text-left focus:outline-none focus:ring-2 focus:ring-black\"\n >\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center space-x-3 flex-1 min-w-0\">\n {/* Avatar */}\n <Avatar\n id={participant.id}\n name={displayName}\n image={participant.image}\n size={40}\n />\n\n {/* Info */}\n <div className=\"flex-1 min-w-0\">\n <h4 className=\"text-sm font-medium text-charcoal truncate\">\n {displayName}\n </h4>\n {displaySecondary && (\n <p className=\"text-xs text-stone truncate\">\n {displaySecondary}\n </p>\n )}\n </div>\n </div>\n\n {/* Icon */}\n <div className=\"flex-shrink-0\">\n {startingChatWithId === participant.id ? (\n <SpinnerGapIcon className=\"h-5 w-5 text-primary animate-spin\" />\n ) : (\n <ChatCircleDotsIcon className=\"h-5 w-5 text-stone\" />\n )}\n </div>\n </div>\n </button>\n </li>\n )\n })}\n\n {/* Loading indicator */}\n {loading && (\n <li className=\"p-4 flex justify-center\">\n <div className=\"flex items-center space-x-2\">\n <div className=\"w-4 h-4 animate-spin rounded-full border-2 border-primary border-t-transparent\"></div>\n <span className=\"text-sm text-stone\">Loading more...</span>\n </div>\n </li>\n )}\n </ul>\n )}\n </div>\n </div>\n )\n}\n","import React from 'react'\n\nconst ChatBubblesIllustration = ({ className }: { className?: string }) => (\n <svg\n width=\"140\"\n height=\"120\"\n viewBox=\"44 -2 144 126\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n >\n <g clipPath=\"url(#clip0_empty_state)\">\n <path\n d=\"M123.68 82.1932C123.383 103.675 105.839 121 84.2417 121C77.4724 121 71.0986 119.297 65.5327 116.299L52.5873 119.687L53.8036 106.673C48.1776 99.8701 44.7994 91.1453 44.7994 81.6356C44.7994 59.8965 62.4554 42.2754 84.2374 42.2754C89.1328 42.2754 93.8175 43.1633 98.1413 44.789\"\n fill=\"#D7D4CE\"\n />\n <path\n d=\"M84.2458 86.0364C82.2851 86.0364 80.6957 84.4501 80.6957 82.4933C80.6957 80.5365 82.2851 78.9502 84.2458 78.9502C86.2065 78.9502 87.7959 80.5365 87.7959 82.4933C87.7959 84.4501 86.2065 86.0364 84.2458 86.0364Z\"\n fill=\"white\"\n />\n <path\n d=\"M68.3044 86.0364C66.3437 86.0364 64.7543 84.4501 64.7543 82.4933C64.7543 80.5365 66.3437 78.9502 68.3044 78.9502C70.2651 78.9502 71.8545 80.5365 71.8545 82.4933C71.8545 84.4501 70.2651 86.0364 68.3044 86.0364Z\"\n fill=\"white\"\n />\n <path\n d=\"M100.183 86.0364C98.2226 86.0364 96.6332 84.4501 96.6332 82.4933C96.6332 80.5365 98.2226 78.9502 100.183 78.9502C102.144 78.9502 103.733 80.5365 103.733 82.4933C103.733 84.4501 102.144 86.0364 100.183 86.0364Z\"\n fill=\"white\"\n />\n <g filter=\"url(#filter0_empty_state)\">\n <path\n d=\"M171.522 68.7154C177.443 61.4539 181 52.1488 181 42C181 18.8027 162.421 0 139.5 0C116.579 0 98 18.8027 98 42C98 65.1973 116.579 84 139.5 84C146.622 84 153.328 82.1857 159.184 78.9829L172.801 82.5993L171.522 68.7154Z\"\n fill=\"white\"\n />\n <path\n d=\"M171.522 68.7154C177.443 61.4539 181 52.1488 181 42C181 18.8027 162.421 0 139.5 0C116.579 0 98 18.8027 98 42C98 65.1973 116.579 84 139.5 84C146.622 84 153.328 82.1857 159.184 78.9829L172.801 82.5993L171.522 68.7154Z\"\n stroke=\"#D7D4CE\"\n strokeWidth=\"2\"\n strokeMiterlimit=\"10\"\n />\n </g>\n <path\n d=\"M139.502 45.5431C137.541 45.5431 135.952 43.9568 135.952 42C135.952 40.0432 137.541 38.4569 139.502 38.4569C141.462 38.4569 143.052 40.0432 143.052 42C143.052 43.9568 141.462 45.5431 139.502 45.5431Z\"\n fill=\"#D7D4CE\"\n />\n <path\n d=\"M123.561 45.5431C121.601 45.5431 120.011 43.9568 120.011 42C120.011 40.0432 121.601 38.4569 123.561 38.4569C125.522 38.4569 127.111 40.0432 127.111 42C127.111 43.9568 125.522 45.5431 123.561 45.5431Z\"\n fill=\"#D7D4CE\"\n />\n <path\n d=\"M155.439 45.5431C153.478 45.5431 151.889 43.9568 151.889 42C151.889 40.0432 153.478 38.4569 155.439 38.4569C157.4 38.4569 158.989 40.0432 158.989 42C158.989 43.9568 157.4 45.5431 155.439 45.5431Z\"\n fill=\"#D7D4CE\"\n />\n </g>\n <defs>\n <filter\n id=\"filter0_empty_state\"\n x=\"97\"\n y=\"-1\"\n width=\"89\"\n height=\"90\"\n filterUnits=\"userSpaceOnUse\"\n colorInterpolationFilters=\"sRGB\"\n >\n <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n <feColorMatrix\n in=\"SourceAlpha\"\n type=\"matrix\"\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\n result=\"hardAlpha\"\n />\n <feOffset dx=\"4\" dy=\"4\" />\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\n <feColorMatrix\n type=\"matrix\"\n values=\"0 0 0 0 0.8428 0 0 0 0 0.830064 0 0 0 0 0.8095 0 0 0 1 0\"\n />\n <feBlend\n mode=\"normal\"\n in2=\"BackgroundImageFix\"\n result=\"effect1_dropShadow\"\n />\n <feBlend\n mode=\"normal\"\n in=\"SourceGraphic\"\n in2=\"effect1_dropShadow\"\n result=\"shape\"\n />\n </filter>\n <clipPath id=\"clip0_empty_state\">\n <rect width=\"233\" height=\"233\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n)\n\n/**\n * Empty state component shown when no channel is selected\n */\nexport const EmptyState = React.memo<{ hasChannels: boolean; channelsLoaded: boolean }>(\n ({ hasChannels, channelsLoaded }) => (\n <div className=\"messaging-empty-state flex items-center justify-center h-full p-8 text-balance\">\n <div className=\"flex flex-col items-center max-w-sm text-center\">\n <ChatBubblesIllustration />\n {channelsLoaded && !hasChannels && (\n <div className=\"mt-8\">\n <h2 className=\"font-medium text-black text-[18px] mb-2\">\n Your inbox is empty\n </h2>\n <p className=\"text-[#676B5F] text-sm mb-6\">\n Share with your followers to start receiving messages\n </p>\n </div>\n )}\n </div>\n </div>\n))\nEmptyState.displayName = 'EmptyState'\n","import React from 'react'\n\ntype ErrorStateProps = {\n message: string\n onBack?: () => void\n}\n\n/**\n * Error state component shown when something goes wrong\n */\nexport const ErrorState = React.memo<ErrorStateProps>(({ message, onBack }) => (\n <div className=\"messaging-error-state flex items-center justify-center h-full p-8\">\n <div className=\"text-center max-w-sm\">\n <div className=\"w-24 h-24 bg-danger-alt/20 rounded-full flex items-center justify-center mx-auto mb-6\">\n <span className=\"text-4xl\">⚠️</span>\n </div>\n\n <h2 className=\"font-semibold text-charcoal mb-2\">Oops!</h2>\n\n <p className=\"text-stone text-sm mb-6\">{message}</p>\n\n {onBack && (\n <button\n type=\"button\"\n onClick={onBack}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-[#7f22fe] hover:bg-primary-alt rounded-lg focus:outline-none focus:ring-2 focus:ring-primary transition-colors\"\n >\n Go Back\n </button>\n )}\n </div>\n </div>\n))\nErrorState.displayName = 'ErrorState'\n","import classNames from 'classnames'\nimport React, { useState, useCallback, useRef, useEffect } from 'react'\nimport type { Channel } from 'stream-chat'\n\nimport { useMessaging } from '../../hooks/useMessaging'\nimport type { MessagingShellProps, Participant } from '../../types'\nimport { ChannelList } from '../ChannelList'\nimport { ChannelView } from '../ChannelView'\nimport { ParticipantPicker } from '../ParticipantPicker'\n\nimport { EmptyState } from './EmptyState'\nimport { ErrorState } from './ErrorState'\nimport { LoadingState } from './LoadingState'\n\n/**\n * Main messaging interface component that combines channel list and channel view\n */\nexport const MessagingShell: React.FC<MessagingShellProps> = ({\n capabilities = {},\n className,\n renderMessageInputActions,\n onChannelSelect,\n onParticipantSelect,\n initialParticipantFilter,\n initialParticipantData,\n CustomChannelEmptyState,\n showChannelList = true,\n filters,\n channelListCustomEmptyStateIndicator,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n}) => {\n const {\n service,\n client,\n isConnected,\n isLoading,\n error,\n refreshConnection,\n debug,\n } = useMessaging()\n\n const [selectedChannel, setSelectedChannel] = useState<Channel | null>(null)\n const [hasChannels, setHasChannels] = useState(false)\n const [channelsLoaded, setChannelsLoaded] = useState(false)\n const [_showParticipantPicker, setShowParticipantPicker] = useState(false)\n const [existingParticipantIds, setExistingParticipantIds] = useState<\n Set<string>\n >(new Set())\n const [pickerKey, _setPickerKey] = useState(0) // Key to force remount of ParticipantPicker\n const [directConversationMode, setDirectConversationMode] = useState(false)\n const [directConversationError, setDirectConversationError] = useState<\n string | null\n >(null)\n\n const participantPickerRef = useRef<HTMLDialogElement>(null)\n\n const {\n participantSource,\n participantLabel = 'participants',\n showDeleteConversation = true,\n } = capabilities\n\n // Create default filters and merge with provided filters\n const channelFilters = React.useMemo(() => {\n const userId = client?.userID\n\n // Base filters that should always be present\n const baseFilters = {\n type: 'messaging',\n last_message_at: { $exists: true },\n ...(userId && {\n members: { $in: [userId] },\n hidden: false,\n }),\n }\n\n // Merge provided filters with base filters\n // Provided filters can override base filters if needed\n return {\n ...baseFilters,\n ...filters,\n }\n }, [filters, client?.userID])\n\n // Track if we've already synced channels to prevent repeated API calls\n const syncedRef = useRef<string | null>(null)\n\n // Function to sync channels (extracted for reuse)\n const syncChannels = useCallback(async () => {\n if (!client || !isConnected) return\n\n const userId = client.userID\n if (!userId) return\n\n try {\n if (debug) {\n console.log('[MessagingShell] Syncing channels for user:', userId)\n }\n\n const channels = await client.queryChannels(\n {\n type: 'messaging',\n members: { $in: [userId] },\n },\n {},\n { limit: 100 }\n )\n\n const memberIds = new Set<string>()\n channels.forEach((channel: Channel) => {\n const members = channel.state.members\n Object.values(members).forEach((member) => {\n const memberId = member.user?.id\n if (memberId && memberId !== userId) {\n memberIds.add(memberId)\n }\n })\n })\n\n // Only update if the set contents have changed to prevent re-renders\n setExistingParticipantIds((prev) => {\n if (\n prev.size === memberIds.size &&\n [...prev].every((id) => memberIds.has(id))\n ) {\n return prev\n }\n return memberIds\n })\n setHasChannels(channels.length > 0)\n setChannelsLoaded(true)\n syncedRef.current = userId // Mark as synced for this user\n\n if (debug) {\n console.log('[MessagingShell] Channels synced successfully:', {\n channelCount: channels.length,\n memberCount: memberIds.size,\n })\n }\n } catch (error) {\n console.error('[MessagingShell] Failed to sync channels:', error)\n // Don't mark as synced on error, allow retry\n }\n }, [client, isConnected, debug])\n\n // Sync existing channels to track which participants we can already message\n useEffect(() => {\n if (!client || !isConnected) return\n\n const userId = client.userID\n if (!userId) return\n\n // Prevent repeated sync for the same user\n if (syncedRef.current === userId) return\n\n syncChannels()\n }, [client, isConnected, syncChannels])\n\n // Load initial channel for direct conversation mode\n useEffect(() => {\n if (!initialParticipantFilter || !client || !isConnected) return\n\n const loadInitialChannel = async () => {\n const userId = client.userID\n if (!userId) return\n\n try {\n if (debug) {\n console.log(\n '[MessagingShell] Loading initial conversation with:',\n initialParticipantFilter\n )\n }\n\n const channels = await client.queryChannels(\n {\n type: 'messaging',\n members: { $eq: [userId, initialParticipantFilter] },\n },\n {},\n { limit: 1 }\n )\n\n if (channels.length > 0) {\n setSelectedChannel(channels[0])\n setDirectConversationMode(true)\n setDirectConversationError(null)\n\n // Notify parent component of channel selection\n if (onChannelSelect) {\n onChannelSelect(channels[0])\n }\n\n if (debug) {\n console.log(\n '[MessagingShell] Initial conversation loaded:',\n channels[0].id\n )\n }\n } else {\n // No channel found - try to create one if participant data is provided\n if (initialParticipantData && service) {\n if (debug) {\n console.log(\n '[MessagingShell] No conversation found, creating one for:',\n initialParticipantData\n )\n }\n\n try {\n // Use the existing service method to create the channel\n const channel = await service.startChannelWithParticipant({\n id: initialParticipantData.id,\n name: initialParticipantData.name,\n email: initialParticipantData.email,\n phone: initialParticipantData.phone,\n })\n\n setSelectedChannel(channel)\n setDirectConversationMode(true)\n setDirectConversationError(null)\n\n // Notify parent component of channel selection\n if (onChannelSelect) {\n onChannelSelect(channel)\n }\n\n if (debug) {\n console.log(\n '[MessagingShell] Channel created and loaded:',\n channel.id\n )\n }\n } catch (createErr) {\n console.error(\n '[MessagingShell] Failed to create conversation:',\n createErr\n )\n setDirectConversationError('Failed to create conversation')\n }\n } else {\n // No participant data provided, show error\n setDirectConversationError(\n 'No conversation found with this account'\n )\n\n if (debug) {\n console.log(\n '[MessagingShell] No conversation found for:',\n initialParticipantFilter\n )\n }\n }\n }\n } catch (err) {\n console.error(\n '[MessagingShell] Failed to load initial conversation:',\n err\n )\n setDirectConversationError('Failed to load conversation')\n }\n }\n\n loadInitialChannel()\n }, [\n initialParticipantFilter,\n initialParticipantData,\n client,\n isConnected,\n service,\n debug,\n onChannelSelect,\n ])\n\n const handleChannelSelect = useCallback(\n (channel: Channel) => {\n setSelectedChannel(channel)\n onChannelSelect?.(channel)\n },\n [onChannelSelect]\n )\n\n const handleBackToChannelList = useCallback(() => {\n // In direct conversation mode, don't allow going back to channel list\n // The parent component should handle navigation\n if (directConversationMode) return\n\n setSelectedChannel(null)\n }, [directConversationMode])\n\n const handleSelectParticipant = useCallback(\n async (participant: Participant) => {\n if (!service) return\n\n try {\n if (debug) {\n console.log(\n '[MessagingShell] Starting conversation with:',\n participant.id\n )\n }\n\n const channel = await service.startChannelWithParticipant({\n id: participant.id,\n name: participant.name,\n email: participant.email,\n phone: participant.phone,\n })\n\n // Show the channel\n try {\n await channel.show()\n } catch (error) {\n console.warn('[MessagingShell] Failed to unhide channel:', error)\n }\n\n setSelectedChannel(channel)\n setShowParticipantPicker(false)\n participantPickerRef.current?.close()\n\n onParticipantSelect?.(participant)\n } catch (error) {\n console.error('[MessagingShell] Failed to start conversation:', error)\n }\n },\n [service, onParticipantSelect, debug]\n )\n\n const handleCloseParticipantPicker = useCallback(() => {\n setShowParticipantPicker(false)\n participantPickerRef.current?.close()\n }, [])\n\n const handleDialogBackdropClick = useCallback(\n (e: React.MouseEvent<HTMLDialogElement>) => {\n if (e.target === participantPickerRef.current) {\n handleCloseParticipantPicker()\n }\n },\n [handleCloseParticipantPicker]\n )\n\n const handleLeaveConversation = useCallback(\n async (channel: Channel) => {\n if (debug) {\n console.log('[MessagingShell] Leaving conversation:', channel.id)\n }\n setSelectedChannel(null)\n setDirectConversationMode(false) // Exit direct conversation mode\n\n // Force re-sync to update the existing participants list\n syncedRef.current = null\n await syncChannels()\n },\n [syncChannels, debug]\n )\n\n const handleBlockParticipant = useCallback(\n async (participantId?: string) => {\n if (debug) {\n console.log('[MessagingShell] Blocking participant:', participantId)\n }\n setSelectedChannel(null)\n setDirectConversationMode(false) // Exit direct conversation mode\n\n // Force re-sync to update the existing participants list\n syncedRef.current = null\n await syncChannels()\n },\n [syncChannels, debug]\n )\n\n const isChannelSelected = Boolean(selectedChannel)\n\n console.log('[MessagingShell] render', {\n isLoading,\n error,\n isConnected,\n hasClient: !!client,\n directConversationError,\n selectedChannelId: selectedChannel?.id,\n directConversationMode\n })\n\n // Show loading state\n if (isLoading) {\n console.log('[MessagingShell] showing LOADING state')\n return (\n <div className={classNames('h-full', className)}>\n <LoadingState />\n </div>\n )\n }\n\n // Show error state\n if (error) {\n console.log('[MessagingShell] showing ERROR state:', error)\n return (\n <div className={classNames('h-full', className)}>\n <ErrorState message={error} onBack={refreshConnection} />\n </div>\n )\n }\n\n // Show not connected state\n if (!isConnected || !client) {\n console.log('[MessagingShell] showing NOT CONNECTED state')\n return (\n <div className={classNames('h-full', className)}>\n <ErrorState\n message=\"Not connected to messaging service\"\n onBack={refreshConnection}\n />\n </div>\n )\n }\n\n // Show direct conversation error state\n if (directConversationError) {\n console.log('[MessagingShell] showing DIRECT CONVERSATION ERROR:', directConversationError)\n return (\n <div className={classNames('h-full', className)}>\n <ErrorState message={directConversationError} />\n </div>\n )\n }\n\n console.log('[MessagingShell] rendering main UI with ChannelView')\n return (\n <div\n className={classNames(\n 'messaging-shell h-full bg-background-secondary overflow-hidden',\n className\n )}\n >\n <div className=\"flex h-full min-h-0\">\n {/* Channel List Sidebar */}\n <div\n className={classNames(\n 'messaging-channel-list-sidebar min-h-0 min-w-0 lg:flex lg:flex-col',\n {\n '!hidden': showChannelList === false || directConversationMode,\n // Hide on mobile when channel selected, show on desktop with consistent narrow width\n 'hidden lg:flex lg:w-80 lg:min-w-[280px] lg:max-w-[360px]':\n showChannelList !== false &&\n !directConversationMode &&\n isChannelSelected,\n // Show on mobile when no channel selected, use same narrow width on desktop\n 'flex flex-col w-full lg:w-80 lg:min-w-[280px] lg:max-w-[360px]':\n showChannelList !== false &&\n !directConversationMode &&\n !isChannelSelected,\n }\n )}\n >\n <ChannelList\n onChannelSelect={handleChannelSelect}\n selectedChannel={selectedChannel || undefined}\n filters={channelFilters}\n customEmptyStateIndicator={channelListCustomEmptyStateIndicator}\n />\n </div>\n\n {/* Channel View */}\n <div\n className={classNames(\n 'messaging-conversation-view flex-1 flex-col min-w-0 min-h-0',\n {\n // In direct conversation mode, always show (full width)\n flex: directConversationMode || isChannelSelected,\n // Normal mode: hide on mobile when no channel selected\n 'hidden lg:flex': !directConversationMode && !isChannelSelected,\n }\n )}\n >\n {selectedChannel ? (\n <div className=\"flex-1 min-h-0 flex flex-col\">\n <ChannelView\n channel={selectedChannel}\n key={selectedChannel.id}\n onBack={handleBackToChannelList}\n showBackButton={!directConversationMode}\n renderMessageInputActions={renderMessageInputActions}\n onLeaveConversation={handleLeaveConversation}\n onBlockParticipant={handleBlockParticipant}\n CustomChannelEmptyState={CustomChannelEmptyState}\n showDeleteConversation={showDeleteConversation}\n onDeleteConversationClick={onDeleteConversationClick}\n onBlockParticipantClick={onBlockParticipantClick}\n onReportParticipantClick={onReportParticipantClick}\n />\n </div>\n ) : (\n <EmptyState\n hasChannels={hasChannels}\n channelsLoaded={channelsLoaded}\n />\n )}\n </div>\n </div>\n\n {/* Participant Picker Dialog */}\n {participantSource && (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions\n <dialog\n ref={participantPickerRef}\n className=\"mes-dialog\"\n onClick={handleDialogBackdropClick}\n onClose={handleCloseParticipantPicker}\n >\n <div className=\"h-full w-full bg-white shadow-max-elevation-light\">\n <ParticipantPicker\n key={pickerKey}\n participantSource={participantSource}\n onSelectParticipant={handleSelectParticipant}\n onClose={handleCloseParticipantPicker}\n existingParticipantIds={existingParticipantIds}\n participantLabel={participantLabel}\n searchPlaceholder={`Search ${participantLabel}...`}\n />\n </div>\n </dialog>\n )}\n </div>\n )\n}\n","import classNames from 'classnames'\nimport React from 'react'\nexport interface FaqListItemProps {\n question: string\n onClick: () => void\n loading?: boolean\n className?: string\n}\n\nexport const FaqListItem: React.FC<FaqListItemProps> = ({\n question,\n onClick,\n loading = false,\n className,\n}) => {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={loading}\n style={{ backgroundColor: '#E6E5E3' }}\n className={classNames(\n 'w-full text-center p-4 rounded-xl text-charcoal font-medium transition-colors',\n {\n 'hover:brightness-95 active:brightness-90': !loading,\n 'opacity-50 cursor-not-allowed': loading,\n },\n className\n )}\n >\n {question}\n </button>\n )\n}\n","import React from 'react'\n\nimport { Avatar } from '../Avatar'\n\nimport { FaqListItem } from './FaqListItem'\n\nexport interface Faq {\n id: string\n question: string\n answer: string\n enabled: boolean\n order?: number | null\n}\n\nexport interface FaqListProps {\n faqs: Faq[]\n onFaqClick: (faqId: string) => void\n loadingFaqId?: string | null\n headerText?: string\n className?: string\n avatarImage?: string\n avatarName?: string\n}\n\nexport const FaqList: React.FC<FaqListProps> = ({\n faqs,\n onFaqClick,\n loadingFaqId,\n headerText,\n className,\n avatarImage,\n avatarName,\n}) => {\n const enabledFaqs = faqs\n .filter((faq) => faq.enabled)\n .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))\n\n if (enabledFaqs.length === 0) {\n return null\n }\n\n return (\n <div className={className}>\n <div className=\"flex gap-3 items-end\">\n {/* Avatar at bottom-left, outside grey background */}\n {(avatarImage || avatarName) && (\n <div className=\"flex-none\">\n <Avatar\n id={avatarName || 'account'}\n name={avatarName || 'Account'}\n image={avatarImage}\n size={24}\n shape=\"circle\"\n />\n </div>\n )}\n\n {/* FAQs with grey background */}\n <div\n className=\"flex-1 flex flex-col gap-3 rounded-lg p-4\"\n style={{ backgroundColor: '#F1F0EE' }}\n >\n {headerText && (\n <p className=\"text-md text-charcoal mb-4\">{headerText}</p>\n )}\n {enabledFaqs.map((faq) => (\n <FaqListItem\n key={faq.id}\n question={faq.question}\n onClick={() => onFaqClick(faq.id)}\n loading={loadingFaqId === faq.id}\n />\n ))}\n </div>\n </div>\n </div>\n )\n}\n","import { useState, useEffect, useCallback } from 'react';\n\nimport type { ParticipantSource, Participant } from '../types';\n\n/**\n * Hook for managing participant loading with search and pagination\n */\nexport const useParticipants = (\n participantSource: ParticipantSource,\n options: {\n initialSearch?: string;\n pageSize?: number;\n } = {}\n) => {\n const { initialSearch = '', pageSize = 20 } = options;\n \n const [participants, setParticipants] = useState<Participant[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [searchQuery, setSearchQuery] = useState(initialSearch);\n const [hasMore, setHasMore] = useState(true);\n const [cursor, setCursor] = useState<string | undefined>();\n\n // Load participants with current search query\n const loadParticipants = useCallback(async (\n reset = false,\n customSearch?: string\n ) => {\n if (loading) return;\n \n const search = customSearch !== undefined ? customSearch : searchQuery;\n \n setLoading(true);\n setError(null);\n\n try {\n const result = await participantSource.loadParticipants({\n search: search || undefined,\n limit: pageSize,\n cursor: reset ? undefined : cursor,\n });\n\n setParticipants(prev => \n reset ? result.participants : [...prev, ...result.participants]\n );\n setHasMore(result.hasMore);\n setCursor(result.nextCursor);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Failed to load participants';\n setError(errorMessage);\n console.error('[useParticipants] Load error:', err);\n } finally {\n setLoading(false);\n }\n }, [participantSource, searchQuery, cursor, pageSize, loading]);\n\n // Load more participants (pagination)\n const loadMore = useCallback(() => {\n if (hasMore && !loading) {\n loadParticipants(false);\n }\n }, [hasMore, loading, loadParticipants]);\n\n // Search participants\n const search = useCallback((query: string) => {\n setSearchQuery(query);\n setCursor(undefined);\n loadParticipants(true, query);\n }, [loadParticipants]);\n\n // Refresh participants\n const refresh = useCallback(() => {\n setCursor(undefined);\n loadParticipants(true);\n }, [loadParticipants]);\n\n // Initial load - only run once when participantSource changes\n useEffect(() => {\n loadParticipants(true);\n }, [participantSource.loadParticipants]); // Only depend on the function to avoid loops\n\n return {\n participants,\n loading,\n error,\n searchQuery,\n hasMore,\n totalCount: participantSource.totalCount,\n loadMore,\n search,\n refresh,\n };\n};\n"],"names":["MessagingContext","createContext","useMessagingContext","useContext","MessagingProvider","children","user","serviceConfig","apiKey","capabilities","debug","debugLog","useCallback","message","args","service","setService","useState","client","setClient","isConnected","setIsConnected","isLoading","setIsLoading","error","setError","connectingRef","useRef","prevPropsRef","renderCountRef","useEffect","currentRender","newService","StreamChatService","connectedUserRef","_a","_b","streamClient","err","errorMessage","refreshConnection","contextValue","React","jsx","Chat","useMessaging","getDaysDifference","date1","date2","d1","diffTime","formatRelativeTime","date","now","daysDiff","EMOJIS","hashString","str","hash","i","char","getAvatarEmoji","id","index","Avatar","image","size","className","shape","emoji","fontSizeClass","borderStyle","classNames","CustomChannelPreview","channel","selectedChannel","onChannelSelect","unread","isSelected","handleClick","participant","member","participantName","participantImage","_c","lastMessage","_e","_d","lastMessageText","attachment","lastMessageTime","unreadCount","jsxs","_f","ChannelList","filters","customEmptyStateIndicator","PreviewComponent","props","StreamChannelList","ActionButton","variant","rest","IconButton","label","CloseButton","onClick","XIcon","linkPreviewsManagerStateSelector","state","preview","LinkPreviewsManager","CustomLinkPreviewCard","link","onDismiss","og_scrape_url","title","image_url","e","CustomLinkPreviewList","linkPreviewsManager","useMessageComposer","stateLinkPreviews","useStateStore","handleDismiss","url","linkPreview","CustomMessageInputInner","handleSubmit","useMessageInputContext","hasSendableData","useMessageComposerHasSendableData","Fragment","SimpleAttachmentSelector","QuotedMessagePreview","AttachmentPreviewList","TextareaComposer","ArrowUpIcon","CustomMessageInput","renderActions","MessageInput","CustomSystemMessage","isDateHidden","MessageTimestamp","ChannelEmptyState","Loading","LoadingState","CustomChannelHeader","onBack","showBackButton","onShowInfo","canShowInfo","useChannelStateContext","ArrowLeftIcon","DotsThreeIcon","ChannelInfoDialog","dialogRef","onClose","followerStatusLabel","onLeaveConversation","onBlockParticipant","showDeleteConversation","onDeleteConversationClick","onBlockParticipantClick","onReportParticipantClick","isParticipantBlocked","setIsParticipantBlocked","isLeaving","setIsLeaving","isUpdatingBlockStatus","setIsUpdatingBlockStatus","checkIsParticipantBlocked","isBlocked","handleLeaveConversation","actingUserId","handleBlockUser","handleUnblockUser","handleReportUser","participantEmail","participantUsername","participantSecondary","participantId","_g","SpinnerGapIcon","SignOutIcon","ProhibitInsetIcon","FlagIcon","ChannelViewInner","renderMessageInputActions","infoDialogRef","channelExtraData","handleShowInfo","handleCloseInfo","Window","MessageList","ChannelView","CustomChannelEmptyState","Channel","SearchInput","searchQuery","setSearchQuery","placeholder","searchInputRef","MagnifyingGlassIcon","ParticipantPicker","participantSource","onSelectParticipant","existingParticipantIds","participantLabel","searchPlaceholder","participants","setParticipants","loading","setLoading","startingChatWithId","setStartingChatWithId","loadedRef","result","availableParticipants","searchLower","handleSelectParticipant","handleKeyDown","event","ChatCircleDotsIcon","displayName","displaySecondary","ChatBubblesIllustration","EmptyState","hasChannels","channelsLoaded","ErrorState","MessagingShell","onParticipantSelect","initialParticipantFilter","initialParticipantData","showChannelList","channelListCustomEmptyStateIndicator","setSelectedChannel","setHasChannels","setChannelsLoaded","_showParticipantPicker","setShowParticipantPicker","setExistingParticipantIds","pickerKey","_setPickerKey","directConversationMode","setDirectConversationMode","directConversationError","setDirectConversationError","participantPickerRef","channelFilters","userId","syncedRef","syncChannels","channels","memberIds","members","memberId","prev","createErr","handleChannelSelect","handleBackToChannelList","handleCloseParticipantPicker","handleDialogBackdropClick","handleBlockParticipant","isChannelSelected","FaqListItem","question","FaqList","faqs","onFaqClick","loadingFaqId","headerText","avatarImage","avatarName","enabledFaqs","faq","a","b","useParticipants","options","initialSearch","pageSize","hasMore","setHasMore","cursor","setCursor","loadParticipants","reset","customSearch","search","loadMore","query","refresh"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/providers/MessagingProvider.tsx","../src/hooks/useMessaging.ts","../src/utils/formatRelativeTime.ts","../src/components/Avatar/getAvatarEmoji.ts","../src/components/Avatar/index.tsx","../src/components/ChannelList/CustomChannelPreview.tsx","../src/components/ChannelList/index.tsx","../src/components/ActionButton/index.tsx","../src/components/IconButton/index.tsx","../src/components/CloseButton/index.tsx","../src/components/CustomLinkPreviewList/index.tsx","../src/components/CustomMessageInput/index.tsx","../src/components/CustomSystemMessage/index.tsx","../src/components/MessagingShell/ChannelEmptyState.tsx","../src/components/Loading/index.tsx","../src/components/MessagingShell/LoadingState.tsx","../src/components/ChannelView.tsx","../src/components/SearchInput/index.tsx","../src/components/ParticipantPicker/index.tsx","../src/components/MessagingShell/EmptyState.tsx","../src/components/MessagingShell/ErrorState.tsx","../src/components/MessagingShell/index.tsx","../src/components/FaqList/FaqListItem.tsx","../src/components/FaqList/index.tsx","../src/hooks/useParticipants.ts"],"sourcesContent":["import { StreamChatService } from '@linktr.ee/messaging-core'\nimport React, {\n createContext,\n useContext,\n useEffect,\n useState,\n useRef,\n useCallback,\n} from 'react'\nimport type { StreamChat } from 'stream-chat'\nimport { Chat } from 'stream-chat-react'\n\nimport type { MessagingProviderProps, MessagingCapabilities } from '../types'\n\n/**\n * Context value for messaging state and service\n */\nexport interface MessagingContextValue {\n service: StreamChatService | null\n client: StreamChat | null // Stream Chat client\n isConnected: boolean\n isLoading: boolean\n error: string | null\n capabilities: MessagingCapabilities\n refreshConnection: () => Promise<void>\n debug: boolean\n}\n\nconst MessagingContext = createContext<MessagingContextValue>({\n service: null,\n client: null,\n isConnected: false,\n isLoading: false,\n error: null,\n capabilities: {},\n refreshConnection: async () => {},\n debug: false,\n})\n\n/**\n * Hook to access messaging context\n */\nexport const useMessagingContext = () => useContext(MessagingContext)\n\n/**\n * Provider component that wraps messaging-core with React state management\n */\nexport const MessagingProvider: React.FC<MessagingProviderProps> = ({\n children,\n user,\n serviceConfig,\n apiKey,\n capabilities = {},\n debug = false,\n}) => {\n // Create debug logger that respects the debug prop\n const debugLog = useCallback(\n (message: string, ...args: unknown[]) => {\n if (debug) {\n console.log(`🔥 [MessagingProvider] ${message}`, ...args)\n }\n },\n [debug]\n )\n\n debugLog('🔄 RENDER START', {\n userId: user?.id,\n apiKey: apiKey?.substring(0, 8) + '...',\n serviceConfig: !!serviceConfig,\n capabilities: Object.keys(capabilities),\n })\n\n const [service, setService] = useState<StreamChatService | null>(null)\n const [client, setClient] = useState<StreamChat | null>(null)\n const [isConnected, setIsConnected] = useState(false)\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n // Prevent multiple concurrent connection attempts\n const connectingRef = useRef(false)\n\n // Track renders and prop changes\n const prevPropsRef = useRef({\n userId: user?.id,\n apiKey,\n serviceConfig,\n capabilities,\n })\n const renderCountRef = useRef(0)\n renderCountRef.current++\n\n debugLog('📊 RENDER INFO', {\n renderCount: renderCountRef.current,\n currentProps: { userId: user?.id, apiKey: apiKey?.substring(0, 8) + '...' },\n propChanges: {\n userChanged: prevPropsRef.current.userId !== user?.id,\n apiKeyChanged: prevPropsRef.current.apiKey !== apiKey,\n serviceConfigChanged:\n prevPropsRef.current.serviceConfig !== serviceConfig,\n capabilitiesChanged: prevPropsRef.current.capabilities !== capabilities,\n },\n })\n\n prevPropsRef.current = {\n userId: user?.id,\n apiKey,\n serviceConfig,\n capabilities,\n }\n\n // Initialize service when config changes\n useEffect(() => {\n const currentRender = renderCountRef.current\n debugLog('🔧 SERVICE INIT EFFECT TRIGGERED', {\n renderCount: currentRender,\n apiKey: !!apiKey,\n serviceConfig: !!serviceConfig,\n dependencies: {\n apiKey: apiKey?.substring(0, 8) + '...',\n serviceConfigRef: serviceConfig,\n serviceConfigStable:\n prevPropsRef.current.serviceConfig === serviceConfig,\n apiKeyStable: prevPropsRef.current.apiKey === apiKey,\n },\n })\n\n if (!apiKey || !serviceConfig) {\n debugLog('⚠️ SERVICE INIT SKIPPED', {\n renderCount: currentRender,\n reason: 'Missing apiKey or serviceConfig',\n })\n return\n }\n\n debugLog('🚀 CREATING NEW SERVICE', {\n renderCount: currentRender,\n apiKey: apiKey?.substring(0, 8) + '...',\n serviceConfigChanged:\n prevPropsRef.current.serviceConfig !== serviceConfig,\n })\n\n const newService = new StreamChatService({\n ...serviceConfig,\n apiKey,\n debug,\n })\n\n setService(newService)\n debugLog('✅ SERVICE SET', {\n renderCount: currentRender,\n serviceInstance: !!newService,\n })\n\n return () => {\n debugLog('🧹 SERVICE CLEANUP', {\n renderCount: currentRender,\n reason: 'Effect cleanup',\n })\n newService.disconnectUser().catch(console.error)\n }\n }, [apiKey, serviceConfig, debug, debugLog]) // Use serviceConfig object directly, not individual properties\n\n // Track if we've already connected this user with this service to prevent duplicate connections\n const connectedUserRef = useRef<{\n serviceId: StreamChatService\n userId: string\n } | null>(null)\n\n // Connect user when service and user are available\n useEffect(() => {\n debugLog('🔗 USER CONNECTION EFFECT TRIGGERED', {\n hasService: !!service,\n hasUser: !!user,\n userId: user?.id,\n isConnecting: connectingRef.current,\n isConnected: isConnected,\n dependencies: { service: !!service, userId: user?.id },\n })\n\n if (!service || !user) {\n debugLog('⚠️ USER CONNECTION SKIPPED', 'Missing service or user')\n return\n }\n\n if (connectingRef.current) {\n debugLog('⚠️ USER CONNECTION SKIPPED', 'Already connecting')\n return\n }\n\n // Check if we've already connected this exact user with this exact service instance\n if (\n connectedUserRef.current?.serviceId === service &&\n connectedUserRef.current?.userId === user.id\n ) {\n debugLog(\n '⚠️ USER CONNECTION SKIPPED',\n 'Already connected this user with this service'\n )\n return\n }\n\n const connectUser = async () => {\n debugLog('🚀 STARTING USER CONNECTION', { userId: user.id })\n connectingRef.current = true\n setIsLoading(true)\n setError(null)\n\n try {\n debugLog('📞 CALLING SERVICE.CONNECTUSER', { userId: user.id })\n const streamClient = await service.connectUser(user)\n setClient(streamClient)\n setIsConnected(true)\n connectedUserRef.current = { serviceId: service, userId: user.id } // Mark as connected\n debugLog('✅ USER CONNECTION SUCCESS', {\n userId: user.id,\n clientId: streamClient.userID,\n })\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : 'Connection failed'\n setError(errorMessage)\n debugLog('❌ USER CONNECTION ERROR', {\n userId: user.id,\n error: errorMessage,\n })\n } finally {\n setIsLoading(false)\n connectingRef.current = false\n debugLog('🔄 USER CONNECTION FINISHED', {\n userId: user.id,\n isConnected,\n })\n }\n }\n\n connectUser()\n }, [service, user, debugLog, isConnected]) // Remove isConnected to prevent circular dependency\n\n // Disconnect when user is removed (cleanup effect)\n useEffect(() => {\n debugLog('🔌 CLEANUP EFFECT REGISTERED', {\n hasService: !!service,\n isConnected,\n })\n return () => {\n if (service && isConnected) {\n debugLog(\n '🧹 CLEANUP EFFECT TRIGGERED',\n 'Cleaning up connection on unmount'\n )\n connectedUserRef.current = null // Reset connection tracking\n service.disconnectUser().catch(console.error)\n } else {\n debugLog('🔇 CLEANUP EFFECT SKIPPED', {\n hasService: !!service,\n isConnected,\n })\n }\n }\n }, [service, isConnected, debugLog])\n\n const refreshConnection = useCallback(async () => {\n debugLog('🔄 REFRESH CONNECTION CALLED', {\n hasService: !!service,\n hasUser: !!user,\n })\n\n if (!service || !user) {\n debugLog('⚠️ REFRESH CONNECTION SKIPPED', 'Missing service or user')\n return\n }\n\n debugLog('🚀 STARTING CONNECTION REFRESH', { userId: user.id })\n setIsLoading(true)\n try {\n debugLog('🔌 DISCONNECTING FOR REFRESH')\n await service.disconnectUser()\n debugLog('📞 RECONNECTING FOR REFRESH')\n const streamClient = await service.connectUser(user)\n setClient(streamClient)\n setIsConnected(true)\n setError(null)\n debugLog('✅ CONNECTION REFRESH SUCCESS', { userId: user.id })\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Refresh failed'\n setError(errorMessage)\n debugLog('❌ CONNECTION REFRESH ERROR', {\n userId: user.id,\n error: errorMessage,\n })\n } finally {\n setIsLoading(false)\n debugLog('🔄 CONNECTION REFRESH FINISHED', { userId: user.id })\n }\n }, [service, user, debugLog])\n\n // Memoize context value to prevent unnecessary re-renders\n const contextValue: MessagingContextValue = React.useMemo(() => {\n debugLog('💫 CONTEXT VALUE MEMOIZATION', {\n hasService: !!service,\n hasClient: !!client,\n isConnected,\n isLoading,\n hasError: !!error,\n capabilitiesKeys: Object.keys(capabilities),\n })\n\n return {\n service,\n client,\n isConnected,\n isLoading,\n error,\n capabilities,\n refreshConnection,\n debug,\n }\n }, [\n service,\n client,\n isConnected,\n isLoading,\n error,\n capabilities,\n refreshConnection,\n debug,\n debugLog,\n ])\n\n debugLog('🔄 RENDER END', {\n renderCount: renderCountRef.current,\n willRenderChat: !!(client && isConnected),\n contextValueReady: !!contextValue,\n })\n\n return (\n <MessagingContext.Provider value={contextValue}>\n {client && isConnected ? (\n <Chat\n client={client}\n customClasses={{\n channelList:\n 'str-chat__channel-list str-chat__channel-list-react bg-transparent lg:border-r-2 border-r-0 border-[#0000000A]',\n }}\n >\n {children}\n </Chat>\n ) : (\n children\n )}\n </MessagingContext.Provider>\n )\n}\n","import { useMessagingContext } from '../providers/MessagingProvider';\nimport type { MessagingContextValue } from '../providers/MessagingProvider';\n\n/**\n * Hook to access messaging service and state\n */\nexport const useMessaging = (): MessagingContextValue => {\n return useMessagingContext();\n};\n","/**\n * Get the number of days between two dates (calendar days in UTC, not 24-hour periods)\n * Uses UTC to ensure consistent day calculations globally since messages are stored in UTC\n */\nconst getDaysDifference = (date1: Date, date2: Date): number => {\n const d1 = new Date(\n Date.UTC(date1.getUTCFullYear(), date1.getUTCMonth(), date1.getUTCDate())\n )\n const d2 = new Date(\n Date.UTC(date2.getUTCFullYear(), date2.getUTCMonth(), date2.getUTCDate())\n )\n const diffTime = d2.getTime() - d1.getTime()\n return Math.floor(diffTime / (1000 * 60 * 60 * 24))\n}\n\n/**\n * Format a date - shows time for today, relative time for older messages\n * (e.g., \"Just now\", \"2:08 PM\" for today, \"Yesterday\" for yesterday, \"2d\" for 2 days ago)\n */\nexport const formatRelativeTime = (date: Date): string => {\n const now = new Date()\n const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000)\n\n // Less than 1 minute\n if (diffInSeconds < 60) {\n return 'Just now'\n }\n\n // Check if it's today (same calendar day)\n const daysDiff = getDaysDifference(date, now)\n\n // If today, show the time (e.g., \"2:08 PM\")\n if (daysDiff === 0) {\n return date.toLocaleTimeString([], {\n hour: 'numeric',\n minute: '2-digit',\n })\n }\n\n // Yesterday\n if (daysDiff === 1) {\n return 'Yesterday'\n }\n\n // Less than 7 days - show days\n if (daysDiff < 7) {\n return `${daysDiff}d`\n }\n\n // Less than 4 weeks - show weeks\n if (daysDiff < 28) {\n const weeks = Math.floor(daysDiff / 7)\n return `${weeks}w`\n }\n\n // More than 4 weeks - show date as MM/DD/YY\n return date.toLocaleDateString('en-US', {\n month: 'numeric',\n day: 'numeric',\n year: '2-digit',\n })\n}\n","/**\n * Generate a fruit emoji based on a string id\n * Returns a consistent fruit emoji for the same id\n */\nconst EMOJIS = [\n '🍎', // Apple\n '🍌', // Banana\n '🍇', // Grape\n '🍊', // Orange\n '🍓', // Strawberry\n '🥥', // Coconut\n '🍒', // Cherry\n '🥭', // Mango\n '🍉', // Watermelon\n '🍋', // Lemon\n '🥝', // Kiwi\n '🫒', // Olive\n '🍈', // Melon\n]\n\n/**\n * Simple hash function to convert string to number\n */\nfunction hashString(str: string): number {\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32-bit integer\n }\n return Math.abs(hash)\n}\n\n/**\n * Get a fruit emoji based on an id string\n * @param id - The string id to generate emoji from\n * @returns A fruit emoji string\n */\nexport function getAvatarEmoji(id: string): string {\n const hash = hashString(id)\n const index = hash % EMOJIS.length\n return EMOJIS[index]\n}\n\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport { getAvatarEmoji } from './getAvatarEmoji'\n\nexport interface AvatarProps {\n id: string\n name: string\n image?: string\n size?: number\n className?: string\n shape?: 'squircle' | 'circle'\n}\n\n/**\n * Avatar component that displays a user image or colored initial fallback\n */\nexport const Avatar: React.FC<AvatarProps> = ({\n id,\n image,\n size = 40,\n className,\n shape = 'squircle',\n}) => {\n const emoji = getAvatarEmoji(id)\n\n // Determine font size based on avatar size\n const getFontSizeClass = () => {\n if (size < 32) return 'text-xs'\n if (size < 56) return 'text-sm'\n return 'text-lg'\n }\n\n const fontSizeClass = getFontSizeClass()\n\n const borderStyle =\n shape === 'circle'\n ? { borderRadius: '50%' }\n : {\n borderRadius: '33%',\n 'corner-shape': 'superellipse(1.3)',\n }\n\n return (\n <div\n className={classNames('flex-shrink-0 overflow-hidden', className)}\n style={{\n width: `${size}px`,\n height: `${size}px`,\n ...borderStyle,\n }}\n >\n {image ? (\n <img\n src={image}\n alt=\"\"\n className=\"h-full w-full object-cover aspect-square\"\n />\n ) : (\n <div\n aria-hidden=\"true\"\n className={classNames(\n 'avatar-fallback flex h-full w-full items-center justify-center font-semibold bg-[#E6E5E3] select-none transition-colors',\n fontSizeClass\n )}\n >\n {emoji}\n </div>\n )}\n </div>\n )\n}\n","import classNames from 'classnames'\nimport React from 'react'\nimport { Channel } from 'stream-chat'\nimport { ChannelPreviewUIComponentProps } from 'stream-chat-react'\n\nimport { formatRelativeTime } from '../../utils/formatRelativeTime'\nimport { Avatar } from '../Avatar'\n\ntype CustomChannelPreviewProps = ChannelPreviewUIComponentProps & {\n selectedChannel?: Channel | null\n onChannelSelect: (channel: Channel) => void\n debug?: boolean\n}\n\n/**\n * Custom channel preview that handles selection\n */\nconst CustomChannelPreview = React.memo<CustomChannelPreviewProps>(\n ({ channel, selectedChannel, onChannelSelect, debug = false, unread }) => {\n const isSelected = selectedChannel?.id === channel?.id\n\n const handleClick = () => {\n if (channel) {\n onChannelSelect(channel)\n }\n }\n\n // Get participant info\n const members = Object.values(channel?.state?.members || {})\n const participant = members.find(\n (member) => member.user?.id && member.user.id !== channel?._client?.userID\n )\n const participantName = participant?.user?.name || 'Conversation'\n const participantImage = participant?.user?.image\n\n // Get last message and format timestamp\n const lastMessage =\n channel?.state?.messages?.[channel.state.messages.length - 1]\n\n // Fallback order: text -> attachment URL -> \"No messages yet\"\n const getLastMessageText = () => {\n if (lastMessage?.text) return lastMessage.text\n\n const attachment = lastMessage?.attachments?.[0]\n if (attachment?.asset_url) return attachment.asset_url\n if (attachment?.image_url) return attachment.image_url\n if (attachment?.og_scrape_url) return attachment.og_scrape_url\n if (attachment?.thumb_url) return attachment.thumb_url\n\n return 'No messages yet'\n }\n\n const lastMessageText = getLastMessageText()\n const lastMessageTime = lastMessage?.created_at\n ? formatRelativeTime(new Date(lastMessage.created_at))\n : ''\n\n // Use the unread prop passed by Stream Chat (reactive and updates automatically)\n const unreadCount = unread ?? 0\n\n if (debug) {\n console.log('📺 [ChannelList] 📋 CHANNEL PREVIEW RENDER', {\n channelId: channel?.id,\n isSelected,\n participantName,\n unreadCount,\n hasTimestamp: !!lastMessageTime,\n })\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n className={classNames(\n 'group w-full px-4 py-3 transition-colors text-left max-w-full overflow-hidden focus-ring',\n {\n 'bg-primary-alt/10 border-l-4 border-l-primary': isSelected,\n 'hover:bg-sand': !isSelected,\n }\n )}\n >\n <div className=\"flex items-start gap-3\">\n {/* Avatar */}\n <Avatar\n id={participant?.user?.id || channel.id || 'unknown'}\n name={participantName}\n image={participantImage}\n size={44}\n className=\"[&_.avatar-fallback]:group-hover:bg-[#eeeeee]\"\n />\n\n {/* Content column */}\n <div className=\"flex-1 min-w-0 flex flex-col gap-1\">\n {/* Name and timestamp row */}\n <div className=\"flex items-center justify-between gap-2\">\n <h3\n className={classNames(\n 'text-sm font-medium truncate',\n isSelected ? 'text-primary' : 'text-charcoal'\n )}\n >\n {participantName}\n </h3>\n {lastMessageTime && (\n <span className=\"text-xs text-stone flex-shrink-0\">\n {lastMessageTime}\n </span>\n )}\n </div>\n\n {/* Message and unread badge row */}\n <div className=\"flex items-center justify-between gap-2 min-w-0\">\n <p className=\"text-xs text-stone mr-2 flex-1 line-clamp-2\">\n {lastMessageText}\n </p>\n {unreadCount > 0 && (\n <span className=\"bg-[#7f22fe] text-white text-xs px-2 py-0.5 rounded-full min-w-[20px] text-center flex-shrink-0\">\n {unreadCount > 99 ? '99+' : unreadCount}\n </span>\n )}\n </div>\n </div>\n </div>\n </button>\n )\n }\n)\n\nexport default CustomChannelPreview\nCustomChannelPreview.displayName = 'CustomChannelPreview'\n","import classNames from 'classnames'\nimport React from 'react'\nimport type { ChannelPreviewUIComponentProps } from 'stream-chat-react'\nimport { ChannelList as StreamChannelList } from 'stream-chat-react'\n\nimport { useMessagingContext } from '../../providers/MessagingProvider'\nimport type { ChannelListProps } from '../../types'\n\nimport CustomChannelPreview from './CustomChannelPreview'\n\n/**\n * Channel list component with customizable header and actions\n */\nexport const ChannelList = React.memo<ChannelListProps>(\n ({\n onChannelSelect,\n selectedChannel,\n filters,\n className,\n customEmptyStateIndicator,\n }) => {\n // Track renders\n const renderCountRef = React.useRef(0)\n renderCountRef.current++\n\n // Get debug flag from context\n const { debug = false } = useMessagingContext()\n\n if (debug) {\n console.log('📺 [ChannelList] 🔄 RENDER START', {\n renderCount: renderCountRef.current,\n selectedChannelId: selectedChannel?.id,\n filters,\n })\n }\n\n // Memoize Preview component to prevent re-renders\n const PreviewComponent = React.useMemo(() => {\n const Preview = (props: ChannelPreviewUIComponentProps) => (\n <CustomChannelPreview\n {...props}\n selectedChannel={selectedChannel}\n onChannelSelect={onChannelSelect}\n debug={debug}\n />\n )\n return Preview\n }, [selectedChannel, onChannelSelect, debug])\n\n return (\n <div\n className={classNames(\n 'messaging-channel-list h-full flex flex-col min-w-0 overflow-hidden',\n className\n )}\n >\n {/* Channel List */}\n <div className=\"flex-1 overflow-hidden min-w-0\">\n <StreamChannelList\n key={JSON.stringify(filters)}\n filters={filters}\n sort={{ last_message_at: -1 }}\n options={{ limit: 30 }}\n Preview={PreviewComponent}\n EmptyStateIndicator={customEmptyStateIndicator}\n />\n </div>\n </div>\n )\n }\n)\nChannelList.displayName = 'ChannelList'\n","import classNames from \"classnames\";\nimport React from \"react\";\n\ninterface ActionButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: \"default\" | \"danger\";\n}\n\nconst ActionButton = ({\n variant = \"default\",\n className,\n children,\n ...rest\n}: ActionButtonProps) => {\n const isDanger = variant === \"danger\";\n return (\n <button\n type=\"button\"\n className={classNames(\n \"flex w-full items-center gap-3 rounded-lg px-4 py-3 text-left text-sm transition-colors focus-ring disabled:cursor-not-allowed disabled:opacity-60\",\n isDanger\n ? \"text-danger hover:bg-danger/50\"\n : \"text-charcoal hover:bg-sand\",\n className,\n )}\n {...rest}\n >\n {children}\n </button>\n );\n};\n\nexport default ActionButton;\n","import classNames from \"classnames\";\nimport React from \"react\";\n\ninterface IconButtonProps\n extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n \"type\" | \"children\"\n > {\n label: string;\n children: React.ReactNode;\n className?: string;\n}\n\nexport function IconButton({ label, className, children, ...rest }: IconButtonProps) {\n return (\n <button\n type=\"button\"\n className={classNames(\n \"rounded-full p-2 transition-colors focus-ring\",\n {\n \"cursor-not-allowed opacity-50\": rest.disabled,\n \"hover:bg-sand\": !rest.disabled,\n },\n className,\n )}\n {...rest}\n >\n <span className=\"sr-only\">{label}</span>\n {children}\n </button>\n );\n}","import { XIcon } from '@phosphor-icons/react'\n\nimport { IconButton } from '../IconButton'\n\ninterface CloseButtonProps {\n onClick: () => void\n}\n\nexport function CloseButton({ onClick }: CloseButtonProps) {\n return (\n <IconButton label=\"Close\" onClick={onClick} className=\"p-1\">\n <XIcon className=\"h-5 w-5 text-stone\" weight=\"bold\" />\n </IconButton>\n )\n}\n","import { XIcon } from '@phosphor-icons/react'\nimport React from 'react'\nimport {\n LinkPreview,\n LinkPreviewsManager,\n LinkPreviewsManagerState,\n} from 'stream-chat'\nimport { useMessageComposer, useStateStore } from 'stream-chat-react'\n\nconst linkPreviewsManagerStateSelector = (state: LinkPreviewsManagerState) => ({\n linkPreviews: Array.from(state.previews.values()).filter(\n (preview) =>\n LinkPreviewsManager.previewIsLoaded(preview) ||\n LinkPreviewsManager.previewIsLoading(preview)\n ),\n})\n\ninterface CustomLinkPreviewCardProps {\n link: LinkPreview\n onDismiss: (url: string) => void\n}\n\nconst CustomLinkPreviewCard: React.FC<CustomLinkPreviewCardProps> = ({\n link,\n onDismiss,\n}) => {\n const { og_scrape_url, title, image_url } = link\n\n const handleDismissLink = (e: React.MouseEvent) => {\n e.preventDefault()\n onDismiss(og_scrape_url)\n }\n\n return (\n <a\n href={og_scrape_url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"relative w-full block rounded-[24px] bg-[#121110] p-2 no-underline transition-opacity hover:opacity-90\"\n >\n {image_url && (\n <img\n src={image_url}\n alt={title || ''}\n className=\"h-[148px] w-full rounded-[20px] object-cover\"\n />\n )}\n <button\n type=\"button\"\n onClick={handleDismissLink}\n className=\"absolute right-4 top-4 flex size-6 items-center justify-center rounded-full border border-white/40 bg-white/70 backdrop-blur-2xl\"\n aria-label=\"Close link preview\"\n >\n <XIcon className=\"size-4 text-black/90\" />\n </button>\n <div className=\"p-2\">\n {title && (\n <div className=\"text-[14px] font-medium leading-5 text-white\">\n {title}\n </div>\n )}\n <div className=\"text-[12px] leading-4 text-white/55\">\n {og_scrape_url}\n </div>\n </div>\n </a>\n )\n}\n\nexport const CustomLinkPreviewList = () => {\n const { linkPreviewsManager } = useMessageComposer()\n\n const { linkPreviews: stateLinkPreviews } = useStateStore(\n linkPreviewsManager.state,\n linkPreviewsManagerStateSelector\n )\n\n const handleDismiss = (url: string) => {\n linkPreviewsManager.dismissPreview(url)\n }\n\n const showLinkPreviews = stateLinkPreviews.length > 0\n\n if (!showLinkPreviews) return null\n\n return (\n <div className=\"str-chat__link-preview-list p-0 gap-2 mb-4\">\n {stateLinkPreviews.map((linkPreview) => (\n <CustomLinkPreviewCard\n key={linkPreview.og_scrape_url}\n link={linkPreview}\n onDismiss={handleDismiss}\n />\n ))}\n </div>\n )\n}\n","import { ArrowUpIcon } from '@phosphor-icons/react'\nimport React from 'react'\nimport {\n AttachmentPreviewList,\n MessageInput,\n QuotedMessagePreview,\n SimpleAttachmentSelector,\n TextareaComposer,\n useMessageComposerHasSendableData,\n useMessageInputContext,\n} from 'stream-chat-react'\n\nimport { CustomLinkPreviewList } from '../CustomLinkPreviewList'\n\nconst CustomMessageInputInner: React.FC = () => {\n const { handleSubmit } = useMessageInputContext()\n const hasSendableData = useMessageComposerHasSendableData()\n\n return (\n <>\n <div className=\"left-container\">\n <SimpleAttachmentSelector />\n </div>\n <div className=\"central-container min-w-0 w-full p-2 bg-white rounded-[1.5rem] shadow-[0_4px_16px_0_rgba(0,0,0,0.08),0_1px_2px_0_rgba(0,0,0,0.04),0_0_0_1px_rgba(0,0,0,0.04)]\">\n <QuotedMessagePreview />\n <CustomLinkPreviewList />\n <AttachmentPreviewList />\n <div className=\"flex\">\n <div className=\"w-full ml-2 mr-4 self-center leading-[0]\">\n <TextareaComposer\n className=\"w-full resize-none outline-none leading-6\"\n maxRows={4}\n />\n </div>\n <button\n aria-label=\"Send\"\n className=\"str-chat__send-button mt-auto flex justify-center items-center flex-shrink-0 rounded-full size-8 bg-[#121110] disabled:bg-[#F1F0EE] disabled:text-black/20 text-white\"\n data-testid=\"send-button\"\n disabled={!hasSendableData}\n onClick={handleSubmit}\n type=\"button\"\n >\n <ArrowUpIcon className=\"size-4\" />\n </button>\n </div>\n </div>\n </>\n )\n}\n\nexport interface CustomMessageInputProps {\n renderActions?: () => React.ReactNode\n}\n\nexport const CustomMessageInput: React.FC<CustomMessageInputProps> = ({\n renderActions,\n}) => (\n <div className=\"message-input flex items-center gap-2 p-4\">\n {renderActions && renderActions?.()}\n <MessageInput Input={CustomMessageInputInner} />\n </div>\n)\n","import { MessageTimestamp, type EventComponentProps } from 'stream-chat-react'\n\nexport const CustomSystemMessage: React.FC<EventComponentProps> = (props) => {\n const isDateHidden = props.message.hide_date === true\n\n return (\n <div className=\"str-chat__message--system\" data-testid=\"message-system\">\n <div className=\"str-chat__message--system__text\">\n <div className=\"str-chat__message--system__line\"></div>\n <p>{props.message.text}</p>\n <div className=\"str-chat__message--system__line\"></div>\n </div>\n {!isDateHidden && <MessageTimestamp message={props.message} />}\n </div>\n )\n}\n","import React from 'react'\n\n/**\n * Empty state component shown when a channel has no messages\n * Returns null to show nothing - the LoadingIndicator handles the loading state\n */\nexport const ChannelEmptyState: React.FC = () => {\n console.log('[ChannelEmptyState] render - returning NULL')\n return null\n}\n","import classNames from 'classnames'\n\ntype LoadingProps = {\n className?: string\n message?: string\n}\n\nconst Loading = ({ className, message }: LoadingProps) => (\n <div\n className={classNames('flex items-center justify-center h-full', className)}\n >\n <svg viewBox=\"0 0 100 100\" className=\"size-8 fill-pebble\" stroke=\"none\">\n <circle cx=\"6\" cy=\"50\" r=\"6\">\n <animateTransform\n attributeName=\"transform\"\n dur=\"1s\"\n type=\"translate\"\n values=\"0 15 ; 0 -15; 0 15\"\n repeatCount=\"indefinite\"\n begin=\"0.1\"\n />\n </circle>\n <circle cx=\"30\" cy=\"50\" r=\"6\">\n <animateTransform\n attributeName=\"transform\"\n dur=\"1s\"\n type=\"translate\"\n values=\"0 10 ; 0 -10; 0 10\"\n repeatCount=\"indefinite\"\n begin=\"0.2\"\n />\n </circle>\n <circle cx=\"54\" cy=\"50\" r=\"6\">\n <animateTransform\n attributeName=\"transform\"\n dur=\"1s\"\n type=\"translate\"\n values=\"0 5 ; 0 -5; 0 5\"\n repeatCount=\"indefinite\"\n begin=\"0.3\"\n />\n </circle>\n </svg>\n {message && <span className=\"text-stone\">{message}</span>}\n </div>\n)\n\nexport default Loading\n","import React from 'react'\n\nimport Loading from '../Loading'\n\n/**\n * Loading state component\n */\nexport const LoadingState = React.memo(() => {\n console.log('[LoadingState] render - showing loading spinner')\n return (\n <div className=\"messaging-loading-state flex items-center justify-center h-full\">\n <div className=\"flex items-center\">\n <Loading className=\"w-6 h-6\" />\n <span className=\"text-sm text-stone\">Loading messages</span>\n </div>\n </div>\n )\n})\nLoadingState.displayName = 'LoadingState'\n","import {\n ArrowLeftIcon,\n DotsThreeIcon,\n FlagIcon,\n ProhibitInsetIcon,\n SignOutIcon,\n SpinnerGapIcon,\n} from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React, { useState, useCallback, useRef, useEffect } from 'react'\nimport { Channel as ChannelType, ChannelMemberResponse } from 'stream-chat'\nimport {\n Channel,\n Window,\n MessageList,\n useChannelStateContext,\n} from 'stream-chat-react'\n\nimport { useMessagingContext } from '../providers/MessagingProvider'\nimport type { ChannelViewProps } from '../types'\n\nimport ActionButton from './ActionButton'\nimport { Avatar } from './Avatar'\nimport { CloseButton } from './CloseButton'\nimport { CustomMessageInput } from './CustomMessageInput'\nimport { CustomSystemMessage } from './CustomSystemMessage'\nimport { ChannelEmptyState } from './MessagingShell/ChannelEmptyState'\nimport { LoadingState } from './MessagingShell/LoadingState'\n\n// Custom user type with email and username\ntype CustomUser = {\n email?: string\n username?: string\n}\n\n// Blocked user from Stream Chat API\ntype BlockedUser = {\n blocked_user_id: string\n}\n\n/**\n * Custom channel header component\n */\nconst CustomChannelHeader: React.FC<{\n onBack?: () => void\n showBackButton: boolean\n onShowInfo: () => void\n canShowInfo: boolean\n}> = ({ onBack, showBackButton, onShowInfo, canShowInfo }) => {\n const { channel } = useChannelStateContext()\n\n // Get participant info (excluding current user)\n const participant = React.useMemo(() => {\n const members = Object.values(channel.state.members || {})\n return members.find(\n (member) => member.user?.id && member.user.id !== channel._client.userID\n )\n }, [channel._client.userID, channel.state.members])\n\n const participantName =\n participant?.user?.name || participant?.user?.id || 'Unknown member'\n const participantImage = participant?.user?.image\n\n return (\n <div className=\"@container\">\n <div className=\"flex justify-between items-center @lg:hidden\">\n <button\n className={classNames(\n 'size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center',\n !showBackButton && 'invisible'\n )}\n onClick={onBack || (() => {})}\n type=\"button\"\n aria-label=\"Back to conversations\"\n >\n <ArrowLeftIcon className=\"size-5 text-black/90\" />\n </button>\n <div className=\"flex flex-col gap-1 items-center\">\n <Avatar\n id={participant?.user?.id || channel.id || 'unknown'}\n name={participantName}\n image={participantImage}\n size={40}\n />\n <h1 className=\"text-xs font-medium text-black/90\">\n {participantName}\n </h1>\n </div>\n <button\n className={classNames(\n 'size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center'\n )}\n onClick={onShowInfo}\n type=\"button\"\n aria-label=\"Show info\"\n >\n <DotsThreeIcon className=\"size-5 text-black/90\" />\n </button>\n </div>\n <div className=\"hidden @lg:flex items-center justify-between gap-3 min-h-12\">\n <div className=\"flex items-center gap-4 min-w-0\">\n {showBackButton && onBack && (\n <button\n type=\"button\"\n onClick={onBack}\n className=\"size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center\"\n aria-label=\"Back to conversations\"\n >\n <ArrowLeftIcon className=\"size-5 text-black/90\" />\n </button>\n )}\n {/* Avatar */}\n <Avatar\n id={participant?.user?.id || channel.id || 'unknown'}\n name={participantName}\n image={participantImage}\n size={40}\n />\n <div className=\"min-w-0\">\n <h1 className=\"font-medium text-black/90 truncate\">\n {participantName}\n </h1>\n </div>\n </div>\n {canShowInfo && onShowInfo && (\n <button\n className={classNames(\n 'size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center'\n )}\n onClick={onShowInfo}\n >\n <DotsThreeIcon className=\"size-5 text-black/90\" />\n </button>\n )}\n </div>\n </div>\n )\n}\n\n/**\n * Channel info dialog (matching original implementation)\n */\nconst ChannelInfoDialog: React.FC<{\n dialogRef: React.RefObject<HTMLDialogElement>\n onClose: () => void\n participant: ChannelMemberResponse | undefined\n channel: ChannelType\n followerStatusLabel?: string\n onLeaveConversation?: (channel: ChannelType) => void\n onBlockParticipant?: (participantId?: string) => void\n showDeleteConversation?: boolean\n onDeleteConversationClick?: () => void\n onBlockParticipantClick?: () => void\n onReportParticipantClick?: () => void\n}> = ({\n dialogRef,\n onClose,\n participant,\n channel,\n followerStatusLabel,\n onLeaveConversation,\n onBlockParticipant,\n showDeleteConversation = true,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n}) => {\n const { service, debug } = useMessagingContext()\n const [isParticipantBlocked, setIsParticipantBlocked] = useState(false)\n const [isLeaving, setIsLeaving] = useState(false)\n const [isUpdatingBlockStatus, setIsUpdatingBlockStatus] = useState(false)\n\n // Check if participant is blocked when participant changes\n const checkIsParticipantBlocked = useCallback(async () => {\n if (!service || !participant?.user?.id) return\n\n try {\n const blockedUsers = await service.getBlockedUsers()\n const isBlocked = blockedUsers.some(\n (user: BlockedUser) => user.blocked_user_id === participant?.user?.id\n )\n setIsParticipantBlocked(isBlocked)\n } catch (error) {\n console.error(\n '[ChannelInfoDialog] Failed to check blocked status:',\n error\n )\n }\n }, [service, participant?.user?.id])\n\n useEffect(() => {\n checkIsParticipantBlocked()\n }, [checkIsParticipantBlocked])\n\n const handleLeaveConversation = async () => {\n if (isLeaving) return\n\n // Fire analytics callback before action\n onDeleteConversationClick?.()\n\n if (debug) {\n console.log('[ChannelInfoDialog] Leave conversation', channel.cid)\n }\n setIsLeaving(true)\n\n try {\n const actingUserId = channel._client?.userID ?? null\n await channel.hide(actingUserId, false)\n\n if (onLeaveConversation) {\n await onLeaveConversation(channel)\n }\n\n onClose()\n } catch (error) {\n console.error('[ChannelInfoDialog] Failed to leave conversation', error)\n } finally {\n setIsLeaving(false)\n }\n }\n\n const handleBlockUser = async () => {\n if (isUpdatingBlockStatus || !service) return\n\n // Fire analytics callback before action\n onBlockParticipantClick?.()\n\n if (debug) {\n console.log('[ChannelInfoDialog] Block member', participant?.user?.id)\n }\n setIsUpdatingBlockStatus(true)\n\n try {\n await service.blockUser(participant?.user?.id)\n\n if (onBlockParticipant) {\n await onBlockParticipant(participant?.user?.id)\n }\n\n onClose()\n } catch (error) {\n console.error('[ChannelInfoDialog] Failed to block member', error)\n } finally {\n setIsUpdatingBlockStatus(false)\n }\n }\n\n const handleUnblockUser = async () => {\n if (isUpdatingBlockStatus || !service) return\n\n // Fire analytics callback before action\n onBlockParticipantClick?.()\n\n if (debug) {\n console.log('[ChannelInfoDialog] Unblock member', participant?.user?.id)\n }\n setIsUpdatingBlockStatus(true)\n\n try {\n await service.unBlockUser(participant?.user?.id)\n\n if (onBlockParticipant) {\n await onBlockParticipant(participant?.user?.id)\n }\n\n onClose()\n } catch (error) {\n console.error('[ChannelInfoDialog] Failed to unblock member', error)\n } finally {\n setIsUpdatingBlockStatus(false)\n }\n }\n\n const handleReportUser = () => {\n // Fire analytics callback before action\n onReportParticipantClick?.()\n\n onClose()\n window.open(\n 'https://linktr.ee/s/about/trust-center/report',\n '_blank',\n 'noopener,noreferrer'\n )\n }\n\n if (!participant) return null\n\n const participantName =\n participant.user?.name || participant.user?.id || 'Unknown member'\n const participantImage = participant.user?.image\n const participantEmail = (participant.user as CustomUser)?.email\n const participantUsername = (participant.user as CustomUser)?.username\n const participantSecondary = participantEmail\n ? participantEmail\n : participantUsername\n ? `linktr.ee/${participantUsername}`\n : undefined\n const participantId = participant.user?.id || 'unknown'\n\n return (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions\n <dialog\n ref={dialogRef}\n className=\"mes-dialog group\"\n onClose={onClose}\n onClick={(e) => {\n if (e.target === dialogRef.current) {\n onClose()\n }\n }}\n >\n <div className=\"ml-auto flex h-full w-full flex-col bg-white shadow-none transition-shadow duration-200 group-open:shadow-max-elevation-light\">\n <div className=\"flex items-center justify-between border-b border-sand px-4 py-3\">\n <h2 className=\"text-base font-semibold text-charcoal\">Chat info</h2>\n <CloseButton onClick={onClose} />\n </div>\n\n <div className=\"flex-1 px-2 overflow-y-auto w-full\">\n <div\n className=\"flex flex-col items-center gap-3 self-stretch px-4 py-2 mt-6 rounded-lg border border-black/[0.04]\"\n style={{ backgroundColor: '#FBFAF9' }}\n >\n <div className=\"flex items-center gap-3 w-full\">\n <Avatar\n id={participantId}\n name={participantName}\n image={participantImage}\n size={88}\n shape=\"circle\"\n />\n <div className=\"flex flex-col min-w-0 flex-1\">\n <p className=\"truncate text-base font-semibold text-charcoal\">\n {participantName}\n </p>\n {participantSecondary && (\n <p className=\"truncate text-sm text-[#00000055]\">\n {participantSecondary}\n </p>\n )}\n {followerStatusLabel && (\n <span\n className=\"mt-1 rounded-full text-xs font-normal w-fit\"\n style={{\n padding: '4px 8px',\n backgroundColor:\n followerStatusLabel === 'Subscribed to you'\n ? '#DCFCE7'\n : '#F5F5F4',\n color:\n followerStatusLabel === 'Subscribed to you'\n ? '#008236'\n : '#78716C',\n lineHeight: '133.333%',\n letterSpacing: '0.21px',\n }}\n >\n {followerStatusLabel}\n </span>\n )}\n </div>\n </div>\n </div>\n\n <ul className=\"flex flex-col gap-2 mt-2\">\n {showDeleteConversation && (\n <li>\n <ActionButton\n onClick={handleLeaveConversation}\n disabled={isLeaving}\n aria-busy={isLeaving}\n >\n {isLeaving ? (\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n ) : (\n <SignOutIcon className=\"h-5 w-5\" />\n )}\n <span>Delete Conversation</span>\n </ActionButton>\n </li>\n )}\n <li>\n {isParticipantBlocked ? (\n <ActionButton\n onClick={handleUnblockUser}\n disabled={isUpdatingBlockStatus}\n aria-busy={isUpdatingBlockStatus}\n >\n {isUpdatingBlockStatus ? (\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n ) : (\n <ProhibitInsetIcon className=\"h-5 w-5\" />\n )}\n <span>Unblock</span>\n </ActionButton>\n ) : (\n <ActionButton\n onClick={handleBlockUser}\n disabled={isUpdatingBlockStatus}\n aria-busy={isUpdatingBlockStatus}\n >\n {isUpdatingBlockStatus ? (\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n ) : (\n <ProhibitInsetIcon className=\"h-5 w-5\" />\n )}\n <span>Block</span>\n </ActionButton>\n )}\n </li>\n <li>\n <ActionButton variant=\"danger\" onClick={handleReportUser}>\n <FlagIcon className=\"h-5 w-5\" />\n <span>Report</span>\n </ActionButton>\n </li>\n </ul>\n </div>\n </div>\n </dialog>\n )\n}\n\n/**\n * Inner component that has access to channel context\n */\nconst ChannelViewInner: React.FC<{\n onBack?: () => void\n showBackButton: boolean\n renderMessageInputActions?: (channel: ChannelType) => React.ReactNode\n onLeaveConversation?: (channel: ChannelType) => void\n onBlockParticipant?: (participantId?: string) => void\n CustomChannelEmptyState?: React.ComponentType\n showDeleteConversation?: boolean\n onDeleteConversationClick?: () => void\n onBlockParticipantClick?: () => void\n onReportParticipantClick?: () => void\n}> = ({\n onBack,\n showBackButton,\n renderMessageInputActions,\n onLeaveConversation,\n onBlockParticipant,\n showDeleteConversation = true,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n}) => {\n const { channel } = useChannelStateContext()\n const infoDialogRef = useRef<HTMLDialogElement>(null)\n\n // Get participant info for info dialog\n const participant = React.useMemo(() => {\n const members = Object.values(channel.state.members || {})\n return members.find(\n (member) => member.user?.id && member.user.id !== channel._client.userID\n )\n }, [channel._client.userID, channel.state.members])\n\n // Get follower status label from channel data\n const followerStatusLabel = React.useMemo(() => {\n const channelExtraData = (channel.data ?? {}) as {\n followerStatus?: string\n isFollower?: boolean\n }\n\n // If explicit followerStatus is provided, use it\n if (channelExtraData.followerStatus) {\n return String(channelExtraData.followerStatus)\n }\n // If isFollower is explicitly defined, use it to determine status\n if (channelExtraData.isFollower !== undefined) {\n return channelExtraData.isFollower\n ? 'Subscribed to you'\n : 'Not subscribed'\n }\n // Otherwise, don't show any status\n return undefined\n }, [channel.data])\n\n const handleShowInfo = useCallback(() => {\n infoDialogRef.current?.showModal()\n }, [])\n\n const handleCloseInfo = useCallback(() => {\n infoDialogRef.current?.close()\n }, [])\n\n return (\n <>\n <Window>\n {/* Custom Channel Header */}\n <div className=\"p-4\">\n <CustomChannelHeader\n onBack={onBack}\n showBackButton={showBackButton}\n onShowInfo={handleShowInfo}\n canShowInfo={Boolean(participant)}\n />\n </div>\n\n {/* Message List */}\n <div className=\"flex-1 overflow-hidden relative\">\n <MessageList\n hideDeletedMessages\n hideNewMessageSeparator={false}\n messageActions={[]}\n />\n </div>\n\n {/* Message Input */}\n <CustomMessageInput\n renderActions={() => renderMessageInputActions?.(channel)}\n />\n </Window>\n\n {/* Channel Info Dialog */}\n <ChannelInfoDialog\n dialogRef={infoDialogRef}\n onClose={handleCloseInfo}\n participant={participant}\n channel={channel}\n followerStatusLabel={followerStatusLabel}\n onLeaveConversation={onLeaveConversation}\n onBlockParticipant={onBlockParticipant}\n showDeleteConversation={showDeleteConversation}\n onDeleteConversationClick={onDeleteConversationClick}\n onBlockParticipantClick={onBlockParticipantClick}\n onReportParticipantClick={onReportParticipantClick}\n />\n </>\n )\n}\n\n/**\n * Channel view component with message list and input\n */\nexport const ChannelView = React.memo<ChannelViewProps>(\n ({\n channel,\n onBack,\n showBackButton = false,\n renderMessageInputActions,\n onLeaveConversation,\n onBlockParticipant,\n className,\n CustomChannelEmptyState = ChannelEmptyState,\n showDeleteConversation = true,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n }) => {\n console.log('[ChannelView] render', {\n channelId: channel.id,\n channelInitialized: channel.initialized,\n messageCount: channel.state?.messages?.length\n })\n return (\n <div\n className={classNames(\n 'messaging-channel-view h-full flex flex-col',\n className\n )}\n >\n <Channel\n channel={channel}\n MessageSystem={CustomSystemMessage}\n EmptyStateIndicator={CustomChannelEmptyState}\n LoadingIndicator={LoadingState}\n >\n <ChannelViewInner\n onBack={onBack}\n showBackButton={showBackButton}\n renderMessageInputActions={renderMessageInputActions}\n onLeaveConversation={onLeaveConversation}\n onBlockParticipant={onBlockParticipant}\n CustomChannelEmptyState={CustomChannelEmptyState}\n showDeleteConversation={showDeleteConversation}\n onDeleteConversationClick={onDeleteConversationClick}\n onBlockParticipantClick={onBlockParticipantClick}\n onReportParticipantClick={onReportParticipantClick}\n />\n </Channel>\n </div>\n )\n }\n)\nChannelView.displayName = 'ChannelView'\n","import { MagnifyingGlassIcon, XIcon } from '@phosphor-icons/react'\nimport { useRef } from 'react'\n\nimport { IconButton } from '../IconButton'\n\ninterface SearchInputProps {\n searchQuery: string\n setSearchQuery: (value: string) => void\n placeholder: string\n}\n\nexport function SearchInput({\n searchQuery,\n setSearchQuery,\n placeholder,\n}: SearchInputProps) {\n const searchInputRef = useRef<HTMLInputElement>(null)\n\n return (\n <div className=\"relative\">\n <MagnifyingGlassIcon\n className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone\"\n weight=\"bold\"\n />\n\n <input\n ref={searchInputRef}\n type=\"text\"\n placeholder={placeholder}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full pl-10 pr-10 py-3 text-sm border border-sand rounded-xl focus:outline-none focus:ring-2 focus:ring-black focus:border-transparent\"\n />\n\n {searchQuery && (\n <IconButton\n label=\"Clear search\"\n onClick={() => {\n setSearchQuery('')\n searchInputRef.current?.focus()\n }}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 p-1 text-stone hover:text-charcoal\"\n >\n <XIcon className=\"h-4 w-4\" weight=\"bold\" />\n </IconButton>\n )}\n </div>\n )\n}\n","import { ChatCircleDotsIcon, SpinnerGapIcon } from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React, { useCallback, useEffect, useState, useRef } from 'react'\n\nimport { useMessagingContext } from '../../providers/MessagingProvider'\nimport type { ParticipantPickerProps, Participant } from '../../types'\nimport { Avatar } from '../Avatar'\nimport { CloseButton } from '../CloseButton'\nimport { SearchInput } from '../SearchInput'\n\n/**\n * Generic participant picker component for starting conversations\n */\nexport const ParticipantPicker: React.FC<ParticipantPickerProps> = ({\n participantSource,\n onSelectParticipant,\n onClose,\n existingParticipantIds = new Set(),\n participantLabel = 'participants',\n searchPlaceholder = 'Search participants...',\n className,\n}) => {\n const { debug } = useMessagingContext()\n const [searchQuery, setSearchQuery] = useState('')\n const [participants, setParticipants] = useState<Participant[]>([])\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [startingChatWithId, setStartingChatWithId] = useState<string | null>(\n null\n )\n\n // Track if we've already loaded participants to prevent repeated loading\n const loadedRef = useRef(false)\n\n // Load participants initially - wait for participantSource to finish loading first\n useEffect(() => {\n // Wait for the participantSource to finish loading before we try to load participants\n if (participantSource.loading) {\n if (debug) {\n console.log(\n '[ParticipantPicker] Waiting for participant source to finish loading...'\n )\n }\n return\n }\n\n if (loadedRef.current) return // Prevent multiple loads\n\n const loadInitialParticipants = async () => {\n if (debug) {\n console.log('[ParticipantPicker] Loading initial participants...')\n }\n setLoading(true)\n setError(null)\n\n try {\n const result = await participantSource.loadParticipants({\n search: '', // Load all participants initially\n limit: 100,\n })\n setParticipants(result.participants)\n loadedRef.current = true // Mark as loaded\n if (debug) {\n console.log(\n '[ParticipantPicker] Participants loaded successfully:',\n result.participants.length\n )\n }\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : 'Failed to load participants'\n setError(errorMessage)\n console.error('[ParticipantPicker] Failed to load participants:', err)\n // Don't mark as loaded on error, allow retry\n } finally {\n setLoading(false)\n }\n }\n\n loadInitialParticipants()\n }, [participantSource.loading, debug]) // Re-run when loading state changes\n\n // Filter participants by search query and existing participants\n const availableParticipants = participants\n .filter((participant) => !existingParticipantIds.has(participant.id))\n .filter((participant) => {\n if (!searchQuery) return true\n const searchLower = searchQuery.toLowerCase()\n return (\n participant.name.toLowerCase().includes(searchLower) ||\n participant.email?.toLowerCase().includes(searchLower) ||\n false\n )\n })\n\n const handleSelectParticipant = useCallback(\n async (participant: Participant) => {\n if (startingChatWithId) return // Prevent multiple clicks\n\n setStartingChatWithId(participant.id)\n try {\n await onSelectParticipant(participant)\n } catch (error) {\n console.error('[ParticipantPicker] Failed to start chat:', error)\n // Reset the loading state on error\n setStartingChatWithId(null)\n }\n // Note: Don't reset startingChatWithId on success because the dialog will close\n },\n [onSelectParticipant, startingChatWithId]\n )\n\n const handleKeyDown = (\n event: React.KeyboardEvent,\n participant: Participant\n ) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n handleSelectParticipant(participant)\n }\n }\n\n return (\n <div className={classNames('flex flex-col h-full', className)}>\n {/* Header */}\n <div className=\"px-4 py-4 border-b border-sand bg-chalk\">\n <div className=\"flex items-center justify-between mb-3\">\n <h2 className=\"text-lg font-semibold text-charcoal\">\n Start a new Conversation\n </h2>\n <CloseButton onClick={onClose} />\n </div>\n\n <p className=\"text-xs text-stone mb-3\">\n Select a {participantLabel.slice(0, -1)} to start messaging (\n {availableParticipants.length} available)\n {participantSource.totalCount !== undefined &&\n ` • ${participantSource.totalCount} ${participantLabel} total`}\n </p>\n\n <SearchInput\n searchQuery={searchQuery}\n setSearchQuery={setSearchQuery}\n placeholder={searchPlaceholder}\n />\n </div>\n\n {/* Error State */}\n {error && (\n <div className=\"p-4 text-sm text-danger bg-danger-alt\">\n Error loading {participantLabel}: {error}\n </div>\n )}\n\n {/* Participants List */}\n <div className=\"flex-1 overflow-auto\">\n {loading && availableParticipants.length === 0 ? (\n <div className=\"h-32 flex items-center justify-center\">\n <div className=\"flex items-center space-x-2\">\n <div className=\"w-4 h-4 animate-spin rounded-full border-2 border-primary border-t-transparent\"></div>\n <span className=\"text-sm text-stone\">\n Loading {participantLabel}...\n </span>\n </div>\n </div>\n ) : availableParticipants.length === 0 ? (\n <div className=\"p-6 text-center\">\n <div className=\"mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-sand\">\n <ChatCircleDotsIcon className=\"h-8 w-8 text-charcoal\" />\n </div>\n <h3 className=\"text-sm font-semibold text-charcoal mb-2\">\n {searchQuery\n ? `No ${participantLabel} found`\n : participants.length > 0\n ? `Already chatting with all ${participantLabel}`\n : `No ${participantLabel} yet`}\n </h3>\n <p className=\"text-xs text-stone\">\n {searchQuery\n ? 'Try a different search term'\n : participants.length > 0\n ? `You have existing conversations with all your ${participantLabel}`\n : `${participantLabel.charAt(0).toUpperCase() + participantLabel.slice(1)} will appear here`}\n </p>\n </div>\n ) : (\n <ul className=\"space-y-0\">\n {availableParticipants.map((participant) => {\n const displayName =\n participant.name || participant.email || participant.id\n const displaySecondary =\n participant.email && participant.name\n ? participant.email\n : participant.phone\n\n return (\n <li key={participant.id}>\n <button\n type=\"button\"\n onClick={() => handleSelectParticipant(participant)}\n onKeyDown={(e) => handleKeyDown(e, participant)}\n className=\"w-full px-4 py-3 hover:bg-sand transition-colors border-b border-sand text-left focus:outline-none focus:ring-2 focus:ring-black\"\n >\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center space-x-3 flex-1 min-w-0\">\n {/* Avatar */}\n <Avatar\n id={participant.id}\n name={displayName}\n image={participant.image}\n size={40}\n />\n\n {/* Info */}\n <div className=\"flex-1 min-w-0\">\n <h4 className=\"text-sm font-medium text-charcoal truncate\">\n {displayName}\n </h4>\n {displaySecondary && (\n <p className=\"text-xs text-stone truncate\">\n {displaySecondary}\n </p>\n )}\n </div>\n </div>\n\n {/* Icon */}\n <div className=\"flex-shrink-0\">\n {startingChatWithId === participant.id ? (\n <SpinnerGapIcon className=\"h-5 w-5 text-primary animate-spin\" />\n ) : (\n <ChatCircleDotsIcon className=\"h-5 w-5 text-stone\" />\n )}\n </div>\n </div>\n </button>\n </li>\n )\n })}\n\n {/* Loading indicator */}\n {loading && (\n <li className=\"p-4 flex justify-center\">\n <div className=\"flex items-center space-x-2\">\n <div className=\"w-4 h-4 animate-spin rounded-full border-2 border-primary border-t-transparent\"></div>\n <span className=\"text-sm text-stone\">Loading more...</span>\n </div>\n </li>\n )}\n </ul>\n )}\n </div>\n </div>\n )\n}\n","import React from 'react'\n\nconst ChatBubblesIllustration = ({ className }: { className?: string }) => (\n <svg\n width=\"140\"\n height=\"120\"\n viewBox=\"44 -2 144 126\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n >\n <g clipPath=\"url(#clip0_empty_state)\">\n <path\n d=\"M123.68 82.1932C123.383 103.675 105.839 121 84.2417 121C77.4724 121 71.0986 119.297 65.5327 116.299L52.5873 119.687L53.8036 106.673C48.1776 99.8701 44.7994 91.1453 44.7994 81.6356C44.7994 59.8965 62.4554 42.2754 84.2374 42.2754C89.1328 42.2754 93.8175 43.1633 98.1413 44.789\"\n fill=\"#D7D4CE\"\n />\n <path\n d=\"M84.2458 86.0364C82.2851 86.0364 80.6957 84.4501 80.6957 82.4933C80.6957 80.5365 82.2851 78.9502 84.2458 78.9502C86.2065 78.9502 87.7959 80.5365 87.7959 82.4933C87.7959 84.4501 86.2065 86.0364 84.2458 86.0364Z\"\n fill=\"white\"\n />\n <path\n d=\"M68.3044 86.0364C66.3437 86.0364 64.7543 84.4501 64.7543 82.4933C64.7543 80.5365 66.3437 78.9502 68.3044 78.9502C70.2651 78.9502 71.8545 80.5365 71.8545 82.4933C71.8545 84.4501 70.2651 86.0364 68.3044 86.0364Z\"\n fill=\"white\"\n />\n <path\n d=\"M100.183 86.0364C98.2226 86.0364 96.6332 84.4501 96.6332 82.4933C96.6332 80.5365 98.2226 78.9502 100.183 78.9502C102.144 78.9502 103.733 80.5365 103.733 82.4933C103.733 84.4501 102.144 86.0364 100.183 86.0364Z\"\n fill=\"white\"\n />\n <g filter=\"url(#filter0_empty_state)\">\n <path\n d=\"M171.522 68.7154C177.443 61.4539 181 52.1488 181 42C181 18.8027 162.421 0 139.5 0C116.579 0 98 18.8027 98 42C98 65.1973 116.579 84 139.5 84C146.622 84 153.328 82.1857 159.184 78.9829L172.801 82.5993L171.522 68.7154Z\"\n fill=\"white\"\n />\n <path\n d=\"M171.522 68.7154C177.443 61.4539 181 52.1488 181 42C181 18.8027 162.421 0 139.5 0C116.579 0 98 18.8027 98 42C98 65.1973 116.579 84 139.5 84C146.622 84 153.328 82.1857 159.184 78.9829L172.801 82.5993L171.522 68.7154Z\"\n stroke=\"#D7D4CE\"\n strokeWidth=\"2\"\n strokeMiterlimit=\"10\"\n />\n </g>\n <path\n d=\"M139.502 45.5431C137.541 45.5431 135.952 43.9568 135.952 42C135.952 40.0432 137.541 38.4569 139.502 38.4569C141.462 38.4569 143.052 40.0432 143.052 42C143.052 43.9568 141.462 45.5431 139.502 45.5431Z\"\n fill=\"#D7D4CE\"\n />\n <path\n d=\"M123.561 45.5431C121.601 45.5431 120.011 43.9568 120.011 42C120.011 40.0432 121.601 38.4569 123.561 38.4569C125.522 38.4569 127.111 40.0432 127.111 42C127.111 43.9568 125.522 45.5431 123.561 45.5431Z\"\n fill=\"#D7D4CE\"\n />\n <path\n d=\"M155.439 45.5431C153.478 45.5431 151.889 43.9568 151.889 42C151.889 40.0432 153.478 38.4569 155.439 38.4569C157.4 38.4569 158.989 40.0432 158.989 42C158.989 43.9568 157.4 45.5431 155.439 45.5431Z\"\n fill=\"#D7D4CE\"\n />\n </g>\n <defs>\n <filter\n id=\"filter0_empty_state\"\n x=\"97\"\n y=\"-1\"\n width=\"89\"\n height=\"90\"\n filterUnits=\"userSpaceOnUse\"\n colorInterpolationFilters=\"sRGB\"\n >\n <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n <feColorMatrix\n in=\"SourceAlpha\"\n type=\"matrix\"\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\n result=\"hardAlpha\"\n />\n <feOffset dx=\"4\" dy=\"4\" />\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\n <feColorMatrix\n type=\"matrix\"\n values=\"0 0 0 0 0.8428 0 0 0 0 0.830064 0 0 0 0 0.8095 0 0 0 1 0\"\n />\n <feBlend\n mode=\"normal\"\n in2=\"BackgroundImageFix\"\n result=\"effect1_dropShadow\"\n />\n <feBlend\n mode=\"normal\"\n in=\"SourceGraphic\"\n in2=\"effect1_dropShadow\"\n result=\"shape\"\n />\n </filter>\n <clipPath id=\"clip0_empty_state\">\n <rect width=\"233\" height=\"233\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n)\n\n/**\n * Empty state component shown when no channel is selected\n */\nexport const EmptyState = React.memo<{ hasChannels: boolean; channelsLoaded: boolean }>(\n ({ hasChannels, channelsLoaded }) => (\n <div className=\"messaging-empty-state flex items-center justify-center h-full p-8 text-balance\">\n <div className=\"flex flex-col items-center max-w-sm text-center\">\n <ChatBubblesIllustration />\n {channelsLoaded && !hasChannels && (\n <div className=\"mt-8\">\n <h2 className=\"font-medium text-black text-[18px] mb-2\">\n Your inbox is empty\n </h2>\n <p className=\"text-[#676B5F] text-sm mb-6\">\n Share with your followers to start receiving messages\n </p>\n </div>\n )}\n </div>\n </div>\n))\nEmptyState.displayName = 'EmptyState'\n","import React from 'react'\n\ntype ErrorStateProps = {\n message: string\n onBack?: () => void\n}\n\n/**\n * Error state component shown when something goes wrong\n */\nexport const ErrorState = React.memo<ErrorStateProps>(({ message, onBack }) => (\n <div className=\"messaging-error-state flex items-center justify-center h-full p-8\">\n <div className=\"text-center max-w-sm\">\n <div className=\"w-24 h-24 bg-danger-alt/20 rounded-full flex items-center justify-center mx-auto mb-6\">\n <span className=\"text-4xl\">⚠️</span>\n </div>\n\n <h2 className=\"font-semibold text-charcoal mb-2\">Oops!</h2>\n\n <p className=\"text-stone text-sm mb-6\">{message}</p>\n\n {onBack && (\n <button\n type=\"button\"\n onClick={onBack}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-[#7f22fe] hover:bg-primary-alt rounded-lg focus:outline-none focus:ring-2 focus:ring-primary transition-colors\"\n >\n Go Back\n </button>\n )}\n </div>\n </div>\n))\nErrorState.displayName = 'ErrorState'\n","import classNames from 'classnames'\nimport React, { useState, useCallback, useRef, useEffect } from 'react'\nimport type { Channel } from 'stream-chat'\n\nimport { useMessaging } from '../../hooks/useMessaging'\nimport type { MessagingShellProps, Participant } from '../../types'\nimport { ChannelList } from '../ChannelList'\nimport { ChannelView } from '../ChannelView'\nimport { ParticipantPicker } from '../ParticipantPicker'\n\nimport { EmptyState } from './EmptyState'\nimport { ErrorState } from './ErrorState'\nimport { LoadingState } from './LoadingState'\n\n/**\n * Main messaging interface component that combines channel list and channel view\n */\nexport const MessagingShell: React.FC<MessagingShellProps> = ({\n capabilities = {},\n className,\n renderMessageInputActions,\n onChannelSelect,\n onParticipantSelect,\n initialParticipantFilter,\n initialParticipantData,\n CustomChannelEmptyState,\n showChannelList = true,\n filters,\n channelListCustomEmptyStateIndicator,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n}) => {\n const {\n service,\n client,\n isConnected,\n isLoading,\n error,\n refreshConnection,\n debug,\n } = useMessaging()\n\n const [selectedChannel, setSelectedChannel] = useState<Channel | null>(null)\n const [hasChannels, setHasChannels] = useState(false)\n const [channelsLoaded, setChannelsLoaded] = useState(false)\n const [_showParticipantPicker, setShowParticipantPicker] = useState(false)\n const [existingParticipantIds, setExistingParticipantIds] = useState<\n Set<string>\n >(new Set())\n const [pickerKey, _setPickerKey] = useState(0) // Key to force remount of ParticipantPicker\n const [directConversationMode, setDirectConversationMode] = useState(false)\n const [directConversationError, setDirectConversationError] = useState<\n string | null\n >(null)\n\n const participantPickerRef = useRef<HTMLDialogElement>(null)\n\n const {\n participantSource,\n participantLabel = 'participants',\n showDeleteConversation = true,\n } = capabilities\n\n // Create default filters and merge with provided filters\n const channelFilters = React.useMemo(() => {\n const userId = client?.userID\n\n // Base filters that should always be present\n const baseFilters = {\n type: 'messaging',\n last_message_at: { $exists: true },\n ...(userId && {\n members: { $in: [userId] },\n hidden: false,\n }),\n }\n\n // Merge provided filters with base filters\n // Provided filters can override base filters if needed\n return {\n ...baseFilters,\n ...filters,\n }\n }, [filters, client?.userID])\n\n // Track if we've already synced channels to prevent repeated API calls\n const syncedRef = useRef<string | null>(null)\n\n // Function to sync channels (extracted for reuse)\n const syncChannels = useCallback(async () => {\n if (!client || !isConnected) return\n\n const userId = client.userID\n if (!userId) return\n\n try {\n if (debug) {\n console.log('[MessagingShell] Syncing channels for user:', userId)\n }\n\n const channels = await client.queryChannels(\n {\n type: 'messaging',\n members: { $in: [userId] },\n },\n {},\n { limit: 100 }\n )\n\n const memberIds = new Set<string>()\n channels.forEach((channel: Channel) => {\n const members = channel.state.members\n Object.values(members).forEach((member) => {\n const memberId = member.user?.id\n if (memberId && memberId !== userId) {\n memberIds.add(memberId)\n }\n })\n })\n\n // Only update if the set contents have changed to prevent re-renders\n setExistingParticipantIds((prev) => {\n if (\n prev.size === memberIds.size &&\n [...prev].every((id) => memberIds.has(id))\n ) {\n return prev\n }\n return memberIds\n })\n setHasChannels(channels.length > 0)\n setChannelsLoaded(true)\n syncedRef.current = userId // Mark as synced for this user\n\n if (debug) {\n console.log('[MessagingShell] Channels synced successfully:', {\n channelCount: channels.length,\n memberCount: memberIds.size,\n })\n }\n } catch (error) {\n console.error('[MessagingShell] Failed to sync channels:', error)\n // Don't mark as synced on error, allow retry\n }\n }, [client, isConnected, debug])\n\n // Sync existing channels to track which participants we can already message\n useEffect(() => {\n if (!client || !isConnected) return\n\n const userId = client.userID\n if (!userId) return\n\n // Prevent repeated sync for the same user\n if (syncedRef.current === userId) return\n\n syncChannels()\n }, [client, isConnected, syncChannels])\n\n // Load initial channel for direct conversation mode\n useEffect(() => {\n if (!initialParticipantFilter || !client || !isConnected) return\n\n const loadInitialChannel = async () => {\n const userId = client.userID\n if (!userId) return\n\n try {\n if (debug) {\n console.log(\n '[MessagingShell] Loading initial conversation with:',\n initialParticipantFilter\n )\n }\n\n const channels = await client.queryChannels(\n {\n type: 'messaging',\n members: { $eq: [userId, initialParticipantFilter] },\n },\n {},\n { limit: 1 }\n )\n\n if (channels.length > 0) {\n setSelectedChannel(channels[0])\n setDirectConversationMode(true)\n setDirectConversationError(null)\n\n // Notify parent component of channel selection\n if (onChannelSelect) {\n onChannelSelect(channels[0])\n }\n\n if (debug) {\n console.log(\n '[MessagingShell] Initial conversation loaded:',\n channels[0].id\n )\n }\n } else {\n // No channel found - try to create one if participant data is provided\n if (initialParticipantData && service) {\n if (debug) {\n console.log(\n '[MessagingShell] No conversation found, creating one for:',\n initialParticipantData\n )\n }\n\n try {\n // Use the existing service method to create the channel\n const channel = await service.startChannelWithParticipant({\n id: initialParticipantData.id,\n name: initialParticipantData.name,\n email: initialParticipantData.email,\n phone: initialParticipantData.phone,\n })\n\n setSelectedChannel(channel)\n setDirectConversationMode(true)\n setDirectConversationError(null)\n\n // Notify parent component of channel selection\n if (onChannelSelect) {\n onChannelSelect(channel)\n }\n\n if (debug) {\n console.log(\n '[MessagingShell] Channel created and loaded:',\n channel.id\n )\n }\n } catch (createErr) {\n console.error(\n '[MessagingShell] Failed to create conversation:',\n createErr\n )\n setDirectConversationError('Failed to create conversation')\n }\n } else {\n // No participant data provided, show error\n setDirectConversationError(\n 'No conversation found with this account'\n )\n\n if (debug) {\n console.log(\n '[MessagingShell] No conversation found for:',\n initialParticipantFilter\n )\n }\n }\n }\n } catch (err) {\n console.error(\n '[MessagingShell] Failed to load initial conversation:',\n err\n )\n setDirectConversationError('Failed to load conversation')\n }\n }\n\n loadInitialChannel()\n }, [\n initialParticipantFilter,\n initialParticipantData,\n client,\n isConnected,\n service,\n debug,\n onChannelSelect,\n ])\n\n const handleChannelSelect = useCallback(\n (channel: Channel) => {\n setSelectedChannel(channel)\n onChannelSelect?.(channel)\n },\n [onChannelSelect]\n )\n\n const handleBackToChannelList = useCallback(() => {\n // In direct conversation mode, don't allow going back to channel list\n // The parent component should handle navigation\n if (directConversationMode) return\n\n setSelectedChannel(null)\n }, [directConversationMode])\n\n const handleSelectParticipant = useCallback(\n async (participant: Participant) => {\n if (!service) return\n\n try {\n if (debug) {\n console.log(\n '[MessagingShell] Starting conversation with:',\n participant.id\n )\n }\n\n const channel = await service.startChannelWithParticipant({\n id: participant.id,\n name: participant.name,\n email: participant.email,\n phone: participant.phone,\n })\n\n // Show the channel\n try {\n await channel.show()\n } catch (error) {\n console.warn('[MessagingShell] Failed to unhide channel:', error)\n }\n\n setSelectedChannel(channel)\n setShowParticipantPicker(false)\n participantPickerRef.current?.close()\n\n onParticipantSelect?.(participant)\n } catch (error) {\n console.error('[MessagingShell] Failed to start conversation:', error)\n }\n },\n [service, onParticipantSelect, debug]\n )\n\n const handleCloseParticipantPicker = useCallback(() => {\n setShowParticipantPicker(false)\n participantPickerRef.current?.close()\n }, [])\n\n const handleDialogBackdropClick = useCallback(\n (e: React.MouseEvent<HTMLDialogElement>) => {\n if (e.target === participantPickerRef.current) {\n handleCloseParticipantPicker()\n }\n },\n [handleCloseParticipantPicker]\n )\n\n const handleLeaveConversation = useCallback(\n async (channel: Channel) => {\n if (debug) {\n console.log('[MessagingShell] Leaving conversation:', channel.id)\n }\n setSelectedChannel(null)\n setDirectConversationMode(false) // Exit direct conversation mode\n\n // Force re-sync to update the existing participants list\n syncedRef.current = null\n await syncChannels()\n },\n [syncChannels, debug]\n )\n\n const handleBlockParticipant = useCallback(\n async (participantId?: string) => {\n if (debug) {\n console.log('[MessagingShell] Blocking participant:', participantId)\n }\n setSelectedChannel(null)\n setDirectConversationMode(false) // Exit direct conversation mode\n\n // Force re-sync to update the existing participants list\n syncedRef.current = null\n await syncChannels()\n },\n [syncChannels, debug]\n )\n\n const isChannelSelected = Boolean(selectedChannel)\n\n console.log('[MessagingShell] render', {\n isLoading,\n error,\n isConnected,\n hasClient: !!client,\n directConversationError,\n selectedChannelId: selectedChannel?.id,\n directConversationMode\n })\n\n // Show loading state\n if (isLoading) {\n console.log('[MessagingShell] showing LOADING state')\n return (\n <div className={classNames('h-full', className)}>\n <LoadingState />\n </div>\n )\n }\n\n // Show error state\n if (error) {\n console.log('[MessagingShell] showing ERROR state:', error)\n return (\n <div className={classNames('h-full', className)}>\n <ErrorState message={error} onBack={refreshConnection} />\n </div>\n )\n }\n\n // Show not connected state\n if (!isConnected || !client) {\n console.log('[MessagingShell] showing NOT CONNECTED state')\n return (\n <div className={classNames('h-full', className)}>\n <ErrorState\n message=\"Not connected to messaging service\"\n onBack={refreshConnection}\n />\n </div>\n )\n }\n\n // Show direct conversation error state\n if (directConversationError) {\n console.log('[MessagingShell] showing DIRECT CONVERSATION ERROR:', directConversationError)\n return (\n <div className={classNames('h-full', className)}>\n <ErrorState message={directConversationError} />\n </div>\n )\n }\n\n console.log('[MessagingShell] rendering main UI with ChannelView')\n return (\n <div\n className={classNames(\n 'messaging-shell h-full bg-background-secondary overflow-hidden',\n className\n )}\n >\n <div className=\"flex h-full min-h-0\">\n {/* Channel List Sidebar */}\n <div\n className={classNames(\n 'messaging-channel-list-sidebar min-h-0 min-w-0 lg:flex lg:flex-col',\n {\n '!hidden': showChannelList === false || directConversationMode,\n // Hide on mobile when channel selected, show on desktop with consistent narrow width\n 'hidden lg:flex lg:w-80 lg:min-w-[280px] lg:max-w-[360px]':\n showChannelList !== false &&\n !directConversationMode &&\n isChannelSelected,\n // Show on mobile when no channel selected, use same narrow width on desktop\n 'flex flex-col w-full lg:w-80 lg:min-w-[280px] lg:max-w-[360px]':\n showChannelList !== false &&\n !directConversationMode &&\n !isChannelSelected,\n }\n )}\n >\n <ChannelList\n onChannelSelect={handleChannelSelect}\n selectedChannel={selectedChannel || undefined}\n filters={channelFilters}\n customEmptyStateIndicator={channelListCustomEmptyStateIndicator}\n />\n </div>\n\n {/* Channel View */}\n <div\n className={classNames(\n 'messaging-conversation-view flex-1 flex-col min-w-0 min-h-0',\n {\n // In direct conversation mode, always show (full width)\n flex: directConversationMode || isChannelSelected,\n // Normal mode: hide on mobile when no channel selected\n 'hidden lg:flex': !directConversationMode && !isChannelSelected,\n }\n )}\n >\n {selectedChannel ? (\n <div className=\"flex-1 min-h-0 flex flex-col\">\n <ChannelView\n channel={selectedChannel}\n key={selectedChannel.id}\n onBack={handleBackToChannelList}\n showBackButton={!directConversationMode}\n renderMessageInputActions={renderMessageInputActions}\n onLeaveConversation={handleLeaveConversation}\n onBlockParticipant={handleBlockParticipant}\n CustomChannelEmptyState={CustomChannelEmptyState}\n showDeleteConversation={showDeleteConversation}\n onDeleteConversationClick={onDeleteConversationClick}\n onBlockParticipantClick={onBlockParticipantClick}\n onReportParticipantClick={onReportParticipantClick}\n />\n </div>\n ) : initialParticipantFilter ? (\n // Show loading while creating/loading direct conversation channel\n <LoadingState />\n ) : (\n <EmptyState\n hasChannels={hasChannels}\n channelsLoaded={channelsLoaded}\n />\n )}\n </div>\n </div>\n\n {/* Participant Picker Dialog */}\n {participantSource && (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions\n <dialog\n ref={participantPickerRef}\n className=\"mes-dialog\"\n onClick={handleDialogBackdropClick}\n onClose={handleCloseParticipantPicker}\n >\n <div className=\"h-full w-full bg-white shadow-max-elevation-light\">\n <ParticipantPicker\n key={pickerKey}\n participantSource={participantSource}\n onSelectParticipant={handleSelectParticipant}\n onClose={handleCloseParticipantPicker}\n existingParticipantIds={existingParticipantIds}\n participantLabel={participantLabel}\n searchPlaceholder={`Search ${participantLabel}...`}\n />\n </div>\n </dialog>\n )}\n </div>\n )\n}\n","import classNames from 'classnames'\nimport React from 'react'\nexport interface FaqListItemProps {\n question: string\n onClick: () => void\n loading?: boolean\n className?: string\n}\n\nexport const FaqListItem: React.FC<FaqListItemProps> = ({\n question,\n onClick,\n loading = false,\n className,\n}) => {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={loading}\n style={{ backgroundColor: '#E6E5E3' }}\n className={classNames(\n 'w-full text-center p-4 rounded-xl text-charcoal font-medium transition-colors',\n {\n 'hover:brightness-95 active:brightness-90': !loading,\n 'opacity-50 cursor-not-allowed': loading,\n },\n className\n )}\n >\n {question}\n </button>\n )\n}\n","import React from 'react'\n\nimport { Avatar } from '../Avatar'\n\nimport { FaqListItem } from './FaqListItem'\n\nexport interface Faq {\n id: string\n question: string\n answer: string\n enabled: boolean\n order?: number | null\n}\n\nexport interface FaqListProps {\n faqs: Faq[]\n onFaqClick: (faqId: string) => void\n loadingFaqId?: string | null\n headerText?: string\n className?: string\n avatarImage?: string\n avatarName?: string\n}\n\nexport const FaqList: React.FC<FaqListProps> = ({\n faqs,\n onFaqClick,\n loadingFaqId,\n headerText,\n className,\n avatarImage,\n avatarName,\n}) => {\n const enabledFaqs = faqs\n .filter((faq) => faq.enabled)\n .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))\n\n if (enabledFaqs.length === 0) {\n return null\n }\n\n return (\n <div className={className}>\n <div className=\"flex gap-3 items-end\">\n {/* Avatar at bottom-left, outside grey background */}\n {(avatarImage || avatarName) && (\n <div className=\"flex-none\">\n <Avatar\n id={avatarName || 'account'}\n name={avatarName || 'Account'}\n image={avatarImage}\n size={24}\n shape=\"circle\"\n />\n </div>\n )}\n\n {/* FAQs with grey background */}\n <div\n className=\"flex-1 flex flex-col gap-3 rounded-lg p-4\"\n style={{ backgroundColor: '#F1F0EE' }}\n >\n {headerText && (\n <p className=\"text-md text-charcoal mb-4\">{headerText}</p>\n )}\n {enabledFaqs.map((faq) => (\n <FaqListItem\n key={faq.id}\n question={faq.question}\n onClick={() => onFaqClick(faq.id)}\n loading={loadingFaqId === faq.id}\n />\n ))}\n </div>\n </div>\n </div>\n )\n}\n","import { useState, useEffect, useCallback } from 'react';\n\nimport type { ParticipantSource, Participant } from '../types';\n\n/**\n * Hook for managing participant loading with search and pagination\n */\nexport const useParticipants = (\n participantSource: ParticipantSource,\n options: {\n initialSearch?: string;\n pageSize?: number;\n } = {}\n) => {\n const { initialSearch = '', pageSize = 20 } = options;\n \n const [participants, setParticipants] = useState<Participant[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [searchQuery, setSearchQuery] = useState(initialSearch);\n const [hasMore, setHasMore] = useState(true);\n const [cursor, setCursor] = useState<string | undefined>();\n\n // Load participants with current search query\n const loadParticipants = useCallback(async (\n reset = false,\n customSearch?: string\n ) => {\n if (loading) return;\n \n const search = customSearch !== undefined ? customSearch : searchQuery;\n \n setLoading(true);\n setError(null);\n\n try {\n const result = await participantSource.loadParticipants({\n search: search || undefined,\n limit: pageSize,\n cursor: reset ? undefined : cursor,\n });\n\n setParticipants(prev => \n reset ? result.participants : [...prev, ...result.participants]\n );\n setHasMore(result.hasMore);\n setCursor(result.nextCursor);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Failed to load participants';\n setError(errorMessage);\n console.error('[useParticipants] Load error:', err);\n } finally {\n setLoading(false);\n }\n }, [participantSource, searchQuery, cursor, pageSize, loading]);\n\n // Load more participants (pagination)\n const loadMore = useCallback(() => {\n if (hasMore && !loading) {\n loadParticipants(false);\n }\n }, [hasMore, loading, loadParticipants]);\n\n // Search participants\n const search = useCallback((query: string) => {\n setSearchQuery(query);\n setCursor(undefined);\n loadParticipants(true, query);\n }, [loadParticipants]);\n\n // Refresh participants\n const refresh = useCallback(() => {\n setCursor(undefined);\n loadParticipants(true);\n }, [loadParticipants]);\n\n // Initial load - only run once when participantSource changes\n useEffect(() => {\n loadParticipants(true);\n }, [participantSource.loadParticipants]); // Only depend on the function to avoid loops\n\n return {\n participants,\n loading,\n error,\n searchQuery,\n hasMore,\n totalCount: participantSource.totalCount,\n loadMore,\n search,\n refresh,\n };\n};\n"],"names":["MessagingContext","createContext","useMessagingContext","useContext","MessagingProvider","children","user","serviceConfig","apiKey","capabilities","debug","debugLog","useCallback","message","args","service","setService","useState","client","setClient","isConnected","setIsConnected","isLoading","setIsLoading","error","setError","connectingRef","useRef","prevPropsRef","renderCountRef","useEffect","currentRender","newService","StreamChatService","connectedUserRef","_a","_b","streamClient","err","errorMessage","refreshConnection","contextValue","React","jsx","Chat","useMessaging","getDaysDifference","date1","date2","d1","diffTime","formatRelativeTime","date","now","daysDiff","EMOJIS","hashString","str","hash","i","char","getAvatarEmoji","id","index","Avatar","image","size","className","shape","emoji","fontSizeClass","borderStyle","classNames","CustomChannelPreview","channel","selectedChannel","onChannelSelect","unread","isSelected","handleClick","participant","member","participantName","participantImage","_c","lastMessage","_e","_d","lastMessageText","attachment","lastMessageTime","unreadCount","jsxs","_f","ChannelList","filters","customEmptyStateIndicator","PreviewComponent","props","StreamChannelList","ActionButton","variant","rest","IconButton","label","CloseButton","onClick","XIcon","linkPreviewsManagerStateSelector","state","preview","LinkPreviewsManager","CustomLinkPreviewCard","link","onDismiss","og_scrape_url","title","image_url","e","CustomLinkPreviewList","linkPreviewsManager","useMessageComposer","stateLinkPreviews","useStateStore","handleDismiss","url","linkPreview","CustomMessageInputInner","handleSubmit","useMessageInputContext","hasSendableData","useMessageComposerHasSendableData","Fragment","SimpleAttachmentSelector","QuotedMessagePreview","AttachmentPreviewList","TextareaComposer","ArrowUpIcon","CustomMessageInput","renderActions","MessageInput","CustomSystemMessage","isDateHidden","MessageTimestamp","ChannelEmptyState","Loading","LoadingState","CustomChannelHeader","onBack","showBackButton","onShowInfo","canShowInfo","useChannelStateContext","ArrowLeftIcon","DotsThreeIcon","ChannelInfoDialog","dialogRef","onClose","followerStatusLabel","onLeaveConversation","onBlockParticipant","showDeleteConversation","onDeleteConversationClick","onBlockParticipantClick","onReportParticipantClick","isParticipantBlocked","setIsParticipantBlocked","isLeaving","setIsLeaving","isUpdatingBlockStatus","setIsUpdatingBlockStatus","checkIsParticipantBlocked","isBlocked","handleLeaveConversation","actingUserId","handleBlockUser","handleUnblockUser","handleReportUser","participantEmail","participantUsername","participantSecondary","participantId","_g","SpinnerGapIcon","SignOutIcon","ProhibitInsetIcon","FlagIcon","ChannelViewInner","renderMessageInputActions","infoDialogRef","channelExtraData","handleShowInfo","handleCloseInfo","Window","MessageList","ChannelView","CustomChannelEmptyState","Channel","SearchInput","searchQuery","setSearchQuery","placeholder","searchInputRef","MagnifyingGlassIcon","ParticipantPicker","participantSource","onSelectParticipant","existingParticipantIds","participantLabel","searchPlaceholder","participants","setParticipants","loading","setLoading","startingChatWithId","setStartingChatWithId","loadedRef","result","availableParticipants","searchLower","handleSelectParticipant","handleKeyDown","event","ChatCircleDotsIcon","displayName","displaySecondary","ChatBubblesIllustration","EmptyState","hasChannels","channelsLoaded","ErrorState","MessagingShell","onParticipantSelect","initialParticipantFilter","initialParticipantData","showChannelList","channelListCustomEmptyStateIndicator","setSelectedChannel","setHasChannels","setChannelsLoaded","_showParticipantPicker","setShowParticipantPicker","setExistingParticipantIds","pickerKey","_setPickerKey","directConversationMode","setDirectConversationMode","directConversationError","setDirectConversationError","participantPickerRef","channelFilters","userId","syncedRef","syncChannels","channels","memberIds","members","memberId","prev","createErr","handleChannelSelect","handleBackToChannelList","handleCloseParticipantPicker","handleDialogBackdropClick","handleBlockParticipant","isChannelSelected","FaqListItem","question","FaqList","faqs","onFaqClick","loadingFaqId","headerText","avatarImage","avatarName","enabledFaqs","faq","a","b","useParticipants","options","initialSearch","pageSize","hasMore","setHasMore","cursor","setCursor","loadParticipants","reset","customSearch","search","loadMore","query","refresh"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -492,6 +492,9 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
492
492
|
onReportParticipantClick={onReportParticipantClick}
|
|
493
493
|
/>
|
|
494
494
|
</div>
|
|
495
|
+
) : initialParticipantFilter ? (
|
|
496
|
+
// Show loading while creating/loading direct conversation channel
|
|
497
|
+
<LoadingState />
|
|
495
498
|
) : (
|
|
496
499
|
<EmptyState
|
|
497
500
|
hasChannels={hasChannels}
|