@ai-matrx/messaging 0.1.0 → 0.1.2
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 +58 -1
- package/dist/index.cjs +27 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +27 -14
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +44 -19
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +16 -0
- package/dist/react.d.ts +16 -0
- package/dist/react.js +44 -19
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
package/dist/react.cjs
CHANGED
|
@@ -1062,6 +1062,29 @@ function createMessagingStore() {
|
|
|
1062
1062
|
});
|
|
1063
1063
|
emit();
|
|
1064
1064
|
},
|
|
1065
|
+
applyLastMessage(message, args = {}) {
|
|
1066
|
+
const existing = conversations.find(
|
|
1067
|
+
(item) => item.conversation.id === message.conversationId
|
|
1068
|
+
);
|
|
1069
|
+
if (existing === void 0) return;
|
|
1070
|
+
if (message.deliveryState === "sending" || message.deletedAt !== null) return;
|
|
1071
|
+
if (existing.lastMessageAt !== null && message.createdAt < existing.lastMessageAt) return;
|
|
1072
|
+
const isActive = activeConversationId === message.conversationId;
|
|
1073
|
+
const shouldCount = args.incrementUnread === true && !isActive;
|
|
1074
|
+
conversations = normalizeConversations(
|
|
1075
|
+
conversations.map(
|
|
1076
|
+
(item) => item.conversation.id === message.conversationId ? {
|
|
1077
|
+
...item,
|
|
1078
|
+
lastMessageContent: message.content,
|
|
1079
|
+
lastMessageSenderId: message.senderId,
|
|
1080
|
+
lastMessageAt: message.createdAt,
|
|
1081
|
+
sortAt: message.createdAt,
|
|
1082
|
+
unreadCount: shouldCount ? item.unreadCount + 1 : item.unreadCount
|
|
1083
|
+
} : item
|
|
1084
|
+
)
|
|
1085
|
+
);
|
|
1086
|
+
emit();
|
|
1087
|
+
},
|
|
1065
1088
|
markConversationRead(id) {
|
|
1066
1089
|
conversations = conversations.map(
|
|
1067
1090
|
(item) => item.conversation.id === id ? { ...item, unreadCount: 0 } : item
|
|
@@ -1132,7 +1155,7 @@ function createMessagingEngine(options) {
|
|
|
1132
1155
|
onSent: (entry, message) => {
|
|
1133
1156
|
store.ingest(message);
|
|
1134
1157
|
broadcastMessage(message);
|
|
1135
|
-
|
|
1158
|
+
store.applyLastMessage(message);
|
|
1136
1159
|
void entry;
|
|
1137
1160
|
},
|
|
1138
1161
|
onChange: (entries) => {
|
|
@@ -1158,15 +1181,6 @@ function createMessagingEngine(options) {
|
|
|
1158
1181
|
function broadcastMessage(message) {
|
|
1159
1182
|
openChannels.get(message.conversationId)?.send(MESSAGING_EVENTS.message, message);
|
|
1160
1183
|
}
|
|
1161
|
-
async function refreshConversationRow(id) {
|
|
1162
|
-
try {
|
|
1163
|
-
const page = await repository.listConversations({ limit: conversationPageSize });
|
|
1164
|
-
const row = page.items.find((item) => item.conversation.id === id);
|
|
1165
|
-
if (row !== void 0) store.upsertConversation(row);
|
|
1166
|
-
} catch (error) {
|
|
1167
|
-
reportError(error, "refreshConversationRow");
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
1184
|
async function reloadInbox() {
|
|
1171
1185
|
const page = await repository.listConversations({ limit: conversationPageSize });
|
|
1172
1186
|
conversationCursor = page.nextCursor;
|
|
@@ -1217,10 +1231,9 @@ function createMessagingEngine(options) {
|
|
|
1217
1231
|
return;
|
|
1218
1232
|
}
|
|
1219
1233
|
store.ingest(message);
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
void refreshConversationRow(message.conversationId);
|
|
1234
|
+
const isMine = message.senderId === identity.userId;
|
|
1235
|
+
store.applyLastMessage(message, { incrementUnread: !isMine });
|
|
1236
|
+
if (!isMine) options.onIncoming?.(message);
|
|
1224
1237
|
}
|
|
1225
1238
|
},
|
|
1226
1239
|
{
|
|
@@ -2112,7 +2125,12 @@ function useTypists(conversationId, participants) {
|
|
|
2112
2125
|
const typing = (0, import_react4.useTyping)(
|
|
2113
2126
|
{
|
|
2114
2127
|
topic: conversationId === null ? "" : conversationTopic(conversationId),
|
|
2115
|
-
identity: { userId: host?.identity.userId ?? "" }
|
|
2128
|
+
identity: { userId: host?.identity.userId ?? "" },
|
|
2129
|
+
// READ-ONLY. This label and `useComposer` sit on the SAME topic, which is
|
|
2130
|
+
// one channel carrying ONE presence entry per key — so exactly one of
|
|
2131
|
+
// them publishes, and it is the composer that actually knows whether this
|
|
2132
|
+
// user is typing. Publishing here would overwrite that on every heartbeat.
|
|
2133
|
+
publish: false
|
|
2116
2134
|
},
|
|
2117
2135
|
{ enabled: conversationId !== null && host !== null }
|
|
2118
2136
|
);
|
|
@@ -2139,7 +2157,10 @@ function useOnlineUserIds(conversationId) {
|
|
|
2139
2157
|
const presence = (0, import_react4.usePresence)(
|
|
2140
2158
|
{
|
|
2141
2159
|
topic: conversationId === null ? "" : conversationTopic(conversationId),
|
|
2142
|
-
|
|
2160
|
+
// READ-ONLY, for the same reason: `useComposer`'s typing presence already
|
|
2161
|
+
// puts this user in the roster under this key with their `userId`, and a
|
|
2162
|
+
// second publisher on one entry just fights it.
|
|
2163
|
+
presence: { publish: false, state: { userId: host?.identity.userId ?? "" } }
|
|
2143
2164
|
},
|
|
2144
2165
|
{ enabled: conversationId !== null && host !== null }
|
|
2145
2166
|
);
|
|
@@ -2220,7 +2241,7 @@ function useMessagingAi(conversationId) {
|
|
|
2220
2241
|
}
|
|
2221
2242
|
function useMessageAction(message) {
|
|
2222
2243
|
const host = useRequiredMessagingHost();
|
|
2223
|
-
const action = message.action;
|
|
2244
|
+
const action = message.action ?? null;
|
|
2224
2245
|
const [receipt, setReceipt] = (0, import_react3.useState)(
|
|
2225
2246
|
() => action === null ? null : host.actions.receiptFor(action.kind, message.id, host.identity.userId)
|
|
2226
2247
|
);
|
|
@@ -2752,7 +2773,7 @@ function ConversationView(props) {
|
|
|
2752
2773
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TypingDots, {}),
|
|
2753
2774
|
typists.label
|
|
2754
2775
|
] }) : null }),
|
|
2755
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2776
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ComposerView, { composer, disabled: false })
|
|
2756
2777
|
] });
|
|
2757
2778
|
}
|
|
2758
2779
|
function MessageGroupView(props) {
|
|
@@ -2885,6 +2906,10 @@ function MessageActionChips(props) {
|
|
|
2885
2906
|
}
|
|
2886
2907
|
function Composer(props) {
|
|
2887
2908
|
const composer = useComposer(props.conversationId);
|
|
2909
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ComposerView, { composer, disabled: props.conversationId === null });
|
|
2910
|
+
}
|
|
2911
|
+
function ComposerView(props) {
|
|
2912
|
+
const composer = props.composer;
|
|
2888
2913
|
const textareaRef = (0, import_react5.useRef)(null);
|
|
2889
2914
|
(0, import_react5.useEffect)(() => {
|
|
2890
2915
|
const node = textareaRef.current;
|
|
@@ -2918,7 +2943,7 @@ function Composer(props) {
|
|
|
2918
2943
|
value: composer.value,
|
|
2919
2944
|
placeholder: "Message",
|
|
2920
2945
|
"aria-label": "Message",
|
|
2921
|
-
disabled: props.
|
|
2946
|
+
disabled: props.disabled,
|
|
2922
2947
|
onChange: (event) => {
|
|
2923
2948
|
composer.setValue(event.target.value);
|
|
2924
2949
|
composer.onKeystroke();
|