@ai-matrx/messaging 0.15.9 → 0.15.10
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/CHANGELOG.md +6 -0
- package/dist/index.cjs +43 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +43 -6
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +334 -63
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +24 -45
- package/dist/react.d.ts +24 -45
- package/dist/react.js +335 -64
- package/dist/react.js.map +1 -1
- package/package.json +3 -3
package/dist/react.js
CHANGED
|
@@ -251,7 +251,7 @@ function splitText(content) {
|
|
|
251
251
|
}
|
|
252
252
|
function summarizeText(content, maxLength = 140) {
|
|
253
253
|
const parts = splitText(content).map(
|
|
254
|
-
(segment) => segment.type === "text" ? segment.value : segment.type === "reference" ? segment.reference.label : (
|
|
254
|
+
(segment) => segment.type === "text" ? segment.value.replace(/```[^\n]*\n([\s\S]*?)```/g, "$1").replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/^\s{0,3}(?:#{1,6}\s+|>\s*|[-*+]\s+|\d+\.\s+)/gm, "").replace(/([*_`~])\1*(.*?)\1+/g, "$2") : segment.type === "reference" ? segment.reference.label : (
|
|
255
255
|
// A fence we cannot read still SAYS something. Collapsing it to
|
|
256
256
|
// nothing is how a reference-only message becomes an inbox row that
|
|
257
257
|
// reads "No messages yet" — a screen telling a lie.
|
|
@@ -722,8 +722,7 @@ function projectMessageAction(value) {
|
|
|
722
722
|
payload: jsonObject(record["payload"])
|
|
723
723
|
};
|
|
724
724
|
}
|
|
725
|
-
function
|
|
726
|
-
const raw = metadata["attachments"];
|
|
725
|
+
function projectAttachmentList(raw) {
|
|
727
726
|
if (!Array.isArray(raw)) return [];
|
|
728
727
|
const attachments = [];
|
|
729
728
|
for (const entry of raw) {
|
|
@@ -745,8 +744,13 @@ function projectAttachments(metadata) {
|
|
|
745
744
|
}
|
|
746
745
|
return attachments;
|
|
747
746
|
}
|
|
747
|
+
function projectAttachments(metadata) {
|
|
748
|
+
return projectAttachmentList(metadata["attachments"]);
|
|
749
|
+
}
|
|
748
750
|
function projectReferences(metadata) {
|
|
749
|
-
|
|
751
|
+
return projectReferenceList(metadata["references"]);
|
|
752
|
+
}
|
|
753
|
+
function projectReferenceList(raw) {
|
|
750
754
|
if (!Array.isArray(raw)) return [];
|
|
751
755
|
const references = [];
|
|
752
756
|
for (const entry of raw) {
|
|
@@ -765,6 +769,35 @@ function projectReferences(metadata) {
|
|
|
765
769
|
}
|
|
766
770
|
return references;
|
|
767
771
|
}
|
|
772
|
+
function projectBroadcastMessage(value) {
|
|
773
|
+
const operation = "projectBroadcastMessage";
|
|
774
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
775
|
+
throw invalidResponse(operation, "broadcast payload was not an object");
|
|
776
|
+
}
|
|
777
|
+
const record = value;
|
|
778
|
+
const kindRaw = str(record, "kind") ?? str(record, "messageType") ?? "text";
|
|
779
|
+
const stateRaw = str(record, "deliveryState") ?? str(record, "status") ?? "sent";
|
|
780
|
+
const metadata = jsonObject(record["metadata"]);
|
|
781
|
+
return {
|
|
782
|
+
id: requiredStr(record, "id", operation),
|
|
783
|
+
conversationId: requiredStr(record, "conversationId", operation),
|
|
784
|
+
senderId: requiredStr(record, "senderId", operation),
|
|
785
|
+
organizationId: requiredStr(record, "organizationId", operation),
|
|
786
|
+
content: typeof record["content"] === "string" ? record["content"] : "",
|
|
787
|
+
kind: MESSAGE_KINDS.has(kindRaw) ? kindRaw : "text",
|
|
788
|
+
deliveryState: DELIVERY_STATES.has(stateRaw) ? stateRaw : "sent",
|
|
789
|
+
replyToId: str(record, "replyToId"),
|
|
790
|
+
clientMessageId: str(record, "clientMessageId"),
|
|
791
|
+
createdAt: requiredStr(record, "createdAt", operation),
|
|
792
|
+
editedAt: str(record, "editedAt"),
|
|
793
|
+
deletedAt: str(record, "deletedAt"),
|
|
794
|
+
deletedForEveryone: bool(record, "deletedForEveryone", false),
|
|
795
|
+
action: projectMessageAction(record["action"]),
|
|
796
|
+
attachments: projectAttachmentList(record["attachments"]),
|
|
797
|
+
references: projectReferenceList(record["references"]),
|
|
798
|
+
metadata
|
|
799
|
+
};
|
|
800
|
+
}
|
|
768
801
|
function projectMessage(row, fallbackOrganizationId) {
|
|
769
802
|
const operation = "projectMessage";
|
|
770
803
|
const metadata = jsonObject(row["metadata"]);
|
|
@@ -1238,6 +1271,7 @@ function createMessagingEngine(options) {
|
|
|
1238
1271
|
store,
|
|
1239
1272
|
outbox,
|
|
1240
1273
|
identity,
|
|
1274
|
+
reportDiagnostic: report,
|
|
1241
1275
|
async start() {
|
|
1242
1276
|
if (options.archiveFilter !== void 0) {
|
|
1243
1277
|
store.setArchiveFilter(options.archiveFilter);
|
|
@@ -1379,8 +1413,11 @@ function createMessagingEngine(options) {
|
|
|
1379
1413
|
{
|
|
1380
1414
|
event: MESSAGING_EVENTS.message,
|
|
1381
1415
|
onMessage: ({ data }) => {
|
|
1382
|
-
|
|
1383
|
-
|
|
1416
|
+
try {
|
|
1417
|
+
store.ingest(projectBroadcastMessage(data));
|
|
1418
|
+
} catch (error) {
|
|
1419
|
+
reportError(error, "broadcastMessage");
|
|
1420
|
+
}
|
|
1384
1421
|
}
|
|
1385
1422
|
}
|
|
1386
1423
|
],
|
|
@@ -2289,6 +2326,7 @@ function MessagingRuntime(props) {
|
|
|
2289
2326
|
}, [renderers]);
|
|
2290
2327
|
const renderReference = props.renderReference ?? null;
|
|
2291
2328
|
const renderFence = props.renderFence ?? null;
|
|
2329
|
+
const renderAttachment = props.renderAttachment ?? null;
|
|
2292
2330
|
const wrapMessage = props.wrapMessage ?? null;
|
|
2293
2331
|
const wrapConversationRow = props.wrapConversationRow ?? null;
|
|
2294
2332
|
const host = useMemo(() => {
|
|
@@ -2302,6 +2340,7 @@ function MessagingRuntime(props) {
|
|
|
2302
2340
|
actionRenderers: rendererMap,
|
|
2303
2341
|
renderReference,
|
|
2304
2342
|
renderFence,
|
|
2343
|
+
renderAttachment,
|
|
2305
2344
|
wrapMessage,
|
|
2306
2345
|
wrapConversationRow
|
|
2307
2346
|
};
|
|
@@ -2312,6 +2351,7 @@ function MessagingRuntime(props) {
|
|
|
2312
2351
|
rendererMap,
|
|
2313
2352
|
renderReference,
|
|
2314
2353
|
renderFence,
|
|
2354
|
+
renderAttachment,
|
|
2315
2355
|
wrapMessage,
|
|
2316
2356
|
wrapConversationRow
|
|
2317
2357
|
]);
|
|
@@ -2342,7 +2382,7 @@ function useMessagingSnapshot() {
|
|
|
2342
2382
|
}
|
|
2343
2383
|
|
|
2344
2384
|
// src/react/hooks.ts
|
|
2345
|
-
import { useCallback, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState } from "react";
|
|
2385
|
+
import { useCallback, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
2346
2386
|
import { useTyping, usePresence } from "@ai-matrx/realtime/react";
|
|
2347
2387
|
|
|
2348
2388
|
// src/core/format.ts
|
|
@@ -2523,11 +2563,117 @@ function useConversation(id) {
|
|
|
2523
2563
|
}
|
|
2524
2564
|
};
|
|
2525
2565
|
}
|
|
2566
|
+
var EMPTY_COMPOSER_SESSION = {
|
|
2567
|
+
drafts: {},
|
|
2568
|
+
replies: {},
|
|
2569
|
+
additions: {}
|
|
2570
|
+
};
|
|
2571
|
+
var emptyComposerSnapshot = () => EMPTY_COMPOSER_SESSION;
|
|
2572
|
+
var subscribeToNothing = () => () => void 0;
|
|
2573
|
+
var composerSessions = /* @__PURE__ */ new WeakMap();
|
|
2574
|
+
var composerStorageFailures = /* @__PURE__ */ new WeakSet();
|
|
2575
|
+
function composerStorageKey(engine) {
|
|
2576
|
+
return `ai-matrx.messaging.composer.${engine.identity.userId}`;
|
|
2577
|
+
}
|
|
2578
|
+
function readComposerSession(engine) {
|
|
2579
|
+
try {
|
|
2580
|
+
if (typeof sessionStorage === "undefined") return EMPTY_COMPOSER_SESSION;
|
|
2581
|
+
const serialized = sessionStorage.getItem(composerStorageKey(engine));
|
|
2582
|
+
if (serialized === null) return EMPTY_COMPOSER_SESSION;
|
|
2583
|
+
const parsed = JSON.parse(serialized);
|
|
2584
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
2585
|
+
throw new Error("saved composer state was not an object");
|
|
2586
|
+
}
|
|
2587
|
+
const source = parsed;
|
|
2588
|
+
const drafts = {};
|
|
2589
|
+
if (typeof source["drafts"] === "object" && source["drafts"] !== null) {
|
|
2590
|
+
for (const [id, value] of Object.entries(source["drafts"])) {
|
|
2591
|
+
if (typeof value === "string") drafts[id] = value;
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2594
|
+
const replies = {};
|
|
2595
|
+
if (typeof source["replies"] === "object" && source["replies"] !== null) {
|
|
2596
|
+
for (const [id, value] of Object.entries(source["replies"])) {
|
|
2597
|
+
if (value === null) replies[id] = null;
|
|
2598
|
+
else replies[id] = projectBroadcastMessage(value);
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2601
|
+
const additions = {};
|
|
2602
|
+
if (typeof source["additions"] === "object" && source["additions"] !== null) {
|
|
2603
|
+
for (const [id, value] of Object.entries(source["additions"])) {
|
|
2604
|
+
if (!Array.isArray(value)) continue;
|
|
2605
|
+
additions[id] = value.filter((item) => {
|
|
2606
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) return false;
|
|
2607
|
+
const record = item;
|
|
2608
|
+
return typeof record["id"] === "string" && typeof record["label"] === "string";
|
|
2609
|
+
});
|
|
2610
|
+
}
|
|
2611
|
+
}
|
|
2612
|
+
return { drafts, replies, additions };
|
|
2613
|
+
} catch (error) {
|
|
2614
|
+
if (!composerStorageFailures.has(engine)) {
|
|
2615
|
+
composerStorageFailures.add(engine);
|
|
2616
|
+
engine.reportDiagnostic({
|
|
2617
|
+
level: "warn",
|
|
2618
|
+
message: `A saved message draft could not be restored: ${String(error?.message ?? error)}`,
|
|
2619
|
+
remedy: "The current draft remains usable. Re-add any missing attachments before sending."
|
|
2620
|
+
});
|
|
2621
|
+
}
|
|
2622
|
+
return EMPTY_COMPOSER_SESSION;
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2625
|
+
function writeComposerSession(engine, snapshot) {
|
|
2626
|
+
try {
|
|
2627
|
+
if (typeof sessionStorage === "undefined") return;
|
|
2628
|
+
sessionStorage.setItem(composerStorageKey(engine), JSON.stringify(snapshot));
|
|
2629
|
+
} catch (error) {
|
|
2630
|
+
if (!composerStorageFailures.has(engine)) {
|
|
2631
|
+
composerStorageFailures.add(engine);
|
|
2632
|
+
engine.reportDiagnostic({
|
|
2633
|
+
level: "warn",
|
|
2634
|
+
message: `The current message draft could not be saved for reload recovery: ${String(error?.message ?? error)}`,
|
|
2635
|
+
remedy: "Keep this tab open until the message is sent, or copy the draft before reloading."
|
|
2636
|
+
});
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
function getComposerSession(engine) {
|
|
2641
|
+
const existing = composerSessions.get(engine);
|
|
2642
|
+
if (existing !== void 0) return existing;
|
|
2643
|
+
let snapshot = readComposerSession(engine);
|
|
2644
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
2645
|
+
const store = {
|
|
2646
|
+
getSnapshot: () => snapshot,
|
|
2647
|
+
subscribe: (listener) => {
|
|
2648
|
+
listeners.add(listener);
|
|
2649
|
+
return () => listeners.delete(listener);
|
|
2650
|
+
},
|
|
2651
|
+
update: (change) => {
|
|
2652
|
+
snapshot = change(snapshot);
|
|
2653
|
+
writeComposerSession(engine, snapshot);
|
|
2654
|
+
listeners.forEach((listener) => listener());
|
|
2655
|
+
}
|
|
2656
|
+
};
|
|
2657
|
+
composerSessions.set(engine, store);
|
|
2658
|
+
return store;
|
|
2659
|
+
}
|
|
2526
2660
|
function useComposer(conversationId) {
|
|
2527
2661
|
const host = useMessagingHost();
|
|
2528
|
-
const
|
|
2529
|
-
const
|
|
2530
|
-
|
|
2662
|
+
const session = host === null ? null : getComposerSession(host.engine);
|
|
2663
|
+
const composer = useSyncExternalStore2(
|
|
2664
|
+
session?.subscribe ?? subscribeToNothing,
|
|
2665
|
+
session?.getSnapshot ?? emptyComposerSnapshot,
|
|
2666
|
+
emptyComposerSnapshot
|
|
2667
|
+
);
|
|
2668
|
+
const replyTo = conversationId === null ? null : composer.replies[conversationId] ?? null;
|
|
2669
|
+
const additions = conversationId === null ? [] : composer.additions[conversationId] ?? [];
|
|
2670
|
+
const setReplyTo = (message) => {
|
|
2671
|
+
if (conversationId !== null) session?.update((current) => ({
|
|
2672
|
+
...current,
|
|
2673
|
+
replies: { ...current.replies, [conversationId]: message }
|
|
2674
|
+
}));
|
|
2675
|
+
};
|
|
2676
|
+
const value = conversationId === null ? "" : composer.drafts[conversationId] ?? "";
|
|
2531
2677
|
const typing = useTyping(
|
|
2532
2678
|
{
|
|
2533
2679
|
topic: conversationId === null ? "" : conversationTopic(conversationId),
|
|
@@ -2538,26 +2684,57 @@ function useComposer(conversationId) {
|
|
|
2538
2684
|
const setValue = useCallback(
|
|
2539
2685
|
(next) => {
|
|
2540
2686
|
if (conversationId === null) return;
|
|
2541
|
-
|
|
2687
|
+
session?.update((current) => ({
|
|
2688
|
+
...current,
|
|
2689
|
+
drafts: { ...current.drafts, [conversationId]: next }
|
|
2690
|
+
}));
|
|
2542
2691
|
},
|
|
2543
|
-
[conversationId]
|
|
2692
|
+
[conversationId, session]
|
|
2544
2693
|
);
|
|
2545
2694
|
return {
|
|
2546
2695
|
value,
|
|
2547
2696
|
setValue,
|
|
2548
|
-
|
|
2697
|
+
additions,
|
|
2698
|
+
add: (item) => {
|
|
2699
|
+
if (conversationId !== null) session?.update((current) => ({
|
|
2700
|
+
...current,
|
|
2701
|
+
additions: {
|
|
2702
|
+
...current.additions,
|
|
2703
|
+
[conversationId]: [
|
|
2704
|
+
...(current.additions[conversationId] ?? []).filter((existing) => existing.id !== item.id),
|
|
2705
|
+
item
|
|
2706
|
+
]
|
|
2707
|
+
}
|
|
2708
|
+
}));
|
|
2709
|
+
},
|
|
2710
|
+
removeAddition: (id) => {
|
|
2711
|
+
if (conversationId !== null) session?.update((current) => ({
|
|
2712
|
+
...current,
|
|
2713
|
+
additions: {
|
|
2714
|
+
...current.additions,
|
|
2715
|
+
[conversationId]: (current.additions[conversationId] ?? []).filter((item) => item.id !== id)
|
|
2716
|
+
}
|
|
2717
|
+
}));
|
|
2718
|
+
},
|
|
2719
|
+
canSend: (value.trim().length > 0 || additions.length > 0) && conversationId !== null && host !== null,
|
|
2549
2720
|
send: () => {
|
|
2550
|
-
if (host === null || conversationId === null) return;
|
|
2551
|
-
const content = value.trim();
|
|
2552
|
-
|
|
2721
|
+
if (host === null || conversationId === null || session === null) return;
|
|
2722
|
+
const content = [value.trim(), ...additions.map((item) => item.content ?? "")].filter(Boolean).join("\n\n");
|
|
2723
|
+
const attachments = additions.flatMap((item) => item.attachment ? [item.attachment] : []);
|
|
2724
|
+
if (content.length === 0 && attachments.length === 0) return;
|
|
2553
2725
|
const draft = {
|
|
2554
2726
|
conversationId,
|
|
2555
2727
|
content,
|
|
2728
|
+
attachments,
|
|
2556
2729
|
...replyTo !== null ? { replyToId: replyTo.id } : {}
|
|
2557
2730
|
};
|
|
2558
2731
|
host.engine.send(draft);
|
|
2559
|
-
|
|
2560
|
-
|
|
2732
|
+
session.update((current) => ({
|
|
2733
|
+
...current,
|
|
2734
|
+
drafts: { ...current.drafts, [conversationId]: "" },
|
|
2735
|
+
replies: { ...current.replies, [conversationId]: null },
|
|
2736
|
+
additions: { ...current.additions, [conversationId]: [] }
|
|
2737
|
+
}));
|
|
2561
2738
|
typing.stopTyping();
|
|
2562
2739
|
},
|
|
2563
2740
|
onKeystroke: typing.onKeystroke,
|
|
@@ -3073,6 +3250,7 @@ function ConversationList(props) {
|
|
|
3073
3250
|
} = useConversations();
|
|
3074
3251
|
const RowChrome = useMessagingHost()?.wrapConversationRow ?? null;
|
|
3075
3252
|
const [query, setQuery] = useState2("");
|
|
3253
|
+
const favoritePageRequestCount = useRef3(null);
|
|
3076
3254
|
const showingArchive = archiveFilter === "archived";
|
|
3077
3255
|
const archiveReveal = useMemo3(() => {
|
|
3078
3256
|
if (showingArchive) {
|
|
@@ -3098,6 +3276,51 @@ function ConversationList(props) {
|
|
|
3098
3276
|
(item) => item.displayName.toLowerCase().includes(needle) || (item.lastMessageContent ?? "").toLowerCase().includes(needle)
|
|
3099
3277
|
);
|
|
3100
3278
|
}, [conversations, query]);
|
|
3279
|
+
const loadNextPage = () => {
|
|
3280
|
+
if (favoritePageRequestCount.current === conversations.length) return;
|
|
3281
|
+
favoritePageRequestCount.current = conversations.length;
|
|
3282
|
+
loadMore();
|
|
3283
|
+
};
|
|
3284
|
+
const hasUnloadedFavorites = (props.pinnedConversationIds ?? []).some(
|
|
3285
|
+
(id) => !conversations.some((item) => String(item.conversation.id) === id)
|
|
3286
|
+
);
|
|
3287
|
+
useEffect3(() => {
|
|
3288
|
+
if (!hasUnloadedFavorites || !hasMore || isInitialLoading || loadError !== null || favoritePageRequestCount.current === conversations.length) {
|
|
3289
|
+
return;
|
|
3290
|
+
}
|
|
3291
|
+
loadNextPage();
|
|
3292
|
+
}, [
|
|
3293
|
+
conversations,
|
|
3294
|
+
hasMore,
|
|
3295
|
+
hasUnloadedFavorites,
|
|
3296
|
+
isInitialLoading,
|
|
3297
|
+
loadError,
|
|
3298
|
+
loadMore,
|
|
3299
|
+
loadNextPage
|
|
3300
|
+
]);
|
|
3301
|
+
const { favoriteItems, otherPinnedItems, unpinnedItems } = useMemo3(() => {
|
|
3302
|
+
const visibleById = new Map(
|
|
3303
|
+
visible.map((item) => [String(item.conversation.id), item])
|
|
3304
|
+
);
|
|
3305
|
+
const pinnedItems = (props.pinnedConversationIds ?? []).map((id) => visibleById.get(id)).filter((item) => item !== void 0);
|
|
3306
|
+
const uniquePinnedItems = Array.from(
|
|
3307
|
+
new Map(pinnedItems.map((item) => [item.conversation.id, item])).values()
|
|
3308
|
+
).sort((left, right) => {
|
|
3309
|
+
const byRecency = Date.parse(right.sortAt) - Date.parse(left.sortAt);
|
|
3310
|
+
return Number.isNaN(byRecency) || byRecency === 0 ? String(left.conversation.id).localeCompare(String(right.conversation.id)) : byRecency;
|
|
3311
|
+
});
|
|
3312
|
+
const pinnedIds = new Set(uniquePinnedItems.map((item) => item.conversation.id));
|
|
3313
|
+
return {
|
|
3314
|
+
favoriteItems: uniquePinnedItems.slice(0, 3),
|
|
3315
|
+
otherPinnedItems: uniquePinnedItems.slice(3),
|
|
3316
|
+
unpinnedItems: visible.filter((item) => !pinnedIds.has(item.conversation.id))
|
|
3317
|
+
};
|
|
3318
|
+
}, [visible, props.pinnedConversationIds]);
|
|
3319
|
+
const selectItem = (item) => {
|
|
3320
|
+
select(item.conversation.id);
|
|
3321
|
+
props.onSelect?.(item.conversation.id);
|
|
3322
|
+
};
|
|
3323
|
+
const wrapRow = (item, row) => RowChrome !== null ? /* @__PURE__ */ jsx4(RowChrome, { conversation: item, children: row }) : row;
|
|
3101
3324
|
return /* @__PURE__ */ jsxs2("div", { className: `mx-msg__list${props.className !== void 0 ? ` ${props.className}` : ""}`, children: [
|
|
3102
3325
|
/* @__PURE__ */ jsxs2("div", { className: "mx-msg__search", children: [
|
|
3103
3326
|
/* @__PURE__ */ jsx4(SearchIcon, { style: { color: "var(--mx-msg-text-faint)" } }),
|
|
@@ -3153,33 +3376,67 @@ function ConversationList(props) {
|
|
|
3153
3376
|
title: query.length > 0 ? "No matches" : showingArchive ? "No archived conversations" : "No conversations yet",
|
|
3154
3377
|
body: query.length > 0 ? "Try a different name or word." : showingArchive ? "Archiving a conversation moves it here." : "Start one and it will appear here."
|
|
3155
3378
|
}
|
|
3156
|
-
) : /* @__PURE__ */
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
props.onSelect?.(item.conversation.id);
|
|
3379
|
+
) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
3380
|
+
favoriteItems.length > 0 ? /* @__PURE__ */ jsx4("ul", { className: "mx-msg__favorites", "aria-label": "Favorite conversations", children: favoriteItems.map((item) => {
|
|
3381
|
+
const row = /* @__PURE__ */ jsx4(
|
|
3382
|
+
ConversationFavorite,
|
|
3383
|
+
{
|
|
3384
|
+
summary: item,
|
|
3385
|
+
isActive: item.conversation.id === activeConversationId,
|
|
3386
|
+
onSelect: () => selectItem(item)
|
|
3165
3387
|
}
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3388
|
+
);
|
|
3389
|
+
return /* @__PURE__ */ jsx4("li", { children: wrapRow(item, row) }, item.conversation.id);
|
|
3390
|
+
}) }) : null,
|
|
3391
|
+
/* @__PURE__ */ jsx4("ul", { className: "mx-msg__rows", children: [...otherPinnedItems, ...unpinnedItems].map((item) => {
|
|
3392
|
+
const row = /* @__PURE__ */ jsx4(
|
|
3393
|
+
ConversationRow,
|
|
3394
|
+
{
|
|
3395
|
+
summary: item,
|
|
3396
|
+
isActive: item.conversation.id === activeConversationId,
|
|
3397
|
+
onSelect: () => selectItem(item)
|
|
3398
|
+
}
|
|
3399
|
+
);
|
|
3400
|
+
return /* @__PURE__ */ jsx4("li", { children: wrapRow(item, row) }, item.conversation.id);
|
|
3401
|
+
}) })
|
|
3402
|
+
] }),
|
|
3170
3403
|
hasMore && !isInitialLoading ? /* @__PURE__ */ jsx4(
|
|
3171
3404
|
"button",
|
|
3172
3405
|
{
|
|
3173
3406
|
type: "button",
|
|
3174
3407
|
className: "mx-msg__chip",
|
|
3175
3408
|
style: { margin: "8px auto", display: "block" },
|
|
3176
|
-
onClick:
|
|
3409
|
+
onClick: loadNextPage,
|
|
3177
3410
|
children: "Load older conversations"
|
|
3178
3411
|
}
|
|
3179
3412
|
) : null
|
|
3180
3413
|
] })
|
|
3181
3414
|
] });
|
|
3182
3415
|
}
|
|
3416
|
+
function ConversationFavorite(props) {
|
|
3417
|
+
const { summary } = props;
|
|
3418
|
+
return /* @__PURE__ */ jsxs2(
|
|
3419
|
+
"button",
|
|
3420
|
+
{
|
|
3421
|
+
type: "button",
|
|
3422
|
+
className: "mx-msg__favorite",
|
|
3423
|
+
"aria-current": props.isActive,
|
|
3424
|
+
"aria-label": `Open favorite conversation with ${summary.displayName}`,
|
|
3425
|
+
onClick: props.onSelect,
|
|
3426
|
+
children: [
|
|
3427
|
+
/* @__PURE__ */ jsx4(
|
|
3428
|
+
Avatar,
|
|
3429
|
+
{
|
|
3430
|
+
name: summary.displayName,
|
|
3431
|
+
imageUrl: summary.displayImageUrl,
|
|
3432
|
+
seed: summary.conversation.id
|
|
3433
|
+
}
|
|
3434
|
+
),
|
|
3435
|
+
/* @__PURE__ */ jsx4("span", { className: "mx-msg__favorite-name", children: summary.displayName })
|
|
3436
|
+
]
|
|
3437
|
+
}
|
|
3438
|
+
);
|
|
3439
|
+
}
|
|
3183
3440
|
function ConversationRow(props) {
|
|
3184
3441
|
const { summary } = props;
|
|
3185
3442
|
return /* @__PURE__ */ jsxs2(
|
|
@@ -3354,6 +3611,8 @@ function ConversationView(props) {
|
|
|
3354
3611
|
/* @__PURE__ */ jsx4(
|
|
3355
3612
|
MessageGroupView,
|
|
3356
3613
|
{
|
|
3614
|
+
allMessages: messages,
|
|
3615
|
+
showAuthor: conversation.summary?.conversation.type !== "direct",
|
|
3357
3616
|
messages: group.messages,
|
|
3358
3617
|
actor,
|
|
3359
3618
|
isMine,
|
|
@@ -3385,37 +3644,41 @@ function MessageGroupView(props) {
|
|
|
3385
3644
|
const first = props.messages[0];
|
|
3386
3645
|
if (first === void 0) return null;
|
|
3387
3646
|
const actor = props.actor;
|
|
3388
|
-
return /* @__PURE__ */ jsxs2(
|
|
3389
|
-
/* @__PURE__ */ jsx4(
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
imageUrl: actor.avatarUrl,
|
|
3394
|
-
seed: actor.isAgent ? `agent:${actor.displayName}` : actor.principalUserId,
|
|
3395
|
-
small: true
|
|
3396
|
-
}
|
|
3397
|
-
),
|
|
3398
|
-
/* @__PURE__ */ jsxs2("div", { className: "mx-msg__group-body", children: [
|
|
3399
|
-
!props.isMine || actor.isAgent ? /* @__PURE__ */ jsxs2("div", { className: "mx-msg__author", children: [
|
|
3400
|
-
actor.displayName,
|
|
3401
|
-
actor.isAgent ? /* @__PURE__ */ jsx4(AgentTag, {}) : null,
|
|
3402
|
-
actor.onBehalfOfName !== null ? /* @__PURE__ */ jsxs2("span", { style: { fontWeight: 400, color: "var(--mx-msg-text-faint)" }, children: [
|
|
3403
|
-
"via ",
|
|
3404
|
-
actor.onBehalfOfName
|
|
3405
|
-
] }) : null
|
|
3406
|
-
] }) : null,
|
|
3407
|
-
props.messages.map((message, index) => /* @__PURE__ */ jsx4(
|
|
3408
|
-
MessageBubble,
|
|
3647
|
+
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
3648
|
+
/* @__PURE__ */ jsx4("div", { className: "mx-msg__group-time", children: formatMessageTime(first.createdAt) }),
|
|
3649
|
+
/* @__PURE__ */ jsxs2("div", { className: `mx-msg__group${props.isMine ? " mx-msg__group--mine" : ""}`, children: [
|
|
3650
|
+
props.showAuthor || actor.isAgent ? /* @__PURE__ */ jsx4(
|
|
3651
|
+
Avatar,
|
|
3409
3652
|
{
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3653
|
+
name: actor.displayName,
|
|
3654
|
+
imageUrl: actor.avatarUrl,
|
|
3655
|
+
seed: actor.isAgent ? `agent:${actor.displayName}` : actor.principalUserId,
|
|
3656
|
+
small: true
|
|
3657
|
+
}
|
|
3658
|
+
) : null,
|
|
3659
|
+
/* @__PURE__ */ jsxs2("div", { className: "mx-msg__group-body", children: [
|
|
3660
|
+
props.showAuthor && !props.isMine || actor.isAgent ? /* @__PURE__ */ jsxs2("div", { className: "mx-msg__author", children: [
|
|
3661
|
+
actor.displayName,
|
|
3662
|
+
actor.isAgent ? /* @__PURE__ */ jsx4(AgentTag, {}) : null,
|
|
3663
|
+
actor.onBehalfOfName !== null ? /* @__PURE__ */ jsxs2("span", { style: { fontWeight: 400, color: "var(--mx-msg-text-faint)" }, children: [
|
|
3664
|
+
"via ",
|
|
3665
|
+
actor.onBehalfOfName
|
|
3666
|
+
] }) : null
|
|
3667
|
+
] }) : null,
|
|
3668
|
+
props.messages.map((message, index) => /* @__PURE__ */ jsx4(
|
|
3669
|
+
MessageBubble,
|
|
3670
|
+
{
|
|
3671
|
+
message,
|
|
3672
|
+
replyTo: props.allMessages.find((parent) => parent.id === message.replyToId),
|
|
3673
|
+
isMine: props.isMine,
|
|
3674
|
+
isLast: index === props.messages.length - 1,
|
|
3675
|
+
onRetry: props.onRetry,
|
|
3676
|
+
onReply: props.onReply,
|
|
3677
|
+
failedEntryId: message.clientMessageId !== null ? props.failedEntryIdByClientId.get(message.clientMessageId) ?? null : null
|
|
3678
|
+
},
|
|
3679
|
+
message.id
|
|
3680
|
+
))
|
|
3681
|
+
] })
|
|
3419
3682
|
] })
|
|
3420
3683
|
] });
|
|
3421
3684
|
}
|
|
@@ -3436,7 +3699,12 @@ function MessageBubble(props) {
|
|
|
3436
3699
|
message.deliveryState === "failed" ? "mx-msg__bubble--failed" : ""
|
|
3437
3700
|
].filter(Boolean).join(" ");
|
|
3438
3701
|
const bubble = /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
3439
|
-
/* @__PURE__ */ jsxs2("div", { className: classes, children: [
|
|
3702
|
+
/* @__PURE__ */ jsxs2("div", { className: classes, title: formatMessageTime(message.createdAt), children: [
|
|
3703
|
+
message.replyToId !== null ? /* @__PURE__ */ jsx4("blockquote", { className: "mx-msg__quoted-reply", children: props.replyTo ? props.replyTo.deletedAt ? "Message deleted" : summarizeText(props.replyTo.content, 180) || "Attachment" : "Earlier message" }) : null,
|
|
3704
|
+
message.attachments.map((attachment) => {
|
|
3705
|
+
const RenderAttachment = props.renderAttachment ?? host?.renderAttachment;
|
|
3706
|
+
return RenderAttachment ? /* @__PURE__ */ jsx4(RenderAttachment, { attachment }, attachment.fileId) : /* @__PURE__ */ jsx4(ReferenceCard, { reference: { entityType: "file", entityId: attachment.fileId, label: attachment.fileName }, onOpen: host?.openReference ?? null }, attachment.fileId);
|
|
3707
|
+
}),
|
|
3440
3708
|
splitText(message.content).map(
|
|
3441
3709
|
(segment, index) => segment.type === "text" ? /* @__PURE__ */ jsx4("div", { className: "mx-msg__markdown", children: /* @__PURE__ */ jsx4(ReactMarkdown, { remarkPlugins: [remarkGfm, remarkBreaks], children: segment.value }) }, index) : segment.type === "fence" ? HostFence !== null ? /* @__PURE__ */ jsx4(HostFence, { body: segment.body }, `fence:${index}`) : /* @__PURE__ */ jsx4(UnreadableReference, {}, `fence:${index}`) : HostReference !== null ? /* @__PURE__ */ jsx4(
|
|
3442
3710
|
HostReference,
|
|
@@ -3476,7 +3744,7 @@ function MessageBubble(props) {
|
|
|
3476
3744
|
{
|
|
3477
3745
|
className: `mx-msg__meta${message.deliveryState === "failed" ? " mx-msg__meta--failed" : ""}`,
|
|
3478
3746
|
children: [
|
|
3479
|
-
props.isLast ? formatMessageTime(message.createdAt) : null,
|
|
3747
|
+
/* @__PURE__ */ jsx4("span", { className: "mx-msg__message-time", children: props.isLast ? formatMessageTime(message.createdAt) : null }),
|
|
3480
3748
|
message.editedAt !== null ? " \xB7 edited" : null,
|
|
3481
3749
|
isMine ? /* @__PURE__ */ jsx4(DeliveryTick, { state: message.deliveryState }) : null,
|
|
3482
3750
|
message.deliveryState === "failed" && props.failedEntryId != null && props.onRetry !== void 0 ? /* @__PURE__ */ jsx4(
|
|
@@ -3571,6 +3839,9 @@ function ComposerView(props) {
|
|
|
3571
3839
|
)
|
|
3572
3840
|
] }) : null,
|
|
3573
3841
|
props.renderInput !== void 0 ? props.renderInput({
|
|
3842
|
+
additions: composer.additions,
|
|
3843
|
+
add: composer.add,
|
|
3844
|
+
removeAddition: composer.removeAddition,
|
|
3574
3845
|
value: composer.value,
|
|
3575
3846
|
disabled: props.disabled,
|
|
3576
3847
|
canSend: composer.canSend,
|