@antzsoft/chat-core 1.0.2 → 1.0.3
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 +454 -39
- package/dist/chat.store-PY3YVYGN.js +7 -0
- package/dist/chat.store-PY3YVYGN.js.map +1 -0
- package/dist/chunk-TB52RCSF.js +54 -0
- package/dist/chunk-TB52RCSF.js.map +1 -0
- package/dist/index.cjs +173 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +155 -12
- package/dist/index.d.ts +155 -12
- package/dist/index.js +108 -55
- package/dist/index.js.map +1 -1
- package/docs/integration-guide.html +2076 -0
- package/package.json +3 -2
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// src/stores/chat.store.ts
|
|
2
|
+
import { create } from "zustand";
|
|
3
|
+
var useChatStore = create((set) => ({
|
|
4
|
+
activeConversationId: null,
|
|
5
|
+
pendingTarget: null,
|
|
6
|
+
typingUsers: {},
|
|
7
|
+
onlineUsers: [],
|
|
8
|
+
lastRead: {},
|
|
9
|
+
lastSeen: {},
|
|
10
|
+
replyingTo: null,
|
|
11
|
+
editingMessage: null,
|
|
12
|
+
isSidebarOpen: true,
|
|
13
|
+
isGroupInfoOpen: false,
|
|
14
|
+
isStarredPanelOpen: false,
|
|
15
|
+
setActiveConversation: (id) => set({ activeConversationId: id, replyingTo: null, editingMessage: null }),
|
|
16
|
+
setPendingTarget: (target) => set({ pendingTarget: target }),
|
|
17
|
+
addTypingUser: (conversationId, user) => set((state) => {
|
|
18
|
+
const existing = state.typingUsers[conversationId] ?? [];
|
|
19
|
+
const deduped = existing.filter((u) => u.userId !== user.userId);
|
|
20
|
+
return { typingUsers: { ...state.typingUsers, [conversationId]: [...deduped, user] } };
|
|
21
|
+
}),
|
|
22
|
+
removeTypingUser: (conversationId, userId) => set((state) => ({
|
|
23
|
+
typingUsers: {
|
|
24
|
+
...state.typingUsers,
|
|
25
|
+
[conversationId]: (state.typingUsers[conversationId] ?? []).filter(
|
|
26
|
+
(u) => u.userId !== userId
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
})),
|
|
30
|
+
setUserOnline: (userId) => set((state) => ({
|
|
31
|
+
onlineUsers: state.onlineUsers.includes(userId) ? state.onlineUsers : [...state.onlineUsers, userId]
|
|
32
|
+
})),
|
|
33
|
+
setUserOffline: (userId) => set((state) => ({ onlineUsers: state.onlineUsers.filter((id) => id !== userId) })),
|
|
34
|
+
setOnlineUsers: (userIds) => set({ onlineUsers: userIds }),
|
|
35
|
+
setLastRead: (conversationId, messageId, readAt) => set((state) => ({
|
|
36
|
+
lastRead: { ...state.lastRead, [conversationId]: { messageId, readAt } }
|
|
37
|
+
})),
|
|
38
|
+
setLastSeen: (userId, lastSeenAt) => set((state) => ({
|
|
39
|
+
lastSeen: { ...state.lastSeen, [userId]: lastSeenAt }
|
|
40
|
+
})),
|
|
41
|
+
setReplyingTo: (message) => set({ replyingTo: message, editingMessage: null }),
|
|
42
|
+
setEditingMessage: (message) => set({ editingMessage: message, replyingTo: null }),
|
|
43
|
+
toggleSidebar: () => set((state) => ({ isSidebarOpen: !state.isSidebarOpen })),
|
|
44
|
+
setSidebarOpen: (open) => set({ isSidebarOpen: open }),
|
|
45
|
+
toggleGroupInfo: () => set((state) => ({ isGroupInfoOpen: !state.isGroupInfoOpen })),
|
|
46
|
+
setGroupInfoOpen: (open) => set({ isGroupInfoOpen: open }),
|
|
47
|
+
toggleStarredPanel: () => set((state) => ({ isStarredPanelOpen: !state.isStarredPanelOpen })),
|
|
48
|
+
setStarredPanelOpen: (open) => set({ isStarredPanelOpen: open })
|
|
49
|
+
}));
|
|
50
|
+
|
|
51
|
+
export {
|
|
52
|
+
useChatStore
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=chunk-TB52RCSF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/stores/chat.store.ts"],"sourcesContent":["import { create } from 'zustand';\nimport type { Message } from '../types/index.js';\n\ninterface TypingUser {\n userId: string;\n displayName: string;\n avatarUrl?: string;\n}\n\nexport interface LastReadEntry {\n messageId: string;\n readAt: string;\n}\n\ninterface ChatState {\n activeConversationId: string | null;\n pendingTarget: { conversationId: string; messageId: string } | null;\n typingUsers: Record<string, TypingUser[]>;\n onlineUsers: string[];\n /** keyed by conversationId — current user's last read pointer per conversation */\n lastRead: Record<string, LastReadEntry>;\n /** keyed by userId — last seen timestamp for each user */\n lastSeen: Record<string, string>;\n replyingTo: Message | null;\n editingMessage: Message | null;\n isSidebarOpen: boolean;\n isGroupInfoOpen: boolean;\n isStarredPanelOpen: boolean;\n\n setActiveConversation: (id: string | null) => void;\n setPendingTarget: (target: { conversationId: string; messageId: string } | null) => void;\n addTypingUser: (conversationId: string, user: TypingUser) => void;\n removeTypingUser: (conversationId: string, userId: string) => void;\n setUserOnline: (userId: string) => void;\n setUserOffline: (userId: string) => void;\n setOnlineUsers: (userIds: string[]) => void;\n setLastRead: (conversationId: string, messageId: string, readAt: string) => void;\n setLastSeen: (userId: string, lastSeenAt: string) => void;\n setReplyingTo: (message: Message | null) => void;\n setEditingMessage: (message: Message | null) => void;\n toggleSidebar: () => void;\n setSidebarOpen: (open: boolean) => void;\n toggleGroupInfo: () => void;\n setGroupInfoOpen: (open: boolean) => void;\n toggleStarredPanel: () => void;\n setStarredPanelOpen: (open: boolean) => void;\n}\n\nexport const useChatStore = create<ChatState>((set) => ({\n activeConversationId: null,\n pendingTarget: null,\n typingUsers: {},\n onlineUsers: [],\n lastRead: {},\n lastSeen: {},\n replyingTo: null,\n editingMessage: null,\n isSidebarOpen: true,\n isGroupInfoOpen: false,\n isStarredPanelOpen: false,\n\n setActiveConversation: (id) =>\n set({ activeConversationId: id, replyingTo: null, editingMessage: null }),\n\n setPendingTarget: (target) => set({ pendingTarget: target }),\n\n addTypingUser: (conversationId, user) =>\n set((state) => {\n const existing = state.typingUsers[conversationId] ?? [];\n const deduped = existing.filter((u) => u.userId !== user.userId);\n return { typingUsers: { ...state.typingUsers, [conversationId]: [...deduped, user] } };\n }),\n\n removeTypingUser: (conversationId, userId) =>\n set((state) => ({\n typingUsers: {\n ...state.typingUsers,\n [conversationId]: (state.typingUsers[conversationId] ?? []).filter(\n (u) => u.userId !== userId,\n ),\n },\n })),\n\n setUserOnline: (userId) =>\n set((state) => ({\n onlineUsers: state.onlineUsers.includes(userId)\n ? state.onlineUsers\n : [...state.onlineUsers, userId],\n })),\n\n setUserOffline: (userId) =>\n set((state) => ({ onlineUsers: state.onlineUsers.filter((id) => id !== userId) })),\n\n setOnlineUsers: (userIds) => set({ onlineUsers: userIds }),\n\n setLastRead: (conversationId, messageId, readAt) =>\n set((state) => ({\n lastRead: { ...state.lastRead, [conversationId]: { messageId, readAt } },\n })),\n\n setLastSeen: (userId, lastSeenAt) =>\n set((state) => ({\n lastSeen: { ...state.lastSeen, [userId]: lastSeenAt },\n })),\n\n setReplyingTo: (message) => set({ replyingTo: message, editingMessage: null }),\n\n setEditingMessage: (message) => set({ editingMessage: message, replyingTo: null }),\n\n toggleSidebar: () => set((state) => ({ isSidebarOpen: !state.isSidebarOpen })),\n setSidebarOpen: (open) => set({ isSidebarOpen: open }),\n\n toggleGroupInfo: () => set((state) => ({ isGroupInfoOpen: !state.isGroupInfoOpen })),\n setGroupInfoOpen: (open) => set({ isGroupInfoOpen: open }),\n\n toggleStarredPanel: () => set((state) => ({ isStarredPanelOpen: !state.isStarredPanelOpen })),\n setStarredPanelOpen: (open) => set({ isStarredPanelOpen: open }),\n}));\n"],"mappings":";AAAA,SAAS,cAAc;AAgDhB,IAAM,eAAe,OAAkB,CAAC,SAAS;AAAA,EACtD,sBAAsB;AAAA,EACtB,eAAe;AAAA,EACf,aAAa,CAAC;AAAA,EACd,aAAa,CAAC;AAAA,EACd,UAAU,CAAC;AAAA,EACX,UAAU,CAAC;AAAA,EACX,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EAEpB,uBAAuB,CAAC,OACtB,IAAI,EAAE,sBAAsB,IAAI,YAAY,MAAM,gBAAgB,KAAK,CAAC;AAAA,EAE1E,kBAAkB,CAAC,WAAW,IAAI,EAAE,eAAe,OAAO,CAAC;AAAA,EAE3D,eAAe,CAAC,gBAAgB,SAC9B,IAAI,CAAC,UAAU;AACb,UAAM,WAAW,MAAM,YAAY,cAAc,KAAK,CAAC;AACvD,UAAM,UAAU,SAAS,OAAO,CAAC,MAAM,EAAE,WAAW,KAAK,MAAM;AAC/D,WAAO,EAAE,aAAa,EAAE,GAAG,MAAM,aAAa,CAAC,cAAc,GAAG,CAAC,GAAG,SAAS,IAAI,EAAE,EAAE;AAAA,EACvF,CAAC;AAAA,EAEH,kBAAkB,CAAC,gBAAgB,WACjC,IAAI,CAAC,WAAW;AAAA,IACd,aAAa;AAAA,MACX,GAAG,MAAM;AAAA,MACT,CAAC,cAAc,IAAI,MAAM,YAAY,cAAc,KAAK,CAAC,GAAG;AAAA,QAC1D,CAAC,MAAM,EAAE,WAAW;AAAA,MACtB;AAAA,IACF;AAAA,EACF,EAAE;AAAA,EAEJ,eAAe,CAAC,WACd,IAAI,CAAC,WAAW;AAAA,IACd,aAAa,MAAM,YAAY,SAAS,MAAM,IAC1C,MAAM,cACN,CAAC,GAAG,MAAM,aAAa,MAAM;AAAA,EACnC,EAAE;AAAA,EAEJ,gBAAgB,CAAC,WACf,IAAI,CAAC,WAAW,EAAE,aAAa,MAAM,YAAY,OAAO,CAAC,OAAO,OAAO,MAAM,EAAE,EAAE;AAAA,EAEnF,gBAAgB,CAAC,YAAY,IAAI,EAAE,aAAa,QAAQ,CAAC;AAAA,EAEzD,aAAa,CAAC,gBAAgB,WAAW,WACvC,IAAI,CAAC,WAAW;AAAA,IACd,UAAU,EAAE,GAAG,MAAM,UAAU,CAAC,cAAc,GAAG,EAAE,WAAW,OAAO,EAAE;AAAA,EACzE,EAAE;AAAA,EAEJ,aAAa,CAAC,QAAQ,eACpB,IAAI,CAAC,WAAW;AAAA,IACd,UAAU,EAAE,GAAG,MAAM,UAAU,CAAC,MAAM,GAAG,WAAW;AAAA,EACtD,EAAE;AAAA,EAEJ,eAAe,CAAC,YAAY,IAAI,EAAE,YAAY,SAAS,gBAAgB,KAAK,CAAC;AAAA,EAE7E,mBAAmB,CAAC,YAAY,IAAI,EAAE,gBAAgB,SAAS,YAAY,KAAK,CAAC;AAAA,EAEjF,eAAe,MAAM,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,MAAM,cAAc,EAAE;AAAA,EAC7E,gBAAgB,CAAC,SAAS,IAAI,EAAE,eAAe,KAAK,CAAC;AAAA,EAErD,iBAAiB,MAAM,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,MAAM,gBAAgB,EAAE;AAAA,EACnF,kBAAkB,CAAC,SAAS,IAAI,EAAE,iBAAiB,KAAK,CAAC;AAAA,EAEzD,oBAAoB,MAAM,IAAI,CAAC,WAAW,EAAE,oBAAoB,CAAC,MAAM,mBAAmB,EAAE;AAAA,EAC5F,qBAAqB,CAAC,SAAS,IAAI,EAAE,oBAAoB,KAAK,CAAC;AACjE,EAAE;","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
10
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,6 +30,66 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
30
|
));
|
|
28
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
32
|
|
|
33
|
+
// src/stores/chat.store.ts
|
|
34
|
+
var chat_store_exports = {};
|
|
35
|
+
__export(chat_store_exports, {
|
|
36
|
+
useChatStore: () => useChatStore
|
|
37
|
+
});
|
|
38
|
+
var import_zustand, useChatStore;
|
|
39
|
+
var init_chat_store = __esm({
|
|
40
|
+
"src/stores/chat.store.ts"() {
|
|
41
|
+
"use strict";
|
|
42
|
+
import_zustand = require("zustand");
|
|
43
|
+
useChatStore = (0, import_zustand.create)((set) => ({
|
|
44
|
+
activeConversationId: null,
|
|
45
|
+
pendingTarget: null,
|
|
46
|
+
typingUsers: {},
|
|
47
|
+
onlineUsers: [],
|
|
48
|
+
lastRead: {},
|
|
49
|
+
lastSeen: {},
|
|
50
|
+
replyingTo: null,
|
|
51
|
+
editingMessage: null,
|
|
52
|
+
isSidebarOpen: true,
|
|
53
|
+
isGroupInfoOpen: false,
|
|
54
|
+
isStarredPanelOpen: false,
|
|
55
|
+
setActiveConversation: (id) => set({ activeConversationId: id, replyingTo: null, editingMessage: null }),
|
|
56
|
+
setPendingTarget: (target) => set({ pendingTarget: target }),
|
|
57
|
+
addTypingUser: (conversationId, user) => set((state) => {
|
|
58
|
+
const existing = state.typingUsers[conversationId] ?? [];
|
|
59
|
+
const deduped = existing.filter((u) => u.userId !== user.userId);
|
|
60
|
+
return { typingUsers: { ...state.typingUsers, [conversationId]: [...deduped, user] } };
|
|
61
|
+
}),
|
|
62
|
+
removeTypingUser: (conversationId, userId) => set((state) => ({
|
|
63
|
+
typingUsers: {
|
|
64
|
+
...state.typingUsers,
|
|
65
|
+
[conversationId]: (state.typingUsers[conversationId] ?? []).filter(
|
|
66
|
+
(u) => u.userId !== userId
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
})),
|
|
70
|
+
setUserOnline: (userId) => set((state) => ({
|
|
71
|
+
onlineUsers: state.onlineUsers.includes(userId) ? state.onlineUsers : [...state.onlineUsers, userId]
|
|
72
|
+
})),
|
|
73
|
+
setUserOffline: (userId) => set((state) => ({ onlineUsers: state.onlineUsers.filter((id) => id !== userId) })),
|
|
74
|
+
setOnlineUsers: (userIds) => set({ onlineUsers: userIds }),
|
|
75
|
+
setLastRead: (conversationId, messageId, readAt) => set((state) => ({
|
|
76
|
+
lastRead: { ...state.lastRead, [conversationId]: { messageId, readAt } }
|
|
77
|
+
})),
|
|
78
|
+
setLastSeen: (userId, lastSeenAt) => set((state) => ({
|
|
79
|
+
lastSeen: { ...state.lastSeen, [userId]: lastSeenAt }
|
|
80
|
+
})),
|
|
81
|
+
setReplyingTo: (message) => set({ replyingTo: message, editingMessage: null }),
|
|
82
|
+
setEditingMessage: (message) => set({ editingMessage: message, replyingTo: null }),
|
|
83
|
+
toggleSidebar: () => set((state) => ({ isSidebarOpen: !state.isSidebarOpen })),
|
|
84
|
+
setSidebarOpen: (open) => set({ isSidebarOpen: open }),
|
|
85
|
+
toggleGroupInfo: () => set((state) => ({ isGroupInfoOpen: !state.isGroupInfoOpen })),
|
|
86
|
+
setGroupInfoOpen: (open) => set({ isGroupInfoOpen: open }),
|
|
87
|
+
toggleStarredPanel: () => set((state) => ({ isStarredPanelOpen: !state.isStarredPanelOpen })),
|
|
88
|
+
setStarredPanelOpen: (open) => set({ isStarredPanelOpen: open })
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
30
93
|
// src/index.ts
|
|
31
94
|
var src_exports = {};
|
|
32
95
|
__export(src_exports, {
|
|
@@ -55,7 +118,8 @@ __export(src_exports, {
|
|
|
55
118
|
storageApi: () => storageApi,
|
|
56
119
|
tryGetSocket: () => tryGetSocket,
|
|
57
120
|
uploadBatch: () => uploadBatch,
|
|
58
|
-
useChatStore: () => useChatStore
|
|
121
|
+
useChatStore: () => useChatStore,
|
|
122
|
+
usersApi: () => usersApi
|
|
59
123
|
});
|
|
60
124
|
module.exports = __toCommonJS(src_exports);
|
|
61
125
|
|
|
@@ -104,7 +168,10 @@ function resolveConfig(config) {
|
|
|
104
168
|
onProgress: config.upload?.onProgress
|
|
105
169
|
},
|
|
106
170
|
platformUploadFn: config.platformUploadFn,
|
|
107
|
-
persistStorage: config.persistStorage
|
|
171
|
+
persistStorage: config.persistStorage,
|
|
172
|
+
messagePageSize: config.messagePageSize ?? 40,
|
|
173
|
+
starredMessagePageSize: config.starredMessagePageSize ?? 30,
|
|
174
|
+
searchPageSize: config.searchPageSize ?? 50
|
|
108
175
|
};
|
|
109
176
|
}
|
|
110
177
|
|
|
@@ -238,9 +305,14 @@ var authApi = {
|
|
|
238
305
|
// src/api/messages.ts
|
|
239
306
|
var messagesApi = {
|
|
240
307
|
async list(conversationId, params = {}) {
|
|
308
|
+
const { cursor, direction, ...rest } = params;
|
|
309
|
+
const serverParams = { ...rest };
|
|
310
|
+
if (cursor) {
|
|
311
|
+
serverParams[direction === "after" ? "after" : "before"] = cursor;
|
|
312
|
+
}
|
|
241
313
|
const { data } = await getApiClient().get(
|
|
242
314
|
`/conversations/${conversationId}/messages`,
|
|
243
|
-
{ params }
|
|
315
|
+
{ params: serverParams }
|
|
244
316
|
);
|
|
245
317
|
return data;
|
|
246
318
|
},
|
|
@@ -289,6 +361,12 @@ var messagesApi = {
|
|
|
289
361
|
const { data } = await getApiClient().get("/messages/search", { params });
|
|
290
362
|
return data;
|
|
291
363
|
},
|
|
364
|
+
async getLastRead(conversationId) {
|
|
365
|
+
const { data } = await getApiClient().get(
|
|
366
|
+
`/conversations/${conversationId}/read-receipt`
|
|
367
|
+
);
|
|
368
|
+
return data;
|
|
369
|
+
},
|
|
292
370
|
async markAsRead(conversationId, messageId) {
|
|
293
371
|
await getApiClient().post(`/conversations/${conversationId}/read`, messageId ? { messageId } : {});
|
|
294
372
|
},
|
|
@@ -417,9 +495,25 @@ var conversationsApi = {
|
|
|
417
495
|
const { data } = await getApiClient().get(`/conversations/${conversationId}/participants`);
|
|
418
496
|
return data;
|
|
419
497
|
},
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
498
|
+
/**
|
|
499
|
+
* Get unread message count for a single conversation.
|
|
500
|
+
* Use this after app foreground or socket reconnect to refresh a specific count.
|
|
501
|
+
*/
|
|
502
|
+
async getUnreadCount(conversationId) {
|
|
503
|
+
const { data } = await getApiClient().get(
|
|
504
|
+
`/conversations/${conversationId}/unread`
|
|
505
|
+
);
|
|
506
|
+
return data;
|
|
507
|
+
},
|
|
508
|
+
/**
|
|
509
|
+
* Get total unread count across all conversations + per-conversation breakdown.
|
|
510
|
+
* Use on app cold start, foreground resume, or after socket reconnect.
|
|
511
|
+
* The socket keeps counts live while connected — this is the source of truth
|
|
512
|
+
* when the socket was down.
|
|
513
|
+
*/
|
|
514
|
+
async getUnreadSummary() {
|
|
515
|
+
const { data } = await getApiClient().get("/conversations/unread");
|
|
516
|
+
return data;
|
|
423
517
|
}
|
|
424
518
|
};
|
|
425
519
|
|
|
@@ -524,6 +618,44 @@ var devicesApi = {
|
|
|
524
618
|
}
|
|
525
619
|
};
|
|
526
620
|
|
|
621
|
+
// src/api/users.ts
|
|
622
|
+
var usersApi = {
|
|
623
|
+
async list(params = {}) {
|
|
624
|
+
const { data } = await getApiClient().get("/users", { params });
|
|
625
|
+
return data;
|
|
626
|
+
},
|
|
627
|
+
async getById(userId) {
|
|
628
|
+
const { data } = await getApiClient().get(`/users/${userId}`);
|
|
629
|
+
return data;
|
|
630
|
+
},
|
|
631
|
+
async getLastSeen(userId) {
|
|
632
|
+
const { data } = await getApiClient().get(`/users/${userId}`);
|
|
633
|
+
return { lastSeenAt: data.lastSeenAt ?? null };
|
|
634
|
+
},
|
|
635
|
+
/**
|
|
636
|
+
* Update notification preferences for the current user.
|
|
637
|
+
* Partial update — only send fields you want to change.
|
|
638
|
+
* A prefs record is automatically created with defaults when a device
|
|
639
|
+
* token is first registered, so this never fails with "not found".
|
|
640
|
+
*/
|
|
641
|
+
async updatePreferences(prefs) {
|
|
642
|
+
const { data } = await getApiClient().put("/users/me/preferences", prefs);
|
|
643
|
+
return data;
|
|
644
|
+
},
|
|
645
|
+
/**
|
|
646
|
+
* Fetch current notification preferences for the current user.
|
|
647
|
+
* Returns null if no prefs record exists yet (all defaults apply).
|
|
648
|
+
*/
|
|
649
|
+
async getPreferences() {
|
|
650
|
+
try {
|
|
651
|
+
const { data } = await getApiClient().get("/users/me/preferences");
|
|
652
|
+
return data;
|
|
653
|
+
} catch {
|
|
654
|
+
return null;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
};
|
|
658
|
+
|
|
527
659
|
// src/socket/socket.ts
|
|
528
660
|
var import_socket = require("socket.io-client");
|
|
529
661
|
var _socket = null;
|
|
@@ -550,17 +682,17 @@ function onSocketStatus(listener) {
|
|
|
550
682
|
_statusListeners.add(listener);
|
|
551
683
|
return () => _statusListeners.delete(listener);
|
|
552
684
|
}
|
|
553
|
-
async function connectSocket(config, getToken
|
|
554
|
-
if (_socket
|
|
685
|
+
async function connectSocket(config, getToken) {
|
|
686
|
+
if (_socket && !_socket.disconnected) return _socket;
|
|
555
687
|
_getToken = getToken;
|
|
556
|
-
_userId = userId;
|
|
557
|
-
_tenantId = tenantId;
|
|
688
|
+
_userId = config.userId;
|
|
689
|
+
_tenantId = config.tenantId;
|
|
558
690
|
const token = getToken();
|
|
559
691
|
_socket = (0, import_socket.io)(`${config.socketOrigin}/chat`, {
|
|
560
692
|
auth: {
|
|
561
693
|
token: token ? `Bearer ${token}` : "",
|
|
562
|
-
...userId && { userId },
|
|
563
|
-
...tenantId && { tenantId },
|
|
694
|
+
...config.userId && { userId: config.userId },
|
|
695
|
+
...config.tenantId && { tenantId: config.tenantId },
|
|
564
696
|
...config.avatar?.url && { avatarUrl: config.avatar.url },
|
|
565
697
|
...config.avatar?.base64 && { avatarBase64: config.avatar.base64 }
|
|
566
698
|
},
|
|
@@ -578,9 +710,30 @@ async function connectSocket(config, getToken, userId, tenantId) {
|
|
|
578
710
|
setStatus("connecting");
|
|
579
711
|
_socket.on("connect", () => setStatus("connected"));
|
|
580
712
|
_socket.on("disconnect", () => setStatus("disconnected"));
|
|
581
|
-
_socket.on("connect_error", () =>
|
|
713
|
+
_socket.on("connect_error", (err) => {
|
|
714
|
+
console.error("[AntzChat] Socket connect_error:", err?.message, err?.data);
|
|
715
|
+
setStatus("error");
|
|
716
|
+
});
|
|
582
717
|
_socket.on("reconnecting", () => setStatus("reconnecting"));
|
|
583
718
|
_socket.on("reconnect", () => setStatus("connected"));
|
|
719
|
+
_socket.on("read_receipt", (event) => {
|
|
720
|
+
Promise.resolve().then(() => (init_chat_store(), chat_store_exports)).then(({ useChatStore: useChatStore2 }) => {
|
|
721
|
+
useChatStore2.getState().setLastRead(event.conversationId, event.messageId, event.readAt);
|
|
722
|
+
});
|
|
723
|
+
});
|
|
724
|
+
_socket.on("user_online", (event) => {
|
|
725
|
+
Promise.resolve().then(() => (init_chat_store(), chat_store_exports)).then(({ useChatStore: useChatStore2 }) => {
|
|
726
|
+
const store = useChatStore2.getState();
|
|
727
|
+
store.setUserOnline(event.userId);
|
|
728
|
+
});
|
|
729
|
+
});
|
|
730
|
+
_socket.on("user_offline", (event) => {
|
|
731
|
+
Promise.resolve().then(() => (init_chat_store(), chat_store_exports)).then(({ useChatStore: useChatStore2 }) => {
|
|
732
|
+
const store = useChatStore2.getState();
|
|
733
|
+
store.setUserOffline(event.userId);
|
|
734
|
+
if (event.lastSeenAt) store.setLastSeen(event.userId, event.lastSeenAt);
|
|
735
|
+
});
|
|
736
|
+
});
|
|
584
737
|
return _socket;
|
|
585
738
|
}
|
|
586
739
|
function disconnectSocket() {
|
|
@@ -695,12 +848,12 @@ var socketEmit = {
|
|
|
695
848
|
};
|
|
696
849
|
|
|
697
850
|
// src/stores/auth.store.ts
|
|
698
|
-
var
|
|
851
|
+
var import_zustand2 = require("zustand");
|
|
699
852
|
var import_middleware = require("zustand/middleware");
|
|
700
853
|
function createAuthStore(storage) {
|
|
701
854
|
if (!storage) throw new Error("[AntzChat] createAuthStore requires a valid PersistStorage \u2014 received undefined. Make sure the SDK config is fully resolved before initializing the store.");
|
|
702
855
|
const ref = { store: null };
|
|
703
|
-
const store = (0,
|
|
856
|
+
const store = (0, import_zustand2.create)()(
|
|
704
857
|
(0, import_middleware.persist)(
|
|
705
858
|
(set) => ({
|
|
706
859
|
user: null,
|
|
@@ -781,47 +934,8 @@ function resetAuthStore() {
|
|
|
781
934
|
_authStore = null;
|
|
782
935
|
}
|
|
783
936
|
|
|
784
|
-
// src/
|
|
785
|
-
|
|
786
|
-
var useChatStore = (0, import_zustand2.create)((set) => ({
|
|
787
|
-
activeConversationId: null,
|
|
788
|
-
pendingTarget: null,
|
|
789
|
-
typingUsers: {},
|
|
790
|
-
onlineUsers: [],
|
|
791
|
-
replyingTo: null,
|
|
792
|
-
editingMessage: null,
|
|
793
|
-
isSidebarOpen: true,
|
|
794
|
-
isGroupInfoOpen: false,
|
|
795
|
-
isStarredPanelOpen: false,
|
|
796
|
-
setActiveConversation: (id) => set({ activeConversationId: id, replyingTo: null, editingMessage: null }),
|
|
797
|
-
setPendingTarget: (target) => set({ pendingTarget: target }),
|
|
798
|
-
addTypingUser: (conversationId, user) => set((state) => {
|
|
799
|
-
const existing = state.typingUsers[conversationId] ?? [];
|
|
800
|
-
const deduped = existing.filter((u) => u.userId !== user.userId);
|
|
801
|
-
return { typingUsers: { ...state.typingUsers, [conversationId]: [...deduped, user] } };
|
|
802
|
-
}),
|
|
803
|
-
removeTypingUser: (conversationId, userId) => set((state) => ({
|
|
804
|
-
typingUsers: {
|
|
805
|
-
...state.typingUsers,
|
|
806
|
-
[conversationId]: (state.typingUsers[conversationId] ?? []).filter(
|
|
807
|
-
(u) => u.userId !== userId
|
|
808
|
-
)
|
|
809
|
-
}
|
|
810
|
-
})),
|
|
811
|
-
setUserOnline: (userId) => set((state) => ({
|
|
812
|
-
onlineUsers: state.onlineUsers.includes(userId) ? state.onlineUsers : [...state.onlineUsers, userId]
|
|
813
|
-
})),
|
|
814
|
-
setUserOffline: (userId) => set((state) => ({ onlineUsers: state.onlineUsers.filter((id) => id !== userId) })),
|
|
815
|
-
setOnlineUsers: (userIds) => set({ onlineUsers: userIds }),
|
|
816
|
-
setReplyingTo: (message) => set({ replyingTo: message, editingMessage: null }),
|
|
817
|
-
setEditingMessage: (message) => set({ editingMessage: message, replyingTo: null }),
|
|
818
|
-
toggleSidebar: () => set((state) => ({ isSidebarOpen: !state.isSidebarOpen })),
|
|
819
|
-
setSidebarOpen: (open) => set({ isSidebarOpen: open }),
|
|
820
|
-
toggleGroupInfo: () => set((state) => ({ isGroupInfoOpen: !state.isGroupInfoOpen })),
|
|
821
|
-
setGroupInfoOpen: (open) => set({ isGroupInfoOpen: open }),
|
|
822
|
-
toggleStarredPanel: () => set((state) => ({ isStarredPanelOpen: !state.isStarredPanelOpen })),
|
|
823
|
-
setStarredPanelOpen: (open) => set({ isStarredPanelOpen: open })
|
|
824
|
-
}));
|
|
937
|
+
// src/index.ts
|
|
938
|
+
init_chat_store();
|
|
825
939
|
|
|
826
940
|
// src/client-facade.ts
|
|
827
941
|
var AntzChatClient = class {
|
|
@@ -830,6 +944,7 @@ var AntzChatClient = class {
|
|
|
830
944
|
this.messages = messagesApi;
|
|
831
945
|
this.conversations = conversationsApi;
|
|
832
946
|
this.storage = storageApi;
|
|
947
|
+
this.users = usersApi;
|
|
833
948
|
this.socket = {
|
|
834
949
|
emit: socketEmit,
|
|
835
950
|
on: (event, handler) => getSocket().on(event, handler),
|
|
@@ -885,6 +1000,7 @@ var AntzChatClient = class {
|
|
|
885
1000
|
storageApi,
|
|
886
1001
|
tryGetSocket,
|
|
887
1002
|
uploadBatch,
|
|
888
|
-
useChatStore
|
|
1003
|
+
useChatStore,
|
|
1004
|
+
usersApi
|
|
889
1005
|
});
|
|
890
1006
|
//# sourceMappingURL=index.cjs.map
|