diff --git a/packages/im/src/ImClient.ts b/packages/im/src/ImClient.ts index ca5aee3..ca3b839 100644 --- a/packages/im/src/ImClient.ts +++ b/packages/im/src/ImClient.ts @@ -210,6 +210,14 @@ export class ImClient { if (frame.command === 'MESSAGE') { const message: ImMessage = this.normalizeMessage(JSON.parse(frame.body)) + if (message.status === 'READ') { + this.listeners.forEach(listener => listener.onRead?.(message)) + } + if (message.revoked || message.status === 'REVOKED' || message.msgType === 'REVOKED') { + this.listeners.forEach(listener => + listener.onRevoke?.({ msgId: message.id, operatorId: message.fromId ?? message.fromUserId }), + ) + } if (message.chatType === 'GROUP') { this.listeners.forEach(listener => listener.onGroupMessage?.(message)) } else { diff --git a/packages/im/src/ImSDK.ts b/packages/im/src/ImSDK.ts index ee9accb..c16eef8 100644 --- a/packages/im/src/ImSDK.ts +++ b/packages/im/src/ImSDK.ts @@ -335,6 +335,38 @@ export const ImSDK = { return messages }, + async locateHistoryPage( + toId: string, + messageId: string, + pageSize = 20, + maxPages = 20, + ): Promise { + for (let page = 0; page < Math.max(maxPages, 1); page += 1) { + const messages = await this.fetchHistory(toId, page, pageSize) + if (messages.some((item) => item.id === messageId)) { + return messages + } + if (messages.length < pageSize) return null + } + return null + }, + + async locateGroupHistoryPage( + groupId: string, + messageId: string, + pageSize = 50, + maxPages = 20, + ): Promise { + for (let page = 0; page < Math.max(maxPages, 1); page += 1) { + const messages = await this.fetchGroupHistory(groupId, page, pageSize) + if (messages.some((item) => item.id === messageId)) { + return messages + } + if (messages.length < pageSize) return null + } + return null + }, + async sendMessage( toId: string, chatType: ChatType, @@ -534,6 +566,19 @@ export const ImSDK = { return msg }, + async editMessage(messageId: string, content: string): Promise { + const config = getConfig() + const msg = await apiRequest(`/api/im/messages/${encodeURIComponent(messageId)}`, { + method: 'PUT', + params: { appId: config.appId }, + body: { content }, + }) + if (ImDatabase.isInitialized() && _currentUserId) { + await ImDatabase.saveMessage(normalizeMessage(msg), _currentUserId) + } + return msg + }, + async createGroup(name: string, memberIds: string[], groupType = 'WORK'): Promise { const config = getConfig() return apiRequest('/api/im/groups', { @@ -948,6 +993,15 @@ export const ImSDK = { } listener.onSystemMessage?.(normalizeMessage(msg)) }, + onRead: async (msg) => { + if (ImDatabase.isInitialized() && _currentUserId) { + await ImDatabase.saveMessage(normalizeMessage(msg), _currentUserId) + } + listener.onRead?.(normalizeMessage(msg)) + }, + onRevoke: async (data) => { + listener.onRevoke?.(data) + }, } listenerMap.set(listener, wrapped) client?.addListener(wrapped) diff --git a/packages/im/src/index.ts b/packages/im/src/index.ts index 7cbd547..43c9f05 100644 --- a/packages/im/src/index.ts +++ b/packages/im/src/index.ts @@ -8,6 +8,9 @@ export const removeFriend = (friendId: string): Promise => _ImSDK.removeFr export const searchUsers = (keyword: string, size?: number): ReturnType => _ImSDK.searchUsers(keyword, size) export const searchGroups = (keyword: string, size?: number): ReturnType => _ImSDK.searchGroups(keyword, size) export const searchMessages = (params: Parameters[0]): ReturnType => _ImSDK.searchMessages(params) +export const editMessage = (messageId: string, content: string): ReturnType => _ImSDK.editMessage(messageId, content) +export const locateHistoryPage = (toId: string, messageId: string, pageSize?: number, maxPages?: number): ReturnType => _ImSDK.locateHistoryPage(toId, messageId, pageSize, maxPages) +export const locateGroupHistoryPage = (groupId: string, messageId: string, pageSize?: number, maxPages?: number): ReturnType => _ImSDK.locateGroupHistoryPage(groupId, messageId, pageSize, maxPages) export { ImClient } from './ImClient' export { ImDatabase } from './db/ImDatabase' export type { MessageSearchParams } from './db/ImDatabase' diff --git a/packages/im/src/types.ts b/packages/im/src/types.ts index 1f88c61..b04bd71 100644 --- a/packages/im/src/types.ts +++ b/packages/im/src/types.ts @@ -41,6 +41,8 @@ export interface ImEventListener { onMessage?: (msg: ImMessage) => void onGroupMessage?: (msg: ImMessage) => void onSystemMessage?: (msg: ImMessage) => void + onRead?: (msg: ImMessage) => void + onRevoke?: (data: { msgId: string; operatorId: string }) => void onError?: (error: string) => void }