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 { MessageSearchParams } from './db/ImDatabase'
|
||||||
import type {
|
import type {
|
||||||
BlacklistEntry,
|
BlacklistEntry,
|
||||||
|
BlacklistCheckResult,
|
||||||
ChatType,
|
ChatType,
|
||||||
ConversationData,
|
ConversationData,
|
||||||
|
ConversationGroupItem,
|
||||||
FriendRequest,
|
FriendRequest,
|
||||||
|
GroupReadReceiptSummary,
|
||||||
GroupJoinRequest,
|
GroupJoinRequest,
|
||||||
ImEventListener,
|
ImEventListener,
|
||||||
ImGroup,
|
ImGroup,
|
||||||
@ -103,6 +106,7 @@ function normalizeConversation(item: {
|
|||||||
unreadCount: number
|
unreadCount: number
|
||||||
isMuted: boolean
|
isMuted: boolean
|
||||||
isPinned: boolean
|
isPinned: boolean
|
||||||
|
conversationGroup?: string | null
|
||||||
}): ConversationData {
|
}): ConversationData {
|
||||||
return {
|
return {
|
||||||
targetId: item.targetId,
|
targetId: item.targetId,
|
||||||
@ -113,6 +117,7 @@ function normalizeConversation(item: {
|
|||||||
unreadCount: item.unreadCount,
|
unreadCount: item.unreadCount,
|
||||||
isMuted: item.isMuted,
|
isMuted: item.isMuted,
|
||||||
isPinned: item.isPinned,
|
isPinned: item.isPinned,
|
||||||
|
conversationGroup: item.conversationGroup ?? null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,6 +177,15 @@ function setConversationPinnedMemory(targetId: string, chatType: ChatType, pinne
|
|||||||
emitConversationMemory()
|
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 {
|
function deleteConversationMemory(targetId: string, chatType: ChatType): void {
|
||||||
conversationMemory = conversationMemory.filter(
|
conversationMemory = conversationMemory.filter(
|
||||||
item => !(item.targetId === targetId && item.chatType === chatType),
|
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> {
|
async dismissGroup(groupId: string): Promise<void> {
|
||||||
await apiRequest(`/api/im/groups/${encodeURIComponent(groupId)}`, { method: 'DELETE' })
|
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[]> {
|
async listFriendRequests(direction: 'incoming' | 'outgoing' = 'incoming'): Promise<FriendRequest[]> {
|
||||||
const config = getConfig()
|
const config = getConfig()
|
||||||
const res = await apiRequest<FriendRequest[] | { content?: FriendRequest[] }>('/api/im/friend-requests', {
|
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> {
|
async getProfile(userId: string): Promise<UserProfile> {
|
||||||
const config = getConfig()
|
const config = getConfig()
|
||||||
return apiRequest<UserProfile>(`/api/im/accounts/${encodeURIComponent(userId)}`, {
|
return apiRequest<UserProfile>(`/api/im/accounts/${encodeURIComponent(userId)}`, {
|
||||||
@ -977,6 +1055,7 @@ export const ImSDK = {
|
|||||||
unreadCount: model.unreadCount,
|
unreadCount: model.unreadCount,
|
||||||
isMuted: model.isMuted,
|
isMuted: model.isMuted,
|
||||||
isPinned: model.isPinned,
|
isPinned: model.isPinned,
|
||||||
|
conversationGroup: null,
|
||||||
}))
|
}))
|
||||||
conversationMemory = conversations
|
conversationMemory = conversations
|
||||||
emitConversationMemory()
|
emitConversationMemory()
|
||||||
@ -1013,6 +1092,7 @@ export const ImSDK = {
|
|||||||
unreadCount: c.unreadCount,
|
unreadCount: c.unreadCount,
|
||||||
isMuted: c.isMuted,
|
isMuted: c.isMuted,
|
||||||
isPinned: c.isPinned,
|
isPinned: c.isPinned,
|
||||||
|
conversationGroup: null,
|
||||||
}))
|
}))
|
||||||
callback(data)
|
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> {
|
async getDraft(targetId: string, chatType: ChatType): Promise<string> {
|
||||||
const config = getConfig()
|
const config = getConfig()
|
||||||
if (ImDatabase.isInitialized()) {
|
if (ImDatabase.isInitialized()) {
|
||||||
|
|||||||
@ -5,10 +5,19 @@ import { ImSDK as _ImSDK } from './ImSDK'
|
|||||||
export const listFriends = (): Promise<string[]> => _ImSDK.listFriends()
|
export const listFriends = (): Promise<string[]> => _ImSDK.listFriends()
|
||||||
export const addFriend = (friendId: string): Promise<void> => _ImSDK.addFriend(friendId)
|
export const addFriend = (friendId: string): Promise<void> => _ImSDK.addFriend(friendId)
|
||||||
export const removeFriend = (friendId: string): Promise<void> => _ImSDK.removeFriend(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 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 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 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 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 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 const locateGroupHistoryPage = (groupId: string, messageId: string, pageSize?: number, maxPages?: number): ReturnType<typeof _ImSDK.locateGroupHistoryPage> => _ImSDK.locateGroupHistoryPage(groupId, messageId, pageSize, maxPages)
|
||||||
export { ImClient } from './ImClient'
|
export { ImClient } from './ImClient'
|
||||||
@ -18,11 +27,14 @@ export type {
|
|||||||
ImMessage, ImGroup, ChatType, MsgType, MsgStatus,
|
ImMessage, ImGroup, ChatType, MsgType, MsgStatus,
|
||||||
ImEventListener, SendMessageParams,
|
ImEventListener, SendMessageParams,
|
||||||
ConversationData,
|
ConversationData,
|
||||||
|
ConversationGroupItem,
|
||||||
HistoryQuery,
|
HistoryQuery,
|
||||||
PageResult,
|
PageResult,
|
||||||
FriendRequest,
|
FriendRequest,
|
||||||
GroupJoinRequest,
|
GroupJoinRequest,
|
||||||
BlacklistEntry,
|
BlacklistEntry,
|
||||||
|
BlacklistCheckResult,
|
||||||
|
GroupReadReceiptSummary,
|
||||||
UserProfile,
|
UserProfile,
|
||||||
} from './types'
|
} from './types'
|
||||||
export { uploadFile } from './upload'
|
export { uploadFile } from './upload'
|
||||||
|
|||||||
@ -65,6 +65,8 @@ export interface ImGroup {
|
|||||||
memberIds: string
|
memberIds: string
|
||||||
adminIds: string
|
adminIds: string
|
||||||
announcement?: string | null
|
announcement?: string | null
|
||||||
|
memberInfo?: string | null
|
||||||
|
extAttributes?: string | null
|
||||||
createdAt: number
|
createdAt: number
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +79,13 @@ export interface ConversationData {
|
|||||||
unreadCount: number
|
unreadCount: number
|
||||||
isMuted: boolean
|
isMuted: boolean
|
||||||
isPinned: boolean
|
isPinned: boolean
|
||||||
|
conversationGroup?: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ConversationGroupItem {
|
||||||
|
targetId: string
|
||||||
|
chatType: ChatType
|
||||||
|
groupName: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface HistoryQuery {
|
export interface HistoryQuery {
|
||||||
@ -130,6 +139,21 @@ export interface BlacklistEntry {
|
|||||||
createdAt: number
|
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 {
|
export interface UserProfile {
|
||||||
id?: string
|
id?: string
|
||||||
appId?: string
|
appId?: string
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户