@linktr.ee/messaging-react 1.8.5 → 1.8.6-rc-1764053798

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -134,10 +134,10 @@ const fe = Ie({
134
134
  clientId: M.userID
135
135
  });
136
136
  } catch (M) {
137
- const B = M instanceof Error ? M.message : "Connection failed";
138
- k(B), l("❌ USER CONNECTION ERROR", {
137
+ const A = M instanceof Error ? M.message : "Connection failed";
138
+ k(A), l("❌ USER CONNECTION ERROR", {
139
139
  userId: s.id,
140
- error: B
140
+ error: A
141
141
  });
142
142
  } finally {
143
143
  C(!1), I.current = !1, l("🔄 USER CONNECTION FINISHED", {
@@ -215,18 +215,18 @@ const fe = Ie({
215
215
  willRenderChat: !!(v && g),
216
216
  contextValueReady: !!f
217
217
  }), /* @__PURE__ */ e(fe.Provider, { value: f, children: v && g ? /* @__PURE__ */ e(ke, { client: v, children: t }) : t });
218
- }, _e = () => se(), Be = (t, s) => {
218
+ }, _e = () => se(), Ae = (t, s) => {
219
219
  const n = new Date(
220
220
  Date.UTC(t.getUTCFullYear(), t.getUTCMonth(), t.getUTCDate())
221
221
  ), a = new Date(
222
222
  Date.UTC(s.getUTCFullYear(), s.getUTCMonth(), s.getUTCDate())
223
223
  ).getTime() - n.getTime();
224
224
  return Math.floor(a / (1e3 * 60 * 60 * 24));
225
- }, Ae = (t) => {
225
+ }, Be = (t) => {
226
226
  const s = /* @__PURE__ */ new Date();
227
227
  if (Math.floor((s.getTime() - t.getTime()) / 1e3) < 60)
228
228
  return "Just now";
229
- const r = Be(t, s);
229
+ const r = Ae(t, s);
230
230
  return r === 0 ? t.toLocaleTimeString([], {
231
231
  hour: "numeric",
232
232
  minute: "2-digit"
@@ -327,7 +327,7 @@ const J = ({
327
327
  if (m != null && m.text) return m.text;
328
328
  const i = (f = m == null ? void 0 : m.attachments) == null ? void 0 : f[0];
329
329
  return i != null && i.asset_url ? i.asset_url : i != null && i.image_url ? i.image_url : i != null && i.og_scrape_url ? i.og_scrape_url : i != null && i.thumb_url ? i.thumb_url : "No messages yet";
330
- })(), x = m != null && m.created_at ? Ae(new Date(m.created_at)) : "", C = a ?? 0;
330
+ })(), x = m != null && m.created_at ? Be(new Date(m.created_at)) : "", C = a ?? 0;
331
331
  return r && console.log("📺 [ChannelList] 📋 CHANNEL PREVIEW RENDER", {
332
332
  channelId: t == null ? void 0 : t.id,
333
333
  isSelected: d,
@@ -519,7 +519,7 @@ const xe = () => /* @__PURE__ */ e("div", { className: "messaging-channel-empty-
519
519
  onLeaveConversation: d,
520
520
  onBlockParticipant: c
521
521
  }) => {
522
- var M, B, Y, H, V, Q, W;
522
+ var M, A, Y, H, V, Q, W;
523
523
  const { service: l, debug: o } = se(), E = $(null), [v, m] = w(!1), [g, R] = w(!1), [x, C] = w(!1);
524
524
  G(() => {
525
525
  const S = E.current;
@@ -591,7 +591,7 @@ const xe = () => /* @__PURE__ */ e("div", { className: "messaging-channel-empty-
591
591
  );
592
592
  };
593
593
  if (!n) return null;
594
- const U = ((B = n.user) == null ? void 0 : B.name) || ((Y = n.user) == null ? void 0 : Y.id) || "Unknown member", i = (H = n.user) == null ? void 0 : H.image, f = (V = n.user) == null ? void 0 : V.email, b = (Q = n.user) == null ? void 0 : Q.username, F = f || (b ? `linktr.ee/${b}` : void 0), z = ((W = n.user) == null ? void 0 : W.id) || "unknown";
594
+ const U = ((A = n.user) == null ? void 0 : A.name) || ((Y = n.user) == null ? void 0 : Y.id) || "Unknown member", i = (H = n.user) == null ? void 0 : H.image, f = (V = n.user) == null ? void 0 : V.email, b = (Q = n.user) == null ? void 0 : Q.username, F = f || (b ? `linktr.ee/${b}` : void 0), z = ((W = n.user) == null ? void 0 : W.id) || "unknown";
595
595
  return (
596
596
  // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions
597
597
  /* @__PURE__ */ e(
@@ -725,7 +725,14 @@ const xe = () => /* @__PURE__ */ e("div", { className: "messaging-channel-empty-
725
725
  }
726
726
  ) }),
727
727
  /* @__PURE__ */ u("div", { className: "flex-1 overflow-hidden relative", children: [
728
- /* @__PURE__ */ e(Me, { hideDeletedMessages: !0, hideNewMessageSeparator: !1 }),
728
+ /* @__PURE__ */ e(
729
+ Me,
730
+ {
731
+ hideDeletedMessages: !0,
732
+ hideNewMessageSeparator: !1,
733
+ messageActions: []
734
+ }
735
+ ),
729
736
  !E && d && /* @__PURE__ */ e("div", { className: "absolute inset-0 w-full h-full bg-white", children: /* @__PURE__ */ e(d, {}) })
730
737
  ] }),
731
738
  /* @__PURE__ */ e(
@@ -1062,7 +1069,7 @@ const Xe = ({
1062
1069
  error: x,
1063
1070
  refreshConnection: C,
1064
1071
  debug: h
1065
- } = _e(), [k, I] = w(null), [y, T] = w(!1), [U, i] = w(!1), [f, b] = w(/* @__PURE__ */ new Set()), [F, z] = w(0), [M, B] = w(!1), [Y, H] = w(null), V = $(null), {
1072
+ } = _e(), [k, I] = w(null), [y, T] = w(!1), [U, i] = w(!1), [f, b] = w(/* @__PURE__ */ new Set()), [F, z] = w(0), [M, A] = w(!1), [Y, H] = w(null), V = $(null), {
1066
1073
  showStartConversation: Q = !1,
1067
1074
  participantSource: W,
1068
1075
  participantLabel: S = "participants"
@@ -1093,8 +1100,8 @@ const Xe = ({
1093
1100
  {},
1094
1101
  { limit: 100 }
1095
1102
  ), p = /* @__PURE__ */ new Set();
1096
- L.forEach((A) => {
1097
- const Ee = A.state.members;
1103
+ L.forEach((B) => {
1104
+ const Ee = B.state.members;
1098
1105
  Object.values(Ee).forEach((ye) => {
1099
1106
  var ae;
1100
1107
  const te = (ae = ye.user) == null ? void 0 : ae.id;
@@ -1131,7 +1138,7 @@ const Xe = ({
1131
1138
  { limit: 1 }
1132
1139
  );
1133
1140
  if (p.length > 0)
1134
- I(p[0]), B(!0), H(null), r && r(p[0]), h && console.log(
1141
+ I(p[0]), A(!0), H(null), r && r(p[0]), h && console.log(
1135
1142
  "[MessagingShell] Initial conversation loaded:",
1136
1143
  p[0].id
1137
1144
  );
@@ -1141,20 +1148,20 @@ const Xe = ({
1141
1148
  c
1142
1149
  );
1143
1150
  try {
1144
- const A = await v.startChannelWithParticipant({
1151
+ const B = await v.startChannelWithParticipant({
1145
1152
  id: c.id,
1146
1153
  name: c.name,
1147
1154
  email: c.email,
1148
1155
  phone: c.phone
1149
1156
  });
1150
- I(A), B(!0), H(null), r && r(A), h && console.log(
1157
+ I(B), A(!0), H(null), r && r(B), h && console.log(
1151
1158
  "[MessagingShell] Channel created and loaded:",
1152
- A.id
1159
+ B.id
1153
1160
  );
1154
- } catch (A) {
1161
+ } catch (B) {
1155
1162
  console.error(
1156
1163
  "[MessagingShell] Failed to create conversation:",
1157
- A
1164
+ B
1158
1165
  ), H("Failed to create conversation");
1159
1166
  }
1160
1167
  } else
@@ -1207,8 +1214,8 @@ const Xe = ({
1207
1214
  });
1208
1215
  try {
1209
1216
  await p.show();
1210
- } catch (A) {
1211
- console.warn("[MessagingShell] Failed to unhide channel:", A);
1217
+ } catch (B) {
1218
+ console.warn("[MessagingShell] Failed to unhide channel:", B);
1212
1219
  }
1213
1220
  I(p), i(!1), (L = V.current) == null || L.close(), a == null || a(N);
1214
1221
  } catch (p) {
@@ -1221,12 +1228,12 @@ const Xe = ({
1221
1228
  i(!1), (N = V.current) == null || N.close();
1222
1229
  }, []), Ce = P(
1223
1230
  async (N) => {
1224
- h && console.log("[MessagingShell] Leaving conversation:", N.id), I(null), B(!1), j.current = null, await _();
1231
+ h && console.log("[MessagingShell] Leaving conversation:", N.id), I(null), A(!1), j.current = null, await _();
1225
1232
  },
1226
1233
  [_, h]
1227
1234
  ), we = P(
1228
1235
  async (N) => {
1229
- h && console.log("[MessagingShell] Blocking participant:", N), I(null), B(!1), j.current = null, await _();
1236
+ h && console.log("[MessagingShell] Blocking participant:", N), I(null), A(!1), j.current = null, await _();
1230
1237
  },
1231
1238
  [_, h]
1232
1239
  ), Z = !!k;
@@ -1444,7 +1451,7 @@ export {
1444
1451
  is as MessagingProvider,
1445
1452
  cs as MessagingShell,
1446
1453
  Xe as ParticipantPicker,
1447
- Ae as formatRelativeTime,
1454
+ Be as formatRelativeTime,
1448
1455
  _e as useMessaging,
1449
1456
  us as useParticipants
1450
1457
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/providers/MessagingProvider.tsx","../src/hooks/useMessaging.ts","../src/utils/formatRelativeTime.ts","../src/components/Avatar/getAvatarEmoji.ts","../src/components/Avatar/index.tsx","../src/components/ChannelList/CustomChannelPreview.tsx","../src/components/ChannelList/index.tsx","../src/components/ActionButton/index.tsx","../src/components/IconButton/index.tsx","../src/components/CloseButton/index.tsx","../src/components/MessagingShell/ChannelEmptyState.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","/**\n * Get the number of days between two dates (calendar days in UTC, not 24-hour periods)\n * Uses UTC to ensure consistent day calculations globally since messages are stored in UTC\n */\nconst getDaysDifference = (date1: Date, date2: Date): number => {\n const d1 = new Date(\n Date.UTC(date1.getUTCFullYear(), date1.getUTCMonth(), date1.getUTCDate())\n )\n const d2 = new Date(\n Date.UTC(date2.getUTCFullYear(), date2.getUTCMonth(), date2.getUTCDate())\n )\n const diffTime = d2.getTime() - d1.getTime()\n return Math.floor(diffTime / (1000 * 60 * 60 * 24))\n}\n\n/**\n * Format a date - shows time for today, relative time for older messages\n * (e.g., \"Just now\", \"2:08 PM\" for today, \"Yesterday\" for yesterday, \"2d\" for 2 days ago)\n */\nexport const formatRelativeTime = (date: Date): string => {\n const now = new Date()\n const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000)\n\n // Less than 1 minute\n if (diffInSeconds < 60) {\n return 'Just now'\n }\n\n // Check if it's today (same calendar day)\n const daysDiff = getDaysDifference(date, now)\n\n // If today, show the time (e.g., \"2:08 PM\")\n if (daysDiff === 0) {\n return date.toLocaleTimeString([], {\n hour: 'numeric',\n minute: '2-digit',\n })\n }\n\n // Yesterday\n if (daysDiff === 1) {\n return 'Yesterday'\n }\n\n // Less than 7 days - show days\n if (daysDiff < 7) {\n return `${daysDiff}d`\n }\n\n // Less than 4 weeks - show weeks\n if (daysDiff < 28) {\n const weeks = Math.floor(daysDiff / 7)\n return `${weeks}w`\n }\n\n // More than 4 weeks - show date as MM/DD/YY\n return date.toLocaleDateString('en-US', {\n month: 'numeric',\n day: 'numeric',\n year: '2-digit',\n })\n}\n","/**\n * Generate a fruit emoji based on a string id\n * Returns a consistent fruit emoji for the same id\n */\nconst EMOJIS = [\n '🍎', // Apple\n '🍌', // Banana\n '🍇', // Grape\n '🍊', // Orange\n '🍓', // Strawberry\n '🥥', // Coconut\n '🍒', // Cherry\n '🥭', // Mango\n '🍉', // Watermelon\n '🍋', // Lemon\n '🥝', // Kiwi\n '🫒', // Olive\n '🍈', // Melon\n]\n\n/**\n * Simple hash function to convert string to number\n */\nfunction hashString(str: string): number {\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32-bit integer\n }\n return Math.abs(hash)\n}\n\n/**\n * Get a fruit emoji based on an id string\n * @param id - The string id to generate emoji from\n * @returns A fruit emoji string\n */\nexport function getAvatarEmoji(id: string): string {\n const hash = hashString(id)\n const index = hash % EMOJIS.length\n return EMOJIS[index]\n}\n\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport { getAvatarEmoji } from './getAvatarEmoji'\n\nexport interface AvatarProps {\n id: string\n name: string\n image?: string\n size?: number\n className?: string\n}\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 // 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('flex-shrink-0 overflow-hidden', className)}\n style={{\n width: `${size}px`,\n height: `${size}px`,\n borderRadius: '33%',\n // @ts-expect-error - corner-shape is not recognized by react types\n 'corner-shape': 'superellipse(1.3)',\n }}\n >\n {image ? (\n <img\n src={image}\n alt=\"\"\n className=\"h-full w-full object-cover aspect-square\"\n />\n ) : (\n <div\n aria-hidden=\"true\"\n className={classNames(\n 'avatar-fallback flex h-full w-full items-center justify-center font-semibold bg-[#E6E5E3] select-none transition-colors',\n fontSizeClass\n )}\n >\n {emoji}\n </div>\n )}\n </div>\n )\n}\n","import classNames from 'classnames'\nimport React from 'react'\nimport { Channel } from 'stream-chat'\nimport { ChannelPreviewUIComponentProps } from 'stream-chat-react'\n\nimport { formatRelativeTime } from '../../utils/formatRelativeTime'\nimport { Avatar } from '../Avatar'\n\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\n // Fallback order: text -> attachment URL -> \"No messages yet\"\n const getLastMessageText = () => {\n if (lastMessage?.text) return lastMessage.text\n\n const attachment = lastMessage?.attachments?.[0]\n if (attachment?.asset_url) return attachment.asset_url\n if (attachment?.image_url) return attachment.image_url\n if (attachment?.og_scrape_url) return attachment.og_scrape_url\n if (attachment?.thumb_url) return attachment.thumb_url\n\n return 'No messages yet'\n }\n\n const lastMessageText = getLastMessageText()\n const lastMessageTime = lastMessage?.created_at\n ? formatRelativeTime(new Date(lastMessage.created_at))\n : ''\n\n // Use the unread prop passed by Stream Chat (reactive and updates automatically)\n const unreadCount = unread ?? 0\n\n if (debug) {\n console.log('📺 [ChannelList] 📋 CHANNEL PREVIEW RENDER', {\n channelId: channel?.id,\n isSelected,\n participantName,\n unreadCount,\n hasTimestamp: !!lastMessageTime,\n })\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n className={classNames(\n 'group w-full px-4 py-3 transition-colors 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 className=\"[&_.avatar-fallback]:group-hover:bg-[#eeeeee]\"\n />\n\n {/* Content column */}\n <div className=\"flex-1 min-w-0 flex flex-col gap-1\">\n {/* Name and timestamp row */}\n <div className=\"flex items-center justify-between gap-2\">\n <h3\n className={classNames(\n 'text-sm font-medium truncate',\n isSelected ? 'text-primary' : 'text-charcoal'\n )}\n >\n {participantName}\n </h3>\n {lastMessageTime && (\n <span className=\"text-xs text-stone flex-shrink-0\">\n {lastMessageTime}\n </span>\n )}\n </div>\n\n {/* Message and unread badge row */}\n <div className=\"flex items-center justify-between gap-2 min-w-0\">\n <p className=\"text-xs text-stone mr-2 flex-1 line-clamp-2\">\n {lastMessageText}\n </p>\n {unreadCount > 0 && (\n <span className=\"bg-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 classNames from 'classnames'\nimport React from 'react'\nimport { ChannelList as StreamChannelList } from 'stream-chat-react'\n\nimport { useMessagingContext } from '../../providers/MessagingProvider'\nimport type { ChannelListProps } from '../../types'\n\nimport CustomChannelPreview from './CustomChannelPreview'\n\n/**\n * Channel list component with customizable header and actions\n */\nexport const ChannelList: React.FC<ChannelListProps> = ({\n onChannelSelect,\n selectedChannel,\n filters,\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 filters,\n })\n }\n\n return (\n <div\n className={classNames(\n 'messaging-channel-list h-full flex flex-col min-w-0 overflow-hidden',\n className\n )}\n >\n {/* Channel List */}\n <div className=\"flex-1 overflow-hidden min-w-0\">\n {(() => {\n if (debug) {\n console.log('📺 [ChannelList] 🎬 RENDERING STREAM CHANNEL LIST', {\n renderCount: renderCountRef.current,\n filters,\n })\n }\n\n return (\n <StreamChannelList\n key={JSON.stringify(filters)}\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 classNames from \"classnames\";\nimport React from \"react\";\n\ninterface IconButtonProps\n extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n \"type\" | \"children\"\n > {\n label: string;\n children: React.ReactNode;\n className?: string;\n}\n\nexport function IconButton({ label, className, children, ...rest }: IconButtonProps) {\n return (\n <button\n type=\"button\"\n className={classNames(\n \"rounded-full p-2 transition-colors focus-ring\",\n {\n \"cursor-not-allowed opacity-50\": rest.disabled,\n \"hover:bg-sand\": !rest.disabled,\n },\n className,\n )}\n {...rest}\n >\n <span className=\"sr-only\">{label}</span>\n {children}\n </button>\n );\n}","import { XIcon } from '@phosphor-icons/react'\n\nimport { IconButton } from '../IconButton'\n\ninterface CloseButtonProps {\n onClick: () => void\n}\n\nexport function CloseButton({ onClick }: CloseButtonProps) {\n return (\n <IconButton label=\"Close\" onClick={onClick} className=\"p-1\">\n <XIcon className=\"h-5 w-5 text-stone\" weight=\"bold\" />\n </IconButton>\n )\n}\n","import React from 'react'\n\n/**\n * Empty state component shown when a channel has no messages\n */\nexport const ChannelEmptyState: React.FC = () => (\n <div className=\"messaging-channel-empty-state flex items-center justify-center h-full p-8 text-balance\">\n <div className=\"text-center max-w-sm\">\n <h2 className=\"font-semibold text-charcoal mb-2\">No messages yet 👀</h2>\n\n <p className=\"text-stone text-xs\">\n Share to social media to generate more conversations\n </p>\n </div>\n </div>\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'\nimport { ChannelEmptyState } from './MessagingShell/ChannelEmptyState'\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 px-2 overflow-y-auto w-full\">\n <div\n className=\"flex flex-col items-center gap-3 self-stretch px-4 py-2 mt-6 rounded-lg border border-black/[0.04]\"\n style={{ backgroundColor: '#FBFAF9' }}\n >\n <div className=\"flex items-center gap-3 w-full\">\n <Avatar\n id={participantId}\n name={participantName}\n image={participantImage}\n size={88}\n className=\"!rounded-full\"\n />\n <div className=\"flex flex-col min-w-0 flex-1\">\n <p className=\"truncate text-base font-semibold text-charcoal\">\n {participantName}\n </p>\n {participantSecondary && (\n <p className=\"truncate text-sm text-[#00000055]\">\n {participantSecondary}\n </p>\n )}\n {followerStatusLabel && (\n <span\n className=\"mt-1 rounded-full text-xs font-normal w-fit\"\n style={{\n padding: '4px 8px',\n backgroundColor:\n followerStatusLabel === 'Subscribed to you'\n ? '#DCFCE7'\n : '#F5F5F4',\n color:\n followerStatusLabel === 'Subscribed to you'\n ? '#008236'\n : '#78716C',\n lineHeight: '133.333%',\n letterSpacing: '0.21px',\n }}\n >\n {followerStatusLabel}\n </span>\n )}\n </div>\n </div>\n </div>\n\n <ul className=\"flex flex-col gap-2 mt-2\">\n <li>\n <ActionButton\n onClick={handleLeaveConversation}\n disabled={isLeaving}\n aria-busy={isLeaving}\n >\n {isLeaving ? (\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n ) : (\n <SignOutIcon className=\"h-5 w-5\" />\n )}\n <span>Delete Conversation</span>\n </ActionButton>\n </li>\n <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 = ChannelEmptyState,\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\n // If explicit followerStatus is provided, use it\n if (channelExtraData.followerStatus) {\n return String(channelExtraData.followerStatus)\n }\n // If isFollower is explicitly defined, use it to determine status\n if (channelExtraData.isFollower !== undefined) {\n return channelExtraData.isFollower\n ? 'Subscribed to you'\n : 'Not subscribed'\n }\n // Otherwise, don't show any status\n return undefined\n }, [channel.data])\n\n 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 w-full h-full 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 = ChannelEmptyState,\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 filters,\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 // Create default filters and merge with provided filters\n const channelFilters = React.useMemo(() => {\n const userId = client?.userID\n\n // Base filters that should always be present\n const baseFilters = {\n type: 'messaging',\n last_message_at: { $exists: true },\n ...(userId && {\n members: { $in: [userId] },\n hidden: false,\n }),\n }\n\n // Merge provided filters with base filters\n // Provided filters can override base filters if needed\n return {\n ...baseFilters,\n ...filters,\n }\n }, [filters, client?.userID])\n\n // Track if we've already synced channels to prevent repeated API calls\n const syncedRef = useRef<string | null>(null)\n\n // Function to sync channels (extracted for reuse)\n const syncChannels = useCallback(async () => {\n if (!client || !isConnected) return\n\n const userId = client.userID\n if (!userId) return\n\n try {\n if (debug) {\n console.log('[MessagingShell] Syncing channels for user:', userId)\n }\n\n const channels = await client.queryChannels(\n {\n type: 'messaging',\n members: { $in: [userId] },\n },\n {},\n { limit: 100 }\n )\n\n const memberIds = new Set<string>()\n channels.forEach((channel: Channel) => {\n const members = channel.state.members\n Object.values(members).forEach((member) => {\n const memberId = member.user?.id\n if (memberId && memberId !== userId) {\n memberIds.add(memberId)\n }\n })\n })\n\n 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 filters={channelFilters}\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'\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","getDaysDifference","date1","date2","d1","diffTime","formatRelativeTime","date","now","daysDiff","EMOJIS","hashString","str","hash","i","char","getAvatarEmoji","id","index","Avatar","image","size","className","emoji","fontSizeClass","classNames","CustomChannelPreview","channel","selectedChannel","onChannelSelect","unread","isSelected","handleClick","participant","member","participantName","participantImage","_c","lastMessage","_e","_d","lastMessageText","attachment","lastMessageTime","unreadCount","jsxs","_f","ChannelList","filters","StreamChannelList","props","ActionButton","variant","rest","IconButton","label","CloseButton","onClick","XIcon","ChannelEmptyState","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","participantLabel","searchPlaceholder","participants","setParticipants","loading","setLoading","startingChatWithId","setStartingChatWithId","loadedRef","result","availableParticipants","searchLower","handleSelectParticipant","handleKeyDown","event","ChatCircleDotsIcon","displayName","displaySecondary","EmptyState","hasChannels","onStartConversation","TextButton","ErrorState","Loading","LoadingState","MessagingShell","onParticipantSelect","initialParticipantFilter","initialParticipantData","showChannelList","setSelectedChannel","setHasChannels","_showParticipantPicker","setShowParticipantPicker","setExistingParticipantIds","pickerKey","setPickerKey","directConversationMode","setDirectConversationMode","directConversationError","setDirectConversationError","participantPickerRef","showStartConversation","channelFilters","userId","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","b","useParticipants","options","initialSearch","pageSize","hasMore","setHasMore","cursor","setCursor","loadParticipants","reset","customSearch","search","loadMore","query","refresh"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/providers/MessagingProvider.tsx","../src/hooks/useMessaging.ts","../src/utils/formatRelativeTime.ts","../src/components/Avatar/getAvatarEmoji.ts","../src/components/Avatar/index.tsx","../src/components/ChannelList/CustomChannelPreview.tsx","../src/components/ChannelList/index.tsx","../src/components/ActionButton/index.tsx","../src/components/IconButton/index.tsx","../src/components/CloseButton/index.tsx","../src/components/MessagingShell/ChannelEmptyState.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","/**\n * Get the number of days between two dates (calendar days in UTC, not 24-hour periods)\n * Uses UTC to ensure consistent day calculations globally since messages are stored in UTC\n */\nconst getDaysDifference = (date1: Date, date2: Date): number => {\n const d1 = new Date(\n Date.UTC(date1.getUTCFullYear(), date1.getUTCMonth(), date1.getUTCDate())\n )\n const d2 = new Date(\n Date.UTC(date2.getUTCFullYear(), date2.getUTCMonth(), date2.getUTCDate())\n )\n const diffTime = d2.getTime() - d1.getTime()\n return Math.floor(diffTime / (1000 * 60 * 60 * 24))\n}\n\n/**\n * Format a date - shows time for today, relative time for older messages\n * (e.g., \"Just now\", \"2:08 PM\" for today, \"Yesterday\" for yesterday, \"2d\" for 2 days ago)\n */\nexport const formatRelativeTime = (date: Date): string => {\n const now = new Date()\n const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000)\n\n // Less than 1 minute\n if (diffInSeconds < 60) {\n return 'Just now'\n }\n\n // Check if it's today (same calendar day)\n const daysDiff = getDaysDifference(date, now)\n\n // If today, show the time (e.g., \"2:08 PM\")\n if (daysDiff === 0) {\n return date.toLocaleTimeString([], {\n hour: 'numeric',\n minute: '2-digit',\n })\n }\n\n // Yesterday\n if (daysDiff === 1) {\n return 'Yesterday'\n }\n\n // Less than 7 days - show days\n if (daysDiff < 7) {\n return `${daysDiff}d`\n }\n\n // Less than 4 weeks - show weeks\n if (daysDiff < 28) {\n const weeks = Math.floor(daysDiff / 7)\n return `${weeks}w`\n }\n\n // More than 4 weeks - show date as MM/DD/YY\n return date.toLocaleDateString('en-US', {\n month: 'numeric',\n day: 'numeric',\n year: '2-digit',\n })\n}\n","/**\n * Generate a fruit emoji based on a string id\n * Returns a consistent fruit emoji for the same id\n */\nconst EMOJIS = [\n '🍎', // Apple\n '🍌', // Banana\n '🍇', // Grape\n '🍊', // Orange\n '🍓', // Strawberry\n '🥥', // Coconut\n '🍒', // Cherry\n '🥭', // Mango\n '🍉', // Watermelon\n '🍋', // Lemon\n '🥝', // Kiwi\n '🫒', // Olive\n '🍈', // Melon\n]\n\n/**\n * Simple hash function to convert string to number\n */\nfunction hashString(str: string): number {\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32-bit integer\n }\n return Math.abs(hash)\n}\n\n/**\n * Get a fruit emoji based on an id string\n * @param id - The string id to generate emoji from\n * @returns A fruit emoji string\n */\nexport function getAvatarEmoji(id: string): string {\n const hash = hashString(id)\n const index = hash % EMOJIS.length\n return EMOJIS[index]\n}\n\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport { getAvatarEmoji } from './getAvatarEmoji'\n\nexport interface AvatarProps {\n id: string\n name: string\n image?: string\n size?: number\n className?: string\n}\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 // 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('flex-shrink-0 overflow-hidden', className)}\n style={{\n width: `${size}px`,\n height: `${size}px`,\n borderRadius: '33%',\n // @ts-expect-error - corner-shape is not recognized by react types\n 'corner-shape': 'superellipse(1.3)',\n }}\n >\n {image ? (\n <img\n src={image}\n alt=\"\"\n className=\"h-full w-full object-cover aspect-square\"\n />\n ) : (\n <div\n aria-hidden=\"true\"\n className={classNames(\n 'avatar-fallback flex h-full w-full items-center justify-center font-semibold bg-[#E6E5E3] select-none transition-colors',\n fontSizeClass\n )}\n >\n {emoji}\n </div>\n )}\n </div>\n )\n}\n","import classNames from 'classnames'\nimport React from 'react'\nimport { Channel } from 'stream-chat'\nimport { ChannelPreviewUIComponentProps } from 'stream-chat-react'\n\nimport { formatRelativeTime } from '../../utils/formatRelativeTime'\nimport { Avatar } from '../Avatar'\n\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\n // Fallback order: text -> attachment URL -> \"No messages yet\"\n const getLastMessageText = () => {\n if (lastMessage?.text) return lastMessage.text\n\n const attachment = lastMessage?.attachments?.[0]\n if (attachment?.asset_url) return attachment.asset_url\n if (attachment?.image_url) return attachment.image_url\n if (attachment?.og_scrape_url) return attachment.og_scrape_url\n if (attachment?.thumb_url) return attachment.thumb_url\n\n return 'No messages yet'\n }\n\n const lastMessageText = getLastMessageText()\n const lastMessageTime = lastMessage?.created_at\n ? formatRelativeTime(new Date(lastMessage.created_at))\n : ''\n\n // Use the unread prop passed by Stream Chat (reactive and updates automatically)\n const unreadCount = unread ?? 0\n\n if (debug) {\n console.log('📺 [ChannelList] 📋 CHANNEL PREVIEW RENDER', {\n channelId: channel?.id,\n isSelected,\n participantName,\n unreadCount,\n hasTimestamp: !!lastMessageTime,\n })\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n className={classNames(\n 'group w-full px-4 py-3 transition-colors 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 className=\"[&_.avatar-fallback]:group-hover:bg-[#eeeeee]\"\n />\n\n {/* Content column */}\n <div className=\"flex-1 min-w-0 flex flex-col gap-1\">\n {/* Name and timestamp row */}\n <div className=\"flex items-center justify-between gap-2\">\n <h3\n className={classNames(\n 'text-sm font-medium truncate',\n isSelected ? 'text-primary' : 'text-charcoal'\n )}\n >\n {participantName}\n </h3>\n {lastMessageTime && (\n <span className=\"text-xs text-stone flex-shrink-0\">\n {lastMessageTime}\n </span>\n )}\n </div>\n\n {/* Message and unread badge row */}\n <div className=\"flex items-center justify-between gap-2 min-w-0\">\n <p className=\"text-xs text-stone mr-2 flex-1 line-clamp-2\">\n {lastMessageText}\n </p>\n {unreadCount > 0 && (\n <span className=\"bg-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 classNames from 'classnames'\nimport React from 'react'\nimport { ChannelList as StreamChannelList } from 'stream-chat-react'\n\nimport { useMessagingContext } from '../../providers/MessagingProvider'\nimport type { ChannelListProps } from '../../types'\n\nimport CustomChannelPreview from './CustomChannelPreview'\n\n/**\n * Channel list component with customizable header and actions\n */\nexport const ChannelList: React.FC<ChannelListProps> = ({\n onChannelSelect,\n selectedChannel,\n filters,\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 filters,\n })\n }\n\n return (\n <div\n className={classNames(\n 'messaging-channel-list h-full flex flex-col min-w-0 overflow-hidden',\n className\n )}\n >\n {/* Channel List */}\n <div className=\"flex-1 overflow-hidden min-w-0\">\n {(() => {\n if (debug) {\n console.log('📺 [ChannelList] 🎬 RENDERING STREAM CHANNEL LIST', {\n renderCount: renderCountRef.current,\n filters,\n })\n }\n\n return (\n <StreamChannelList\n key={JSON.stringify(filters)}\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 classNames from \"classnames\";\nimport React from \"react\";\n\ninterface IconButtonProps\n extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n \"type\" | \"children\"\n > {\n label: string;\n children: React.ReactNode;\n className?: string;\n}\n\nexport function IconButton({ label, className, children, ...rest }: IconButtonProps) {\n return (\n <button\n type=\"button\"\n className={classNames(\n \"rounded-full p-2 transition-colors focus-ring\",\n {\n \"cursor-not-allowed opacity-50\": rest.disabled,\n \"hover:bg-sand\": !rest.disabled,\n },\n className,\n )}\n {...rest}\n >\n <span className=\"sr-only\">{label}</span>\n {children}\n </button>\n );\n}","import { XIcon } from '@phosphor-icons/react'\n\nimport { IconButton } from '../IconButton'\n\ninterface CloseButtonProps {\n onClick: () => void\n}\n\nexport function CloseButton({ onClick }: CloseButtonProps) {\n return (\n <IconButton label=\"Close\" onClick={onClick} className=\"p-1\">\n <XIcon className=\"h-5 w-5 text-stone\" weight=\"bold\" />\n </IconButton>\n )\n}\n","import React from 'react'\n\n/**\n * Empty state component shown when a channel has no messages\n */\nexport const ChannelEmptyState: React.FC = () => (\n <div className=\"messaging-channel-empty-state flex items-center justify-center h-full p-8 text-balance\">\n <div className=\"text-center max-w-sm\">\n <h2 className=\"font-semibold text-charcoal mb-2\">No messages yet 👀</h2>\n\n <p className=\"text-stone text-xs\">\n Share to social media to generate more conversations\n </p>\n </div>\n </div>\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'\nimport { ChannelEmptyState } from './MessagingShell/ChannelEmptyState'\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 px-2 overflow-y-auto w-full\">\n <div\n className=\"flex flex-col items-center gap-3 self-stretch px-4 py-2 mt-6 rounded-lg border border-black/[0.04]\"\n style={{ backgroundColor: '#FBFAF9' }}\n >\n <div className=\"flex items-center gap-3 w-full\">\n <Avatar\n id={participantId}\n name={participantName}\n image={participantImage}\n size={88}\n className=\"!rounded-full\"\n />\n <div className=\"flex flex-col min-w-0 flex-1\">\n <p className=\"truncate text-base font-semibold text-charcoal\">\n {participantName}\n </p>\n {participantSecondary && (\n <p className=\"truncate text-sm text-[#00000055]\">\n {participantSecondary}\n </p>\n )}\n {followerStatusLabel && (\n <span\n className=\"mt-1 rounded-full text-xs font-normal w-fit\"\n style={{\n padding: '4px 8px',\n backgroundColor:\n followerStatusLabel === 'Subscribed to you'\n ? '#DCFCE7'\n : '#F5F5F4',\n color:\n followerStatusLabel === 'Subscribed to you'\n ? '#008236'\n : '#78716C',\n lineHeight: '133.333%',\n letterSpacing: '0.21px',\n }}\n >\n {followerStatusLabel}\n </span>\n )}\n </div>\n </div>\n </div>\n\n <ul className=\"flex flex-col gap-2 mt-2\">\n <li>\n <ActionButton\n onClick={handleLeaveConversation}\n disabled={isLeaving}\n aria-busy={isLeaving}\n >\n {isLeaving ? (\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n ) : (\n <SignOutIcon className=\"h-5 w-5\" />\n )}\n <span>Delete Conversation</span>\n </ActionButton>\n </li>\n <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 = ChannelEmptyState,\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\n // If explicit followerStatus is provided, use it\n if (channelExtraData.followerStatus) {\n return String(channelExtraData.followerStatus)\n }\n // If isFollower is explicitly defined, use it to determine status\n if (channelExtraData.isFollower !== undefined) {\n return channelExtraData.isFollower\n ? 'Subscribed to you'\n : 'Not subscribed'\n }\n // Otherwise, don't show any status\n return undefined\n }, [channel.data])\n\n 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\n hideDeletedMessages\n hideNewMessageSeparator={false}\n messageActions={[]}\n />\n\n {/* Show custom empty state when no messages */}\n {!hasMessages && CustomChannelEmptyState && (\n <div className=\"absolute inset-0 w-full h-full 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 = ChannelEmptyState,\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 filters,\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 // Create default filters and merge with provided filters\n const channelFilters = React.useMemo(() => {\n const userId = client?.userID\n\n // Base filters that should always be present\n const baseFilters = {\n type: 'messaging',\n last_message_at: { $exists: true },\n ...(userId && {\n members: { $in: [userId] },\n hidden: false,\n }),\n }\n\n // Merge provided filters with base filters\n // Provided filters can override base filters if needed\n return {\n ...baseFilters,\n ...filters,\n }\n }, [filters, client?.userID])\n\n // Track if we've already synced channels to prevent repeated API calls\n const syncedRef = useRef<string | null>(null)\n\n // Function to sync channels (extracted for reuse)\n const syncChannels = useCallback(async () => {\n if (!client || !isConnected) return\n\n const userId = client.userID\n if (!userId) return\n\n try {\n if (debug) {\n console.log('[MessagingShell] Syncing channels for user:', userId)\n }\n\n const channels = await client.queryChannels(\n {\n type: 'messaging',\n members: { $in: [userId] },\n },\n {},\n { limit: 100 }\n )\n\n const memberIds = new Set<string>()\n channels.forEach((channel: Channel) => {\n const members = channel.state.members\n Object.values(members).forEach((member) => {\n const memberId = member.user?.id\n if (memberId && memberId !== userId) {\n memberIds.add(memberId)\n }\n })\n })\n\n 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 filters={channelFilters}\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'\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","getDaysDifference","date1","date2","d1","diffTime","formatRelativeTime","date","now","daysDiff","EMOJIS","hashString","str","hash","i","char","getAvatarEmoji","id","index","Avatar","image","size","className","emoji","fontSizeClass","classNames","CustomChannelPreview","channel","selectedChannel","onChannelSelect","unread","isSelected","handleClick","participant","member","participantName","participantImage","_c","lastMessage","_e","_d","lastMessageText","attachment","lastMessageTime","unreadCount","jsxs","_f","ChannelList","filters","StreamChannelList","props","ActionButton","variant","rest","IconButton","label","CloseButton","onClick","XIcon","ChannelEmptyState","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","participantLabel","searchPlaceholder","participants","setParticipants","loading","setLoading","startingChatWithId","setStartingChatWithId","loadedRef","result","availableParticipants","searchLower","handleSelectParticipant","handleKeyDown","event","ChatCircleDotsIcon","displayName","displaySecondary","EmptyState","hasChannels","onStartConversation","TextButton","ErrorState","Loading","LoadingState","MessagingShell","onParticipantSelect","initialParticipantFilter","initialParticipantData","showChannelList","setSelectedChannel","setHasChannels","_showParticipantPicker","setShowParticipantPicker","setExistingParticipantIds","pickerKey","setPickerKey","directConversationMode","setDirectConversationMode","directConversationError","setDirectConversationError","participantPickerRef","showStartConversation","channelFilters","userId","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","b","useParticipants","options","initialSearch","pageSize","hasMore","setHasMore","cursor","setCursor","loadParticipants","reset","customSearch","search","loadMore","query","refresh"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linktr.ee/messaging-react",
3
- "version": "1.8.5",
3
+ "version": "1.8.6-rc-1764053798",
4
4
  "description": "React messaging components built on messaging-core for web applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -457,7 +457,11 @@ const ChannelViewInner: React.FC<{
457
457
 
458
458
  {/* Message List */}
459
459
  <div className="flex-1 overflow-hidden relative">
460
- <MessageList hideDeletedMessages hideNewMessageSeparator={false} />
460
+ <MessageList
461
+ hideDeletedMessages
462
+ hideNewMessageSeparator={false}
463
+ messageActions={[]}
464
+ />
461
465
 
462
466
  {/* Show custom empty state when no messages */}
463
467
  {!hasMessages && CustomChannelEmptyState && (