@rongcloud/imkit-store
Version:
RongCloud IM UIKit Store
870 lines (856 loc) • 23.9 kB
TypeScript
import * as mobx from 'mobx';
import { ObservableMap } from 'mobx';
import * as _rongcloud_engine from '@rongcloud/engine';
import { FileType, IAsyncRes, ILogger, PluginContext, IConversationOption as IConversationOption$1, ConversationType as ConversationType$1, RCConnectionStatus } from '@rongcloud/engine';
import { LogL, ConversationType, IAReceivedMessage, NotificationLevel, ReadReceiptInfoV5, BaseMessage, ISendMessageOptions, IConversationOption, IAsyncRes as IAsyncRes$1, GetHistoryMessageResult, ITypingUser, ErrorCode, LogDBProxy } from '@rongcloud/imlib-next';
/**
* 上传信息
* @category Interface
*/
interface IKitUploadInfo {
file?: File;
path?: string;
buffer?: ArrayBuffer;
fileName?: string;
fileSize: number;
fileType: FileType;
duration?: number;
onProgress?: (progress: number) => void;
onComplete?: (res: IAsyncRes<IKitUploadCompleteData>) => void;
}
/**
* 上传请求数据接口
* 用于外部调用者发起请求
* @category Interface
*/
interface IKitUploadRequestData {
url: string;
headers: Record<string, string>;
body: Record<string, string> | ArrayBuffer | any;
contentType?: string;
method: 'PUT' | 'POST';
filePath?: string;
}
/**
* @hidden
*/
interface IKitUploadResult {
name: string;
downloadUrl: string;
uniqueName: string;
size: number;
type: string;
/**
* 音频时长,单位秒
*/
duration?: number;
length?: number;
/**
* 图片缩略图
*/
thumbnail?: string;
/**
* 图片宽度
*/
width?: number;
/**
* 图片高度
*/
height?: number;
}
/**
* 图片信息
* @category Interface
*/
interface IKitImageInfo {
/**
* 图片缩略图的 base64 数据
*/
thumbnail?: string;
/**
* 图片宽度
*/
width?: number;
/**
* 图片高度
*/
height?: number;
}
/**
* 缩略图配置
* @category Interface
*/
interface IKitThumbnailConfig {
/**
* 最大高度
*/
maxHeight?: number;
/**
* 最大宽度
*/
maxWidth?: number;
/**
* 图片质量
*/
quality?: number;
/**
* 缩放比例
*/
scale?: number;
}
/**
* 上传完成返回数据信息
* @category Interface
*/
interface IKitUploadCompleteData {
downloadUrl: string;
msg?: string;
}
/**
* 上传请求协议接口
* 由外部实现,用于执行上传请求
* @category class
*/
declare abstract class AKitUploadRequest {
uploadInfo: IKitUploadInfo;
protected _abortStatus: boolean;
/**
* @hidden
*/
constructor(info: IKitUploadInfo);
/**
* 执行上传请求
* @returns 上传结果
*/
abstract execute(data: IKitUploadRequestData): Promise<IAsyncRes<IKitUploadResult>>;
/**
* 取消上传请求
*/
abort(): void;
isAbort(): boolean;
}
/**
* store 初始化参数
* @category Interface
*/
interface IRCStoreInitOpts {
/**
* 日志输出等级,默认值 `LogL.WARN(2)`
*/
logLevel?: LogL.DEBUG | LogL.INFO | LogL.WARN | LogL.ERROR;
/**
* 业务数据模块钩子,用于向 SDK 注入用户信息、群组信息等。
*/
hooks?: IKitServiceHooks;
}
/**
* 会话信息
* @category Interface
*/
interface IKitConversation {
/**
* 根据 targetId、conversationType、channelId 生成的唯一标识
*/
key: string;
targetId: string;
conversationType: ConversationType;
channelId: string;
name: string;
nickName: string;
portraitUri: string;
draft: string;
latestMessage: IAReceivedMessage | null;
isTop: boolean;
notificationLevel: NotificationLevel;
unreadCount: number;
updateTime: number;
memberCount: number;
readReceiptInfo?: ReadReceiptInfoV5;
}
/**
* @hidden
*/
type CacheType<T> = ObservableMap<string, {
data: T;
expires: number;
pending: boolean;
}>;
/**
* Profile 基础信息
* @category Interface
* @hidden
*/
interface IBaseProfile {
/**
* 唯一标识
*/
id: string;
/**
* 名称
*/
name: string;
/**
* 头像
*/
portraitUri?: string;
}
/**
* 用户信息
* @category Interface
*/
interface IUserProfile extends IBaseProfile {
/**
* 用户备注
*/
remark?: string;
}
/**
* 群组信息
* @category Interface
*/
interface IGroupProfile extends IBaseProfile {
/**
* 群组成员数量
*/
memberCount: number;
/**
* 群组备注
*/
remark?: string;
}
/**
* 系统信息
* @category Interface
*/
interface ISystemProfile extends IBaseProfile {
}
/**
* 群组成员信息
* @category Interface
*/
interface IGroupMemberProfile {
/**
* 群成员昵称
*/
groupNickname: string;
/**
* 用户信息
*/
user: {
/**
* 用户 ID
*/
id: string;
/**
* 用户昵称
*/
nickname: string;
/**
* 用户头像
*/
portraitUri?: string;
};
}
/**
* 数据源接口约束
* @hidden
*/
interface IDataSource {
getUserProfile(userIds: string[]): Promise<IUserProfile[]>;
getGroupProfile(groupIds: string[]): Promise<IGroupProfile[]>;
getSystemProfile(systemIds: string[]): Promise<ISystemProfile[]>;
getGroupMembers(groupId: string): Promise<IGroupMemberProfile[]>;
}
/**
* 用户信息回调钩子
* @category Interface
*/
interface IKitServiceHooks {
/**
* 根据 userId 批量获取用户信息
* @param userIds - 用户 ID 列表
*/
reqUserProfiles?(userIds: string[]): Promise<IUserProfile[]>;
/**
* 根据 groupId 批量获取群组信息
* @param groupIds - 群组 ID 列表
*/
reqGroupProfiles?(groupIds: string[]): Promise<IGroupProfile[]>;
/**
* 批量获取系统会话信息,当会话列表中存在 ConversationType.SYSTEM 类型时,会调用此方法获取系统会话信息
* @param targetIds - 系统会话 ID 列表
*/
reqSystemProfiles?(targetIds: string[]): Promise<ISystemProfile[]>;
/**
* 根据 groupId 获取群组成员列表信息
* @param groupId - 群组 ID
*/
reqGroupMembers?(groupId: string): Promise<IGroupMemberProfile[]>;
}
/**
* 消息信息
* @category Interface
*/
interface IKitMessage extends IKitMessageCache {
user: {
nickname: string;
portraitUri: string;
groupNickname?: string;
};
}
/**
* @category Interface
*/
interface IKitMessageCache extends IAReceivedMessage {
/**
* 媒体消息本地临时路径
*/
localTmpPath?: string;
/**
* V5 已读信息(UI 绑定使用)
*/
readReceiptInfo?: ReadReceiptInfoV5;
}
/**
* 内存态会话更新信息
* @category Interface
*/
interface IConversationUpdate {
/**
* 置顶变更
*/
isTop?: boolean;
/**
* 免打扰状态变更
*/
notificationLevel?: NotificationLevel;
/**
* 未读数变更
*/
unreadCount?: number;
/**
* 会话最后一条消息变更
*/
latestMessage?: IAReceivedMessage | null;
/**
* 会话草稿变更
*/
draft?: string;
/**
* 会话最新消息的 V5 已读信息变更
*/
readReceiptInfo?: ReadReceiptInfoV5;
}
/**
* 媒体消息参数
* @category Interface
*/
interface IKitMediaMessageOptions {
/**
* 会话 key
*/
conversationKey: string;
/**
* 消息
*/
message: BaseMessage;
/**
* 发送消息选项
*/
sendOptions?: ISendMessageOptions;
/**
* 上传信息
*/
info: IKitUploadInfo;
/**
* 上传请求器
*/
request: AKitUploadRequest;
}
/**
* 消息列表状态管理
* @category class
*/
declare class RCKitMessageStore {
#private;
private readonly _logger;
private rootStore;
private _context;
/**
* @hidden
*/
constructor(_logger: ILogger, rootStore: RCKitStore, _context: PluginContext);
getMessages(conversationKey: string): IKitMessage[];
/**
* 根据会话信息 + messageUId 获取内存中的消息对象(若存在)
*/
getMessageByUid(conversation: IConversationOption, messageUId: string): IKitMessage | undefined;
/**
* 获取历史消息
* @param conversationKey 会话ID
* @param endTime 结束时间戳, 精确到 ms
* @param lastMsgUId 上次查询的最后一条消息的 messageUId, 第一次不填
* @param limit 查询的数量, 默认 20
* @returns
*/
getHistoryMsgList(conversationKey: string, endTime: number, lastMsgUId?: string, limit?: number): Promise<IAsyncRes$1<GetHistoryMessageResult>>;
/**
* 从消息队列尾部插入一条消息,如果缓存中不存在消息所在会话,则不做任何操作
* @param message 消息对象
* @param isTrim 是否需要移除超出队列缓存上限部分,默认为 true
*/
insertMessage(message: IKitMessageCache, isTrim?: boolean, isLog?: boolean): IKitMessageCache;
/**
* 更新缓存中的消息,如果缓存中不存在则不做任何操作
* @param message 消息对象
* @returns
*/
updateCatchedMessage(message: IKitMessageCache): void;
/**
* 移除一条缓存中的消息
* @param message 消息对象
*/
removeCatchedMessage(message: Pick<IAReceivedMessage, 'conversationType' | 'targetId' | 'channelId' | 'messageUId' | 'messageId'>): void;
/**
* 撤回消息
* @param message 消息对象
*/
recallMessage(message: IAReceivedMessage): Promise<_rongcloud_engine.RCResult<IAReceivedMessage>>;
/**
* 发送消息
* @param message 消息实例
*/
sendMessage(conversationKey: string, message: BaseMessage, options: ISendMessageOptions): Promise<IAsyncRes$1<IAReceivedMessage>>;
/**
* 发送媒体消息
*/
sendMediaMessage(mediaOptions: IKitMediaMessageOptions): Promise<IAsyncRes$1<IAReceivedMessage>>;
/**
* 发送 V5 回执(对当前会话内指定消息)
* messageUIds 需要根据内存态消息存储做校验去重、过滤缓存中非接收向、已有回执或不存在的消息
*/
sendV5Receipts(conversation: IConversationOption, messageUIds: string[]): Promise<void>;
/**
* 拉取并绑定 V5 已读信息,刷新 UI
*/
fetchReadReceiptV5(conversation: IConversationOption, messageUIds: string[]): Promise<void>;
/**
* 获取指定消息的已读/未读用户(V5)- 分页接口
*
* @param conversation 会话
* @param messageUId 消息 UId
* @param options.type 可选,0=已读,1=未读;不传则同时查询两个列表
* @param options.pageTokenRead 已读列表翻页 token(当 type 为 0 或未传时生效)
* @param options.pageTokenUnread 未读列表翻页 token(当 type 为 1 或未传时生效)
* @param options.pageCount 每页数量,默认 100
* @param options.order 排序,默认 0(按阅读时间降序)
*/
getReadReceiptUsersV5(conversation: IConversationOption, messageUId: string, options?: {
type?: 0 | 1;
pageTokenRead?: string;
pageTokenUnread?: string;
pageCount?: number;
order?: 0 | 1;
}): Promise<{
read: {
list: {
id: string;
name: string;
portraitUri?: string | undefined;
timestamp?: number | undefined;
}[];
total: number;
pageToken: string | undefined;
};
unread: {
list: {
id: string;
name: string;
portraitUri?: string | undefined;
timestamp?: number | undefined;
}[];
total: number;
pageToken: string | undefined;
};
}>;
/**
* 转发消息
* @param conversationKey 会话ID
* @param message 消息列表
*/
forwardMessage(conversationKey: string, message: IAReceivedMessage): Promise<{
code: number;
data?: IAReceivedMessage | undefined;
}>;
/**
* 取消指定消息的上传请求
* @param messageId 消息ID
*/
cancelSendMediaMessage(messageId: number): void;
/**
* 获取选中的消息
*/
getSelectedMessages(): IKitMessage[];
/**
* 设置选中的消息
* @param messages 消息列表
*/
setSelectedMessages(messages: IKitMessage[]): void;
/**
* 清理超出缓存上限的消息
* @param conversationKey 会话ID
* @hidden
*/
clearExcessMessage(conversationKey: string): void;
destroy(): void;
/**
* 清理内存数据
*/
clearMemoryData(): void;
}
/**
* Typing 状态管理器
* - 发送端:同一会话 6s 内只发一次 typing
* - 接收端:维护会话下的 typing 用户列表,超时自动消失(基于 SDK 事件,SDK 自身会 6s 过期刷新)
*/
declare class RCKitTypingStore {
#private;
/** 6 秒防抖间隔 */
static readonly DISAPPEAR_INTERVAL = 6000;
/** 支持 typing 的会话类型仅单聊 */
static readonly typingSupportTypes: ConversationType[];
/** key: `${conversationType};;;${targetId};;;${channelId||''}` → value: Map<userId, ITypingUser> */
typingMap: mobx.ObservableMap<string, Map<string, ITypingUser>>;
constructor();
dispose(): void;
/** 发送 typing 状态(限 ConversationType.PRIVATE) */
sendTyping(conversation: IConversationOption, typingContentType: string): Promise<void>;
/**
* 是否显示“正在输入中...”,并返回 typing 的用户列表
* 返回值说明:
* - active: 是否有正在输入/说话的用户
* - list: typing 用户详细信息列表(ITypingUser)
*/
isTyping(conversation: IConversationOption): {
active: boolean;
list: ITypingUser[];
};
/** 发送端:发送了真实消息后,解除该会话 6s typing 发送限制 */
releaseTypingThrottle(conversation: IConversationOption): void;
getTypingMapKey(conversation: IConversationOption): string;
}
/**
* 会话管理模块
* @category class
*/
declare class RCKitConversationStore {
#private;
private _kitStore;
/**
* 当前打开的会话信息
*/
openedConversation: IKitConversation | null;
/**
* 内存太缓存会话列表
*/
conversations: IKitConversation[];
/**
* @hidden
*/
constructor(_kitStore: RCKitStore, _logger: ILogger);
/**
* 获取更多会话(分页)
*
* 根据会话对象获取更多会话,若传入 null 则获取首页
* @param conversation 类型为 IKitConversation 的会话对象
* @param count 获取数量
* @returns 会话列表
*/
getConversations(conversation?: IKitConversation | null, count?: number): {
hasMore: boolean;
code: _rongcloud_engine.ErrorCode;
list: IKitConversation[];
isFirstScreen: boolean;
} | undefined;
/**
* 打开会话
*
* 传递 null 为清空当前选中会话
* @param conversation 会话对象
*/
openConversation(conversation: IKitConversation | null): void;
/**
* 创建会话缓存数据对象,若已存在则直接返回
* @param conversation 会话对象
*/
createCachedConversation(conversation: IConversationOption$1): IKitConversation;
/**
* 删除会话
* 可通过 trans2ConversationKey 生成会话 key
* @param conversationKey 会话 key
*/
removeConversation(conversationKey: string): void;
/**
* 更新会话缓存数据
* @param conversationKey 会话 key
* @param data 会话更新数据
*/
updateCacheConversation(conversationKey: string, data: IConversationUpdate): void;
/**
* 获取所有会话的未读消息总数
*/
getTotalUnreadCount(): number;
/**
* 清除会话未读消息
* 可通过 trans2ConversationKey 生成会话 key
* @param conversationKey 会话 key
*/
clearUnreadCount(conversationKey: string): Promise<void>;
/**
* 清理内存数据
*/
clearMemoryData(): void;
/**
* 销毁
*/
destroy(): void;
}
/**
* 语音转文字内存态管理器
* - 仅缓存成功结果,按 messageUId 作为 key
* - LRU 上限 200 条
*/
declare class SpeechToTextStore {
#private;
private readonly _logger;
/** 仅存储成功转换的文本结果(可观察 Map,确保 UI 响应式) */
cache: mobx.ObservableMap<string, string>;
/** 正在转换中的 messageUId 集合 */
converting: mobx.ObservableSet<string>;
/** 转换失败的 messageUId 集合(用于 UI 标记,可重试) */
error: mobx.ObservableSet<string>;
/** 缓存最大条数(LRU) */
static readonly MAX_CACHE_SIZE = 200;
/** 请求超时时间(毫秒) */
static readonly REQUEST_TIMEOUT = 30000;
constructor(_logger: ILogger);
/** 获取转换文本(命中缓存时返回) */
getSTTText(messageUId: string): string | undefined;
/** 是否处于转换中 */
isConverting(messageUId: string): boolean;
/** 是否处于失败态 */
hasError(messageUId: string): boolean;
/**
* 发起语音转文字请求:若缓存命中或正在转换则直接返回 SUCCESS
*/
requestForMessage(message: Pick<IAReceivedMessage, 'messageUId' | 'messageType' | 'content'>): Promise<ErrorCode>;
/** 清理内存态数据 */
clearMemoryData(): void;
/** 销毁 */
destroy(): void;
}
/**
* 群组成员缓存
* @category class
*/
declare class GroupMembersCache {
#private;
private logger;
private dataSource;
/**
* @hidden
*/
constructor(logger: ILogger, dataSource: IDataSource);
/**
* 初始化群组成员信息
* @param groupId 群组 ID
* @hidden
*/
initGroupMembers(groupId: string): Promise<void>;
/**
* 获取群组成员信息
* @param groupId 群组 ID
*/
getGroupMembers(groupId: string): IGroupMemberProfile[];
/**
* 获取群组成员信息
* @param groupId 群组 ID
* @param userId 用户 ID
*/
getGroupMember(groupId: string, userId: string): IGroupMemberProfile | undefined;
/**
* 获取群组成员信息 map
* @param groupId 群组 ID
* @hidden
*/
getGroupMemberMap(groupId: string): Map<string, IGroupMemberProfile>;
/**
* 清理内存数据
*/
clearMemoryData(): void;
}
/**
* 用户数据模块
* @category class
*/
declare class AppDataModule {
#private;
private logger;
groupMembersCache: GroupMembersCache;
/**
* @hidden
*/
constructor(logger: ILogger, hooks?: IKitServiceHooks);
/**
* 获取用户信息
* @param userId - 用户 ID
* @returns 用户信息
*/
getUserProfile(userId: string): IUserProfile | undefined;
/**
* 获取群组信息
* @param groupId - 群组 ID
* @returns 群组信息
*/
getGroupProfile(groupId: string): IGroupProfile | undefined;
/**
* 获取系统信息
* @param systemId - 系统 ID
* @returns 系统信息
*/
getSystemProfile(systemId: string): ISystemProfile | undefined;
/**
* 获取本地用户信息
* @param userId - 用户 ID
* @returns 用户信息
*/
getUserInfo(userId: string): IUserProfile | undefined;
/**
* @hidden
*/
getUsersCache(): CacheType<IUserProfile>;
/**
* @hidden
*/
getGroupsCache(): CacheType<IGroupProfile>;
/**
* @hidden
*/
getSystemsCache(): CacheType<ISystemProfile>;
/**
* 更新用户信息
* 如果 profile 不为空,查询缓存中是否存在,如果存在,更新缓存,如果不存在,则添加到缓存中
* 如果 profile 为空,请求远端数据补充到缓存中
* @param userId - 用户 ID
* @param profile - 用户信息
*/
updateUserProfile(userId: string, profile?: IUserProfile): void;
/**
* 更新群组信息
* @param groupId - 群组 ID
* @param profile - 群组信息
* 如果 profile 不为空,查询缓存中是否存在,如果存在,更新缓存,如果不存在,则添加到缓存中
* 如果 profile 为空,请求远端数据补充到缓存中
*/
updateGroupProfile(groupId: string, profile?: IGroupProfile): void;
/**
* 更新系统信息
* @param systemId - 系统 ID
* @param profile - 系统信息
* 如果 profile 不为空,查询缓存中是否存在,如果存在,更新缓存,如果不存在,则添加到缓存中
* 如果 profile 为空,请求远端数据补充到缓存中
*/
updateSystemProfile(systemId: string, profile?: ISystemProfile): void;
/**
* 获取会话信息
* @param id - 会话 ID
* @param type - 类型
* @returns 会话信息
*/
getProfileSync(id: string, type: ConversationType$1): Promise<IUserProfile | IGroupProfile | ISystemProfile | undefined>;
/**
* 清理内存数据
*/
clearMemoryData(): void;
}
/**
* @category class
*/
declare class RCKitStore {
#private;
private _context;
private readonly _logger;
private _option;
/**
* 消息状态管理器
*/
messageStore: RCKitMessageStore;
/**
* 会话状态管理器
*/
conversationStore: RCKitConversationStore;
/**
* 输入状态管理器
*/
typingStore: RCKitTypingStore;
/**
* 语音转文字状态管理器
*/
speechToTextStore: SpeechToTextStore;
/**
* 用户数据模块
*/
appData: AppDataModule;
/**
* 当前用户 Id
*/
currentUserId: string;
/**
* 当前连接状态
*/
connectStatus: mobx.IObservableValue<RCConnectionStatus>;
get enableReadV5(): boolean;
/**
* @hidden
*/
constructor(_context: PluginContext, _logger: ILogger, _option: IRCStoreInitOpts);
/**
* 设置已读 V5 开关(结合服务端 getAppSettings 结果)
*/
setEnableReadV5(enable: boolean): void;
private _onConnected;
private _onDisconnected;
private _onSuspend;
private _onConnecting;
/**
* 销毁
*/
destroy(): void;
/**
* 清理内存数据
*/
clearMemoryData(): void;
}
/**
* kit store 初始化
* @param option 初始化参数
* @category function
*/
declare const RCKitStoreInstaller: (option: IRCStoreInitOpts) => RCKitStore | null;
/**
* 根据会话 targetId、conversationType、channelId 生成的唯一标识
* @category function
*/
declare const trans2ConversationKey: (conversation: IConversationOption$1) => string;
/**
* 创建日志代理
* 1. 日志代理需要运行在 uni-app 环境
* 2. 日志代理仅支持 CustomLogPlatform 中的平台
* @returns 日志代理
*/
declare function createIMLogProxy(): Promise<LogDBProxy | null>;
/**
* 销毁日志代理
*/
declare function destroyIMLogProxy(): void;
export { AKitUploadRequest, AppDataModule, CacheType, GroupMembersCache, IBaseProfile, IConversationUpdate, IDataSource, IGroupMemberProfile, IGroupProfile, IKitConversation, IKitImageInfo, IKitMediaMessageOptions, IKitMessage, IKitMessageCache, IKitServiceHooks, IKitThumbnailConfig, IKitUploadCompleteData, IKitUploadInfo, IKitUploadRequestData, IKitUploadResult, IRCStoreInitOpts, ISystemProfile, IUserProfile, RCKitConversationStore, RCKitMessageStore, RCKitStore, RCKitStoreInstaller, RCKitTypingStore, createIMLogProxy, destroyIMLogProxy, trans2ConversationKey };