k2-im 0.1.32 → 0.1.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/browser.d.ts CHANGED
@@ -382,5 +382,27 @@ interface CreateBrowserApiProtocolClientInput extends Omit<ApiProtocolClientDepe
382
382
  */
383
383
  declare function createLazyBrowserApiProtocolClient(input: CreateBrowserApiProtocolClientInput, createClient?: (input: CreateBrowserApiProtocolClientInput) => Promise<ApiProtocolClient>): ApiProtocolClient;
384
384
 
385
- export { createLazyBrowserApiProtocolClient };
386
- export type { ApiProtocolClient };
385
+ /** 浏览器图片复制的数据来源;消息读取由 Chat Kit 提供,页面生命周期由宿主提供。 */
386
+ interface ImageClipboardSource {
387
+ /** 返回高清图片的明文 Blob。 */
388
+ loadOriginal: () => Promise<Blob>;
389
+ /** 高清读取或转码失败时,返回当前图片的缩略图。 */
390
+ loadThumbnail: () => Promise<Blob>;
391
+ /** 每个异步步骤完成后检查账号、会话及当前操作是否仍有效。 */
392
+ isCurrent: () => boolean;
393
+ }
394
+ /** 只检查 API 是否存在;浏览器权限拒绝仍由实际复制 Promise 报错。 */
395
+ declare function canCopyImageToClipboard(): boolean;
396
+ /**
397
+ * 在用户点击的同步调用栈内启动图片复制,返回最终复制的是高清图还是缩略图。
398
+ * 高清下载、解密或转码失败时,在同一个 ClipboardItem Promise 内尝试缩略图;两者失败则拒绝。
399
+ * 图片写入失败时再尝试一次缩略图;权限、安全或用户激活拒绝立即交由宿主提示。
400
+ * 传入非空 text 时复制高清图片和文字,图文失败改为只写文字,返回 text;失效取消不触发降级。
401
+ * 宿主必须直接调用,不能先 await 下载;账号切换或关闭页面应让 isCurrent 返回 false。
402
+ * @example
403
+ * await copyImageToClipboard({ loadOriginal, loadThumbnail, isCurrent });
404
+ */
405
+ declare function copyImageToClipboard(source: ImageClipboardSource, text?: string): Promise<'original' | 'thumbnail' | 'text'>;
406
+
407
+ export { canCopyImageToClipboard, copyImageToClipboard, createLazyBrowserApiProtocolClient };
408
+ export type { ApiProtocolClient, ImageClipboardSource };
package/dist/browser.js CHANGED
@@ -1 +1 @@
1
- export{B as createLazyBrowserApiProtocolClient}from'./chunk-GAAHNTJM.js';import'./chunk-QQ23QYWK.js';import'./chunk-WOT6VMZA.js';
1
+ export{Ta as canCopyImageToClipboard,Ua as copyImageToClipboard,B as createLazyBrowserApiProtocolClient}from'./chunk-OFXCH5DZ.js';import'./chunk-F6DQBWJW.js';import'./chunk-WOT6VMZA.js';
@@ -43,7 +43,7 @@ interface ConversationDraft$1 {
43
43
  updatedAt: number;
44
44
  }
45
45
  /** 消息内容类型。sticker=表情/贴图(BMessage contentType=7);call=单聊通话记录(contentType=10);transfer=转账(contentType=16);gift=礼品/刮刮卡(contentType=17);robot=机器人卡片(contentType=18);miniProgram=小程序分享卡(contentType=22);redPacket=红包卡(contentType=25);game=小游戏(contentType=27);未知 wire 正文统一归一为 unknown。 */
46
- type MessageContentType = 'text' | 'system' | 'image' | 'video' | 'voice' | 'file' | 'sticker' | 'contact' | 'miniProgram' | 'game' | 'transfer' | 'gift' | 'call' | 'redPacket' | 'mediaAlbum' | 'robot' | 'unknown';
46
+ type MessageContentType = 'text' | 'system' | 'image' | 'video' | 'voice' | 'file' | 'sticker' | 'contact' | 'miniProgram' | 'game' | 'transfer' | 'gift' | 'call' | 'redPacket' | 'mediaAlbum' | 'filesAlbum' | 'robot' | 'unknown';
47
47
  /**
48
48
  * 发送态(客户端态):消息从本地创建到服务端确认的生命周期。
49
49
  * `uploading` 仅媒体消息使用:文件上传阶段(uploading→pending→sending→sent);
@@ -125,6 +125,12 @@ type LastMessageSummary = {
125
125
  kind: 'voice';
126
126
  durationMs?: number;
127
127
  }
128
+ /** 文件合集的有序文件数量与可选配文,文案由 i18n 决定。 */
129
+ | {
130
+ kind: 'filesAlbum';
131
+ count: number;
132
+ caption?: string;
133
+ }
128
134
  /**
129
135
  * 媒体合集(contentType 28)。
130
136
  *
@@ -217,6 +223,13 @@ interface ImVideoBody {
217
223
  /** 文件加密类型:1=不加密,3=完整 TEA(BMessage.fileEncryptType;视频与图片同体系走完整 TEA)。 */
218
224
  fileEncryptType?: number;
219
225
  }
226
+ /** 文件合集正文;接收保留所有有序文件项,首次发送每条只包含一个文件。 */
227
+ interface ImFilesAlbumBody {
228
+ /** 文件下方的配文;无配文时省略。 */
229
+ caption?: string;
230
+ /** 文件元数据与独立解密参数;本地上传占位允许 URL 暂为空。 */
231
+ items: readonly ImFileBody[];
232
+ }
220
233
  /**
221
234
  * 文件(附件)消息内容体(contentType==='file')。领域友好类型(string/number),协议 BMessage 的 bytes/bigint 字段在 mapping 层互转。
222
235
  * 对齐 Android IMFileMsgBody / BMessage 文件字段(见 outputs/architecture/subagent-read-docs/研究Android文件上传实现.md):
@@ -628,6 +641,8 @@ interface ImMessageBody {
628
641
  redPacket?: ImRedPacketBody;
629
642
  /** contentType==='mediaAlbum' 时的媒体合集正文(配文 + 1~9 个图片/视频项)。 */
630
643
  mediaAlbum?: ImMediaAlbumBody;
644
+ /** 文件合集(协议 29),与图片/视频合集独立。 */
645
+ filesAlbum?: ImFilesAlbumBody;
631
646
  /** contentType==='robot' 时的机器人卡片。 */
632
647
  robot?: ImRobotBody;
633
648
  /** contentType==='unknown' 时的稳定未知正文,不含原始 wire type。 */
@@ -664,7 +679,7 @@ type ImMessageFailureReason = 'timeout' | 'rejected' | 'encrypt_failed' | 'netwo
664
679
  * 失败**展示语义**码(强类型枚举,非裸串):供 im-i18n 按 locale 渲染失败气泡文案。
665
680
  * 由 `reason` / `SendMediaFailReason` / ACK errcode 穷尽映射而来,与 im-i18n failure catalog 键一一对应(media.* 带 mediaKind 参数)。
666
681
  */
667
- type ImFailureDisplayCode = 'media.empty' | 'media.noCrypto' | 'media.previewFailed' | 'media.encryptFailed' | 'media.uploadFailed' | 'media.cancelled' | 'media.invalidDuration' | 'media.uploadInterrupted' | 'media.contentTooLarge' | 'contactRequired' | 'messageRefused' | 'forbiddenOrLeft' | 'contentRejected' | 'groupDismissed' | 'groupUnavailable' | 'channelDismissed' | 'channelMuted' | 'channelNotMember' | 'channelAdminRequired' | 'conversationUnsupported' | 'sendCanceled' | 'sessionLoggedOut' | 'timeout' | 'network' | 'unknown';
682
+ type ImFailureDisplayCode = 'media.empty' | 'media.noCrypto' | 'media.previewFailed' | 'media.encryptFailed' | 'media.resumeUnavailable' | 'media.cleanupUnconfirmed' | 'media.uploadFailed' | 'media.cancelled' | 'media.invalidDuration' | 'media.uploadInterrupted' | 'media.contentTooLarge' | 'contactRequired' | 'messageRefused' | 'forbiddenOrLeft' | 'contentRejected' | 'groupDismissed' | 'groupUnavailable' | 'channelDismissed' | 'channelMuted' | 'channelNotMember' | 'channelAdminRequired' | 'conversationUnsupported' | 'sendCanceled' | 'sessionLoggedOut' | 'timeout' | 'network' | 'unknown';
668
683
  interface ImMessageFailure {
669
684
  /** 归一后的错误码(来自 MESChatAck.errcode 或本地失败码,本地码用负值)。 */
670
685
  code: number;
@@ -2371,6 +2386,11 @@ type ImEvent = {
2371
2386
  } | {
2372
2387
  type: 'sync:complete';
2373
2388
  conversations: ConversationRef[];
2389
+ }
2390
+ /** SDK 会话同步或前台内容读取的汇总状态;结束不代表所有请求成功。 */
2391
+ | {
2392
+ type: 'receiving:changed';
2393
+ receiving: boolean;
2374
2394
  } | {
2375
2395
  type: 'auth:invalid';
2376
2396
  issue: ImAuthIssue;
@@ -3037,12 +3057,17 @@ interface ImMessageReactions {
3037
3057
  aggregates: readonly ImMessageReactionAggregate[];
3038
3058
  }
3039
3059
  /** 可渲染媒体正文;密钥和底层文件加密策略只允许留在 SDK/Core。 */
3040
- interface ImMessageViewBody extends Omit<ImMessageBody, 'image' | 'video' | 'voice' | 'file' | 'sticker' | 'mediaAlbum'> {
3060
+ interface ImMessageViewBody extends Omit<ImMessageBody, 'image' | 'video' | 'voice' | 'file' | 'sticker' | 'mediaAlbum' | 'filesAlbum'> {
3041
3061
  image?: Readonly<Omit<NonNullable<ImMessageBody['image']>, 'teaKey' | 'fileEncryptType'>>;
3042
3062
  video?: Readonly<Omit<NonNullable<ImMessageBody['video']>, 'teaKey' | 'fileEncryptType'>>;
3043
3063
  voice?: Readonly<Omit<NonNullable<ImMessageBody['voice']>, 'teaKey' | 'fileEncryptType'>>;
3044
3064
  file?: Readonly<Omit<NonNullable<ImMessageBody['file']>, 'teaKey' | 'fileEncryptType'>>;
3045
3065
  sticker?: Readonly<NonNullable<ImMessageBody['sticker']>>;
3066
+ /** 文件合集产品视图不包含逐项密钥,下载只接受消息引用与下标。 */
3067
+ filesAlbum?: Readonly<{
3068
+ caption?: string;
3069
+ items: readonly Readonly<Omit<NonNullable<ImMessageBody['file']>, 'teaKey' | 'fileEncryptType'>>[];
3070
+ }>;
3046
3071
  /** 合集的每一项都带自己的密钥材料,逐项剥离后才交给产品层;按项下载走 SDK handle,不需要这些字段。 */
3047
3072
  mediaAlbum?: Readonly<Omit<NonNullable<ImMessageBody['mediaAlbum']>, 'items'> & {
3048
3073
  items: readonly Readonly<Omit<ImMediaAlbumItem, 'teaKey' | 'fileEncryptType'>>[];
@@ -3205,10 +3230,13 @@ interface VoiceMessageMetadata {
3205
3230
  /**
3206
3231
  * 文件发送附加数据。
3207
3232
  *
3208
- * @remarks 传 `Blob` 时必须提供 `fileName`;传 `File` 时默认读取其 name。当前协议无文件 caption,非空值显式 unsupported。
3233
+ * @remarks 传 `Blob` 时必须提供 `fileName`;传 `File` 时默认读取其 name。非空 caption 使用协议 29,无配文默认保持 11。
3209
3234
  */
3210
3235
  interface FileMessageOptions {
3236
+ /** 文件卡下方配文,最长 1024 字符。 */
3211
3237
  caption?: string;
3238
+ /** 同一带配文批次的前序文件使用 29,即使自身没有配文。 */
3239
+ filesAlbum?: boolean;
3212
3240
  fileName?: string;
3213
3241
  replyToMessageId?: string;
3214
3242
  }
@@ -3843,6 +3871,8 @@ interface ImLifecycleSnapshot {
3843
3871
  prepared: boolean;
3844
3872
  connectionDesired: boolean;
3845
3873
  authenticated: boolean;
3874
+ /** 会话同步或前台内容读取仍在进行;不包含后台预取、媒体下载和写操作,也不代表同步成功。 */
3875
+ receiving: boolean;
3846
3876
  }
3847
3877
  /** logout 的本地数据与在途消息策略。 */
3848
3878
  interface ImLogoutOptions {
@@ -4248,6 +4278,12 @@ type ConversationLastMessageSummary = {
4248
4278
  kind: 'voice';
4249
4279
  durationMs?: number;
4250
4280
  }
4281
+ /** 文件合集的文件数量与可选配文,供列表生成摘要。 */
4282
+ | {
4283
+ kind: 'filesAlbum';
4284
+ count: number;
4285
+ caption?: string;
4286
+ }
4251
4287
  /**
4252
4288
  * 媒体合集(一条消息内 1~9 个图片/视频 + 可选配文)。
4253
4289
  *
@@ -4940,7 +4976,8 @@ interface ChannelConversationMessageApi extends ConversationMessageApi {
4940
4976
  * 由社群管理员或社群主删除一条全员可见消息。
4941
4977
  *
4942
4978
  * @remarks 不受本人撤回时间窗限制;权限由 CHANNEL profile 预检并由服务端最终校验。成功后消息进入
4943
- * `deletedForEveryone` 终态,所有端显示“管理员删除了一条消息”。该方法不用于本机删除,也不适用于普通群。
4979
+ * `deletedForEveryone` 终态;Chat Kit 时间线仅向社群群主和管理员显示删除提示,普通成员隐藏该项。
4980
+ * 该方法不用于本机删除,也不适用于普通群。
4944
4981
  * @example
4945
4982
  * ```ts
4946
4983
  * const channel = await client.openConversation({ conversationType: 'channel', conversationId: '9001' })
@@ -5173,9 +5210,15 @@ interface ImMediaTasksApi {
5173
5210
  cancel: (taskId: string) => Promise<void>;
5174
5211
  /**
5175
5212
  * 重试 failed/canceled 任务;上传复用保留原文件,下载重新解析同一精确消息引用。
5213
+ * 续传不可用或清理未确认时,必须先征得用户同意重新上传,再传 restartUpload:true。
5214
+ * 用户取消后的重发始终重新上传尚未完成的资源;成功的合集项仍可复用。
5215
+ * 下载取消已受理后即可创建新尝试,不复用旧取消 Promise;旧 loader 结束前仍占用并发槽,但不能覆盖新任务。
5176
5216
  * @throws 原文件已淘汰、任务仍在途或消息/下载 capability 不可用时显式拒绝。
5177
5217
  */
5178
- retry: (taskId: string) => Promise<void>;
5218
+ retry: (taskId: string, options?: {
5219
+ /** 用户已确认放弃旧进度并重新上传;仅上传任务接受,清理失败时仍停止。 */
5220
+ restartUpload?: boolean;
5221
+ }) => Promise<void>;
5179
5222
  /**
5180
5223
  * 下载并按消息正文合同解密,同一消息并发调用复用同一 Promise,成功返回 Blob。
5181
5224
  * @throws 消息不存在/非媒体/无远端 URL/未装配 capability、传输失败、取消或 teardown 均以稳定错误拒绝,不返回空 Blob。
@@ -5386,6 +5429,10 @@ interface ImProductEventMap {
5386
5429
  'sync:complete': Readonly<{
5387
5430
  conversations: readonly ConversationRef<ProductConversationListType>[];
5388
5431
  }>;
5432
+ /** 当前账号仍有会话同步或前台内容读取;false 仅表示读取结束,错误仍走 error 事件。 */
5433
+ 'receiving:changed': Readonly<{
5434
+ receiving: boolean;
5435
+ }>;
5389
5436
  /** `lastLoginTime` 为服务端记录的上次登录时间(毫秒),仅被踢且走登录 ACK 的路径才有值。 */
5390
5437
  'auth:invalid': Readonly<{
5391
5438
  code: string;
@@ -7513,7 +7560,9 @@ declare function defineImMediaStore(pinia: Pinia): pinia.StoreDefinition<"k2-im-
7513
7560
  start: () => void;
7514
7561
  reset: () => void;
7515
7562
  cancel: (taskId: string) => Promise<ImMediaOperationResult>;
7516
- retry: (taskId: string) => Promise<ImMediaOperationResult>;
7563
+ retry: (taskId: string, options?: {
7564
+ restartUpload?: boolean;
7565
+ }) => Promise<ImMediaOperationResult>;
7517
7566
  cancelUpload: (messageId: string) => Promise<ImMediaOperationResult>;
7518
7567
  cancelDownload: (messageId: string, itemIndex?: number) => Promise<ImMediaOperationResult>;
7519
7568
  requestReplacement: (message: ImMessageView) => boolean;
@@ -7532,7 +7581,9 @@ declare function defineImMediaStore(pinia: Pinia): pinia.StoreDefinition<"k2-im-
7532
7581
  start: () => void;
7533
7582
  reset: () => void;
7534
7583
  cancel: (taskId: string) => Promise<ImMediaOperationResult>;
7535
- retry: (taskId: string) => Promise<ImMediaOperationResult>;
7584
+ retry: (taskId: string, options?: {
7585
+ restartUpload?: boolean;
7586
+ }) => Promise<ImMediaOperationResult>;
7536
7587
  cancelUpload: (messageId: string) => Promise<ImMediaOperationResult>;
7537
7588
  cancelDownload: (messageId: string, itemIndex?: number) => Promise<ImMediaOperationResult>;
7538
7589
  requestReplacement: (message: ImMessageView) => boolean;
@@ -7551,7 +7602,9 @@ declare function defineImMediaStore(pinia: Pinia): pinia.StoreDefinition<"k2-im-
7551
7602
  start: () => void;
7552
7603
  reset: () => void;
7553
7604
  cancel: (taskId: string) => Promise<ImMediaOperationResult>;
7554
- retry: (taskId: string) => Promise<ImMediaOperationResult>;
7605
+ retry: (taskId: string, options?: {
7606
+ restartUpload?: boolean;
7607
+ }) => Promise<ImMediaOperationResult>;
7555
7608
  cancelUpload: (messageId: string) => Promise<ImMediaOperationResult>;
7556
7609
  cancelDownload: (messageId: string, itemIndex?: number) => Promise<ImMediaOperationResult>;
7557
7610
  requestReplacement: (message: ImMessageView) => boolean;
@@ -7683,7 +7736,10 @@ interface ImMessageOperationsStoreActions {
7683
7736
  recall: (message: ImMessageView) => Promise<ImMessageActionResult>;
7684
7737
  deleteLocal: (message: ImMessageView) => Promise<ImMessageActionResult>;
7685
7738
  deleteForEveryone: (message: ImMessageView) => Promise<ImMessageActionResult>;
7686
- retry: (messageId: string) => Promise<ImMessageActionResult>;
7739
+ /** 完整重传需由宿主先取得用户确认,普通重发不传 options。 */
7740
+ retry: (messageId: string, options?: {
7741
+ restartUpload?: boolean;
7742
+ }) => Promise<ImMessageActionResult>;
7687
7743
  pin: (message: ImMessageView) => Promise<ImPinnedMessageActionResult>;
7688
7744
  unpin: () => Promise<ImPinnedMessageActionResult>;
7689
7745
  syncPinned: () => Promise<ImPinnedMessageActionResult>;
@@ -8199,7 +8255,10 @@ declare function defineImProfileDirectoryStore(pinia: Pinia): pinia.StoreDefinit
8199
8255
  forceRefresh?: boolean;
8200
8256
  }) => Promise<ImProfileDirectoryResult>;
8201
8257
  requestMembershipJoin: (ref: ConversationRef<"group" | "channel">, options?: {
8258
+ /** 指定邀请码时走邀请码加入流程,不提交申请说明。 */
8202
8259
  inviteCode?: string;
8260
+ /** 申请加入时附带给管理员的说明,原样交给对应群类型的 SDK API。 */
8261
+ remarks?: string;
8203
8262
  }) => Promise<ImMembershipJoinActionResult>;
8204
8263
  updateChannelName: (ref: ConversationRef<"channel">, name: string) => Promise<ImChannelProfileActionResultFor<"update-name">>;
8205
8264
  updateChannelDescription: (ref: ConversationRef<"channel">, description: string) => Promise<ImChannelProfileActionResultFor<"update-description">>;
@@ -8373,7 +8432,10 @@ declare function defineImProfileDirectoryStore(pinia: Pinia): pinia.StoreDefinit
8373
8432
  forceRefresh?: boolean;
8374
8433
  }) => Promise<ImProfileDirectoryResult>;
8375
8434
  requestMembershipJoin: (ref: ConversationRef<"group" | "channel">, options?: {
8435
+ /** 指定邀请码时走邀请码加入流程,不提交申请说明。 */
8376
8436
  inviteCode?: string;
8437
+ /** 申请加入时附带给管理员的说明,原样交给对应群类型的 SDK API。 */
8438
+ remarks?: string;
8377
8439
  }) => Promise<ImMembershipJoinActionResult>;
8378
8440
  updateChannelName: (ref: ConversationRef<"channel">, name: string) => Promise<ImChannelProfileActionResultFor<"update-name">>;
8379
8441
  updateChannelDescription: (ref: ConversationRef<"channel">, description: string) => Promise<ImChannelProfileActionResultFor<"update-description">>;
@@ -8547,7 +8609,10 @@ declare function defineImProfileDirectoryStore(pinia: Pinia): pinia.StoreDefinit
8547
8609
  forceRefresh?: boolean;
8548
8610
  }) => Promise<ImProfileDirectoryResult>;
8549
8611
  requestMembershipJoin: (ref: ConversationRef<"group" | "channel">, options?: {
8612
+ /** 指定邀请码时走邀请码加入流程,不提交申请说明。 */
8550
8613
  inviteCode?: string;
8614
+ /** 申请加入时附带给管理员的说明,原样交给对应群类型的 SDK API。 */
8615
+ remarks?: string;
8551
8616
  }) => Promise<ImMembershipJoinActionResult>;
8552
8617
  updateChannelName: (ref: ConversationRef<"channel">, name: string) => Promise<ImChannelProfileActionResultFor<"update-name">>;
8553
8618
  updateChannelDescription: (ref: ConversationRef<"channel">, description: string) => Promise<ImChannelProfileActionResultFor<"update-description">>;
@@ -8910,6 +8975,8 @@ interface ApplyImSessionInput {
8910
8975
  interface ImSessionStore {
8911
8976
  readonly accountId: string;
8912
8977
  readonly connectionState: ImConnectionState;
8978
+ /** SDK 正在同步会话、离线消息或读取前台会话内容;连接异常提示仍应优先展示。 */
8979
+ readonly receiving: boolean;
8913
8980
  readonly generation: number;
8914
8981
  readonly phase: ImSessionPhase;
8915
8982
  readonly errorKey: string;
@@ -8926,6 +8993,7 @@ interface ImSessionStore {
8926
8993
  declare function defineImSessionStore(pinia: Pinia): pinia.StoreDefinition<"k2-im-session", Pick<{
8927
8994
  accountId: any;
8928
8995
  connectionState: any;
8996
+ receiving: any;
8929
8997
  generation: any;
8930
8998
  phase: any;
8931
8999
  errorKey: any;
@@ -8942,6 +9010,7 @@ declare function defineImSessionStore(pinia: Pinia): pinia.StoreDefinition<"k2-i
8942
9010
  }, any>, Pick<{
8943
9011
  accountId: any;
8944
9012
  connectionState: any;
9013
+ receiving: any;
8945
9014
  generation: any;
8946
9015
  phase: any;
8947
9016
  errorKey: any;
@@ -8958,6 +9027,7 @@ declare function defineImSessionStore(pinia: Pinia): pinia.StoreDefinition<"k2-i
8958
9027
  }, any>, Pick<{
8959
9028
  accountId: any;
8960
9029
  connectionState: any;
9030
+ receiving: any;
8961
9031
  generation: any;
8962
9032
  phase: any;
8963
9033
  errorKey: any;