@linktr.ee/messaging-react 1.6.4 → 1.6.5
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 +44 -39
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ChannelList/index.tsx +7 -2
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as e, jsxs as d, Fragment as oe } from "react/jsx-runtime";
|
|
2
2
|
import D from "classnames";
|
|
3
|
-
import X, { createContext as we, useContext as Ee, useCallback as F, useState as E, useRef as
|
|
3
|
+
import X, { createContext as we, useContext as Ee, useCallback as F, useState as E, useRef as _, useEffect as $ } from "react";
|
|
4
4
|
import { StreamChatService as Ie } from "@linktr.ee/messaging-core";
|
|
5
5
|
import { Chat as ye, useChatContext as Se, ChannelList as Re, Channel as ke, useChannelStateContext as me, Window as Te, MessageList as Pe, MessageInput as De } from "stream-chat-react";
|
|
6
6
|
import { NotePencilIcon as Oe, XIcon as he, ArrowLeftIcon as Me, DotsThreeIcon as Fe, SpinnerGapIcon as ee, SignOutIcon as Ue, ProhibitInsetIcon as ie, FlagIcon as Le, MagnifyingGlassIcon as pe, ChatCircleDotsIcon as ce } from "@phosphor-icons/react";
|
|
@@ -37,13 +37,13 @@ const fe = we({
|
|
|
37
37
|
capabilities: Object.keys(i),
|
|
38
38
|
customization: Object.keys(c)
|
|
39
39
|
});
|
|
40
|
-
const [r, b] = E(null), [u, g] = E(null), [m, I] = E(!1), [N, h] = E(!1), [v, S] = E(null), M =
|
|
40
|
+
const [r, b] = E(null), [u, g] = E(null), [m, I] = E(!1), [N, h] = E(!1), [v, S] = E(null), M = _(!1), y = _({
|
|
41
41
|
userId: s == null ? void 0 : s.id,
|
|
42
42
|
apiKey: o,
|
|
43
43
|
serviceConfig: n,
|
|
44
44
|
capabilities: i,
|
|
45
45
|
customization: c
|
|
46
|
-
}), k =
|
|
46
|
+
}), k = _(0);
|
|
47
47
|
k.current++, l("📊 RENDER INFO", {
|
|
48
48
|
renderCount: k.current,
|
|
49
49
|
currentProps: { userId: s == null ? void 0 : s.id, apiKey: (o == null ? void 0 : o.substring(0, 8)) + "..." },
|
|
@@ -60,7 +60,7 @@ const fe = we({
|
|
|
60
60
|
serviceConfig: n,
|
|
61
61
|
capabilities: i,
|
|
62
62
|
customization: c
|
|
63
|
-
},
|
|
63
|
+
}, $(() => {
|
|
64
64
|
const w = k.current;
|
|
65
65
|
if (l("🔧 SERVICE INIT EFFECT TRIGGERED", {
|
|
66
66
|
renderCount: w,
|
|
@@ -99,8 +99,8 @@ const fe = we({
|
|
|
99
99
|
}), O.disconnectUser().catch(console.error);
|
|
100
100
|
};
|
|
101
101
|
}, [o, n, a, l]);
|
|
102
|
-
const T =
|
|
103
|
-
|
|
102
|
+
const T = _(null);
|
|
103
|
+
$(() => {
|
|
104
104
|
var O, L;
|
|
105
105
|
if (l("🔗 USER CONNECTION EFFECT TRIGGERED", {
|
|
106
106
|
hasService: !!r,
|
|
@@ -134,10 +134,10 @@ const fe = we({
|
|
|
134
134
|
clientId: p.userID
|
|
135
135
|
});
|
|
136
136
|
} catch (p) {
|
|
137
|
-
const
|
|
138
|
-
S(
|
|
137
|
+
const H = p instanceof Error ? p.message : "Connection failed";
|
|
138
|
+
S(H), l("❌ USER CONNECTION ERROR", {
|
|
139
139
|
userId: s.id,
|
|
140
|
-
error:
|
|
140
|
+
error: H
|
|
141
141
|
});
|
|
142
142
|
} finally {
|
|
143
143
|
h(!1), M.current = !1, l("🔄 USER CONNECTION FINISHED", {
|
|
@@ -146,7 +146,7 @@ const fe = we({
|
|
|
146
146
|
});
|
|
147
147
|
}
|
|
148
148
|
})();
|
|
149
|
-
}, [r, s, l, m]),
|
|
149
|
+
}, [r, s, l, m]), $(() => (l("🔌 CLEANUP EFFECT REGISTERED", {
|
|
150
150
|
hasService: !!r,
|
|
151
151
|
isConnected: m
|
|
152
152
|
}), () => {
|
|
@@ -316,7 +316,7 @@ const J = ({
|
|
|
316
316
|
)
|
|
317
317
|
}
|
|
318
318
|
);
|
|
319
|
-
},
|
|
319
|
+
}, _e = ({ channel: t, selectedChannel: s, onChannelSelect: n, debug: o = !1, unread: i }) => {
|
|
320
320
|
var h, v, S, M, y, k;
|
|
321
321
|
const c = (s == null ? void 0 : s.id) === (t == null ? void 0 : t.id), a = () => {
|
|
322
322
|
t && n(t);
|
|
@@ -379,7 +379,7 @@ const J = ({
|
|
|
379
379
|
] })
|
|
380
380
|
}
|
|
381
381
|
);
|
|
382
|
-
},
|
|
382
|
+
}, $e = ({
|
|
383
383
|
onChannelSelect: t,
|
|
384
384
|
selectedChannel: s,
|
|
385
385
|
showStartConversation: n = !1,
|
|
@@ -405,7 +405,12 @@ const J = ({
|
|
|
405
405
|
clientConnected: (u = r == null ? void 0 : r.wsConnection) == null ? void 0 : u.isHealthy
|
|
406
406
|
});
|
|
407
407
|
const b = X.useMemo(() => {
|
|
408
|
-
const g = r.userID, m = g ? {
|
|
408
|
+
const g = r.userID, m = g ? {
|
|
409
|
+
type: "messaging",
|
|
410
|
+
members: { $in: [g] },
|
|
411
|
+
hidden: !1,
|
|
412
|
+
last_message_at: { $exists: !0 }
|
|
413
|
+
} : { type: "messaging", last_message_at: { $exists: !0 } };
|
|
409
414
|
return l && console.log("📺 [ChannelList] 🔍 FILTERS MEMOIZED", {
|
|
410
415
|
renderCount: a.current,
|
|
411
416
|
userId: g,
|
|
@@ -450,7 +455,7 @@ const J = ({
|
|
|
450
455
|
selectedChannelId: s == null ? void 0 : s.id,
|
|
451
456
|
isSelected: (s == null ? void 0 : s.id) === ((I = g.channel) == null ? void 0 : I.id)
|
|
452
457
|
}), /* @__PURE__ */ e(
|
|
453
|
-
|
|
458
|
+
_e,
|
|
454
459
|
{
|
|
455
460
|
...g,
|
|
456
461
|
selectedChannel: s,
|
|
@@ -485,10 +490,10 @@ const J = ({
|
|
|
485
490
|
function ge({ onClick: t }) {
|
|
486
491
|
return /* @__PURE__ */ e(ne, { label: "Close", onClick: t, className: "p-1", children: /* @__PURE__ */ e(he, { className: "h-5 w-5 text-stone", weight: "bold" }) });
|
|
487
492
|
}
|
|
488
|
-
const
|
|
493
|
+
const He = ({ renderActions: t }) => /* @__PURE__ */ d("div", { className: "message-input flex items-center gap-2 p-4", children: [
|
|
489
494
|
t && t(),
|
|
490
495
|
/* @__PURE__ */ e("div", { className: "flex-1", children: /* @__PURE__ */ e(De, { focus: !0, maxRows: 4 }) })
|
|
491
|
-
] }),
|
|
496
|
+
] }), Ge = ({ onBack: t, showBackButton: s, onShowInfo: n, canShowInfo: o }) => {
|
|
492
497
|
var r, b, u, g;
|
|
493
498
|
const { channel: i } = me(), c = X.useMemo(() => Object.values(i.state.members || {}).find(
|
|
494
499
|
(I) => {
|
|
@@ -530,9 +535,9 @@ const $e = ({ renderActions: t }) => /* @__PURE__ */ d("div", { className: "mess
|
|
|
530
535
|
onLeaveConversation: c,
|
|
531
536
|
onBlockParticipant: a
|
|
532
537
|
}) => {
|
|
533
|
-
var p,
|
|
534
|
-
const { service: l, debug: r } = se(), b =
|
|
535
|
-
|
|
538
|
+
var p, H, G, V, Q, W, z;
|
|
539
|
+
const { service: l, debug: r } = se(), b = _(null), [u, g] = E(!1), [m, I] = E(!1), [N, h] = E(!1);
|
|
540
|
+
$(() => {
|
|
536
541
|
const R = b.current;
|
|
537
542
|
R && (t ? R.showModal() : R.close());
|
|
538
543
|
}, [t]);
|
|
@@ -554,7 +559,7 @@ const $e = ({ renderActions: t }) => /* @__PURE__ */ d("div", { className: "mess
|
|
|
554
559
|
);
|
|
555
560
|
}
|
|
556
561
|
}, [l, (p = n == null ? void 0 : n.user) == null ? void 0 : p.id]);
|
|
557
|
-
|
|
562
|
+
$(() => {
|
|
558
563
|
t && v();
|
|
559
564
|
}, [t, v]);
|
|
560
565
|
const S = async () => {
|
|
@@ -602,7 +607,7 @@ const $e = ({ renderActions: t }) => /* @__PURE__ */ d("div", { className: "mess
|
|
|
602
607
|
);
|
|
603
608
|
};
|
|
604
609
|
if (!n) return null;
|
|
605
|
-
const T = ((
|
|
610
|
+
const T = ((H = n.user) == null ? void 0 : H.name) || ((G = n.user) == null ? void 0 : G.id) || "Unknown member", f = (V = n.user) == null ? void 0 : V.image, x = (Q = n.user) == null ? void 0 : Q.email, w = (W = n.user) == null ? void 0 : W.username, O = x || (w ? `linktr.ee/${w}` : void 0), L = ((z = n.user) == null ? void 0 : z.id) || "unknown";
|
|
606
611
|
return (
|
|
607
612
|
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions
|
|
608
613
|
/* @__PURE__ */ e(
|
|
@@ -703,7 +708,7 @@ const $e = ({ renderActions: t }) => /* @__PURE__ */ d("div", { className: "mess
|
|
|
703
708
|
return /* @__PURE__ */ d(oe, { children: [
|
|
704
709
|
/* @__PURE__ */ d(Te, { children: [
|
|
705
710
|
/* @__PURE__ */ e("div", { className: "border-b border-sand bg-white px-4 py-3", children: /* @__PURE__ */ e(
|
|
706
|
-
|
|
711
|
+
Ge,
|
|
707
712
|
{
|
|
708
713
|
onBack: t,
|
|
709
714
|
showBackButton: s,
|
|
@@ -716,7 +721,7 @@ const $e = ({ renderActions: t }) => /* @__PURE__ */ d("div", { className: "mess
|
|
|
716
721
|
!b && c && /* @__PURE__ */ e("div", { className: "absolute inset-0 flex bg-white", children: /* @__PURE__ */ e(c, {}) })
|
|
717
722
|
] }),
|
|
718
723
|
/* @__PURE__ */ e(
|
|
719
|
-
|
|
724
|
+
He,
|
|
720
725
|
{
|
|
721
726
|
renderActions: () => n == null ? void 0 : n(a)
|
|
722
727
|
}
|
|
@@ -769,7 +774,7 @@ function qe({
|
|
|
769
774
|
setSearchQuery: s,
|
|
770
775
|
placeholder: n
|
|
771
776
|
}) {
|
|
772
|
-
const o =
|
|
777
|
+
const o = _(null);
|
|
773
778
|
return /* @__PURE__ */ d("div", { className: "relative", children: [
|
|
774
779
|
/* @__PURE__ */ e(
|
|
775
780
|
pe,
|
|
@@ -814,8 +819,8 @@ const Xe = ({
|
|
|
814
819
|
}) => {
|
|
815
820
|
const { debug: l } = se(), [r, b] = E(""), [u, g] = E([]), [m, I] = E(!1), [N, h] = E(null), [v, S] = E(
|
|
816
821
|
null
|
|
817
|
-
), M =
|
|
818
|
-
|
|
822
|
+
), M = _(!1);
|
|
823
|
+
$(() => {
|
|
819
824
|
if (t.loading) {
|
|
820
825
|
l && console.log(
|
|
821
826
|
"[ParticipantPicker] Waiting for participant source to finish loading..."
|
|
@@ -1048,11 +1053,11 @@ const Xe = ({
|
|
|
1048
1053
|
error: I,
|
|
1049
1054
|
refreshConnection: N,
|
|
1050
1055
|
debug: h
|
|
1051
|
-
} = je(), [v, S] = E(null), [M, y] = E(!1), [k, T] = E(!1), [f, x] = E(/* @__PURE__ */ new Set()), [w, O] = E(0), [L, p] = E(!1), [
|
|
1056
|
+
} = je(), [v, S] = E(null), [M, y] = E(!1), [k, T] = E(!1), [f, x] = E(/* @__PURE__ */ new Set()), [w, O] = E(0), [L, p] = E(!1), [H, G] = E(null), V = _(null), {
|
|
1052
1057
|
showStartConversation: Q = !1,
|
|
1053
1058
|
participantSource: W,
|
|
1054
1059
|
participantLabel: z = "participants"
|
|
1055
|
-
} = t, R =
|
|
1060
|
+
} = t, R = _(null), P = F(async () => {
|
|
1056
1061
|
if (!u || !g) return;
|
|
1057
1062
|
const C = u.userID;
|
|
1058
1063
|
if (C)
|
|
@@ -1081,11 +1086,11 @@ const Xe = ({
|
|
|
1081
1086
|
console.error("[MessagingShell] Failed to sync channels:", j);
|
|
1082
1087
|
}
|
|
1083
1088
|
}, [u, g, h]);
|
|
1084
|
-
|
|
1089
|
+
$(() => {
|
|
1085
1090
|
if (!u || !g) return;
|
|
1086
1091
|
const C = u.userID;
|
|
1087
1092
|
C && R.current !== C && P();
|
|
1088
|
-
}, [u, g, P]),
|
|
1093
|
+
}, [u, g, P]), $(() => {
|
|
1089
1094
|
if (!c || !u || !g) return;
|
|
1090
1095
|
(async () => {
|
|
1091
1096
|
const j = u.userID;
|
|
@@ -1104,7 +1109,7 @@ const Xe = ({
|
|
|
1104
1109
|
{ limit: 1 }
|
|
1105
1110
|
);
|
|
1106
1111
|
if (U.length > 0)
|
|
1107
|
-
S(U[0]), p(!0),
|
|
1112
|
+
S(U[0]), p(!0), G(null), o && o(U[0]), h && console.log(
|
|
1108
1113
|
"[MessagingShell] Initial conversation loaded:",
|
|
1109
1114
|
U[0].id
|
|
1110
1115
|
);
|
|
@@ -1120,7 +1125,7 @@ const Xe = ({
|
|
|
1120
1125
|
email: a.email,
|
|
1121
1126
|
phone: a.phone
|
|
1122
1127
|
});
|
|
1123
|
-
S(B), p(!0),
|
|
1128
|
+
S(B), p(!0), G(null), o && o(B), h && console.log(
|
|
1124
1129
|
"[MessagingShell] Channel created and loaded:",
|
|
1125
1130
|
B.id
|
|
1126
1131
|
);
|
|
@@ -1128,10 +1133,10 @@ const Xe = ({
|
|
|
1128
1133
|
console.error(
|
|
1129
1134
|
"[MessagingShell] Failed to create conversation:",
|
|
1130
1135
|
B
|
|
1131
|
-
),
|
|
1136
|
+
), G("Failed to create conversation");
|
|
1132
1137
|
}
|
|
1133
1138
|
} else
|
|
1134
|
-
|
|
1139
|
+
G(
|
|
1135
1140
|
"No conversation found with this account"
|
|
1136
1141
|
), h && console.log(
|
|
1137
1142
|
"[MessagingShell] No conversation found for:",
|
|
@@ -1141,7 +1146,7 @@ const Xe = ({
|
|
|
1141
1146
|
console.error(
|
|
1142
1147
|
"[MessagingShell] Failed to load initial conversation:",
|
|
1143
1148
|
U
|
|
1144
|
-
),
|
|
1149
|
+
), G("Failed to load conversation");
|
|
1145
1150
|
}
|
|
1146
1151
|
})();
|
|
1147
1152
|
}, [
|
|
@@ -1209,7 +1214,7 @@ const Xe = ({
|
|
|
1209
1214
|
message: "Not connected to messaging service",
|
|
1210
1215
|
onBack: N
|
|
1211
1216
|
}
|
|
1212
|
-
) }) :
|
|
1217
|
+
) }) : H ? /* @__PURE__ */ e("div", { className: D("h-full", s), children: /* @__PURE__ */ e(le, { message: H }) }) : /* @__PURE__ */ d(
|
|
1213
1218
|
"div",
|
|
1214
1219
|
{
|
|
1215
1220
|
className: D(
|
|
@@ -1233,7 +1238,7 @@ const Xe = ({
|
|
|
1233
1238
|
}
|
|
1234
1239
|
),
|
|
1235
1240
|
children: /* @__PURE__ */ e(
|
|
1236
|
-
|
|
1241
|
+
$e,
|
|
1237
1242
|
{
|
|
1238
1243
|
onChannelSelect: A,
|
|
1239
1244
|
selectedChannel: v || void 0,
|
|
@@ -1395,7 +1400,7 @@ const Xe = ({
|
|
|
1395
1400
|
}, [v]), y = F(() => {
|
|
1396
1401
|
h(void 0), v(!0);
|
|
1397
1402
|
}, [v]);
|
|
1398
|
-
return
|
|
1403
|
+
return $(() => {
|
|
1399
1404
|
v(!0);
|
|
1400
1405
|
}, [t.loadParticipants]), {
|
|
1401
1406
|
participants: i,
|
|
@@ -1411,7 +1416,7 @@ const Xe = ({
|
|
|
1411
1416
|
};
|
|
1412
1417
|
export {
|
|
1413
1418
|
J as Avatar,
|
|
1414
|
-
|
|
1419
|
+
$e as ChannelList,
|
|
1415
1420
|
ze as ChannelView,
|
|
1416
1421
|
as as FaqList,
|
|
1417
1422
|
Ye as FaqListItem,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/providers/MessagingProvider.tsx","../src/hooks/useMessaging.ts","../src/components/IconButton/index.tsx","../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/CloseButton/index.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/Loading/index.tsx","../src/components/MessagingShell/LoadingState.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 {\n MessagingProviderProps,\n MessagingCapabilities,\n MessagingCustomization,\n} 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 customization: MessagingCustomization\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 customization: {},\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 customization = {},\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 customization: Object.keys(customization),\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 customization,\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 customizationChanged:\n prevPropsRef.current.customization !== customization,\n },\n })\n\n prevPropsRef.current = {\n userId: user?.id,\n apiKey,\n serviceConfig,\n capabilities,\n customization,\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 customizationKeys: Object.keys(customization),\n })\n\n return {\n service,\n client,\n isConnected,\n isLoading,\n error,\n capabilities,\n customization,\n refreshConnection,\n debug,\n }\n }, [\n service,\n client,\n isConnected,\n isLoading,\n error,\n capabilities,\n customization,\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 client={client}>{children}</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","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}","/**\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}\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}) => {\n const emoji = getAvatarEmoji(id)\n\n const DEFAULT_COLOR = '#FBFAF9'\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 return (\n <div\n className={classNames(\n 'flex-shrink-0 overflow-hidden rounded-lg',\n className\n )}\n style={{ width: `${size}px`, height: `${size}px` }}\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 'flex h-full w-full items-center justify-center font-semibold rounded-sm',\n fontSizeClass\n )}\n style={{\n color: DEFAULT_COLOR,\n backgroundColor: `color-mix(in srgb, ${DEFAULT_COLOR} 60%, solid)`,\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 { Avatar } from '../Avatar'\n\n/**\n * Custom channel preview that handles selection\n */\nconst CustomChannelPreview: React.FC<\n ChannelPreviewUIComponentProps & {\n selectedChannel?: Channel | null\n onChannelSelect: (channel: Channel) => void\n debug?: boolean\n }\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 const lastMessageText = lastMessage?.text || 'No messages yet'\n const lastMessageTime = lastMessage?.created_at\n ? new Date(lastMessage.created_at).toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n })\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 'w-full px-4 py-3 transition-colors border-b border-sand 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 />\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-primary 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\nexport default CustomChannelPreview\n","import { NotePencilIcon } from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React from 'react'\nimport {\n ChannelList as StreamChannelList,\n useChatContext,\n} from 'stream-chat-react'\n\nimport { useMessagingContext } from '../../providers/MessagingProvider'\nimport type { ChannelListProps } from '../../types'\nimport { IconButton } from '../IconButton'\n\nimport CustomChannelPreview from './CustomChannelPreview'\n\n/**\n * Channel list component with customizable header and actions\n */\nexport const ChannelList: React.FC<ChannelListProps> = ({\n onChannelSelect,\n selectedChannel,\n showStartConversation = false,\n onStartConversation,\n participantLabel = 'participants',\n className,\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 showStartConversation,\n participantLabel,\n })\n }\n\n const { client } = useChatContext()\n\n if (debug) {\n console.log('📺 [ChannelList] 📡 CHAT CONTEXT', {\n renderCount: renderCountRef.current,\n hasClient: !!client,\n clientUserId: client?.userID,\n clientConnected: client?.wsConnection?.isHealthy,\n })\n }\n\n // Filter for messaging channels\n const filters = React.useMemo(() => {\n const userId = client.userID\n const newFilters = userId\n ? { type: 'messaging', members: { $in: [userId] }, hidden: false }\n : { type: 'messaging' }\n\n if (debug) {\n console.log('📺 [ChannelList] 🔍 FILTERS MEMOIZED', {\n renderCount: renderCountRef.current,\n userId,\n filters: newFilters,\n })\n }\n\n return newFilters\n }, [client.userID, 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 {/* Header */}\n <div className=\"px-4 py-4 border-b border-sand bg-chalk\">\n <div className=\"flex items-center justify-between gap-3 min-h-10 min-w-0\">\n <h2 className=\"text-lg font-semibold text-charcoal\">Conversations</h2>\n <div className=\"flex items-center gap-2\">\n {showStartConversation && onStartConversation && (\n <IconButton\n label=\"Start a new conversation\"\n onClick={onStartConversation}\n className=\"inline-flex size-10 items-center justify-center\"\n >\n <NotePencilIcon className=\"h-5 w-5\" />\n </IconButton>\n )}\n </div>\n </div>\n </div>\n\n {/* Channel List */}\n <div className=\"flex-1 overflow-hidden min-w-0\">\n {(() => {\n if (debug) {\n console.log('📺 [ChannelList] 🎬 RENDERING STREAM CHANNEL LIST', {\n renderCount: renderCountRef.current,\n filters,\n hasClient: !!client,\n clientUserId: client?.userID,\n })\n }\n\n return (\n <StreamChannelList\n filters={filters}\n sort={{ last_message_at: -1 }}\n options={{ limit: 30 }}\n Preview={(props) => {\n if (debug) {\n console.log('📺 [ChannelList] 📋 CHANNEL PREVIEW RENDER', {\n channelId: props.channel?.id,\n selectedChannelId: selectedChannel?.id,\n isSelected: selectedChannel?.id === props.channel?.id,\n })\n }\n\n return (\n <CustomChannelPreview\n {...props}\n selectedChannel={selectedChannel}\n onChannelSelect={onChannelSelect}\n debug={debug}\n />\n )\n }}\n />\n )\n })()}\n </div>\n </div>\n )\n}\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 { 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 {\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 MessageInput,\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 { IconButton } from './IconButton'\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 message input component with render prop for actions\n */\nconst CustomMessageInput: React.FC<{\n renderActions?: () => React.ReactNode\n}> = ({ renderActions }) => (\n <div className=\"message-input flex items-center gap-2 p-4\">\n {renderActions && renderActions()}\n\n <div className=\"flex-1\">\n <MessageInput focus maxRows={4} />\n </div>\n </div>\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=\"flex items-center justify-between gap-3 min-h-12\">\n <div className=\"flex items-center gap-3 min-w-0\">\n {showBackButton && onBack && (\n <button\n type=\"button\"\n onClick={onBack}\n className=\"inline-flex items-center justify-center w-8 h-8 rounded-lg hover:bg-sand focus:outline-none focus:ring-2 focus:ring-primary transition-colors lg:hidden\"\n aria-label=\"Back to conversations\"\n >\n <ArrowLeftIcon className=\"h-5 w-5 text-stone\" weight=\"bold\" />\n </button>\n )}\n\n {/* Avatar */}\n <Avatar\n id={participant?.user?.id || channel.id || 'unknown'}\n name={participantName}\n image={participantImage}\n size={40}\n />\n\n <div className=\"min-w-0\">\n <h1 className=\"text-lg font-semibold text-charcoal truncate\">\n {participantName}\n </h1>\n </div>\n </div>\n\n {canShowInfo && onShowInfo && (\n <IconButton label=\"Chat info\" onClick={onShowInfo}>\n <DotsThreeIcon className=\"h-6 w-6 text-charcoal\" weight=\"bold\" />\n </IconButton>\n )}\n </div>\n )\n}\n\n/**\n * Channel info dialog (matching original implementation)\n */\nconst ChannelInfoDialog: React.FC<{\n isOpen: boolean\n onClose: () => void\n participant: ChannelMemberResponse | undefined\n channel: ChannelType\n followerStatusLabel?: string\n onLeaveConversation?: (channel: ChannelType) => void\n onBlockParticipant?: (participantId?: string) => void\n}> = ({\n isOpen,\n onClose,\n participant,\n channel,\n followerStatusLabel,\n onLeaveConversation,\n onBlockParticipant,\n}) => {\n const { service, debug } = useMessagingContext()\n const dialogRef = useRef<HTMLDialogElement>(null)\n const [isParticipantBlocked, setIsParticipantBlocked] = useState(false)\n const [isLeaving, setIsLeaving] = useState(false)\n const [isUpdatingBlockStatus, setIsUpdatingBlockStatus] = useState(false)\n\n // Sync dialog open state with prop\n useEffect(() => {\n const dialog = dialogRef.current\n if (!dialog) return\n\n if (isOpen) {\n dialog.showModal()\n } else {\n dialog.close()\n }\n }, [isOpen])\n\n // Check if participant is blocked\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 if (isOpen) {\n checkIsParticipantBlocked()\n }\n }, [isOpen, checkIsParticipantBlocked])\n\n const handleLeaveConversation = async () => {\n if (isLeaving) return\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 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 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 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\"\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-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 overflow-y-auto px-6 py-6\">\n <div className=\"rounded-2xl bg-chalk p-4\">\n <div className=\"flex items-center gap-4\">\n <Avatar\n id={participantId}\n name={participantName}\n image={participantImage}\n size={64}\n />\n <div className=\"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-stone\">\n {participantSecondary}\n </p>\n )}\n {followerStatusLabel && (\n <span className=\"mt-2 inline-flex items-center rounded-full bg-green-100 px-2 py-0.5 text-xs font-medium text-green-700\">\n {followerStatusLabel}\n </span>\n )}\n </div>\n </div>\n </div>\n\n <ul className=\"flex flex-col gap-2 mt-2\">\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>Leave Conversation</span>\n </ActionButton>\n </li>\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}> = ({\n onBack,\n showBackButton,\n renderMessageInputActions,\n onLeaveConversation,\n onBlockParticipant,\n CustomChannelEmptyState,\n}) => {\n const { channel } = useChannelStateContext()\n const [showInfo, setShowInfo] = useState(false)\n\n // Check if channel has messages - using context to reactively subscribe to message updates\n const hasMessages = (channel?.state?.messages?.length ?? 0) > 0\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 return channelExtraData.followerStatus\n ? String(channelExtraData.followerStatus)\n : channelExtraData.isFollower\n ? 'Subscribed to you'\n : undefined\n }, [channel.data])\n\n return (\n <>\n <Window>\n {/* Custom Channel Header */}\n <div className=\"border-b border-sand bg-white px-4 py-3\">\n <CustomChannelHeader\n onBack={onBack}\n showBackButton={showBackButton}\n onShowInfo={() => setShowInfo(true)}\n canShowInfo={Boolean(participant)}\n />\n </div>\n\n {/* Message List */}\n <div className=\"flex-1 overflow-hidden relative\">\n <MessageList hideDeletedMessages hideNewMessageSeparator={false} />\n\n {/* Show custom empty state when no messages */}\n {!hasMessages && CustomChannelEmptyState && (\n <div className=\"absolute inset-0 flex bg-white\">\n <CustomChannelEmptyState />\n </div>\n )}\n </div>\n\n {/* Message Input */}\n <CustomMessageInput\n renderActions={() => renderMessageInputActions?.(channel)}\n />\n </Window>\n\n {/* Channel Info Dialog */}\n <ChannelInfoDialog\n isOpen={showInfo}\n onClose={() => setShowInfo(false)}\n participant={participant}\n channel={channel}\n followerStatusLabel={followerStatusLabel}\n onLeaveConversation={onLeaveConversation}\n onBlockParticipant={onBlockParticipant}\n />\n </>\n )\n}\n\n/**\n * Channel view component with message list and input\n */\nexport const ChannelView: React.FC<ChannelViewProps> = ({\n channel,\n onBack,\n showBackButton = false,\n renderMessageInputActions,\n onLeaveConversation,\n onBlockParticipant,\n className,\n CustomChannelEmptyState,\n}) => {\n return (\n <div\n className={classNames(\n 'messaging-channel-view h-full flex flex-col',\n className\n )}\n >\n <Channel channel={channel}>\n <ChannelViewInner\n onBack={onBack}\n showBackButton={showBackButton}\n renderMessageInputActions={renderMessageInputActions}\n onLeaveConversation={onLeaveConversation}\n onBlockParticipant={onBlockParticipant}\n CustomChannelEmptyState={CustomChannelEmptyState}\n />\n </Channel>\n </div>\n )\n}\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\n/**\n * Empty state component shown when no channel is selected\n */\nexport const EmptyState: React.FC<{\n hasChannels: boolean\n onStartConversation?: () => void\n participantLabel: string\n}> = ({ hasChannels, onStartConversation, participantLabel }) => (\n <div className=\"messaging-empty-state flex items-center justify-center h-full p-8 text-balance\">\n <div className=\"text-center max-w-sm\">\n <div className=\"w-24 h-24 bg-primary-alt/10 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\">Welcome to Messages</h2>\n\n <p className=\"text-stone text-sm mb-6\">\n {hasChannels ? (\n <>\n Choose a conversation from the list or{' '}\n {onStartConversation && (\n <TextButton onClick={onStartConversation}>\n start a new conversation with a {participantLabel.slice(0, -1)}.\n </TextButton>\n )}\n </>\n ) : (\n onStartConversation && (\n <>\n <TextButton onClick={onStartConversation}>\n Start a new conversation with one of your {participantLabel}\n </TextButton>{' '}\n to begin messaging.\n </>\n )\n )}\n </p>\n </div>\n </div>\n)\n\nconst TextButton = ({\n onClick,\n children,\n}: {\n onClick: () => void\n children: React.ReactNode\n}) => (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"inline-flex items-center gap-1 text-sm font-medium text-primary hover:text-primary-alt focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n {children}\n </button>\n)\n","import React from 'react'\n\n/**\n * Error state component shown when something goes wrong\n */\nexport const ErrorState: React.FC<{\n message: string\n onBack?: () => void\n}> = ({ 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-primary 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)\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 Loading from '../Loading'\n\n/**\n * Loading state component\n */\nexport const LoadingState = () => (\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","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}) => {\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 [_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 showStartConversation = false,\n participantSource,\n participantLabel = 'participants',\n } = capabilities\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 setExistingParticipantIds(memberIds)\n setHasChannels(channels.length > 0)\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 handleStartConversation = useCallback(() => {\n if (participantSource) {\n setPickerKey((prev) => prev + 1) // Increment key to force remount\n setShowParticipantPicker(true)\n participantPickerRef.current?.showModal()\n }\n }, [participantSource])\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 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 // Show loading state\n if (isLoading) {\n return (\n <div className={classNames('h-full', className)}>\n <LoadingState />\n </div>\n )\n }\n\n // Show error state\n if (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 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 return (\n <div className={classNames('h-full', className)}>\n <ErrorState message={directConversationError} />\n </div>\n )\n }\n\n return (\n <div\n className={classNames(\n 'messaging-shell h-full bg-white 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 bg-white lg:bg-chalk lg:flex lg:flex-col lg:border-r lg:border-sand',\n {\n // Explicitly hidden via prop or in direct conversation mode\n '!hidden': showChannelList === false || directConversationMode,\n // Normal mode: hide on mobile when channel selected, show on desktop\n 'hidden lg:flex lg:w-80 lg:min-w-[280px] lg:max-w-[360px]':\n showChannelList !== false &&\n !directConversationMode &&\n isChannelSelected,\n // Normal mode: show when no channel selected\n 'flex flex-col w-full lg:flex-1 lg:max-w-2xl':\n showChannelList !== false &&\n !directConversationMode &&\n !isChannelSelected,\n }\n )}\n >\n <ChannelList\n onChannelSelect={handleChannelSelect}\n selectedChannel={selectedChannel || undefined}\n showStartConversation={\n showStartConversation && Boolean(participantSource)\n }\n onStartConversation={handleStartConversation}\n participantLabel={participantLabel}\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 />\n </div>\n ) : (\n <EmptyState\n hasChannels={hasChannels}\n onStartConversation={\n showStartConversation ? handleStartConversation : undefined\n }\n participantLabel={participantLabel}\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={(e) => {\n if (e.target === participantPickerRef.current) {\n handleCloseParticipantPicker()\n }\n }}\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'\n\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 classNames from 'classnames'\nimport 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={classNames('px-4 py-6', 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 />\n </div>\n )}\n\n {/* FAQs with grey background */}\n <div\n className=\"flex-1 rounded-lg p-4 space-y-3\"\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","customization","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","IconButton","label","className","rest","jsxs","classNames","EMOJIS","hashString","str","hash","i","char","getAvatarEmoji","id","index","Avatar","image","size","emoji","DEFAULT_COLOR","fontSizeClass","CustomChannelPreview","channel","selectedChannel","onChannelSelect","unread","isSelected","handleClick","participant","member","participantName","participantImage","_c","lastMessage","_e","_d","lastMessageText","lastMessageTime","unreadCount","_f","ChannelList","showStartConversation","onStartConversation","participantLabel","useChatContext","filters","userId","newFilters","NotePencilIcon","StreamChannelList","props","ActionButton","variant","CloseButton","onClick","XIcon","CustomMessageInput","renderActions","MessageInput","CustomChannelHeader","onBack","showBackButton","onShowInfo","canShowInfo","useChannelStateContext","ArrowLeftIcon","DotsThreeIcon","ChannelInfoDialog","isOpen","onClose","followerStatusLabel","onLeaveConversation","onBlockParticipant","dialogRef","isParticipantBlocked","setIsParticipantBlocked","isLeaving","setIsLeaving","isUpdatingBlockStatus","setIsUpdatingBlockStatus","dialog","checkIsParticipantBlocked","isBlocked","handleLeaveConversation","actingUserId","handleBlockUser","handleUnblockUser","handleReportUser","participantEmail","participantUsername","participantSecondary","participantId","_g","e","SpinnerGapIcon","SignOutIcon","ProhibitInsetIcon","FlagIcon","ChannelViewInner","renderMessageInputActions","CustomChannelEmptyState","showInfo","setShowInfo","hasMessages","channelExtraData","Fragment","Window","MessageList","ChannelView","Channel","SearchInput","searchQuery","setSearchQuery","placeholder","searchInputRef","MagnifyingGlassIcon","ParticipantPicker","participantSource","onSelectParticipant","existingParticipantIds","searchPlaceholder","participants","setParticipants","loading","setLoading","startingChatWithId","setStartingChatWithId","loadedRef","result","availableParticipants","searchLower","handleSelectParticipant","handleKeyDown","event","ChatCircleDotsIcon","displayName","displaySecondary","EmptyState","hasChannels","TextButton","ErrorState","Loading","LoadingState","MessagingShell","onParticipantSelect","initialParticipantFilter","initialParticipantData","showChannelList","setSelectedChannel","setHasChannels","_showParticipantPicker","setShowParticipantPicker","setExistingParticipantIds","pickerKey","setPickerKey","directConversationMode","setDirectConversationMode","directConversationError","setDirectConversationError","participantPickerRef","syncedRef","syncChannels","channels","memberIds","members","memberId","createErr","handleChannelSelect","handleBackToChannelList","handleStartConversation","prev","handleCloseParticipantPicker","handleBlockParticipant","isChannelSelected","FaqListItem","question","FaqList","faqs","onFaqClick","loadingFaqId","headerText","avatarImage","avatarName","enabledFaqs","faq","a","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/components/IconButton/index.tsx","../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/CloseButton/index.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/Loading/index.tsx","../src/components/MessagingShell/LoadingState.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 {\n MessagingProviderProps,\n MessagingCapabilities,\n MessagingCustomization,\n} 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 customization: MessagingCustomization\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 customization: {},\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 customization = {},\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 customization: Object.keys(customization),\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 customization,\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 customizationChanged:\n prevPropsRef.current.customization !== customization,\n },\n })\n\n prevPropsRef.current = {\n userId: user?.id,\n apiKey,\n serviceConfig,\n capabilities,\n customization,\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 customizationKeys: Object.keys(customization),\n })\n\n return {\n service,\n client,\n isConnected,\n isLoading,\n error,\n capabilities,\n customization,\n refreshConnection,\n debug,\n }\n }, [\n service,\n client,\n isConnected,\n isLoading,\n error,\n capabilities,\n customization,\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 client={client}>{children}</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","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}","/**\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}\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}) => {\n const emoji = getAvatarEmoji(id)\n\n const DEFAULT_COLOR = '#FBFAF9'\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 return (\n <div\n className={classNames(\n 'flex-shrink-0 overflow-hidden rounded-lg',\n className\n )}\n style={{ width: `${size}px`, height: `${size}px` }}\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 'flex h-full w-full items-center justify-center font-semibold rounded-sm',\n fontSizeClass\n )}\n style={{\n color: DEFAULT_COLOR,\n backgroundColor: `color-mix(in srgb, ${DEFAULT_COLOR} 60%, solid)`,\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 { Avatar } from '../Avatar'\n\n/**\n * Custom channel preview that handles selection\n */\nconst CustomChannelPreview: React.FC<\n ChannelPreviewUIComponentProps & {\n selectedChannel?: Channel | null\n onChannelSelect: (channel: Channel) => void\n debug?: boolean\n }\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 const lastMessageText = lastMessage?.text || 'No messages yet'\n const lastMessageTime = lastMessage?.created_at\n ? new Date(lastMessage.created_at).toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n })\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 'w-full px-4 py-3 transition-colors border-b border-sand 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 />\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-primary 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\nexport default CustomChannelPreview\n","import { NotePencilIcon } from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React from 'react'\nimport {\n ChannelList as StreamChannelList,\n useChatContext,\n} from 'stream-chat-react'\n\nimport { useMessagingContext } from '../../providers/MessagingProvider'\nimport type { ChannelListProps } from '../../types'\nimport { IconButton } from '../IconButton'\n\nimport CustomChannelPreview from './CustomChannelPreview'\n\n/**\n * Channel list component with customizable header and actions\n */\nexport const ChannelList: React.FC<ChannelListProps> = ({\n onChannelSelect,\n selectedChannel,\n showStartConversation = false,\n onStartConversation,\n participantLabel = 'participants',\n className,\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 showStartConversation,\n participantLabel,\n })\n }\n\n const { client } = useChatContext()\n\n if (debug) {\n console.log('📺 [ChannelList] 📡 CHAT CONTEXT', {\n renderCount: renderCountRef.current,\n hasClient: !!client,\n clientUserId: client?.userID,\n clientConnected: client?.wsConnection?.isHealthy,\n })\n }\n\n // Filter for messaging channels\n const filters = React.useMemo(() => {\n const userId = client.userID\n const newFilters = userId\n ? { \n type: 'messaging', \n members: { $in: [userId] }, \n hidden: false,\n last_message_at: { $exists: true }\n }\n : { type: 'messaging', last_message_at: { $exists: true } }\n\n if (debug) {\n console.log('📺 [ChannelList] 🔍 FILTERS MEMOIZED', {\n renderCount: renderCountRef.current,\n userId,\n filters: newFilters,\n })\n }\n\n return newFilters\n }, [client.userID, 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 {/* Header */}\n <div className=\"px-4 py-4 border-b border-sand bg-chalk\">\n <div className=\"flex items-center justify-between gap-3 min-h-10 min-w-0\">\n <h2 className=\"text-lg font-semibold text-charcoal\">Conversations</h2>\n <div className=\"flex items-center gap-2\">\n {showStartConversation && onStartConversation && (\n <IconButton\n label=\"Start a new conversation\"\n onClick={onStartConversation}\n className=\"inline-flex size-10 items-center justify-center\"\n >\n <NotePencilIcon className=\"h-5 w-5\" />\n </IconButton>\n )}\n </div>\n </div>\n </div>\n\n {/* Channel List */}\n <div className=\"flex-1 overflow-hidden min-w-0\">\n {(() => {\n if (debug) {\n console.log('📺 [ChannelList] 🎬 RENDERING STREAM CHANNEL LIST', {\n renderCount: renderCountRef.current,\n filters,\n hasClient: !!client,\n clientUserId: client?.userID,\n })\n }\n\n return (\n <StreamChannelList\n filters={filters}\n sort={{ last_message_at: -1 }}\n options={{ limit: 30 }}\n Preview={(props) => {\n if (debug) {\n console.log('📺 [ChannelList] 📋 CHANNEL PREVIEW RENDER', {\n channelId: props.channel?.id,\n selectedChannelId: selectedChannel?.id,\n isSelected: selectedChannel?.id === props.channel?.id,\n })\n }\n\n return (\n <CustomChannelPreview\n {...props}\n selectedChannel={selectedChannel}\n onChannelSelect={onChannelSelect}\n debug={debug}\n />\n )\n }}\n />\n )\n })()}\n </div>\n </div>\n )\n}\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 { 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 {\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 MessageInput,\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 { IconButton } from './IconButton'\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 message input component with render prop for actions\n */\nconst CustomMessageInput: React.FC<{\n renderActions?: () => React.ReactNode\n}> = ({ renderActions }) => (\n <div className=\"message-input flex items-center gap-2 p-4\">\n {renderActions && renderActions()}\n\n <div className=\"flex-1\">\n <MessageInput focus maxRows={4} />\n </div>\n </div>\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=\"flex items-center justify-between gap-3 min-h-12\">\n <div className=\"flex items-center gap-3 min-w-0\">\n {showBackButton && onBack && (\n <button\n type=\"button\"\n onClick={onBack}\n className=\"inline-flex items-center justify-center w-8 h-8 rounded-lg hover:bg-sand focus:outline-none focus:ring-2 focus:ring-primary transition-colors lg:hidden\"\n aria-label=\"Back to conversations\"\n >\n <ArrowLeftIcon className=\"h-5 w-5 text-stone\" weight=\"bold\" />\n </button>\n )}\n\n {/* Avatar */}\n <Avatar\n id={participant?.user?.id || channel.id || 'unknown'}\n name={participantName}\n image={participantImage}\n size={40}\n />\n\n <div className=\"min-w-0\">\n <h1 className=\"text-lg font-semibold text-charcoal truncate\">\n {participantName}\n </h1>\n </div>\n </div>\n\n {canShowInfo && onShowInfo && (\n <IconButton label=\"Chat info\" onClick={onShowInfo}>\n <DotsThreeIcon className=\"h-6 w-6 text-charcoal\" weight=\"bold\" />\n </IconButton>\n )}\n </div>\n )\n}\n\n/**\n * Channel info dialog (matching original implementation)\n */\nconst ChannelInfoDialog: React.FC<{\n isOpen: boolean\n onClose: () => void\n participant: ChannelMemberResponse | undefined\n channel: ChannelType\n followerStatusLabel?: string\n onLeaveConversation?: (channel: ChannelType) => void\n onBlockParticipant?: (participantId?: string) => void\n}> = ({\n isOpen,\n onClose,\n participant,\n channel,\n followerStatusLabel,\n onLeaveConversation,\n onBlockParticipant,\n}) => {\n const { service, debug } = useMessagingContext()\n const dialogRef = useRef<HTMLDialogElement>(null)\n const [isParticipantBlocked, setIsParticipantBlocked] = useState(false)\n const [isLeaving, setIsLeaving] = useState(false)\n const [isUpdatingBlockStatus, setIsUpdatingBlockStatus] = useState(false)\n\n // Sync dialog open state with prop\n useEffect(() => {\n const dialog = dialogRef.current\n if (!dialog) return\n\n if (isOpen) {\n dialog.showModal()\n } else {\n dialog.close()\n }\n }, [isOpen])\n\n // Check if participant is blocked\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 if (isOpen) {\n checkIsParticipantBlocked()\n }\n }, [isOpen, checkIsParticipantBlocked])\n\n const handleLeaveConversation = async () => {\n if (isLeaving) return\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 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 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 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\"\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-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 overflow-y-auto px-6 py-6\">\n <div className=\"rounded-2xl bg-chalk p-4\">\n <div className=\"flex items-center gap-4\">\n <Avatar\n id={participantId}\n name={participantName}\n image={participantImage}\n size={64}\n />\n <div className=\"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-stone\">\n {participantSecondary}\n </p>\n )}\n {followerStatusLabel && (\n <span className=\"mt-2 inline-flex items-center rounded-full bg-green-100 px-2 py-0.5 text-xs font-medium text-green-700\">\n {followerStatusLabel}\n </span>\n )}\n </div>\n </div>\n </div>\n\n <ul className=\"flex flex-col gap-2 mt-2\">\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>Leave Conversation</span>\n </ActionButton>\n </li>\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}> = ({\n onBack,\n showBackButton,\n renderMessageInputActions,\n onLeaveConversation,\n onBlockParticipant,\n CustomChannelEmptyState,\n}) => {\n const { channel } = useChannelStateContext()\n const [showInfo, setShowInfo] = useState(false)\n\n // Check if channel has messages - using context to reactively subscribe to message updates\n const hasMessages = (channel?.state?.messages?.length ?? 0) > 0\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 return channelExtraData.followerStatus\n ? String(channelExtraData.followerStatus)\n : channelExtraData.isFollower\n ? 'Subscribed to you'\n : undefined\n }, [channel.data])\n\n return (\n <>\n <Window>\n {/* Custom Channel Header */}\n <div className=\"border-b border-sand bg-white px-4 py-3\">\n <CustomChannelHeader\n onBack={onBack}\n showBackButton={showBackButton}\n onShowInfo={() => setShowInfo(true)}\n canShowInfo={Boolean(participant)}\n />\n </div>\n\n {/* Message List */}\n <div className=\"flex-1 overflow-hidden relative\">\n <MessageList hideDeletedMessages hideNewMessageSeparator={false} />\n\n {/* Show custom empty state when no messages */}\n {!hasMessages && CustomChannelEmptyState && (\n <div className=\"absolute inset-0 flex bg-white\">\n <CustomChannelEmptyState />\n </div>\n )}\n </div>\n\n {/* Message Input */}\n <CustomMessageInput\n renderActions={() => renderMessageInputActions?.(channel)}\n />\n </Window>\n\n {/* Channel Info Dialog */}\n <ChannelInfoDialog\n isOpen={showInfo}\n onClose={() => setShowInfo(false)}\n participant={participant}\n channel={channel}\n followerStatusLabel={followerStatusLabel}\n onLeaveConversation={onLeaveConversation}\n onBlockParticipant={onBlockParticipant}\n />\n </>\n )\n}\n\n/**\n * Channel view component with message list and input\n */\nexport const ChannelView: React.FC<ChannelViewProps> = ({\n channel,\n onBack,\n showBackButton = false,\n renderMessageInputActions,\n onLeaveConversation,\n onBlockParticipant,\n className,\n CustomChannelEmptyState,\n}) => {\n return (\n <div\n className={classNames(\n 'messaging-channel-view h-full flex flex-col',\n className\n )}\n >\n <Channel channel={channel}>\n <ChannelViewInner\n onBack={onBack}\n showBackButton={showBackButton}\n renderMessageInputActions={renderMessageInputActions}\n onLeaveConversation={onLeaveConversation}\n onBlockParticipant={onBlockParticipant}\n CustomChannelEmptyState={CustomChannelEmptyState}\n />\n </Channel>\n </div>\n )\n}\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\n/**\n * Empty state component shown when no channel is selected\n */\nexport const EmptyState: React.FC<{\n hasChannels: boolean\n onStartConversation?: () => void\n participantLabel: string\n}> = ({ hasChannels, onStartConversation, participantLabel }) => (\n <div className=\"messaging-empty-state flex items-center justify-center h-full p-8 text-balance\">\n <div className=\"text-center max-w-sm\">\n <div className=\"w-24 h-24 bg-primary-alt/10 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\">Welcome to Messages</h2>\n\n <p className=\"text-stone text-sm mb-6\">\n {hasChannels ? (\n <>\n Choose a conversation from the list or{' '}\n {onStartConversation && (\n <TextButton onClick={onStartConversation}>\n start a new conversation with a {participantLabel.slice(0, -1)}.\n </TextButton>\n )}\n </>\n ) : (\n onStartConversation && (\n <>\n <TextButton onClick={onStartConversation}>\n Start a new conversation with one of your {participantLabel}\n </TextButton>{' '}\n to begin messaging.\n </>\n )\n )}\n </p>\n </div>\n </div>\n)\n\nconst TextButton = ({\n onClick,\n children,\n}: {\n onClick: () => void\n children: React.ReactNode\n}) => (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"inline-flex items-center gap-1 text-sm font-medium text-primary hover:text-primary-alt focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n {children}\n </button>\n)\n","import React from 'react'\n\n/**\n * Error state component shown when something goes wrong\n */\nexport const ErrorState: React.FC<{\n message: string\n onBack?: () => void\n}> = ({ 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-primary 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)\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 Loading from '../Loading'\n\n/**\n * Loading state component\n */\nexport const LoadingState = () => (\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","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}) => {\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 [_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 showStartConversation = false,\n participantSource,\n participantLabel = 'participants',\n } = capabilities\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 setExistingParticipantIds(memberIds)\n setHasChannels(channels.length > 0)\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 handleStartConversation = useCallback(() => {\n if (participantSource) {\n setPickerKey((prev) => prev + 1) // Increment key to force remount\n setShowParticipantPicker(true)\n participantPickerRef.current?.showModal()\n }\n }, [participantSource])\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 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 // Show loading state\n if (isLoading) {\n return (\n <div className={classNames('h-full', className)}>\n <LoadingState />\n </div>\n )\n }\n\n // Show error state\n if (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 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 return (\n <div className={classNames('h-full', className)}>\n <ErrorState message={directConversationError} />\n </div>\n )\n }\n\n return (\n <div\n className={classNames(\n 'messaging-shell h-full bg-white 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 bg-white lg:bg-chalk lg:flex lg:flex-col lg:border-r lg:border-sand',\n {\n // Explicitly hidden via prop or in direct conversation mode\n '!hidden': showChannelList === false || directConversationMode,\n // Normal mode: hide on mobile when channel selected, show on desktop\n 'hidden lg:flex lg:w-80 lg:min-w-[280px] lg:max-w-[360px]':\n showChannelList !== false &&\n !directConversationMode &&\n isChannelSelected,\n // Normal mode: show when no channel selected\n 'flex flex-col w-full lg:flex-1 lg:max-w-2xl':\n showChannelList !== false &&\n !directConversationMode &&\n !isChannelSelected,\n }\n )}\n >\n <ChannelList\n onChannelSelect={handleChannelSelect}\n selectedChannel={selectedChannel || undefined}\n showStartConversation={\n showStartConversation && Boolean(participantSource)\n }\n onStartConversation={handleStartConversation}\n participantLabel={participantLabel}\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 />\n </div>\n ) : (\n <EmptyState\n hasChannels={hasChannels}\n onStartConversation={\n showStartConversation ? handleStartConversation : undefined\n }\n participantLabel={participantLabel}\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={(e) => {\n if (e.target === participantPickerRef.current) {\n handleCloseParticipantPicker()\n }\n }}\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'\n\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 classNames from 'classnames'\nimport 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={classNames('px-4 py-6', 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 />\n </div>\n )}\n\n {/* FAQs with grey background */}\n <div\n className=\"flex-1 rounded-lg p-4 space-y-3\"\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","customization","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","IconButton","label","className","rest","jsxs","classNames","EMOJIS","hashString","str","hash","i","char","getAvatarEmoji","id","index","Avatar","image","size","emoji","DEFAULT_COLOR","fontSizeClass","CustomChannelPreview","channel","selectedChannel","onChannelSelect","unread","isSelected","handleClick","participant","member","participantName","participantImage","_c","lastMessage","_e","_d","lastMessageText","lastMessageTime","unreadCount","_f","ChannelList","showStartConversation","onStartConversation","participantLabel","useChatContext","filters","userId","newFilters","NotePencilIcon","StreamChannelList","props","ActionButton","variant","CloseButton","onClick","XIcon","CustomMessageInput","renderActions","MessageInput","CustomChannelHeader","onBack","showBackButton","onShowInfo","canShowInfo","useChannelStateContext","ArrowLeftIcon","DotsThreeIcon","ChannelInfoDialog","isOpen","onClose","followerStatusLabel","onLeaveConversation","onBlockParticipant","dialogRef","isParticipantBlocked","setIsParticipantBlocked","isLeaving","setIsLeaving","isUpdatingBlockStatus","setIsUpdatingBlockStatus","dialog","checkIsParticipantBlocked","isBlocked","handleLeaveConversation","actingUserId","handleBlockUser","handleUnblockUser","handleReportUser","participantEmail","participantUsername","participantSecondary","participantId","_g","e","SpinnerGapIcon","SignOutIcon","ProhibitInsetIcon","FlagIcon","ChannelViewInner","renderMessageInputActions","CustomChannelEmptyState","showInfo","setShowInfo","hasMessages","channelExtraData","Fragment","Window","MessageList","ChannelView","Channel","SearchInput","searchQuery","setSearchQuery","placeholder","searchInputRef","MagnifyingGlassIcon","ParticipantPicker","participantSource","onSelectParticipant","existingParticipantIds","searchPlaceholder","participants","setParticipants","loading","setLoading","startingChatWithId","setStartingChatWithId","loadedRef","result","availableParticipants","searchLower","handleSelectParticipant","handleKeyDown","event","ChatCircleDotsIcon","displayName","displaySecondary","EmptyState","hasChannels","TextButton","ErrorState","Loading","LoadingState","MessagingShell","onParticipantSelect","initialParticipantFilter","initialParticipantData","showChannelList","setSelectedChannel","setHasChannels","_showParticipantPicker","setShowParticipantPicker","setExistingParticipantIds","pickerKey","setPickerKey","directConversationMode","setDirectConversationMode","directConversationError","setDirectConversationError","participantPickerRef","syncedRef","syncChannels","channels","memberIds","members","memberId","createErr","handleChannelSelect","handleBackToChannelList","handleStartConversation","prev","handleCloseParticipantPicker","handleBlockParticipant","isChannelSelected","FaqListItem","question","FaqList","faqs","onFaqClick","loadingFaqId","headerText","avatarImage","avatarName","enabledFaqs","faq","a","useParticipants","options","initialSearch","pageSize","hasMore","setHasMore","cursor","setCursor","loadParticipants","reset","customSearch","search","loadMore","query","refresh"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -54,8 +54,13 @@ export const ChannelList: React.FC<ChannelListProps> = ({
|
|
|
54
54
|
const filters = React.useMemo(() => {
|
|
55
55
|
const userId = client.userID
|
|
56
56
|
const newFilters = userId
|
|
57
|
-
? {
|
|
58
|
-
|
|
57
|
+
? {
|
|
58
|
+
type: 'messaging',
|
|
59
|
+
members: { $in: [userId] },
|
|
60
|
+
hidden: false,
|
|
61
|
+
last_message_at: { $exists: true }
|
|
62
|
+
}
|
|
63
|
+
: { type: 'messaging', last_message_at: { $exists: true } }
|
|
59
64
|
|
|
60
65
|
if (debug) {
|
|
61
66
|
console.log('📺 [ChannelList] 🔍 FILTERS MEMOIZED', {
|