feat(chat): 添加聊天界面视图模型和联系人管理功能
- 实现 ChatViewModel 处理消息收发、历史记录加载和状态管理 - 添加消息搜索、草稿保存、引用回复等功能 - 实现多媒体附件发送包括图片、视频、音频和文件 - 添加群组提及用户功能和消息撤回机制 - 实现联系人管理功能包括好友搜索、添加、删除和黑名单管理 - 添加好友请求处理和实时消息监听 - 实现会话列表管理包含未读消息统计和实时更新 - 集成 IM SDK 的连接状态管理和事件监听 - 添加消息状态跟踪和超时处理机制 - 实现数据缓存机制优化用户体验
这个提交包含在:
父节点
c656bdd202
当前提交
9e5fa3da03
2
.hvigor/cache/file-cache.json
vendored
2
.hvigor/cache/file-cache.json
vendored
文件差异因一行或多行过长而隐藏
2
.hvigor/cache/task-cache.json
vendored
2
.hvigor/cache/task-cache.json
vendored
文件差异因一行或多行过长而隐藏
@ -32,20 +32,27 @@
|
||||
"IS_HVIGORFILE_TYPE_CHECK": false,
|
||||
"TASK_TIME": {
|
||||
"923fe53966c6cd9343e11af776cd4b05be315ea4b200b02e4d5dfb0f929b73bf": {
|
||||
"CreateModuleInfo": 388167,
|
||||
"PreCheckSyscap": 136375,
|
||||
"ProcessIntegratedHsp": 322375,
|
||||
"SyscapTransform": 12371834,
|
||||
"ProcessStartupConfig": 1027750,
|
||||
"ConfigureCmake": 63042,
|
||||
"BuildNativeWithCmake": 75791,
|
||||
"BuildNativeWithNinja": 124459,
|
||||
"BuildJS": 962083
|
||||
"CreateModuleInfo": 314458,
|
||||
"PreCheckSyscap": 126708,
|
||||
"ProcessIntegratedHsp": 218542,
|
||||
"SyscapTransform": 12138250,
|
||||
"ProcessStartupConfig": 988208,
|
||||
"ConfigureCmake": 73375,
|
||||
"BuildNativeWithCmake": 72625,
|
||||
"BuildNativeWithNinja": 129375,
|
||||
"BuildJS": 920292,
|
||||
"CompileArkTS": 2834291708,
|
||||
"ProcessCompiledResources": 207917,
|
||||
"PackageHap": 234451500,
|
||||
"PackingCheck": 2285000,
|
||||
"SignHap": 493042,
|
||||
"CollectDebugSymbol": 273250,
|
||||
"assembleHap": 56166
|
||||
},
|
||||
"77aabe6c19463543339f337db9c84e4d10fd2f56ea0aedaf85a0214d59e93ec4": {
|
||||
"ConfigureCmake": 70375,
|
||||
"BuildNativeWithCmake": 86667,
|
||||
"BuildNativeWithNinja": 204500
|
||||
"ConfigureCmake": 64000,
|
||||
"BuildNativeWithCmake": 77000,
|
||||
"BuildNativeWithNinja": 510500
|
||||
}
|
||||
},
|
||||
"APIS": [
|
||||
@ -56,13 +63,7 @@
|
||||
"ENABLE_CPP_FUNCTION_LEVEL_INCREMENTAL": false
|
||||
},
|
||||
"CONFIG_PROPERTIES": {},
|
||||
"BUILD_ID": "202604282057530700",
|
||||
"ERROR_MESSAGE": [
|
||||
{
|
||||
"CODE": "00000000",
|
||||
"TIMESTAMP": "1777381083000"
|
||||
}
|
||||
],
|
||||
"TOTAL_TIME": 9931347791
|
||||
"BUILD_ID": "202604282229113860",
|
||||
"TOTAL_TIME": 3981273167
|
||||
}
|
||||
}
|
||||
文件差异内容过多而无法显示
加载差异
文件差异内容过多而无法显示
加载差异
文件差异因一行或多行过长而隐藏
文件差异内容过多而无法显示
加载差异
文件差异内容过多而无法显示
加载差异
文件差异内容过多而无法显示
加载差异
文件差异因一行或多行过长而隐藏
@ -19,6 +19,7 @@ export interface ImEventDelegate {
|
||||
onConnected?(): void
|
||||
onDisconnected?(code: number, reason: string): void
|
||||
onMessage?(msg: ImMessage): void
|
||||
onRead?(msg: ImMessage): void
|
||||
onRevoke?(data: RevokeData): void
|
||||
onError?(message: string): void
|
||||
}
|
||||
@ -73,6 +74,10 @@ class GroupJoinRequestBody {
|
||||
remark: string = ''
|
||||
}
|
||||
|
||||
class EditMessageBody {
|
||||
content: string = ''
|
||||
}
|
||||
|
||||
class UpdateProfileBody {
|
||||
appId: string = ''
|
||||
nickname: string = ''
|
||||
@ -141,7 +146,14 @@ export class ImClient {
|
||||
}
|
||||
const frame = JSON.parse(value) as WebSocketFrame
|
||||
if (frame.type === 'MESSAGE') {
|
||||
this.delegate?.onMessage?.(this.normalizeMessage(frame.payload as ImMessage))
|
||||
const message = this.normalizeMessage(frame.payload as ImMessage)
|
||||
if (message.status === 'READ') {
|
||||
this.delegate?.onRead?.(message)
|
||||
}
|
||||
if (message.revoked || message.status === 'REVOKED' || message.msgType === 'REVOKED') {
|
||||
this.delegate?.onRevoke?.({ msgId: message.id, operatorId: message.fromId })
|
||||
}
|
||||
this.delegate?.onMessage?.(message)
|
||||
} else if (frame.type === 'REVOKE') {
|
||||
this.delegate?.onRevoke?.(frame.payload as RevokeData)
|
||||
}
|
||||
@ -223,6 +235,46 @@ export class ImClient {
|
||||
return HttpClient.get<PageResult<ImMessage>>('/api/im/messages/group-history/' + encodeURIComponent(groupId), queryString)
|
||||
}
|
||||
|
||||
async locateHistoryPage(
|
||||
toId: string,
|
||||
messageId: string,
|
||||
pageSize: number = 20,
|
||||
maxPages: number = 20,
|
||||
): Promise<ImMessage[] | null> {
|
||||
const pageCount = Math.max(maxPages, 1)
|
||||
for (let page = 0; page < pageCount; page += 1) {
|
||||
const result = await this.fetchHistory(toId, page, pageSize)
|
||||
const messages = result.content ?? []
|
||||
if (messages.some(item => item.id === messageId)) {
|
||||
return messages
|
||||
}
|
||||
if (messages.length < pageSize) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
async locateGroupHistoryPage(
|
||||
groupId: string,
|
||||
messageId: string,
|
||||
pageSize: number = 50,
|
||||
maxPages: number = 20,
|
||||
): Promise<ImMessage[] | null> {
|
||||
const pageCount = Math.max(maxPages, 1)
|
||||
for (let page = 0; page < pageCount; page += 1) {
|
||||
const result = await this.fetchGroupHistory(groupId, page, pageSize)
|
||||
const messages = result.content ?? []
|
||||
if (messages.some(item => item.id === messageId)) {
|
||||
return messages
|
||||
}
|
||||
if (messages.length < pageSize) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
async listConversations(size: number = 20): Promise<ConversationData[]> {
|
||||
return HttpClient.get<ConversationData[]>('/api/im/conversations', this.buildConversationQuery(size))
|
||||
}
|
||||
@ -298,6 +350,16 @@ export class ImClient {
|
||||
)
|
||||
}
|
||||
|
||||
async editMessage(messageId: string, content: string): Promise<ImMessage> {
|
||||
const body = new EditMessageBody()
|
||||
body.content = content
|
||||
return HttpClient.put<ImMessage>(
|
||||
'/api/im/messages/' + encodeURIComponent(messageId),
|
||||
body,
|
||||
this.buildAppQuery(),
|
||||
)
|
||||
}
|
||||
|
||||
async sendFriendRequest(toUserId: string, remark: string | null = null): Promise<FriendRequest> {
|
||||
const params = new FriendRequestBody()
|
||||
params.appId = SDKContext.getConfig().appKey
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户