@adatechnology/conversations-ui 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -1
- package/dist/{ConversationSimulatorPanel-CrfFjiWh.d.ts → ConversationSimulatorPanel-q-wVgBCN.d.ts} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/participant/index.d.ts +45 -3
- package/dist/participant/index.js +287 -112
- package/dist/preview/index.d.ts +3 -3
- package/dist/{quickReply.types-B4gmZsSr.d.ts → quickReply.types-DzWH3NYV.d.ts} +1 -1
- package/dist/styles.css +74 -29
- package/package.json +1 -1
- package/src/participant/ConversationThread.test.tsx +165 -0
- package/src/participant/ConversationThread.tsx +117 -0
- package/src/participant/ParticipantMessageBubble.tsx +7 -3
- package/src/participant/ParticipantThread.tsx +9 -0
- package/src/participant/ParticipantThreadHeader.tsx +10 -0
- package/src/participant/ParticipantThreadScreen.tsx +6 -46
- package/src/participant/ParticipantTimeline.tsx +6 -3
- package/src/participant/conversationThreadApi.test.ts +27 -0
- package/src/participant/conversationThreadApi.ts +24 -0
- package/src/participant/conversationThreadCss.test.ts +116 -0
- package/src/participant/conversationThreadSummary.ts +34 -0
- package/src/participant/index.ts +3 -0
- package/src/participant/participantContrast.test-helper.ts +116 -0
- package/src/participant/participantGolden.test.tsx +46 -0
- package/src/participant/participantGoldenScenarios.test-helper.tsx +57 -0
- package/src/participant/participantMessages.ts +4 -3
- package/src/participant/participantNewMessages.test.ts +21 -0
- package/src/participant/participantNewMessages.ts +8 -3
- package/src/participant/participantPerspective.test.ts +67 -0
- package/src/participant/participantPerspective.ts +50 -0
- package/src/participant/participantPerspectiveRender.test.tsx +94 -0
- package/src/participant/participantThemeContrast.test.ts +98 -0
- package/src/participant/test-fixtures/conversations-list.golden.html +1 -0
- package/src/participant/test-fixtures/conversations-selected.golden.html +1 -0
- package/src/participant/test-fixtures/thread-avatars-initials.golden.html +1 -0
- package/src/participant/test-fixtures/thread-closed.golden.html +1 -0
- package/src/participant/test-fixtures/thread-default.golden.html +1 -0
- package/src/participant/test-fixtures/thread-error.golden.html +1 -0
- package/src/participant/test-fixtures/thread-loading.golden.html +1 -0
- package/src/participant/test-fixtures/thread-plain.golden.html +1 -0
- package/src/participant/test-fixtures/thread-tail-off.golden.html +1 -0
- package/src/participant/useParticipantConversationView.ts +3 -0
- package/src/participant/useParticipantThread.ts +13 -2
- package/src/participant/useParticipantThreadController.ts +112 -0
- package/src/participant/useParticipantThreadScroll.ts +3 -1
- package/src/participant/useParticipantUnread.test.tsx +40 -0
- package/src/participant/useParticipantUnread.ts +38 -0
- package/src/styles.css +24 -12
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "../chunk-O6457XHK.js";
|
|
8
8
|
|
|
9
9
|
// src/participant/ParticipantConversationsScreen.tsx
|
|
10
|
-
import { useMemo as useMemo5, useReducer as useReducer5, useRef as
|
|
10
|
+
import { useMemo as useMemo5, useReducer as useReducer5, useRef as useRef10, useState as useState8 } from "react";
|
|
11
11
|
|
|
12
12
|
// src/participant/participantLoadView.ts
|
|
13
13
|
function resolveLoadView({ status, hasItems }) {
|
|
@@ -361,7 +361,7 @@ function ParticipantInbox(props) {
|
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
// src/participant/ParticipantThreadScreen.tsx
|
|
364
|
-
import { useEffect as useEffect11,
|
|
364
|
+
import { useEffect as useEffect11, useState as useState7 } from "react";
|
|
365
365
|
|
|
366
366
|
// src/participant/ParticipantBackButton.tsx
|
|
367
367
|
import { ArrowLeft } from "lucide-react";
|
|
@@ -1314,6 +1314,30 @@ function ParticipantAttachmentItem({ attachment, resolveAttachmentUrl, labels })
|
|
|
1314
1314
|
);
|
|
1315
1315
|
}
|
|
1316
1316
|
|
|
1317
|
+
// src/participant/participantPerspective.ts
|
|
1318
|
+
var DEFAULT_PARTICIPANT_PERSPECTIVE = "participant";
|
|
1319
|
+
var OWN_DIRECTION = {
|
|
1320
|
+
participant: "inbound",
|
|
1321
|
+
operator: "outbound"
|
|
1322
|
+
};
|
|
1323
|
+
function isMessageMine(message, perspective = DEFAULT_PARTICIPANT_PERSPECTIVE) {
|
|
1324
|
+
return message.direction === OWN_DIRECTION[perspective];
|
|
1325
|
+
}
|
|
1326
|
+
function isUnreadByViewer(message, perspective) {
|
|
1327
|
+
if (isMessageMine(message, perspective)) return false;
|
|
1328
|
+
return !message.readAt && message.status !== "read";
|
|
1329
|
+
}
|
|
1330
|
+
function countOtherSideMessages(messages, perspective) {
|
|
1331
|
+
return messages.filter((message) => !isMessageMine(message, perspective)).length;
|
|
1332
|
+
}
|
|
1333
|
+
function countUnreadByViewer(messages, perspective) {
|
|
1334
|
+
return messages.filter((message) => isUnreadByViewer(message, perspective)).length;
|
|
1335
|
+
}
|
|
1336
|
+
function resolveViewerUnread({ messages, perspective, acknowledgedCount }) {
|
|
1337
|
+
if (countOtherSideMessages(messages, perspective) <= acknowledgedCount) return 0;
|
|
1338
|
+
return countUnreadByViewer(messages, perspective);
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1317
1341
|
// src/participant/participantMessages.ts
|
|
1318
1342
|
function isSameSubject(left, right) {
|
|
1319
1343
|
return left.subjectType === right.subjectType && left.subjectId === right.subjectId;
|
|
@@ -1339,8 +1363,8 @@ function mergeParticipantMessages(params) {
|
|
|
1339
1363
|
}
|
|
1340
1364
|
return items.sort((left, right) => createdAtOf(left) - createdAtOf(right));
|
|
1341
1365
|
}
|
|
1342
|
-
function isOwnMessage(message) {
|
|
1343
|
-
return message
|
|
1366
|
+
function isOwnMessage(message, perspective) {
|
|
1367
|
+
return isMessageMine(message, perspective);
|
|
1344
1368
|
}
|
|
1345
1369
|
function resolveOwnMessageStatus(params) {
|
|
1346
1370
|
const { displayState, serverStatus, confirmsRead } = params;
|
|
@@ -1353,11 +1377,11 @@ function resolveOwnMessageStatus(params) {
|
|
|
1353
1377
|
|
|
1354
1378
|
// src/participant/ParticipantMessageBubble.tsx
|
|
1355
1379
|
import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1356
|
-
function describeItem(item) {
|
|
1380
|
+
function describeItem(item, perspective) {
|
|
1357
1381
|
if (item.kind === "server") {
|
|
1358
1382
|
const { message } = item;
|
|
1359
1383
|
return {
|
|
1360
|
-
isMine: isOwnMessage(message),
|
|
1384
|
+
isMine: isOwnMessage(message, perspective),
|
|
1361
1385
|
authorName: message.authorName ?? void 0,
|
|
1362
1386
|
text: message.text ?? void 0,
|
|
1363
1387
|
createdAt: message.createdAt,
|
|
@@ -1390,9 +1414,10 @@ function ParticipantMessageBubble({
|
|
|
1390
1414
|
onDiscard,
|
|
1391
1415
|
onEdit,
|
|
1392
1416
|
avatar,
|
|
1393
|
-
tail = true
|
|
1417
|
+
tail = true,
|
|
1418
|
+
perspective
|
|
1394
1419
|
}) {
|
|
1395
|
-
const content = describeItem(item);
|
|
1420
|
+
const content = describeItem(item, perspective);
|
|
1396
1421
|
const { isMine } = content;
|
|
1397
1422
|
const ownStatus = isMine ? resolveOwnMessageStatus({ displayState: content.displayState, serverStatus: content.serverStatus, confirmsRead }) : void 0;
|
|
1398
1423
|
const bubble = /* @__PURE__ */ jsxs13("div", { className: bubbleClassName(isMine, tail), children: [
|
|
@@ -1445,9 +1470,9 @@ function createdAtOf2(item) {
|
|
|
1445
1470
|
function keyOf(item) {
|
|
1446
1471
|
return item.kind === "server" ? item.message.id : `pending:${item.pending.clientMessageId}`;
|
|
1447
1472
|
}
|
|
1448
|
-
function authorOf(item) {
|
|
1473
|
+
function authorOf(item, perspective) {
|
|
1449
1474
|
if (item.kind === "pending") return { isMine: true, author: null };
|
|
1450
|
-
return { isMine: isOwnMessage(item.message), author: item.message.authorName ?? null };
|
|
1475
|
+
return { isMine: isOwnMessage(item.message, perspective), author: item.message.authorName ?? null };
|
|
1451
1476
|
}
|
|
1452
1477
|
function resolveActions(item, pendingActions) {
|
|
1453
1478
|
if (!pendingActions || item.kind === "server") return {};
|
|
@@ -1471,7 +1496,7 @@ function ParticipantTimeline(props) {
|
|
|
1471
1496
|
previousAuthor = void 0;
|
|
1472
1497
|
}
|
|
1473
1498
|
previousDay = day;
|
|
1474
|
-
const { isMine, author } = authorOf(item);
|
|
1499
|
+
const { isMine, author } = authorOf(item, props.perspective);
|
|
1475
1500
|
const showAvatar = shouldShowAvatar({ previousAuthor, author, isMine });
|
|
1476
1501
|
previousAuthor = isMine ? void 0 : author;
|
|
1477
1502
|
const avatar = resolveAvatarSlot({
|
|
@@ -1490,6 +1515,7 @@ function ParticipantTimeline(props) {
|
|
|
1490
1515
|
confirmsRead,
|
|
1491
1516
|
resolveAttachmentUrl,
|
|
1492
1517
|
tail: props.tail,
|
|
1518
|
+
perspective: props.perspective,
|
|
1493
1519
|
avatar,
|
|
1494
1520
|
...resolveActions(item, pendingActions)
|
|
1495
1521
|
},
|
|
@@ -1588,7 +1614,9 @@ function ParticipantThreadHeader({
|
|
|
1588
1614
|
subjectGroups,
|
|
1589
1615
|
renderSubjectIcon,
|
|
1590
1616
|
onBack,
|
|
1591
|
-
onOpenSubject
|
|
1617
|
+
onOpenSubject,
|
|
1618
|
+
counterpartLabel,
|
|
1619
|
+
actions
|
|
1592
1620
|
}) {
|
|
1593
1621
|
const group = subjectGroups?.find((candidate) => candidate.subjectType === conversation.subjectType);
|
|
1594
1622
|
const icon = resolveConversationIcon({ conversation, group, renderSubjectIcon });
|
|
@@ -1599,11 +1627,13 @@ function ParticipantThreadHeader({
|
|
|
1599
1627
|
/* @__PURE__ */ jsxs15("div", { className: "cv-p-thread__heading", children: [
|
|
1600
1628
|
icon === void 0 && group ? /* @__PURE__ */ jsx22("p", { className: "cv-p-thread__eyebrow", children: group.label }) : null,
|
|
1601
1629
|
/* @__PURE__ */ jsx22(Title, { conversation, labels, onOpenSubject }),
|
|
1630
|
+
counterpartLabel ? /* @__PURE__ */ jsx22("p", { className: "cv-p-thread__counterpart", children: counterpartLabel }) : null,
|
|
1602
1631
|
conversation.protocol || hasChannels ? /* @__PURE__ */ jsxs15("div", { className: "cv-p-thread__meta", children: [
|
|
1603
1632
|
conversation.protocol ? /* @__PURE__ */ jsx22(ParticipantProtocolBadge, { protocol: conversation.protocol, labels }) : null,
|
|
1604
1633
|
/* @__PURE__ */ jsx22(ParticipantChannelBadges, { channels: conversation.channels, labels, variant: "inline", iconSize: 16 })
|
|
1605
1634
|
] }) : null
|
|
1606
|
-
] })
|
|
1635
|
+
] }),
|
|
1636
|
+
actions ? /* @__PURE__ */ jsx22("div", { className: "cv-p-thread__actions", children: actions }) : null
|
|
1607
1637
|
] });
|
|
1608
1638
|
}
|
|
1609
1639
|
|
|
@@ -1644,7 +1674,9 @@ function ThreadBody(props) {
|
|
|
1644
1674
|
subjectGroups: props.subjectGroups,
|
|
1645
1675
|
renderSubjectIcon: props.renderSubjectIcon,
|
|
1646
1676
|
onBack: props.onBack,
|
|
1647
|
-
onOpenSubject: props.onOpenSubject
|
|
1677
|
+
onOpenSubject: props.onOpenSubject,
|
|
1678
|
+
counterpartLabel: props.counterpartLabel,
|
|
1679
|
+
actions: props.headerActions
|
|
1648
1680
|
}
|
|
1649
1681
|
),
|
|
1650
1682
|
subjectCard ? /* @__PURE__ */ jsx23("div", { className: "cv-p-thread__subject-card", children: subjectCard }) : null,
|
|
@@ -1672,6 +1704,9 @@ function ParticipantThread(props) {
|
|
|
1672
1704
|
return /* @__PURE__ */ jsx23(ParticipantCopyAnnouncer, { children: /* @__PURE__ */ jsx23(ThreadBody, { ...props }) });
|
|
1673
1705
|
}
|
|
1674
1706
|
|
|
1707
|
+
// src/participant/useParticipantThreadController.ts
|
|
1708
|
+
import { useMemo as useMemo4 } from "react";
|
|
1709
|
+
|
|
1675
1710
|
// src/participant/bindAttachmentUrlResolver.ts
|
|
1676
1711
|
function bindAttachmentUrlResolver(api) {
|
|
1677
1712
|
return (attachment, disposition) => api.resolveAttachmentUrl(attachment, disposition);
|
|
@@ -1753,8 +1788,8 @@ function appendEntryToDraft(entry, current) {
|
|
|
1753
1788
|
return { text, files: [...entry.files, ...current.files] };
|
|
1754
1789
|
}
|
|
1755
1790
|
|
|
1756
|
-
// src/participant/
|
|
1757
|
-
import {
|
|
1791
|
+
// src/participant/useParticipantConversationView.ts
|
|
1792
|
+
import { useCallback as useCallback5, useMemo as useMemo3 } from "react";
|
|
1758
1793
|
|
|
1759
1794
|
// src/participant/participantDrafts.ts
|
|
1760
1795
|
var EMPTY_PARTICIPANT_DRAFT = { text: "", files: [] };
|
|
@@ -1782,30 +1817,6 @@ function takeDraftForSend(drafts, subject) {
|
|
|
1782
1817
|
};
|
|
1783
1818
|
}
|
|
1784
1819
|
|
|
1785
|
-
// src/participant/useParticipantDraft.ts
|
|
1786
|
-
function useParticipantDraft(draftsRef, subject) {
|
|
1787
|
-
const [draft, setDraftState] = useState3(() => getDraft(draftsRef.current, subject));
|
|
1788
|
-
function replaceDrafts(next) {
|
|
1789
|
-
draftsRef.current = next;
|
|
1790
|
-
setDraftState(getDraft(next, subject));
|
|
1791
|
-
}
|
|
1792
|
-
function update(change) {
|
|
1793
|
-
replaceDrafts(setDraft(draftsRef.current, subject, { ...getDraft(draftsRef.current, subject), ...change }));
|
|
1794
|
-
}
|
|
1795
|
-
function takeForSend() {
|
|
1796
|
-
const taken = takeDraftForSend(draftsRef.current, subject);
|
|
1797
|
-
if (taken.content) replaceDrafts(taken.drafts);
|
|
1798
|
-
return taken.content;
|
|
1799
|
-
}
|
|
1800
|
-
function restoreFromEntry(entry) {
|
|
1801
|
-
update(appendEntryToDraft(entry, getDraft(draftsRef.current, subject)));
|
|
1802
|
-
}
|
|
1803
|
-
return { draft, setText: (text) => update({ text }), setFiles: (files) => update({ files }), takeForSend, restoreFromEntry };
|
|
1804
|
-
}
|
|
1805
|
-
|
|
1806
|
-
// src/participant/useParticipantConversationView.ts
|
|
1807
|
-
import { useCallback as useCallback4, useMemo as useMemo3 } from "react";
|
|
1808
|
-
|
|
1809
1820
|
// src/participant/participantSendStates.ts
|
|
1810
1821
|
var NO_ENTRIES = [];
|
|
1811
1822
|
function selectSendEntries(states, subject) {
|
|
@@ -1822,7 +1833,7 @@ function participantSendStatesReducer(states, { subject, action }) {
|
|
|
1822
1833
|
}
|
|
1823
1834
|
|
|
1824
1835
|
// src/participant/useParticipantThread.ts
|
|
1825
|
-
import { useCallback as
|
|
1836
|
+
import { useCallback as useCallback4, useEffect as useEffect9, useMemo as useMemo2, useReducer as useReducer4, useRef as useRef7 } from "react";
|
|
1826
1837
|
|
|
1827
1838
|
// src/participant/participantThreadState.ts
|
|
1828
1839
|
var INITIAL_PARTICIPANT_THREAD_STATE = {
|
|
@@ -1870,9 +1881,9 @@ function shouldMarkParticipantRead(params) {
|
|
|
1870
1881
|
}
|
|
1871
1882
|
|
|
1872
1883
|
// src/participant/useDocumentVisibility.ts
|
|
1873
|
-
import { useEffect as useEffect6, useState as
|
|
1884
|
+
import { useEffect as useEffect6, useState as useState3 } from "react";
|
|
1874
1885
|
function useDocumentVisibility() {
|
|
1875
|
-
const [visibilityState, setVisibilityState] =
|
|
1886
|
+
const [visibilityState, setVisibilityState] = useState3(
|
|
1876
1887
|
() => typeof document === "undefined" ? "visible" : document.visibilityState
|
|
1877
1888
|
);
|
|
1878
1889
|
useEffect6(() => {
|
|
@@ -1982,6 +1993,24 @@ function useParticipantSend(params) {
|
|
|
1982
1993
|
return { send, retry };
|
|
1983
1994
|
}
|
|
1984
1995
|
|
|
1996
|
+
// src/participant/useParticipantUnread.ts
|
|
1997
|
+
import { useCallback as useCallback3, useRef as useRef6, useState as useState4 } from "react";
|
|
1998
|
+
function useParticipantUnread(params) {
|
|
1999
|
+
const { messages, perspective, reportedUnreadCount, onMarkedRead } = params;
|
|
2000
|
+
const [acknowledgedCount, setAcknowledgedCount] = useState4(0);
|
|
2001
|
+
const messagesRef = useRef6(messages);
|
|
2002
|
+
messagesRef.current = messages;
|
|
2003
|
+
const handleMarkedRead = useCallback3(
|
|
2004
|
+
(subject) => {
|
|
2005
|
+
if (perspective) setAcknowledgedCount(countOtherSideMessages(messagesRef.current, perspective));
|
|
2006
|
+
onMarkedRead?.(subject);
|
|
2007
|
+
},
|
|
2008
|
+
[perspective, onMarkedRead]
|
|
2009
|
+
);
|
|
2010
|
+
const unreadCount = perspective ? resolveViewerUnread({ messages, perspective, acknowledgedCount }) : reportedUnreadCount;
|
|
2011
|
+
return { unreadCount, handleMarkedRead };
|
|
2012
|
+
}
|
|
2013
|
+
|
|
1985
2014
|
// src/participant/useParticipantThread.ts
|
|
1986
2015
|
var THREAD_PAGE_SIZE = 30;
|
|
1987
2016
|
function describeError(error) {
|
|
@@ -1992,15 +2021,15 @@ function isForSubject(event, subject) {
|
|
|
1992
2021
|
return event.subject.subjectType === subject.subjectType && event.subject.subjectId === subject.subjectId;
|
|
1993
2022
|
}
|
|
1994
2023
|
function useParticipantThread(params) {
|
|
1995
|
-
const { api, subject, channel, unreadCount = 0, onMarkedRead, sendEntries, dispatchSend, hostPending = [] } = params;
|
|
2024
|
+
const { api, subject, channel, unreadCount = 0, onMarkedRead, sendEntries, dispatchSend, hostPending = [], perspective } = params;
|
|
1996
2025
|
const { subjectType, subjectId } = subject;
|
|
1997
2026
|
const stableSubject = useMemo2(() => ({ subjectType, subjectId }), [subjectType, subjectId]);
|
|
1998
2027
|
const [state, dispatch] = useReducer4(participantThreadReducer, INITIAL_PARTICIPANT_THREAD_STATE);
|
|
1999
|
-
const apiRef =
|
|
2028
|
+
const apiRef = useRef7(api);
|
|
2000
2029
|
apiRef.current = api;
|
|
2001
|
-
const activeSubjectKey =
|
|
2030
|
+
const activeSubjectKey = useRef7("");
|
|
2002
2031
|
const confirmsRead = channelCapabilityFor(channel).confirmsRead;
|
|
2003
|
-
const refresh =
|
|
2032
|
+
const refresh = useCallback4(async () => {
|
|
2004
2033
|
const requestKey = `${subjectType}:${subjectId}`;
|
|
2005
2034
|
dispatch({ type: "started" });
|
|
2006
2035
|
try {
|
|
@@ -2013,7 +2042,7 @@ function useParticipantThread(params) {
|
|
|
2013
2042
|
}
|
|
2014
2043
|
}, [stableSubject, subjectType, subjectId]);
|
|
2015
2044
|
const oldestMessageId = state.messages[0]?.id;
|
|
2016
|
-
const loadOlder =
|
|
2045
|
+
const loadOlder = useCallback4(async () => {
|
|
2017
2046
|
if (!oldestMessageId) return;
|
|
2018
2047
|
const requestKey = `${subjectType}:${subjectId}`;
|
|
2019
2048
|
try {
|
|
@@ -2025,7 +2054,7 @@ function useParticipantThread(params) {
|
|
|
2025
2054
|
if (activeSubjectKey.current === requestKey) dispatch({ type: "failed", error: describeError(error) });
|
|
2026
2055
|
}
|
|
2027
2056
|
}, [stableSubject, subjectType, subjectId, oldestMessageId]);
|
|
2028
|
-
const handleSentMessage =
|
|
2057
|
+
const handleSentMessage = useCallback4((message) => dispatch({ type: "sendConfirmed", message }), []);
|
|
2029
2058
|
const sending = useParticipantSend({ apiRef, subject: stableSubject, entries: sendEntries, dispatchSend, onSentMessage: handleSentMessage });
|
|
2030
2059
|
useEffect9(() => {
|
|
2031
2060
|
activeSubjectKey.current = `${subjectType}:${subjectId}`;
|
|
@@ -2039,7 +2068,14 @@ function useParticipantThread(params) {
|
|
|
2039
2068
|
if (sendEntries.length === 0) return;
|
|
2040
2069
|
dispatchSend({ type: "reflected", knownClientMessageIds: collectKnownClientMessageIds({ messages: state.messages, hostPending }) });
|
|
2041
2070
|
}, [sendEntries, state.messages, hostPending, dispatchSend]);
|
|
2042
|
-
|
|
2071
|
+
const unread = useParticipantUnread({ messages: state.messages, perspective, reportedUnreadCount: unreadCount, onMarkedRead });
|
|
2072
|
+
useParticipantMarkRead({
|
|
2073
|
+
apiRef,
|
|
2074
|
+
subject: stableSubject,
|
|
2075
|
+
unreadCount: unread.unreadCount,
|
|
2076
|
+
messageCount: state.messages.length,
|
|
2077
|
+
onMarkedRead: unread.handleMarkedRead
|
|
2078
|
+
});
|
|
2043
2079
|
const localPending = useMemo2(() => toLocalPending(sendEntries), [sendEntries]);
|
|
2044
2080
|
return { ...state, localPending, confirmsRead, refresh, loadOlder, ...sending };
|
|
2045
2081
|
}
|
|
@@ -2049,7 +2085,7 @@ function useParticipantConversationView(params) {
|
|
|
2049
2085
|
const { api, subject, conversation, pendingMessages, sendStates, dispatchSendStates } = params;
|
|
2050
2086
|
const { subjectType, subjectId } = subject;
|
|
2051
2087
|
const sendEntries = selectSendEntries(sendStates, subject);
|
|
2052
|
-
const dispatchSend =
|
|
2088
|
+
const dispatchSend = useCallback5(
|
|
2053
2089
|
(action) => dispatchSendStates({ subject: { subjectType, subjectId }, action }),
|
|
2054
2090
|
[dispatchSendStates, subjectType, subjectId]
|
|
2055
2091
|
);
|
|
@@ -2061,7 +2097,8 @@ function useParticipantConversationView(params) {
|
|
|
2061
2097
|
onMarkedRead: params.onMarkedRead,
|
|
2062
2098
|
sendEntries,
|
|
2063
2099
|
dispatchSend,
|
|
2064
|
-
hostPending: pendingMessages
|
|
2100
|
+
hostPending: pendingMessages,
|
|
2101
|
+
perspective: params.perspective
|
|
2065
2102
|
});
|
|
2066
2103
|
const items = useMemo3(
|
|
2067
2104
|
() => mergeParticipantMessages({
|
|
@@ -2075,8 +2112,30 @@ function useParticipantConversationView(params) {
|
|
|
2075
2112
|
return { thread, items, sendEntries, dispatchSend };
|
|
2076
2113
|
}
|
|
2077
2114
|
|
|
2115
|
+
// src/participant/useParticipantDraft.ts
|
|
2116
|
+
import { useState as useState5 } from "react";
|
|
2117
|
+
function useParticipantDraft(draftsRef, subject) {
|
|
2118
|
+
const [draft, setDraftState] = useState5(() => getDraft(draftsRef.current, subject));
|
|
2119
|
+
function replaceDrafts(next) {
|
|
2120
|
+
draftsRef.current = next;
|
|
2121
|
+
setDraftState(getDraft(next, subject));
|
|
2122
|
+
}
|
|
2123
|
+
function update(change) {
|
|
2124
|
+
replaceDrafts(setDraft(draftsRef.current, subject, { ...getDraft(draftsRef.current, subject), ...change }));
|
|
2125
|
+
}
|
|
2126
|
+
function takeForSend() {
|
|
2127
|
+
const taken = takeDraftForSend(draftsRef.current, subject);
|
|
2128
|
+
if (taken.content) replaceDrafts(taken.drafts);
|
|
2129
|
+
return taken.content;
|
|
2130
|
+
}
|
|
2131
|
+
function restoreFromEntry(entry) {
|
|
2132
|
+
update(appendEntryToDraft(entry, getDraft(draftsRef.current, subject)));
|
|
2133
|
+
}
|
|
2134
|
+
return { draft, setText: (text) => update({ text }), setFiles: (files) => update({ files }), takeForSend, restoreFromEntry };
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2078
2137
|
// src/participant/useParticipantThreadScroll.ts
|
|
2079
|
-
import { useEffect as useEffect10, useRef as
|
|
2138
|
+
import { useEffect as useEffect10, useRef as useRef9 } from "react";
|
|
2080
2139
|
|
|
2081
2140
|
// src/participant/participantNewMessages.ts
|
|
2082
2141
|
function collectServerMessageIds(items) {
|
|
@@ -2093,17 +2152,17 @@ function latestSeenTime(previousIds, items) {
|
|
|
2093
2152
|
}
|
|
2094
2153
|
return latest;
|
|
2095
2154
|
}
|
|
2096
|
-
function countNewIncomingMessages(previousIds, currentItems) {
|
|
2155
|
+
function countNewIncomingMessages(previousIds, currentItems, perspective) {
|
|
2097
2156
|
const latestSeen = latestSeenTime(previousIds, currentItems);
|
|
2098
2157
|
return currentItems.filter(
|
|
2099
|
-
(item) => item.kind === "server" && item.message
|
|
2158
|
+
(item) => item.kind === "server" && !isMessageMine(item.message, perspective) && !previousIds.has(item.message.id) && Date.parse(item.message.createdAt) > latestSeen
|
|
2100
2159
|
).length;
|
|
2101
2160
|
}
|
|
2102
2161
|
|
|
2103
2162
|
// src/participant/useScrollAwayState.ts
|
|
2104
|
-
import { useCallback as
|
|
2163
|
+
import { useCallback as useCallback6 } from "react";
|
|
2105
2164
|
function useScrollAwayState(ref, isNearBottom) {
|
|
2106
|
-
const scrollToLatest =
|
|
2165
|
+
const scrollToLatest = useCallback6(() => {
|
|
2107
2166
|
const element = ref.current;
|
|
2108
2167
|
if (!element) return;
|
|
2109
2168
|
element.scrollTo(
|
|
@@ -2114,7 +2173,7 @@ function useScrollAwayState(ref, isNearBottom) {
|
|
|
2114
2173
|
}
|
|
2115
2174
|
|
|
2116
2175
|
// src/participant/useStickToBottom.ts
|
|
2117
|
-
import { useCallback as
|
|
2176
|
+
import { useCallback as useCallback7, useLayoutEffect as useLayoutEffect2, useRef as useRef8, useState as useState6 } from "react";
|
|
2118
2177
|
|
|
2119
2178
|
// src/participant/participantScroll.ts
|
|
2120
2179
|
var NEAR_BOTTOM_THRESHOLD_PX = 80;
|
|
@@ -2136,17 +2195,17 @@ function resolveScrollAction(params) {
|
|
|
2136
2195
|
|
|
2137
2196
|
// src/participant/useStickToBottom.ts
|
|
2138
2197
|
function useStickToBottom({ firstKey, lastKey }) {
|
|
2139
|
-
const ref =
|
|
2140
|
-
const snapshot =
|
|
2198
|
+
const ref = useRef8(null);
|
|
2199
|
+
const snapshot = useRef8({
|
|
2141
2200
|
hasPositioned: false,
|
|
2142
2201
|
firstKey: void 0,
|
|
2143
2202
|
lastKey: void 0,
|
|
2144
2203
|
scrollTop: 0,
|
|
2145
2204
|
scrollHeight: 0
|
|
2146
2205
|
});
|
|
2147
|
-
const [isNearBottom, setIsNearBottom] =
|
|
2148
|
-
const isNearBottomRef =
|
|
2149
|
-
const onScroll =
|
|
2206
|
+
const [isNearBottom, setIsNearBottom] = useState6(true);
|
|
2207
|
+
const isNearBottomRef = useRef8(true);
|
|
2208
|
+
const onScroll = useCallback7((event) => {
|
|
2150
2209
|
const { scrollTop, clientHeight, scrollHeight } = event.currentTarget;
|
|
2151
2210
|
const isNear = shouldStickToBottom({ scrollTop, clientHeight, scrollHeight, threshold: NEAR_BOTTOM_THRESHOLD_PX });
|
|
2152
2211
|
snapshot.current.scrollTop = scrollTop;
|
|
@@ -2194,24 +2253,70 @@ function keyOf2(item) {
|
|
|
2194
2253
|
if (!item) return void 0;
|
|
2195
2254
|
return item.kind === "server" ? item.message.id : `pending:${item.pending.clientMessageId}`;
|
|
2196
2255
|
}
|
|
2197
|
-
function useParticipantThreadScroll(items) {
|
|
2256
|
+
function useParticipantThreadScroll(items, perspective) {
|
|
2198
2257
|
const { scroll: base, isNearBottom } = useStickToBottom({
|
|
2199
2258
|
firstKey: keyOf2(items[0]),
|
|
2200
2259
|
lastKey: keyOf2(items[items.length - 1])
|
|
2201
2260
|
});
|
|
2202
2261
|
const { isAwayFromBottom, scrollToLatest } = useScrollAwayState(base.ref, isNearBottom);
|
|
2203
2262
|
const scroll = { ...base, isAwayFromBottom, scrollToLatest };
|
|
2204
|
-
const seenIds =
|
|
2263
|
+
const seenIds = useRef9(/* @__PURE__ */ new Set());
|
|
2205
2264
|
useEffect10(() => {
|
|
2206
2265
|
if (isNearBottom) seenIds.current = collectServerMessageIds(items);
|
|
2207
2266
|
}, [isNearBottom, items]);
|
|
2208
|
-
return { scroll, newMessagesCount: isNearBottom ? 0 : countNewIncomingMessages(seenIds.current, items) };
|
|
2267
|
+
return { scroll, newMessagesCount: isNearBottom ? 0 : countNewIncomingMessages(seenIds.current, items, perspective) };
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2270
|
+
// src/participant/useParticipantThreadController.ts
|
|
2271
|
+
function buildPendingActions({ thread, dispatchSend, handleEdit, onRetryPending }) {
|
|
2272
|
+
return {
|
|
2273
|
+
retryLocal: (clientMessageId) => void thread.retry(clientMessageId),
|
|
2274
|
+
discardLocal: (clientMessageId) => dispatchSend({ type: "discarded", clientMessageId }),
|
|
2275
|
+
editLocal: handleEdit,
|
|
2276
|
+
...onRetryPending ? { retryHost: onRetryPending } : {}
|
|
2277
|
+
};
|
|
2278
|
+
}
|
|
2279
|
+
function useParticipantThreadController(params) {
|
|
2280
|
+
const { api, subject, conversation, draftsRef } = params;
|
|
2281
|
+
const { draft, setText, setFiles, takeForSend, restoreFromEntry } = useParticipantDraft(draftsRef, subject);
|
|
2282
|
+
const { thread, items, sendEntries, dispatchSend } = useParticipantConversationView(params);
|
|
2283
|
+
const resolveAttachmentUrl = useMemo4(() => bindAttachmentUrlResolver(api), [api]);
|
|
2284
|
+
const { scroll, newMessagesCount } = useParticipantThreadScroll(items, params.perspective);
|
|
2285
|
+
function handleSend() {
|
|
2286
|
+
const content = takeForSend();
|
|
2287
|
+
if (content) void thread.send(content);
|
|
2288
|
+
}
|
|
2289
|
+
function handleEdit(clientMessageId) {
|
|
2290
|
+
const entry = findFailedEntry(sendEntries, clientMessageId);
|
|
2291
|
+
if (!entry) return;
|
|
2292
|
+
restoreFromEntry(entry);
|
|
2293
|
+
dispatchSend({ type: "discarded", clientMessageId });
|
|
2294
|
+
}
|
|
2295
|
+
return {
|
|
2296
|
+
conversation,
|
|
2297
|
+
items,
|
|
2298
|
+
hasMore: thread.hasMore,
|
|
2299
|
+
labels: params.labels,
|
|
2300
|
+
resolveAttachmentUrl,
|
|
2301
|
+
draft: { value: draft.text, onChange: setText, files: draft.files, onFilesChange: setFiles },
|
|
2302
|
+
onSend: handleSend,
|
|
2303
|
+
status: thread.status,
|
|
2304
|
+
refresh: () => void thread.refresh(),
|
|
2305
|
+
scroll,
|
|
2306
|
+
newMessagesCount,
|
|
2307
|
+
isSending: hasSendingEntry(sendEntries),
|
|
2308
|
+
channel: params.channel,
|
|
2309
|
+
locale: params.locale,
|
|
2310
|
+
onLoadOlder: () => void thread.loadOlder(),
|
|
2311
|
+
pendingActions: buildPendingActions({ thread, dispatchSend, handleEdit, onRetryPending: params.onRetryPending }),
|
|
2312
|
+
perspective: params.perspective
|
|
2313
|
+
};
|
|
2209
2314
|
}
|
|
2210
2315
|
|
|
2211
2316
|
// src/participant/ParticipantThreadScreen.tsx
|
|
2212
2317
|
import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2213
2318
|
function useOpenedConversation(api, subject, isNeeded) {
|
|
2214
|
-
const [opened, setOpened] =
|
|
2319
|
+
const [opened, setOpened] = useState7({ status: "idle" });
|
|
2215
2320
|
const { subjectType, subjectId } = subject;
|
|
2216
2321
|
const canOpen = api.openConversation !== void 0;
|
|
2217
2322
|
useEffect11(() => {
|
|
@@ -2252,51 +2357,17 @@ function ParticipantThreadScreen(props) {
|
|
|
2252
2357
|
return /* @__PURE__ */ jsx24(NotFound, { labels, onBack: props.onBack });
|
|
2253
2358
|
}
|
|
2254
2359
|
function LoadedThread(props) {
|
|
2255
|
-
const
|
|
2256
|
-
const { draft, setText, setFiles, takeForSend, restoreFromEntry } = useParticipantDraft(draftsRef, selected);
|
|
2257
|
-
const { thread, items, sendEntries, dispatchSend } = useParticipantConversationView({
|
|
2360
|
+
const core = useParticipantThreadController({
|
|
2258
2361
|
...props,
|
|
2259
|
-
subject: selected,
|
|
2260
|
-
onMarkedRead: inbox.markSubjectRead
|
|
2362
|
+
subject: props.selected,
|
|
2363
|
+
onMarkedRead: props.inbox.markSubjectRead
|
|
2261
2364
|
});
|
|
2262
|
-
const resolveAttachmentUrl = useMemo4(() => bindAttachmentUrlResolver(api), [api]);
|
|
2263
|
-
const { scroll, newMessagesCount } = useParticipantThreadScroll(items);
|
|
2264
|
-
function handleSend() {
|
|
2265
|
-
const content = takeForSend();
|
|
2266
|
-
if (content) void thread.send(content);
|
|
2267
|
-
}
|
|
2268
|
-
function handleEdit(clientMessageId) {
|
|
2269
|
-
const entry = findFailedEntry(sendEntries, clientMessageId);
|
|
2270
|
-
if (!entry) return;
|
|
2271
|
-
restoreFromEntry(entry);
|
|
2272
|
-
dispatchSend({ type: "discarded", clientMessageId });
|
|
2273
|
-
}
|
|
2274
2365
|
return /* @__PURE__ */ jsx24(
|
|
2275
2366
|
ParticipantThread,
|
|
2276
2367
|
{
|
|
2277
|
-
|
|
2278
|
-
items,
|
|
2279
|
-
hasMore: thread.hasMore,
|
|
2280
|
-
labels: props.labels,
|
|
2281
|
-
resolveAttachmentUrl,
|
|
2282
|
-
draft: { value: draft.text, onChange: setText, files: draft.files, onFilesChange: setFiles },
|
|
2283
|
-
onSend: handleSend,
|
|
2284
|
-
status: thread.status,
|
|
2285
|
-
refresh: () => void thread.refresh(),
|
|
2286
|
-
scroll,
|
|
2287
|
-
newMessagesCount,
|
|
2288
|
-
isSending: hasSendingEntry(sendEntries),
|
|
2289
|
-
channel: props.channel,
|
|
2290
|
-
locale: props.locale,
|
|
2368
|
+
...core,
|
|
2291
2369
|
onBack: props.onBack,
|
|
2292
2370
|
onOpenSubject: props.onOpenSubject,
|
|
2293
|
-
onLoadOlder: () => void thread.loadOlder(),
|
|
2294
|
-
pendingActions: {
|
|
2295
|
-
retryLocal: (clientMessageId) => void thread.retry(clientMessageId),
|
|
2296
|
-
discardLocal: (clientMessageId) => dispatchSend({ type: "discarded", clientMessageId }),
|
|
2297
|
-
editLocal: handleEdit,
|
|
2298
|
-
...props.onRetryPending ? { retryHost: props.onRetryPending } : {}
|
|
2299
|
-
},
|
|
2300
2371
|
quickReplies: props.quickReplies,
|
|
2301
2372
|
renderSubjectCard: props.renderSubjectCard,
|
|
2302
2373
|
subjectGroups: props.subjectGroups,
|
|
@@ -2433,9 +2504,9 @@ import { jsx as jsx25 } from "react/jsx-runtime";
|
|
|
2433
2504
|
var ALL_FILTER3 = "all";
|
|
2434
2505
|
function ParticipantConversationsScreen(props) {
|
|
2435
2506
|
const { selected, inbox, subjectGroups, classNames } = props;
|
|
2436
|
-
const [filter, setFilter] =
|
|
2437
|
-
const [searchQuery, setSearchQuery] =
|
|
2438
|
-
const draftsRef =
|
|
2507
|
+
const [filter, setFilter] = useState8(ALL_FILTER3);
|
|
2508
|
+
const [searchQuery, setSearchQuery] = useState8("");
|
|
2509
|
+
const draftsRef = useRef10(/* @__PURE__ */ new Map());
|
|
2439
2510
|
const [sendStates, dispatchSendStates] = useReducer5(participantSendStatesReducer, /* @__PURE__ */ new Map());
|
|
2440
2511
|
const labels = useMemo5(() => ({ ...DEFAULT_PARTICIPANT_CONVERSATIONS_LABELS, ...props.labels }), [props.labels]);
|
|
2441
2512
|
const view = useMemo5(
|
|
@@ -2481,7 +2552,7 @@ function ParticipantConversationsScreen(props) {
|
|
|
2481
2552
|
}
|
|
2482
2553
|
|
|
2483
2554
|
// src/participant/useParticipantInbox.ts
|
|
2484
|
-
import { useCallback as
|
|
2555
|
+
import { useCallback as useCallback8, useEffect as useEffect12, useReducer as useReducer6 } from "react";
|
|
2485
2556
|
|
|
2486
2557
|
// src/participant/participantInboxState.ts
|
|
2487
2558
|
var INITIAL_PARTICIPANT_INBOX_STATE = { status: "idle", conversations: [] };
|
|
@@ -2532,7 +2603,7 @@ function describeError2(error) {
|
|
|
2532
2603
|
}
|
|
2533
2604
|
function useParticipantInbox(api) {
|
|
2534
2605
|
const [state, dispatch] = useReducer6(participantInboxReducer, INITIAL_PARTICIPANT_INBOX_STATE);
|
|
2535
|
-
const refresh =
|
|
2606
|
+
const refresh = useCallback8(async () => {
|
|
2536
2607
|
dispatch({ type: "started" });
|
|
2537
2608
|
try {
|
|
2538
2609
|
const page = await api.listConversations();
|
|
@@ -2542,7 +2613,7 @@ function useParticipantInbox(api) {
|
|
|
2542
2613
|
}
|
|
2543
2614
|
}, [api]);
|
|
2544
2615
|
const { nextCursor } = state;
|
|
2545
|
-
const loadMore =
|
|
2616
|
+
const loadMore = useCallback8(async () => {
|
|
2546
2617
|
if (!nextCursor) return;
|
|
2547
2618
|
try {
|
|
2548
2619
|
const page = await api.listConversations({ cursor: nextCursor });
|
|
@@ -2551,7 +2622,7 @@ function useParticipantInbox(api) {
|
|
|
2551
2622
|
dispatch({ type: "failed", error: describeError2(error) });
|
|
2552
2623
|
}
|
|
2553
2624
|
}, [api, nextCursor]);
|
|
2554
|
-
const markSubjectRead =
|
|
2625
|
+
const markSubjectRead = useCallback8((subject) => {
|
|
2555
2626
|
dispatch({ type: "markedRead", subject });
|
|
2556
2627
|
}, []);
|
|
2557
2628
|
useEffect12(() => {
|
|
@@ -2576,7 +2647,111 @@ function ParticipantConversations(props) {
|
|
|
2576
2647
|
}
|
|
2577
2648
|
);
|
|
2578
2649
|
}
|
|
2650
|
+
|
|
2651
|
+
// src/participant/ConversationThread.tsx
|
|
2652
|
+
import { useCallback as useCallback9, useMemo as useMemo6, useReducer as useReducer7, useRef as useRef11 } from "react";
|
|
2653
|
+
|
|
2654
|
+
// src/participant/conversationThreadApi.ts
|
|
2655
|
+
function toParticipantApi(api) {
|
|
2656
|
+
const { subscribe } = api;
|
|
2657
|
+
return {
|
|
2658
|
+
listConversations: async () => ({ data: [] }),
|
|
2659
|
+
fetchMessages: (subject, params) => api.fetchMessages(subject, params),
|
|
2660
|
+
sendMessage: (input) => api.sendMessage(input),
|
|
2661
|
+
markRead: async (subject) => {
|
|
2662
|
+
if (!api.markRead) throw new Error("The host api has no markRead");
|
|
2663
|
+
await api.markRead(subject);
|
|
2664
|
+
},
|
|
2665
|
+
resolveAttachmentUrl: (attachment, disposition) => api.resolveAttachmentUrl(attachment, disposition),
|
|
2666
|
+
...subscribe ? { subscribe: (listener) => api.subscribe?.(listener) ?? (() => void 0) } : {}
|
|
2667
|
+
};
|
|
2668
|
+
}
|
|
2669
|
+
|
|
2670
|
+
// src/participant/conversationThreadSummary.ts
|
|
2671
|
+
function buildThreadSummary({
|
|
2672
|
+
subject,
|
|
2673
|
+
title,
|
|
2674
|
+
protocol,
|
|
2675
|
+
channels,
|
|
2676
|
+
status
|
|
2677
|
+
}) {
|
|
2678
|
+
return {
|
|
2679
|
+
subjectType: subject.subjectType,
|
|
2680
|
+
subjectId: subject.subjectId,
|
|
2681
|
+
subjectLabel: title,
|
|
2682
|
+
lastMessageAt: null,
|
|
2683
|
+
unreadCount: 0,
|
|
2684
|
+
awaitingParticipant: false,
|
|
2685
|
+
status: status ?? "open",
|
|
2686
|
+
...protocol ? { protocol } : {},
|
|
2687
|
+
...channels ? { channels } : {}
|
|
2688
|
+
};
|
|
2689
|
+
}
|
|
2690
|
+
|
|
2691
|
+
// src/participant/ConversationThread.tsx
|
|
2692
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
2693
|
+
function useConversationThreadCore(props) {
|
|
2694
|
+
const { perspective = "participant" } = props;
|
|
2695
|
+
const { subjectType, subjectId } = props.subject;
|
|
2696
|
+
const subject = useMemo6(() => ({ subjectType, subjectId }), [subjectType, subjectId]);
|
|
2697
|
+
const onMarkedReadRef = useRef11(props.onMarkedRead);
|
|
2698
|
+
onMarkedReadRef.current = props.onMarkedRead;
|
|
2699
|
+
const handleMarkedRead = useCallback9((marked) => onMarkedReadRef.current?.(marked), []);
|
|
2700
|
+
const api = useMemo6(() => toParticipantApi(props.api), [props.api]);
|
|
2701
|
+
const draftsRef = useRef11(/* @__PURE__ */ new Map());
|
|
2702
|
+
const [sendStates, dispatchSendStates] = useReducer7(participantSendStatesReducer, /* @__PURE__ */ new Map());
|
|
2703
|
+
const labels = useMemo6(() => ({ ...DEFAULT_PARTICIPANT_CONVERSATIONS_LABELS, ...props.labels }), [props.labels]);
|
|
2704
|
+
const { title, protocol, channels, status } = props;
|
|
2705
|
+
const conversation = useMemo6(
|
|
2706
|
+
() => buildThreadSummary({ subject, title, protocol, channels, status }),
|
|
2707
|
+
[subject, title, protocol, channels, status]
|
|
2708
|
+
);
|
|
2709
|
+
return useParticipantThreadController({
|
|
2710
|
+
api,
|
|
2711
|
+
subject,
|
|
2712
|
+
conversation,
|
|
2713
|
+
labels,
|
|
2714
|
+
draftsRef,
|
|
2715
|
+
sendStates,
|
|
2716
|
+
dispatchSendStates,
|
|
2717
|
+
onMarkedRead: handleMarkedRead,
|
|
2718
|
+
channel: props.channel,
|
|
2719
|
+
locale: props.locale,
|
|
2720
|
+
pendingMessages: props.pendingMessages,
|
|
2721
|
+
onRetryPending: props.onRetryPending,
|
|
2722
|
+
perspective
|
|
2723
|
+
});
|
|
2724
|
+
}
|
|
2725
|
+
function ConversationThreadBody(props) {
|
|
2726
|
+
const core = useConversationThreadCore(props);
|
|
2727
|
+
return /* @__PURE__ */ jsx27(
|
|
2728
|
+
"div",
|
|
2729
|
+
{
|
|
2730
|
+
className: ["cv-p-root", props.className].filter(Boolean).join(" "),
|
|
2731
|
+
style: buildParticipantThemeStyle(props.theme),
|
|
2732
|
+
children: /* @__PURE__ */ jsx27("div", { className: "cv-p-root__screen", children: /* @__PURE__ */ jsx27(
|
|
2733
|
+
ParticipantThread,
|
|
2734
|
+
{
|
|
2735
|
+
...core,
|
|
2736
|
+
onBack: props.onBack,
|
|
2737
|
+
quickReplies: props.quickReplies,
|
|
2738
|
+
subjectGroups: props.subjectGroups,
|
|
2739
|
+
renderSubjectIcon: props.renderSubjectIcon,
|
|
2740
|
+
avatars: props.avatars,
|
|
2741
|
+
renderAuthorAvatar: props.renderAuthorAvatar,
|
|
2742
|
+
tail: props.tail,
|
|
2743
|
+
counterpartLabel: props.counterpartLabel,
|
|
2744
|
+
headerActions: props.headerActions
|
|
2745
|
+
}
|
|
2746
|
+
) })
|
|
2747
|
+
}
|
|
2748
|
+
);
|
|
2749
|
+
}
|
|
2750
|
+
function ConversationThread(props) {
|
|
2751
|
+
return /* @__PURE__ */ jsx27(ConversationThreadBody, { ...props }, draftKey(props.subject));
|
|
2752
|
+
}
|
|
2579
2753
|
export {
|
|
2754
|
+
ConversationThread,
|
|
2580
2755
|
DEFAULT_PARTICIPANT_CONVERSATIONS_LABELS,
|
|
2581
2756
|
ParticipantConversations,
|
|
2582
2757
|
groupParticipantConversations
|