docs(project): 更新需求与开发进度对比报告并完善Android SDK接口定义
- 添加了完整的XuqmGroup平台需求与开发进度对比报告 - 实现了Android SDK的ImApi接口定义,涵盖群组、好友、黑名单等完整功能 - 定义了IM消息、会话、群组、用户资料等核心数据模型 - 实现了Android SDK的ImSDK核心功能类,包括连接管理和消息处理
这个提交包含在:
父节点
3c7ae4d766
当前提交
293f9d6a96
@ -4,9 +4,12 @@ import { ImDatabase } from './db/ImDatabase'
|
||||
import type { MessageSearchParams } from './db/ImDatabase'
|
||||
import type {
|
||||
BlacklistEntry,
|
||||
BlacklistCheckResult,
|
||||
ChatType,
|
||||
ConversationData,
|
||||
ConversationGroupItem,
|
||||
FriendRequest,
|
||||
GroupReadReceiptSummary,
|
||||
GroupJoinRequest,
|
||||
ImEventListener,
|
||||
ImGroup,
|
||||
@ -103,6 +106,7 @@ function normalizeConversation(item: {
|
||||
unreadCount: number
|
||||
isMuted: boolean
|
||||
isPinned: boolean
|
||||
conversationGroup?: string | null
|
||||
}): ConversationData {
|
||||
return {
|
||||
targetId: item.targetId,
|
||||
@ -113,6 +117,7 @@ function normalizeConversation(item: {
|
||||
unreadCount: item.unreadCount,
|
||||
isMuted: item.isMuted,
|
||||
isPinned: item.isPinned,
|
||||
conversationGroup: item.conversationGroup ?? null,
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,6 +177,15 @@ function setConversationPinnedMemory(targetId: string, chatType: ChatType, pinne
|
||||
emitConversationMemory()
|
||||
}
|
||||
|
||||
function setConversationGroupMemory(targetId: string, chatType: ChatType, groupName?: string | null): void {
|
||||
conversationMemory = conversationMemory.map(item =>
|
||||
item.targetId === targetId && item.chatType === chatType
|
||||
? { ...item, conversationGroup: groupName ?? null }
|
||||
: item,
|
||||
)
|
||||
emitConversationMemory()
|
||||
}
|
||||
|
||||
function deleteConversationMemory(targetId: string, chatType: ChatType): void {
|
||||
conversationMemory = conversationMemory.filter(
|
||||
item => !(item.targetId === targetId && item.chatType === chatType),
|
||||
@ -779,6 +793,27 @@ export const ImSDK = {
|
||||
})
|
||||
},
|
||||
|
||||
async transferGroupOwner(groupId: string, newOwnerId: string): Promise<ImGroup> {
|
||||
return apiRequest<ImGroup>(`/api/im/groups/${encodeURIComponent(groupId)}/owner`, {
|
||||
method: 'POST',
|
||||
body: { newOwnerId },
|
||||
})
|
||||
},
|
||||
|
||||
async updateGroupAttributes(groupId: string, attributes: Record<string, unknown>): Promise<ImGroup> {
|
||||
return apiRequest<ImGroup>(`/api/im/groups/${encodeURIComponent(groupId)}/attributes`, {
|
||||
method: 'PUT',
|
||||
body: attributes,
|
||||
})
|
||||
},
|
||||
|
||||
async removeGroupAttributes(groupId: string, keys: string[]): Promise<ImGroup> {
|
||||
return apiRequest<ImGroup>(`/api/im/groups/${encodeURIComponent(groupId)}/attributes/delete`, {
|
||||
method: 'POST',
|
||||
body: { keys },
|
||||
})
|
||||
},
|
||||
|
||||
async dismissGroup(groupId: string): Promise<void> {
|
||||
await apiRequest(`/api/im/groups/${encodeURIComponent(groupId)}`, { method: 'DELETE' })
|
||||
},
|
||||
@ -851,6 +886,42 @@ export const ImSDK = {
|
||||
})
|
||||
},
|
||||
|
||||
async removeAllFriends(): Promise<void> {
|
||||
const config = getConfig()
|
||||
await apiRequest('/api/im/friends', {
|
||||
method: 'DELETE',
|
||||
params: { appId: config.appId },
|
||||
})
|
||||
},
|
||||
|
||||
async setFriendGroup(friendId: string, groupName?: string): Promise<void> {
|
||||
const config = getConfig()
|
||||
await apiRequest(`/api/im/friends/${encodeURIComponent(friendId)}/group`, {
|
||||
method: 'PUT',
|
||||
params: {
|
||||
appId: config.appId,
|
||||
...(groupName ? { groupName } : {}),
|
||||
},
|
||||
})
|
||||
},
|
||||
|
||||
async listFriendGroups(): Promise<string[]> {
|
||||
const config = getConfig()
|
||||
const res = await apiRequest<string[] | { content?: string[] }>('/api/im/friends/groups', {
|
||||
params: { appId: config.appId },
|
||||
})
|
||||
return Array.isArray(res) ? res : (res.content ?? [])
|
||||
},
|
||||
|
||||
async listFriendsByGroup(groupName: string): Promise<string[]> {
|
||||
const config = getConfig()
|
||||
const res = await apiRequest<string[] | { content?: string[] }>(
|
||||
`/api/im/friends/groups/${encodeURIComponent(groupName)}`,
|
||||
{ params: { appId: config.appId } },
|
||||
)
|
||||
return Array.isArray(res) ? res : (res.content ?? [])
|
||||
},
|
||||
|
||||
async listFriendRequests(direction: 'incoming' | 'outgoing' = 'incoming'): Promise<FriendRequest[]> {
|
||||
const config = getConfig()
|
||||
const res = await apiRequest<FriendRequest[] | { content?: FriendRequest[] }>('/api/im/friend-requests', {
|
||||
@ -914,6 +985,13 @@ export const ImSDK = {
|
||||
})
|
||||
},
|
||||
|
||||
async checkBlacklist(targetUserId: string): Promise<BlacklistCheckResult> {
|
||||
const config = getConfig()
|
||||
return apiRequest<BlacklistCheckResult>('/api/im/blacklist/check', {
|
||||
params: { appId: config.appId, targetUserId },
|
||||
})
|
||||
},
|
||||
|
||||
async getProfile(userId: string): Promise<UserProfile> {
|
||||
const config = getConfig()
|
||||
return apiRequest<UserProfile>(`/api/im/accounts/${encodeURIComponent(userId)}`, {
|
||||
@ -977,6 +1055,7 @@ export const ImSDK = {
|
||||
unreadCount: model.unreadCount,
|
||||
isMuted: model.isMuted,
|
||||
isPinned: model.isPinned,
|
||||
conversationGroup: null,
|
||||
}))
|
||||
conversationMemory = conversations
|
||||
emitConversationMemory()
|
||||
@ -1013,6 +1092,7 @@ export const ImSDK = {
|
||||
unreadCount: c.unreadCount,
|
||||
isMuted: c.isMuted,
|
||||
isPinned: c.isPinned,
|
||||
conversationGroup: null,
|
||||
}))
|
||||
callback(data)
|
||||
})
|
||||
@ -1074,6 +1154,64 @@ export const ImSDK = {
|
||||
}
|
||||
},
|
||||
|
||||
async setConversationHidden(targetId: string, chatType: ChatType, hidden: boolean): Promise<void> {
|
||||
const config = getConfig()
|
||||
await apiRequest(`/api/im/conversations/${encodeURIComponent(targetId)}/hidden`, {
|
||||
method: 'PUT',
|
||||
params: {
|
||||
appId: config.appId,
|
||||
chatType,
|
||||
hidden: String(hidden),
|
||||
},
|
||||
})
|
||||
if (hidden) {
|
||||
deleteConversationMemory(targetId, chatType)
|
||||
}
|
||||
},
|
||||
|
||||
async setConversationGroup(targetId: string, chatType: ChatType, groupName?: string): Promise<void> {
|
||||
const config = getConfig()
|
||||
await apiRequest(`/api/im/conversations/${encodeURIComponent(targetId)}/group`, {
|
||||
method: 'PUT',
|
||||
params: {
|
||||
appId: config.appId,
|
||||
chatType,
|
||||
...(groupName ? { groupName } : {}),
|
||||
},
|
||||
})
|
||||
setConversationGroupMemory(targetId, chatType, groupName ?? null)
|
||||
},
|
||||
|
||||
async listConversationGroups(): Promise<string[]> {
|
||||
const config = getConfig()
|
||||
const res = await apiRequest<string[] | { content?: string[] }>('/api/im/conversation-groups', {
|
||||
params: { appId: config.appId },
|
||||
})
|
||||
return Array.isArray(res) ? res : (res.content ?? [])
|
||||
},
|
||||
|
||||
async listConversationGroupItems(groupName: string): Promise<ConversationGroupItem[]> {
|
||||
const config = getConfig()
|
||||
const res = await apiRequest<ConversationGroupItem[] | { content?: ConversationGroupItem[] }>(
|
||||
`/api/im/conversation-groups/${encodeURIComponent(groupName)}`,
|
||||
{ params: { appId: config.appId } },
|
||||
)
|
||||
return Array.isArray(res) ? res : (res.content ?? [])
|
||||
},
|
||||
|
||||
async adminGroupReadReceipts(groupId: string, messageIds: string[]): Promise<GroupReadReceiptSummary[]> {
|
||||
const config = getConfig()
|
||||
const res = await apiRequest<GroupReadReceiptSummary[] | { content?: GroupReadReceiptSummary[] }>(
|
||||
`/api/im/admin/groups/${encodeURIComponent(groupId)}/read-receipts`,
|
||||
{
|
||||
method: 'POST',
|
||||
params: { appId: config.appId },
|
||||
body: { messageIds },
|
||||
},
|
||||
)
|
||||
return Array.isArray(res) ? res : (res.content ?? [])
|
||||
},
|
||||
|
||||
async getDraft(targetId: string, chatType: ChatType): Promise<string> {
|
||||
const config = getConfig()
|
||||
if (ImDatabase.isInitialized()) {
|
||||
|
||||
@ -5,10 +5,19 @@ import { ImSDK as _ImSDK } from './ImSDK'
|
||||
export const listFriends = (): Promise<string[]> => _ImSDK.listFriends()
|
||||
export const addFriend = (friendId: string): Promise<void> => _ImSDK.addFriend(friendId)
|
||||
export const removeFriend = (friendId: string): Promise<void> => _ImSDK.removeFriend(friendId)
|
||||
export const removeAllFriends = (): Promise<void> => _ImSDK.removeAllFriends()
|
||||
export const setFriendGroup = (friendId: string, groupName?: string): Promise<void> => _ImSDK.setFriendGroup(friendId, groupName)
|
||||
export const listFriendGroups = (): ReturnType<typeof _ImSDK.listFriendGroups> => _ImSDK.listFriendGroups()
|
||||
export const listFriendsByGroup = (groupName: string): ReturnType<typeof _ImSDK.listFriendsByGroup> => _ImSDK.listFriendsByGroup(groupName)
|
||||
export const checkBlacklist = (targetUserId: string): ReturnType<typeof _ImSDK.checkBlacklist> => _ImSDK.checkBlacklist(targetUserId)
|
||||
export const searchUsers = (keyword: string, size?: number): ReturnType<typeof _ImSDK.searchUsers> => _ImSDK.searchUsers(keyword, size)
|
||||
export const searchGroups = (keyword: string, size?: number): ReturnType<typeof _ImSDK.searchGroups> => _ImSDK.searchGroups(keyword, size)
|
||||
export const searchMessages = (params: Parameters<typeof _ImSDK.searchMessages>[0]): ReturnType<typeof _ImSDK.searchMessages> => _ImSDK.searchMessages(params)
|
||||
export const editMessage = (messageId: string, content: string): ReturnType<typeof _ImSDK.editMessage> => _ImSDK.editMessage(messageId, content)
|
||||
export const setConversationHidden = (targetId: string, chatType: Parameters<typeof _ImSDK.setConversationHidden>[1], hidden: boolean): ReturnType<typeof _ImSDK.setConversationHidden> => _ImSDK.setConversationHidden(targetId, chatType, hidden)
|
||||
export const setConversationGroup = (targetId: string, chatType: Parameters<typeof _ImSDK.setConversationGroup>[1], groupName?: string): ReturnType<typeof _ImSDK.setConversationGroup> => _ImSDK.setConversationGroup(targetId, chatType, groupName)
|
||||
export const listConversationGroups = (): ReturnType<typeof _ImSDK.listConversationGroups> => _ImSDK.listConversationGroups()
|
||||
export const listConversationGroupItems = (groupName: string): ReturnType<typeof _ImSDK.listConversationGroupItems> => _ImSDK.listConversationGroupItems(groupName)
|
||||
export const locateHistoryPage = (toId: string, messageId: string, pageSize?: number, maxPages?: number): ReturnType<typeof _ImSDK.locateHistoryPage> => _ImSDK.locateHistoryPage(toId, messageId, pageSize, maxPages)
|
||||
export const locateGroupHistoryPage = (groupId: string, messageId: string, pageSize?: number, maxPages?: number): ReturnType<typeof _ImSDK.locateGroupHistoryPage> => _ImSDK.locateGroupHistoryPage(groupId, messageId, pageSize, maxPages)
|
||||
export { ImClient } from './ImClient'
|
||||
@ -18,11 +27,14 @@ export type {
|
||||
ImMessage, ImGroup, ChatType, MsgType, MsgStatus,
|
||||
ImEventListener, SendMessageParams,
|
||||
ConversationData,
|
||||
ConversationGroupItem,
|
||||
HistoryQuery,
|
||||
PageResult,
|
||||
FriendRequest,
|
||||
GroupJoinRequest,
|
||||
BlacklistEntry,
|
||||
BlacklistCheckResult,
|
||||
GroupReadReceiptSummary,
|
||||
UserProfile,
|
||||
} from './types'
|
||||
export { uploadFile } from './upload'
|
||||
|
||||
@ -65,6 +65,8 @@ export interface ImGroup {
|
||||
memberIds: string
|
||||
adminIds: string
|
||||
announcement?: string | null
|
||||
memberInfo?: string | null
|
||||
extAttributes?: string | null
|
||||
createdAt: number
|
||||
}
|
||||
|
||||
@ -77,6 +79,13 @@ export interface ConversationData {
|
||||
unreadCount: number
|
||||
isMuted: boolean
|
||||
isPinned: boolean
|
||||
conversationGroup?: string | null
|
||||
}
|
||||
|
||||
export interface ConversationGroupItem {
|
||||
targetId: string
|
||||
chatType: ChatType
|
||||
groupName: string
|
||||
}
|
||||
|
||||
export interface HistoryQuery {
|
||||
@ -130,6 +139,21 @@ export interface BlacklistEntry {
|
||||
createdAt: number
|
||||
}
|
||||
|
||||
export interface BlacklistCheckResult {
|
||||
targetUserId: string
|
||||
blockedByMe: boolean
|
||||
blockedByTarget: boolean
|
||||
eitherBlocked: boolean
|
||||
}
|
||||
|
||||
export interface GroupReadReceiptSummary {
|
||||
messageId: string
|
||||
groupId: string
|
||||
memberCount: number
|
||||
readCount: number
|
||||
unreadCount: number
|
||||
}
|
||||
|
||||
export interface UserProfile {
|
||||
id?: string
|
||||
appId?: string
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户