@ai-matrx/messaging 0.10.5 → 0.11.1
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 +57 -0
- package/README.md +33 -0
- package/dist/index.cjs +98 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +101 -1
- package/dist/index.d.ts +101 -1
- package/dist/index.js +98 -11
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +145 -14
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +126 -1
- package/dist/react.d.ts +126 -1
- package/dist/react.js +145 -14
- package/dist/react.js.map +1 -1
- package/dist/styles.css +7 -0
- package/package.json +3 -3
package/dist/react.cjs
CHANGED
|
@@ -34,6 +34,7 @@ __export(react_exports, {
|
|
|
34
34
|
ConversationList: () => ConversationList,
|
|
35
35
|
ConversationSkeleton: () => ConversationSkeleton,
|
|
36
36
|
ConversationView: () => ConversationView,
|
|
37
|
+
DEFAULT_MESSAGING_ARCHIVE_FILTER: () => DEFAULT_MESSAGING_ARCHIVE_FILTER,
|
|
37
38
|
DeliveryTick: () => DeliveryTick,
|
|
38
39
|
DoubleCheckIcon: () => DoubleCheckIcon,
|
|
39
40
|
EmptyState: () => EmptyState,
|
|
@@ -96,6 +97,7 @@ __export(react_exports, {
|
|
|
96
97
|
resolveActor: () => resolveActor,
|
|
97
98
|
splitText: () => splitText,
|
|
98
99
|
summarizeText: () => summarizeText,
|
|
100
|
+
toMessagingArchiveFilter: () => toMessagingArchiveFilter,
|
|
99
101
|
unreadCutoff: () => unreadCutoff,
|
|
100
102
|
useComposer: () => useComposer,
|
|
101
103
|
useConversation: () => useConversation,
|
|
@@ -914,6 +916,17 @@ function projectConversationSummary(row, viewerId, fallbackOrganizationId) {
|
|
|
914
916
|
};
|
|
915
917
|
}
|
|
916
918
|
|
|
919
|
+
// src/core/types.ts
|
|
920
|
+
var asConversationId = (value) => value;
|
|
921
|
+
var asMessageId = (value) => value;
|
|
922
|
+
var asUserId = (value) => value;
|
|
923
|
+
var asOrganizationId = (value) => value;
|
|
924
|
+
var asClientMessageId = (value) => value;
|
|
925
|
+
var DEFAULT_MESSAGING_ARCHIVE_FILTER = "active";
|
|
926
|
+
function toMessagingArchiveFilter(value, fallback = DEFAULT_MESSAGING_ARCHIVE_FILTER) {
|
|
927
|
+
return value === "active" || value === "archived" || value === "all" ? value : fallback;
|
|
928
|
+
}
|
|
929
|
+
|
|
917
930
|
// src/core/store.ts
|
|
918
931
|
function timeOf(message) {
|
|
919
932
|
const stamp = message.editedAt ?? message.createdAt;
|
|
@@ -944,6 +957,8 @@ function createMessagingStore() {
|
|
|
944
957
|
let conversations = [];
|
|
945
958
|
let hasMoreConversations = false;
|
|
946
959
|
let hasLoadedConversations = false;
|
|
960
|
+
let archiveFilter = DEFAULT_MESSAGING_ARCHIVE_FILTER;
|
|
961
|
+
let archivedCount = null;
|
|
947
962
|
let threads = /* @__PURE__ */ new Map();
|
|
948
963
|
let activeConversationId = null;
|
|
949
964
|
const listeners = /* @__PURE__ */ new Set();
|
|
@@ -956,7 +971,9 @@ function createMessagingStore() {
|
|
|
956
971
|
hasLoadedConversations,
|
|
957
972
|
threads,
|
|
958
973
|
activeConversationId,
|
|
959
|
-
totalUnreadConversations: conversations.filter((item) => item.unreadCount > 0).length
|
|
974
|
+
totalUnreadConversations: conversations.filter((item) => item.unreadCount > 0).length,
|
|
975
|
+
archiveFilter,
|
|
976
|
+
archivedCount
|
|
960
977
|
};
|
|
961
978
|
return cached;
|
|
962
979
|
}
|
|
@@ -1003,6 +1020,18 @@ function createMessagingStore() {
|
|
|
1003
1020
|
hasLoadedConversations = true;
|
|
1004
1021
|
emit();
|
|
1005
1022
|
},
|
|
1023
|
+
setArchiveFilter(next) {
|
|
1024
|
+
if (next === archiveFilter) return;
|
|
1025
|
+
archiveFilter = next;
|
|
1026
|
+
conversations = [];
|
|
1027
|
+
hasMoreConversations = false;
|
|
1028
|
+
hasLoadedConversations = false;
|
|
1029
|
+
emit();
|
|
1030
|
+
},
|
|
1031
|
+
setArchivedCount(value) {
|
|
1032
|
+
archivedCount = value;
|
|
1033
|
+
emit();
|
|
1034
|
+
},
|
|
1006
1035
|
appendConversations(items, hasMore) {
|
|
1007
1036
|
const byId = new Map(conversations.map((item) => [item.conversation.id, item]));
|
|
1008
1037
|
items.forEach((item) => byId.set(item.conversation.id, item));
|
|
@@ -1209,11 +1238,20 @@ function createMessagingEngine(options) {
|
|
|
1209
1238
|
}
|
|
1210
1239
|
async function reloadInbox() {
|
|
1211
1240
|
if (disposed) return;
|
|
1212
|
-
const page = await repository.listConversations({
|
|
1241
|
+
const page = await repository.listConversations({
|
|
1242
|
+
limit: conversationPageSize,
|
|
1243
|
+
archived: store.snapshot().archiveFilter
|
|
1244
|
+
});
|
|
1213
1245
|
if (disposed) return;
|
|
1214
1246
|
conversationCursor = page.nextCursor;
|
|
1215
1247
|
store.setConversations(page.items, page.hasMore);
|
|
1216
1248
|
}
|
|
1249
|
+
async function reloadArchivedCount() {
|
|
1250
|
+
if (disposed) return;
|
|
1251
|
+
const value = await repository.countArchivedConversations();
|
|
1252
|
+
if (disposed) return;
|
|
1253
|
+
store.setArchivedCount(value);
|
|
1254
|
+
}
|
|
1217
1255
|
async function backfillConversation(id) {
|
|
1218
1256
|
const thread = store.snapshot().threads.get(id);
|
|
1219
1257
|
const since = thread?.latestAt ?? null;
|
|
@@ -1240,7 +1278,13 @@ function createMessagingEngine(options) {
|
|
|
1240
1278
|
outbox,
|
|
1241
1279
|
identity,
|
|
1242
1280
|
async start() {
|
|
1281
|
+
if (options.archiveFilter !== void 0) {
|
|
1282
|
+
store.setArchiveFilter(options.archiveFilter);
|
|
1283
|
+
}
|
|
1243
1284
|
await reloadInbox();
|
|
1285
|
+
void reloadArchivedCount().catch(
|
|
1286
|
+
(error) => reportError(error, "refreshArchivedCount")
|
|
1287
|
+
);
|
|
1244
1288
|
if (disposed || inboxChannel !== null) return;
|
|
1245
1289
|
inboxChannel = manager.open({
|
|
1246
1290
|
topic: inboxTopic(identity.userId),
|
|
@@ -1282,12 +1326,33 @@ function createMessagingEngine(options) {
|
|
|
1282
1326
|
}
|
|
1283
1327
|
});
|
|
1284
1328
|
},
|
|
1329
|
+
async setArchiveFilter(next) {
|
|
1330
|
+
if (next === store.snapshot().archiveFilter) return;
|
|
1331
|
+
store.setArchiveFilter(next);
|
|
1332
|
+
conversationCursor = null;
|
|
1333
|
+
try {
|
|
1334
|
+
await reloadInbox();
|
|
1335
|
+
} catch (error) {
|
|
1336
|
+
reportError(error, "setArchiveFilter");
|
|
1337
|
+
}
|
|
1338
|
+
await reloadArchivedCount().catch(
|
|
1339
|
+
(error) => reportError(error, "refreshArchivedCount")
|
|
1340
|
+
);
|
|
1341
|
+
},
|
|
1342
|
+
async refreshArchivedCount() {
|
|
1343
|
+
try {
|
|
1344
|
+
await reloadArchivedCount();
|
|
1345
|
+
} catch (error) {
|
|
1346
|
+
reportError(error, "refreshArchivedCount");
|
|
1347
|
+
}
|
|
1348
|
+
},
|
|
1285
1349
|
async loadMoreConversations() {
|
|
1286
1350
|
if (conversationCursor === null) return;
|
|
1287
1351
|
try {
|
|
1288
1352
|
const page = await repository.listConversations({
|
|
1289
1353
|
limit: conversationPageSize,
|
|
1290
|
-
cursor: conversationCursor
|
|
1354
|
+
cursor: conversationCursor,
|
|
1355
|
+
archived: store.snapshot().archiveFilter
|
|
1291
1356
|
});
|
|
1292
1357
|
conversationCursor = page.nextCursor;
|
|
1293
1358
|
store.appendConversations(page.items, page.hasMore);
|
|
@@ -1551,6 +1616,7 @@ function createMessagingRepository(options) {
|
|
|
1551
1616
|
identity,
|
|
1552
1617
|
async listConversations(args = {}) {
|
|
1553
1618
|
const limit = args.limit ?? 30;
|
|
1619
|
+
const archived = args.archived ?? DEFAULT_MESSAGING_ARCHIVE_FILTER;
|
|
1554
1620
|
const operation = "listConversations";
|
|
1555
1621
|
const rows = await withSessionRetry(
|
|
1556
1622
|
operation,
|
|
@@ -1560,7 +1626,12 @@ function createMessagingRepository(options) {
|
|
|
1560
1626
|
p_user_id: identity.userId,
|
|
1561
1627
|
p_limit: limit + 1,
|
|
1562
1628
|
p_before_sort_at: args.cursor?.beforeSortAt ?? null,
|
|
1563
|
-
p_before_conversation_id: args.cursor?.beforeConversationId ?? null
|
|
1629
|
+
p_before_conversation_id: args.cursor?.beforeConversationId ?? null,
|
|
1630
|
+
// THE ARCHIVED-ITEMS LAW, SERVER-side. `get_dm_conversations_with_details`
|
|
1631
|
+
// used to hardcode `is_archived IS FALSE` with no parameter at all,
|
|
1632
|
+
// so an archived conversation was not hidden — it was unreachable.
|
|
1633
|
+
// The RPC gained `p_archived` on 2026-09-09 (register row R1).
|
|
1634
|
+
p_archived: archived
|
|
1564
1635
|
},
|
|
1565
1636
|
operation
|
|
1566
1637
|
)
|
|
@@ -1580,6 +1651,29 @@ function createMessagingRepository(options) {
|
|
|
1580
1651
|
nextCursor: hasMore && last !== void 0 ? { beforeSortAt: last.sortAt, beforeConversationId: last.conversation.id } : null
|
|
1581
1652
|
};
|
|
1582
1653
|
},
|
|
1654
|
+
async countArchivedConversations(args = {}) {
|
|
1655
|
+
const limit = args.limit ?? 100;
|
|
1656
|
+
const operation = "countArchivedConversations";
|
|
1657
|
+
const rows = await withSessionRetry(
|
|
1658
|
+
operation,
|
|
1659
|
+
() => rpc(
|
|
1660
|
+
RPCS.conversationsWithDetails,
|
|
1661
|
+
{
|
|
1662
|
+
p_user_id: identity.userId,
|
|
1663
|
+
p_limit: limit + 1,
|
|
1664
|
+
p_before_sort_at: null,
|
|
1665
|
+
p_before_conversation_id: null,
|
|
1666
|
+
p_archived: "archived"
|
|
1667
|
+
},
|
|
1668
|
+
operation
|
|
1669
|
+
)
|
|
1670
|
+
);
|
|
1671
|
+
if (rows !== null && !Array.isArray(rows)) {
|
|
1672
|
+
throw invalidResponse(operation, `${RPCS.conversationsWithDetails} did not return rows`);
|
|
1673
|
+
}
|
|
1674
|
+
const found = (rows ?? []).length;
|
|
1675
|
+
return found > limit ? { count: limit, exact: false } : { count: found, exact: true };
|
|
1676
|
+
},
|
|
1583
1677
|
async getConversation(id) {
|
|
1584
1678
|
const operation = "getConversation";
|
|
1585
1679
|
const { data, error } = await withSessionRetry(
|
|
@@ -1888,6 +1982,7 @@ function MessagingRuntime(props) {
|
|
|
1888
1982
|
onFallback: (message) => report({ level: "warn", message })
|
|
1889
1983
|
}),
|
|
1890
1984
|
onDiagnostic: report,
|
|
1985
|
+
...props.archiveFilter !== void 0 ? { archiveFilter: props.archiveFilter } : {},
|
|
1891
1986
|
onIncoming: (message) => {
|
|
1892
1987
|
const snapshot = built?.store.snapshot();
|
|
1893
1988
|
if (snapshot === void 0) return;
|
|
@@ -2118,6 +2213,11 @@ function useConversations() {
|
|
|
2118
2213
|
},
|
|
2119
2214
|
select,
|
|
2120
2215
|
activeConversationId: snapshot?.activeConversationId ?? null,
|
|
2216
|
+
archiveFilter: snapshot?.archiveFilter ?? DEFAULT_MESSAGING_ARCHIVE_FILTER,
|
|
2217
|
+
setArchiveFilter: (next) => {
|
|
2218
|
+
void host?.engine.setArchiveFilter(next);
|
|
2219
|
+
},
|
|
2220
|
+
archivedCount: snapshot?.archivedCount ?? null,
|
|
2121
2221
|
startDirect: async (otherUserId) => {
|
|
2122
2222
|
if (host === null) {
|
|
2123
2223
|
throw new Error("[@ai-matrx/messaging] startDirect called before the host was ready.");
|
|
@@ -2689,9 +2789,37 @@ var AI_LABELS = {
|
|
|
2689
2789
|
draftReply: "Draft a reply"
|
|
2690
2790
|
};
|
|
2691
2791
|
function ConversationList(props) {
|
|
2692
|
-
const {
|
|
2792
|
+
const {
|
|
2793
|
+
conversations,
|
|
2794
|
+
hasMore,
|
|
2795
|
+
isInitialLoading,
|
|
2796
|
+
loadMore,
|
|
2797
|
+
select,
|
|
2798
|
+
activeConversationId,
|
|
2799
|
+
archiveFilter,
|
|
2800
|
+
setArchiveFilter,
|
|
2801
|
+
archivedCount
|
|
2802
|
+
} = useConversations();
|
|
2693
2803
|
const RowChrome = useMessagingHost()?.wrapConversationRow ?? null;
|
|
2694
2804
|
const [query, setQuery] = (0, import_react5.useState)("");
|
|
2805
|
+
const showingArchive = archiveFilter === "archived";
|
|
2806
|
+
const archiveReveal = (0, import_react5.useMemo)(() => {
|
|
2807
|
+
if (showingArchive) {
|
|
2808
|
+
return {
|
|
2809
|
+
next: "active",
|
|
2810
|
+
label: "\u2190 Back to active conversations",
|
|
2811
|
+
ariaLabel: "Hide archived conversations"
|
|
2812
|
+
};
|
|
2813
|
+
}
|
|
2814
|
+
if (archivedCount === null) return null;
|
|
2815
|
+
if (archivedCount.count === 0) return null;
|
|
2816
|
+
const printed = archivedCount.exact ? `${archivedCount.count}` : `${archivedCount.count}+`;
|
|
2817
|
+
return {
|
|
2818
|
+
next: "archived",
|
|
2819
|
+
label: `Archived (${printed})`,
|
|
2820
|
+
ariaLabel: "Show archived conversations"
|
|
2821
|
+
};
|
|
2822
|
+
}, [showingArchive, archivedCount]);
|
|
2695
2823
|
const visible = (0, import_react5.useMemo)(() => {
|
|
2696
2824
|
const needle = query.trim().toLowerCase();
|
|
2697
2825
|
if (needle.length === 0) return conversations;
|
|
@@ -2724,12 +2852,22 @@ function ConversationList(props) {
|
|
|
2724
2852
|
}
|
|
2725
2853
|
) : null
|
|
2726
2854
|
] }),
|
|
2855
|
+
archiveReveal !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-msg__list-archive", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2856
|
+
"button",
|
|
2857
|
+
{
|
|
2858
|
+
type: "button",
|
|
2859
|
+
className: "mx-msg__chip",
|
|
2860
|
+
onClick: () => setArchiveFilter(archiveReveal.next),
|
|
2861
|
+
"aria-label": archiveReveal.ariaLabel,
|
|
2862
|
+
children: archiveReveal.label
|
|
2863
|
+
}
|
|
2864
|
+
) }) : null,
|
|
2727
2865
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-msg__scroll", children: [
|
|
2728
2866
|
isInitialLoading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ConversationSkeleton, {}) : visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2729
2867
|
EmptyState,
|
|
2730
2868
|
{
|
|
2731
|
-
title: query.length > 0 ? "No matches" : "No conversations yet",
|
|
2732
|
-
body: query.length > 0 ? "Try a different name or word." : "Start one and it will appear here."
|
|
2869
|
+
title: query.length > 0 ? "No matches" : showingArchive ? "No archived conversations" : "No conversations yet",
|
|
2870
|
+
body: query.length > 0 ? "Try a different name or word." : showingArchive ? "Archiving a conversation moves it here." : "Start one and it will appear here."
|
|
2733
2871
|
}
|
|
2734
2872
|
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "mx-msg__rows", children: visible.map((item) => {
|
|
2735
2873
|
const row = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
@@ -3224,11 +3362,4 @@ function MessagingInbox(props) {
|
|
|
3224
3362
|
}
|
|
3225
3363
|
);
|
|
3226
3364
|
}
|
|
3227
|
-
|
|
3228
|
-
// src/core/types.ts
|
|
3229
|
-
var asConversationId = (value) => value;
|
|
3230
|
-
var asMessageId = (value) => value;
|
|
3231
|
-
var asUserId = (value) => value;
|
|
3232
|
-
var asOrganizationId = (value) => value;
|
|
3233
|
-
var asClientMessageId = (value) => value;
|
|
3234
3365
|
//# sourceMappingURL=react.cjs.map
|