k2-im 0.2.13 → 0.2.14

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.
Files changed (33) hide show
  1. package/README.md +6 -0
  2. package/dist/chat-kit-pinia.d.ts +4 -4
  3. package/dist/chat-kit.d.ts +3 -3
  4. package/dist/crypto.worker.js +1 -1
  5. package/dist/index.d.ts +3 -3
  6. package/dist/modules/api-protocol-client/src/client.js +1 -1
  7. package/dist/modules/api-protocol-client/src/nonce.js +1 -1
  8. package/dist/modules/crypto/browser.js +1 -1
  9. package/dist/modules/crypto/driver.js +1 -1
  10. package/dist/modules/crypto/vendor/crypto/index_bg.js +1 -1
  11. package/dist/modules/im-browser/src/http/session-favorite-http-adapter.js +1 -1
  12. package/dist/modules/im-browser/src/media/media-preview-preparation-executor.js +1 -1
  13. package/dist/modules/im-browser/src/media/media-transfer-adapter.js +1 -1
  14. package/dist/modules/im-browser/src/network/browser-connection-ownership.js +1 -1
  15. package/dist/modules/im-browser/src/storage/indexed-db-storage-adapter.js +1 -1
  16. package/dist/modules/im-chat-kit/src/pinia/composer.store.js +1 -1
  17. package/dist/modules/im-chat-kit/src/pinia/expression.store.js +1 -1
  18. package/dist/modules/im-chat-kit/src/utils/emoji/unicode.js +1 -1
  19. package/dist/modules/im-core/src/abort.js +1 -1
  20. package/dist/modules/im-core/src/mapping/message-id.js +1 -1
  21. package/dist/modules/im-core/src/mapping/search-text.js +1 -1
  22. package/dist/modules/im-core/src/media-thumbnail-policy.js +1 -1
  23. package/dist/modules/im-core/src/message-flow/media/media-sender.js +1 -1
  24. package/dist/modules/im-core/src/state/domain-state.js +1 -1
  25. package/dist/modules/im-sdk/src/product/conversation-handle.js +1 -1
  26. package/dist/modules/im-sdk/src/product/diagnostic-memory-buffer.js +1 -1
  27. package/dist/modules/im-sdk/src/product/media.js +1 -1
  28. package/dist/modules/im-sdk/src/runtime/recent-history-prefetch.js +1 -1
  29. package/dist/request-crypto.d.ts +2 -3
  30. package/dist/sdk.d.ts +2 -2
  31. package/dist/vendor/crypto/index_bg.wasm +0 -0
  32. package/package.json +10 -1
  33. package/dist/modules/im-browser/src/media/thumbnail-pixel-profile.js +0 -1
@@ -1 +1 @@
1
- import{abortWithReason as e,throwIfAborted as t}from"../../abort.js";import{resolveMediaThumbnailPolicy as a,MEDIA_THUMBNAIL_MAX_BYTES as i}from"../../media-thumbnail-policy.js";import{MEDIA_ALBUM_CAPTION_MAX_LENGTH as n,MEDIA_ALBUM_MAX_ITEMS as o,resolveMediaAlbumSendContentType as r,measureMediaAlbumContentBytes as d,mediaAlbumBMessageFields as s,MEDIA_ALBUM_CONTENT_WARN_BYTES as l}from"../../mapping/media-album-body.js";import{computeSortKey as c}from"../../mapping/sort.js";import{SIMPLE_ENCRYPT_HEAD_BYTES as u}from"../../ports/crypto-port.js";import{mediaAssetResourceVersion as p}from"../../ports/media-asset-cache-port.js";import{LOCAL_MEDIA_ERROR_CODE as m}from"../../mapping/stored-message.js";function f(e){return Number.isFinite(e)&&e>0}function v(e,t){if(("video"===t||"image"===t)&&void 0!==e&&f(e.width)&&f(e.height)&&("video"!==t||void 0===e.duration||f(e.duration))&&("video"!==t||void 0===e.posterData||e.posterData instanceof Uint8Array&&0!==e.posterData.length&&!(e.posterData.length>i)))return{width:e.width,height:e.height,..."video"===t&&void 0!==e.duration?{duration:e.duration}:{},..."video"===t&&void 0!==e.posterData?{thumbData:new Uint8Array(e.posterData)}:{}}}function g(e,t){return void 0===t?e:{...e,width:t.width,height:t.height,...void 0===t.thumbData?{}:{thumbData:t.thumbData},...void 0===e.duration&&void 0!==t.duration?{duration:t.duration}:{}}}const y={contentType:"image",uploadKind:"image",encryptMode:"integral",streamUpload:!0,async buildPreview(e,t,i,n,o=1){const r=await i.imageDimensions(e,t,n),d=await i.imageThumbnail(e,{mimeType:t,...a(o)},n);return{width:r.width,height:r.height,...d.data.byteLength<=a(o).maxBytes?{thumbData:d.data}:{}}},buildBody:({url:e,meta:t,size:a,teaKey:i,fileEncryptType:n})=>({image:{url:e,width:t.width,height:t.height,...void 0!==t.thumbData?{thumbData:t.thumbData}:{},...void 0!==a?{size:a}:{},...void 0!==n?{fileEncryptType:n}:{},...void 0!==i?{teaKey:i}:{}}})},h={contentType:"video",uploadKind:"video",encryptMode:"integral",streamUpload:!0,async buildPreview(e,t,i,n,o=1){const r=await i.videoPoster(e,{mimeType:t,...a(o)},n);return{width:r.width,height:r.height,...r.data.byteLength<=a(o).maxBytes?{thumbData:r.data}:{},duration:r.duration}},buildBody:({url:e,meta:t,size:a,teaKey:i,fileEncryptType:n},o)=>({video:{url:e,width:t.width,height:t.height,...void 0!==t.duration?{duration:t.duration}:{},...void 0!==o.caption&&""!==o.caption?{describe:o.caption}:{},...void 0!==t.thumbData?{thumbData:t.thumbData}:{},...void 0!==a?{size:a,sizeUnit:"bytes"}:{},...void 0!==n?{fileEncryptType:n}:{},...void 0!==i?{teaKey:i}:{}}})},w={contentType:"voice",uploadKind:"voice",encryptMode:"integral",buildPreview:()=>Promise.resolve({width:0,height:0}),buildBody:({url:e,size:t,teaKey:a,fileEncryptType:i},n)=>({voice:{url:e,durationMs:n.durationMs??0,...void 0!==n.waveform&&n.waveform.length>0?{waveform:n.waveform}:{},...void 0!==t?{size:t}:{},...void 0!==i?{fileEncryptType:i}:{},...void 0!==a?{teaKey:a}:{}}})},b={contentType:"sticker",uploadKind:"sticker",encryptMode:"none",async buildPreview(e,t,a,i){const n=await a.imageDimensions(e,t,i);return{width:n.width,height:n.height}},buildBody:({url:e,meta:t,size:a})=>({sticker:{url:e,width:t.width,height:t.height,exprType:2,imageType:1,...void 0===a?{}:{size:a}}})};const T={contentType:"file",uploadKind:"file",encryptMode:"simple",streamUpload:!0,buildPreview:()=>Promise.resolve({width:0,height:0}),buildBody({url:e,size:t,teaKey:a,fileEncryptType:i},n){const o=n.filename??"",r=function(e){const t=e.lastIndexOf(".");return t>-1&&t<e.length-1?e.slice(t+1).toLowerCase():""}(o),d=function(e,t){const a=t??"";return a.startsWith("image/")||["jpg","jpeg","png","gif","webp","bmp","heic","svg"].includes(e)?1:a.startsWith("video/")||["mp4","mov","m4v","3gp","avi","mkv","webm","flv"].includes(e)?2:a.startsWith("audio/")||["mp3","m4a","wav","aac","flac","ogg"].includes(e)?3:["pdf","doc","docx","xls","xlsx","ppt","pptx","txt","csv","zip","rar","7z","apk","json"].includes(e)?4:0}(r,n.mimeType);return{file:{url:e,fileName:o,...void 0!==t?{size:t}:{},...""!==r?{extension:r}:{},...0!==d?{fileType:d}:{},...void 0!==n.mimeType&&""!==n.mimeType?{mimeType:n.mimeType}:{},...void 0!==i?{fileEncryptType:i}:{},...void 0!==a?{teaKey:a}:{}}}}},k={...T,contentType:"filesAlbum",buildBody(e,t){const a=T.buildBody(e,t).file;return{filesAlbum:{...t.caption?.trim()?{caption:t.caption}:{},items:[{...a,extension:a.extension??"",fileType:a.fileType??0,...["zip","rar","torrent"].includes(a.extension??"")?{fileType:5}:{},...void 0===e.md5?{}:{md5:e.md5}}]}}}};function M(e){switch(e){case"empty":return"media.empty";case"no-crypto":return"media.noCrypto";case"preview-failed":return"media.previewFailed";case"encrypt-failed":return"media.encryptFailed";case"upload-failed":case"offline":return"media.uploadFailed";case"cancelled":return"media.cancelled";case"paused":throw new Error("暂停不是失败状态,不应生成失败文案");case"invalid-duration":return"media.invalidDuration";case"content-too-large":return"media.contentTooLarge"}}function I(e,t){return"video"===e||void 0===t||t>16777216?"large":"small"}function A(){return new DOMException("媒体上传已取消","AbortError")}function E(e){return"album"===e.kind?e.items.flatMap(e=>void 0===e.resume||void 0!==e.uploaded?[]:[{resume:e.resume,kind:e.uploadKind}]):void 0===e.resume?[]:[{resume:e.resume,kind:e.spec.uploadKind}]}function C(e){if("album"===e.kind)return{code:m,reason:"unknown",displayCode:M(e.failureReason),retryable:!1};const t="video"===e.spec.contentType||"file"===e.spec.contentType||"filesAlbum"===e.spec.contentType;return{code:m,reason:"unknown",displayCode:t?"media.uploadInterrupted":M(e.failureReason),mediaKind:e.spec.uploadKind,retryable:!1}}function P(e,t){if(!Number.isInteger(e)||e<1||e>6)throw new RangeError(`媒体上传并发数必须是 1-6 的整数(${t})`)}function K(i){const f=function(e){let t=0,a=0;const i=[];function n(i){return t<e.total&&("large"!==i||a<e.largeFiles)}function o(e){t+=1,"large"===e&&(a+=1);let i=!1;return()=>{i||(i=!0,t-=1,"large"===e&&(a-=1),r())}}function r(){let e=0;for(;e<i.length;){const t=i[e];t.signal.aborted?(i.splice(e,1),t.signal.removeEventListener("abort",t.onAbort),t.reject(A())):n(t.tier)?(i.splice(e,1),t.signal.removeEventListener("abort",t.onAbort),t.resolve(o(t.tier))):e+=1}}return{acquire:(e,t)=>t.aborted?Promise.reject(A()):new Promise((a,n)=>{const o={tier:e,signal:t,resolve:a,reject:n,onAbort:()=>{const e=i.indexOf(o);e>=0&&i.splice(e,1),n(A())}};i.push(o),t.addEventListener("abort",o.onAbort,{once:!0}),r()})}}(function(e){if(void 0===e)return{total:5,largeFiles:3};if("number"==typeof e)return P(e,"总数"),{total:e,largeFiles:e};const t=e.total??5;P(t,"total");const a=e.largeFiles??Math.min(3,t);if(P(a,"largeFiles"),a>t)throw new RangeError(`媒体上传大文件档并发数 ${a} 不能超过总并发数 ${t}`);return{total:t,largeFiles:a}}(i.maxConcurrentUploads)),K=/* @__PURE__ */new Map,R=/* @__PURE__ */new Map,D=/* @__PURE__ */new Map,z=/* @__PURE__ */new Map;let U=!1;const x=/* @__PURE__ */new Map,S=/* @__PURE__ */new Map,_=/* @__PURE__ */new Set,B=/* @__PURE__ */new Map,O=/* @__PURE__ */new Map;function F(e,t){const a=B.get(e)??/* @__PURE__ */new Set;B.set(e,a),a.add(t),_.add(t),t.finally(()=>{a.delete(t),_.delete(t),0===a.size&&B.get(e)===a&&B.delete(e),re(e)})}function L(e){return[...B.get(e)??[]]}const q=/* @__PURE__ */new Map,V=/* @__PURE__ */new Set,j=/* @__PURE__ */new Map,N=/* @__PURE__ */new Map,Y=/* @__PURE__ */new Map,$=/* @__PURE__ */new Map,W=/* @__PURE__ */new Map,G=/* @__PURE__ */new Map;let H=!0,J=0,Q=0;function X(e){return{conversationType:e.conversationType,conversationId:e.conversationId}}function Z(e,t,a,n){i.mediaTransfer.abandonUpload(e).catch(e=>{i.onMediaTransferError?.({stage:"upload",kind:t,messageId:a,conversation:n,cause:e})})}function ee(e,t,a,n,o,r){if(!H)return;const d=X(t);j.set(e,{input:X(t),state:a,percent:n,phase:r}),i.emitter.emit({type:"media-task:updated",conversation:d,task:{id:`upload:${e}`,messageId:e,ref:d,direction:"upload",state:a,percent:Math.max(0,Math.min(100,Math.round(n))),attempt:z.get(e)?.attempt??1,maxAttempts:3,...Y.get(e),...N.has(e)?{items:Object.freeze(N.get(e).map(e=>Object.freeze({...e,state:"completed"===e.state?"completed":"canceled"===a||"failed"===a?a:e.state})))}:{},...S.get(e),...void 0===r?{}:{phase:r},...void 0===o?{}:{failure:o}}})}function te(e,t){oe(),W.delete(e),G.delete(e),W.set(e,t),ne()}function ae(e){const t=z.get(e);if(K.has(e)||q.has(e)||L(e).length>0||void 0!==t&&(!0!==t.settled||void 0!==t.waiting))return!1;const a=j.get(e)?.state;return"failed"===a||"canceled"===a||"paused"===a&&"manual"===t?.pauseReason}function ie(e,t){const a=X(t.input),n=E(t),o="media"===t.kind?t.spec.uploadKind:"image",r={...C(t),displayCode:"media.uploadInterrupted",retryable:!1};W.delete(e),G.delete(e),z.delete(e),$.delete(e),Y.delete(e),N.delete(e),S.delete(e),x.delete(e),j.delete(e),D.delete(e);for(const t of n)Z(t.resume,t.kind,e,a);if(function(e,t,a){const n=i.recoveryPort;if(void 0===n)return;const o=L(e),r=Promise.all(o).then(()=>n.remove(X(t),e)).catch(n=>{i.onMediaTransferError?.({stage:"upload",kind:a,messageId:e,conversation:X(t),cause:n})});F(e,r)}(e,a,o),!H)return;const d=i.domainState.getConversationMessage?.(a,e)??t.message;"sent"!==d.status&&(i.domainState.upsertMessages([{...d,status:"failed",failure:r}],"live"),ee(e,a,"failed",0,r))}function ne(){if(H)for(const[e,t]of W){if(W.size<=3)break;ae(e)&&ie(e,t)}}function oe(){if(!H)return;const e=Date.now();for(const[t,a]of W){const i=G.get(t);void 0!==i&&e-i>=864e5&&ae(t)&&ie(t,a)}}function re(e){H&&(W.has(e)&&ae(e)&&!G.has(e)&&G.set(e,Date.now()),ne())}async function de(a,n,o,r,d,s,l=!1){const y=J,h=()=>H&&y===J;if(!h())return void 0!==s&&void 0!==o&&Z(s,a.uploadKind,o,X(n)),{ok:!1,reason:"cancelled"};const w=Q;let b,T,k=d,E=s,C=Promise.resolve(void 0);const P=/* @__PURE__ */new Set,_="function"==typeof n.data;const B=function(e){return"undefined"!=typeof Blob&&e instanceof Blob}(n.data)?n.data:void 0,L=_||void 0!==B?void 0:n.data,q=_||void 0!==B,V=!0===a.streamUpload&&void 0!==B,N=e=>{if(void 0!==B)return B;if(void 0===e)throw new Error("媒体预览缺少内容:非 Blob 输入必须先读出字节");return new Blob([e],void 0===n.mimeType?void 0:{type:n.mimeType})};if(0===L?.length||0===B?.size)return{ok:!1,reason:"empty"};const G=n.encrypted??!0;if(G&&void 0===i.crypto)return{ok:!1,reason:"no-crypto"};const ae=v(n.localPreviewMetadata,a.contentType);if(("video"===a.contentType||"image"===a.contentType)&&void 0!==n.localPreviewMetadata&&void 0===ae)return{ok:!1,reason:"preview-failed"};const ie=void 0===o||void 0===r?i.outbox.allocateMessageIdentity({conversationId:n.conversationId,conversationType:n.conversationType}):{id:o,createdAt:r},{id:ne,createdAt:oe}=ie,re=i.getSelfId();let de=ae??{width:0,height:0};if(!q)try{de=g(await a.buildPreview(N(L),n.mimeType,i.mediaPreview),ae)}catch{}if(!h())return void 0!==E&&Z(E,a.uploadKind,ne,X(n)),{ok:!1,reason:"cancelled"};const se=B?.size??L?.byteLength,le={url:n.localPreviewUrl??"",...void 0===se?{}:{size:se}};let ce={id:ne,conversationId:n.conversationId,conversationType:n.conversationType,senderId:re,contentType:a.contentType,body:a.buildBody({...le,meta:de},n),createdAt:oe,sortKey:c(oe,ne),status:"uploading",receipt:"unread",encryption:{encrypted:G},...void 0!==n.refMessageId?{refMessageId:n.refMessageId}:{}};i.domainState.upsertMessages([ce],"live",{newOutgoing:!0});const pe=l?0:$.get(ne)??0;l&&Y.delete(ne),$.set(ne,pe),ee(ne,n,"queued",pe,void 0,"waiting-upload-slot");const me=(e,t=!1)=>{const o={code:m,reason:"unknown",displayCode:"cleanup-unconfirmed"===b?"media.cleanupUnconfirmed":"resume-unavailable"===b?"media.resumeUnavailable":"timeout"===b?"media.uploadTimeout":M(e),mediaKind:a.uploadKind,retryable:t};if(!h())return{ok:!1,reason:e};const r=z.get(ne);return"paused"===r?.stopped?(ee(ne,n,"paused",$.get(ne)??0),{ok:!1,reason:e}):void 0!==r&&void 0===r.stopped&&r.attempt<3&&("network"===r.failure||"timeout"===r.failure||"credentials-expired"===r.failure||"offline"===e&&void 0!==i.waitUntilOnline)?(ee(ne,n,"queued",$.get(ne)??0,void 0,"waiting-retry"),{ok:!1,reason:e}):("cancelled"===r?.stopped||void 0!==r&&r.attempt>=3&&("network"===r.failure||"timeout"===r.failure||"credentials-expired"===r.failure)||(i.domainState.upsertMessages([{...ce,status:"failed",failure:o}],"live"),ee(ne,n,"cancelled"===e?"canceled":"failed",$.get(ne)??0,o)),{ok:!1,reason:e})},fe=async()=>{if(void 0!==E)try{await i.mediaTransfer.abandonUpload(E),E=void 0}catch(e){throw b="cleanup-unconfirmed",i.onMediaTransferError?.({stage:"upload",kind:a.uploadKind,messageId:ne,conversation:X(n),cause:e}),e}},ve=async e=>{if(await C,await Promise.all([...P]),"cancelled"===e&&"paused"!==z.get(ne)?.stopped&&!0!==z.get(ne)?.retainCheckpoint&&"cleanup-unconfirmed"!==b)try{await fe()}catch{}return"cancelled"===e&&"paused"!==z.get(ne)?.stopped&&!0!==z.get(ne)?.retainCheckpoint&&void 0!==i.recoveryPort&&(await Promise.all([...P]),await i.recoveryPort.remove(X(n),ne).catch(e=>i.onMediaTransferError?.({stage:"upload",kind:a.uploadKind,messageId:ne,conversation:X(n),cause:e}))),h()?(te(ne,{kind:"media",spec:a,input:n,createdAt:oe,message:ce,failureReason:e,...!0===z.get(ne)?.retainCheckpoint?{retainCheckpoint:!0}:{},..."cleanup-unconfirmed"===b||"resume-unavailable"===b?{restartRequired:!0}:{},...void 0===k?{}:{teaKey:k},...void 0===E?{}:{resume:E}}),me(e,!0)):{ok:!1,reason:"cancelled"}},ge=new AbortController;K.set(ne,ge),R.set(ne,X(n));const ye=z.get(ne)?.stopped;void 0!==ye&&e(ge,"cancelled"===ye&&z.get(ne)?.retainCheckpoint?"cancelled-preserve":ye),!1===i.isOnline?.()&&ue(ne,"offline");try{if(l&&(await fe(),!h()))return{ok:!1,reason:"cancelled"};if(void 0!==B&&("video"!==a.contentType||void 0===ae?.thumbData)){try{de=g(await a.buildPreview(B,n.mimeType,i.mediaPreview,ge.signal),ae)}catch{}if(!h())return{ok:!1,reason:"cancelled"};ce={...ce,body:a.buildBody({url:n.localPreviewUrl??"",meta:de,size:B.size},n)},i.domainState.upsertMessages([ce],"live")}const e=await f.acquire(I(a.contentType,B?.size??L?.byteLength),ge.signal);try{let e;ee(ne,n,"running",$.get(ne)??0);try{V||(e=_?await n.data():void 0!==B?new Uint8Array(await B.arrayBuffer()):L)}catch{return me("upload-failed",!0)}const o=V?B.size:e.length;if(0===o)return me("empty");if(_&&("video"!==a.contentType||void 0===ae?.thumbData)){try{de=g(await a.buildPreview(N(e),n.mimeType,i.mediaPreview,ge.signal),ae)}catch{}if(!h())return{ok:!1,reason:"cancelled"};ce={...ce,body:a.buildBody({url:n.localPreviewUrl??"",meta:de,size:o},n)},i.domainState.upsertMessages([ce],"live")}if(t(ge.signal),("video"===a.contentType||"file"===a.contentType||"filesAlbum"===a.contentType)&&void 0!==i.recoveryPort&&!0===i.shouldPersistUpload?.(a.uploadKind,o)){T=new AbortController,O.set(ne,T);const t=T.signal;S.set(ne,{recovery:"session-only",recoveryReason:"fingerprint-pending"}),C=Promise.resolve().then(()=>i.recoveryPort.fingerprint(V?B:e,t)).catch(e=>{!t.aborted&&h()&&(S.set(ne,{recovery:"session-only",recoveryReason:"unavailable"}),i.onMediaTransferError?.({stage:"upload",kind:a.uploadKind,messageId:ne,conversation:X(n),cause:e}))}),V||await C}if(ge.signal.aborted)throw A();let r,d,s=V?B:e,l=1;if(G&&void 0!==i.crypto&&"none"!==a.encryptMode){const t=i.crypto;try{k??(k=t.randomTeaKey());const i=k;"simple"===a.encryptMode?(s=V?new Blob([new Uint8Array(t.encryptFileSimple({teaKey:i,plain:new Uint8Array(await B.slice(0,u).arrayBuffer())})),B.slice(u)]):t.encryptFileSimple({teaKey:i,plain:e}),l=2):V?(r=e=>t.encryptSymmetricChunked({teaKey:i,plain:e,signal:ge.signal}),l=3):(s=t.encryptSymmetric({teaKey:i,plain:e}),l=3)}catch{return me("encrypt-failed")}}try{!1===i.isOnline?.()&&ue(ne,"offline"),await(i.waitUntilOnline?.(ge.signal)),t(ge.signal);d=(await i.mediaTransfer.upload({recoveryManaged:!0,forceRefreshCredentials:!0===z.get(ne)?.refreshCredentials,data:s,...void 0===r?{}:{transformPart:r},kind:a.uploadKind,conversationType:n.conversationType,signal:ge.signal,...void 0===E?{}:{resume:E},onFailure:e=>{if(h()&&K.get(ne)===ge){b=e;const t=z.get(ne);void 0!==t&&(t.failure=e)}},onResumeInvalidated:()=>{h()&&K.get(ne)===ge&&(E=void 0)},onResumable:e=>{if(h()&&K.get(ne)===ge&&(E=e,!("cancelled"===z.get(ne)?.stopped&&!0!==z.get(ne)?.retainCheckpoint||void 0===T||void 0===i.recoveryPort||"video"!==a.contentType&&"file"!==a.contentType&&"filesAlbum"!==a.contentType))){const t=x.get(ne)??Date.now();x.set(ne,t);const o=C.then(async o=>{void 0===o||T?.signal.aborted||!h()&&!U||K.get(ne)!==ge||"cancelled"===z.get(ne)?.stopped&&!0!==z.get(ne)?.retainCheckpoint&&!U||(await i.recoveryPort.save({version:1,ref:X(n),messageId:ne,kind:"video"===a.contentType?"video":"file",createdAt:oe,savedAt:t,source:{...o,...void 0===n.filename?{}:{filename:n.filename},...void 0===n.mimeType?{}:{mimeType:n.mimeType}},encrypted:G,...void 0===k?{}:{teaKey:k},resume:e,...void 0===n.caption?{}:{caption:n.caption},...void 0===n.filesAlbum?{}:{filesAlbum:n.filesAlbum},...void 0===n.refMessageId?{}:{refMessageId:n.refMessageId},..."video"===a.contentType?{preview:de}:{}}),K.get(ne)!==ge||T?.signal.aborted||S.set(ne,{recovery:"available"}))}).catch(e=>{const t="object"==typeof e&&null!==e&&"reason"in e?String(e.reason):"storage";(K.get(ne)===ge||W.has(ne))&&S.set(ne,{recovery:"session-only",recoveryReason:t}),i.onMediaTransferError?.({stage:"upload",kind:a.uploadKind,messageId:ne,conversation:X(n),cause:e})});P.add(o),F(ne,o),o.finally(()=>{P.delete(o);const e=j.get(ne);!H||void 0===e||"running"!==e.state&&"paused"!==e.state&&"queued"!==e.state||ee(ne,e.input,e.state,e.percent,void 0,e.phase)})}},...void 0!==n.filename?{filename:n.filename}:{},...void 0!==n.mimeType?{mimeType:n.mimeType}:{},onProgress:e=>{if(!h()||ge.signal.aborted||K.get(ne)!==ge)return;const t=Number.isFinite(e.percent)?Math.max(0,Math.min(100,Math.round(e.percent))):0,a=Math.max($.get(ne)??0,t);Y.set(ne,{bytesTransferred:e.bytesTransferred,bytesTotal:e.bytesTotal}),$.set(ne,a),i.emitter.emit({type:"media:progress",conversation:X(n),messageId:ne,percent:a}),ge.signal.aborted||K.get(ne)!==ge||ee(ne,n,"running",a,void 0,e.phase)}})).url}catch(e){if(ge.signal.aborted&&e instanceof Error&&"AbortError"===e.name||i.onMediaTransferError?.({stage:"upload",kind:a.uploadKind,messageId:ne,conversation:X(n),cause:e}),!h())return{ok:!1,reason:"cancelled"};const t=ge.signal.aborted?D.get(ne)??"cancelled":"upload-failed";return await ve(t)}if(!h())return{ok:!1,reason:"cancelled"};if(ge.signal.aborted){const e=D.get(ne)??"cancelled";return await ve(e)}if(w===Q&&("image"===a.contentType||"video"===a.contentType)&&void 0!==i.mediaAssetCache){const t=a.contentType,o=B??new Blob([e],void 0===n.mimeType?void 0:{type:n.mimeType}),r=o.size;i.mediaAssetCache.put({kind:t,messageId:ne,resourceVersion:p(d,{conversation:X(n)}),blob:o,...void 0===n.mimeType?{}:{mimeType:n.mimeType}}).catch(e=>{i.onMediaAssetCacheError?.({operation:"put",kind:t,messageId:ne,byteLength:r,cause:e})})}const c="filesAlbum"===a.contentType?await(i.mediaPreview.fileMd5?.(N(e),ge.signal)):void 0;if(!h())return{ok:!1,reason:"cancelled"};if(t(ge.signal),"filesAlbum"===a.contentType&&void 0===c)throw new Error("FILES_ALBUM requires fileMd5");return await C,await Promise.all([...P]),h()?(t(ge.signal),i.outbox.enqueueMedia({optimisticAlreadyCreated:!0,id:ne,conversationId:n.conversationId,conversationType:n.conversationType,contentType:a.contentType,body:a.buildBody({url:d,meta:de,size:o,...void 0===c?{}:{md5:c},..."none"===a.encryptMode?{}:{teaKey:k,fileEncryptType:l}},n),encryption:{encrypted:G},createdAt:oe,...void 0!==n.refMessageId?{refMessageId:n.refMessageId}:{}}),await Promise.all([...P]),void 0!==i.recoveryPort&&await i.recoveryPort.remove(X(n),ne).catch(e=>i.onMediaTransferError?.({stage:"upload",kind:a.uploadKind,messageId:ne,conversation:X(n),cause:e})),ee(ne,n,"completed",100),{ok:!0,messageId:ne}):{ok:!1,reason:"cancelled"}}finally{e()}}catch{if(!h())return{ok:!1,reason:"cancelled"};const e=ge.signal.aborted?D.get(ne)??"cancelled":"upload-failed";return await ve(e)}finally{await C,await Promise.all([...P]),O.get(ne)===T&&O.delete(ne),!h()&&U&&await Promise.all([...P]),h()||void 0===E||U&&"available"===S.get(ne)?.recovery||Z(E,a.uploadKind,ne,X(n)),K.get(ne)===ge&&(K.delete(ne),R.delete(ne),W.has(ne)||$.delete(ne),D.delete(ne))}}async function se(u,w,b,T,k=!1){const A=J,E=()=>H&&A===J,C=X(u),P=(e,t)=>{for(const a of t)void 0!==a.resume&&Z(a.resume,a.uploadKind,e,C)};if(!E())return void 0!==w&&void 0!==T&&P(w,T),{ok:!1,reason:"cancelled"};if(0===u.items.length)return{ok:!1,reason:"empty"};if(u.items.length>o)throw new RangeError(`媒体合集最多 ${o} 项,收到 ${u.items.length} 项`);const U=void 0!==u.caption&&""!==u.caption.trim()?u.caption:void 0;if(void 0!==U&&Array.from(U).length>n)throw new RangeError(`媒体合集配文最长 ${n} 字符,收到 ${Array.from(U).length}`);if(u.items.some(e=>0===e.data.size))return{ok:!1,reason:"empty"};if(void 0===T&&"mediaAlbum"!==r(u)){const e=u.items[0];return de("video"===e.kind?h:y,{conversationId:u.conversationId,conversationType:u.conversationType,data:e.data,...void 0!==e.mimeType?{mimeType:e.mimeType}:{},...void 0!==e.filename?{filename:e.filename}:{},...void 0!==e.localPreviewUrl?{localPreviewUrl:e.localPreviewUrl}:{},...void 0!==e.localPreviewMetadata?{localPreviewMetadata:e.localPreviewMetadata}:{},...void 0!==u.encrypted?{encrypted:u.encrypted}:{},...void 0!==u.refMessageId?{refMessageId:u.refMessageId}:{}},w,b)}const x=u.encrypted??!0;if(x&&void 0===i.crypto)return{ok:!1,reason:"no-crypto"};const S=x?i.crypto:void 0,_=Q,B=void 0===w||void 0===b?i.outbox.allocateMessageIdentity(C):{id:w,createdAt:b},{id:O,createdAt:F}=B,L=u.items.map((e,t)=>{const a=T?.[t];return{uploadKind:e.kind,...void 0===a?.uploaded?{}:{uploaded:a.uploaded},...void 0===a?.preview?{}:{preview:a.preview},...void 0===a?.teaKey?{}:{teaKey:a.teaKey},...void 0===a?.resume?{}:{resume:a.resume}}}),q=L.map((e,t)=>{const a=u.items[t].data.size,i=void 0!==e.uploaded?a:k?0:e.resume?.bytesUploaded??0;return{itemIndex:t,bytesTransferred:i,bytesTotal:a,percent:void 0!==e.uploaded?100:Math.min(99,Math.floor(i/a*100)),state:void 0!==e.uploaded?"completed":"queued"}});N.set(O,q);const V=()=>({...void 0===U?{}:{caption:U},items:u.items.map((e,t)=>function(e,t,a){const i=t.uploaded,n=i?.meta??t.preview??v(e.localPreviewMetadata,e.kind)??{width:0,height:0};return{kind:e.kind,url:i?.url??e.localPreviewUrl??"",width:n.width,height:n.height,..."video"===e.kind&&void 0!==n.duration&&n.duration>0?{durationMs:Math.max(1,Math.round(1e3*n.duration))}:{},...void 0===n.thumbData?{}:{thumbData:n.thumbData},size:i?.size??e.data.size,...void 0===i?.teaKey?{}:{teaKey:i.teaKey},...void 0===i?{}:{fileEncryptType:i.fileEncryptType},...void 0===a?{}:{hd:a}}}(e,L[t],u.hd))});let j={id:O,conversationId:u.conversationId,conversationType:u.conversationType,senderId:i.getSelfId(),contentType:"mediaAlbum",body:{mediaAlbum:V()},createdAt:F,sortKey:c(F,O),status:"uploading",receipt:"unread",encryption:{encrypted:x},...void 0!==u.refMessageId?{refMessageId:u.refMessageId}:{}};i.domainState.upsertMessages([j],"live",{newOutgoing:!0});const G=k?0:$.get(O)??0;let ae;k&&Y.delete(O),$.set(O,G),ee(O,u,"queued",G,void 0,"waiting-upload-slot");const ie=(e,t)=>{const a={code:m,reason:"unknown",displayCode:"cleanup-unconfirmed"===ae?"media.cleanupUnconfirmed":"resume-unavailable"===ae?"media.resumeUnavailable":"timeout"===ae?"media.uploadTimeout":M(e),retryable:t};if(!E())return{ok:!1,reason:e};const n=z.get(O);return"paused"===n?.stopped?(ee(O,u,"paused",$.get(O)??0),{ok:!1,reason:e}):void 0!==n&&void 0===n.stopped&&n.attempt<3&&("network"===n.failure||"timeout"===n.failure||"credentials-expired"===n.failure||"offline"===e&&void 0!==i.waitUntilOnline)?(ee(O,u,"queued",$.get(O)??0,void 0,"waiting-retry"),{ok:!1,reason:e}):("cancelled"===n?.stopped||void 0!==n&&n.attempt>=3&&("network"===n.failure||"timeout"===n.failure||"credentials-expired"===n.failure)||(i.domainState.upsertMessages([{...j,status:"failed",failure:a}],"live"),ee(O,u,"cancelled"===e?"canceled":"failed",$.get(O)??0,a)),{ok:!1,reason:e})},ne=new AbortController;K.set(O,ne),R.set(O,C);const oe=z.get(O)?.stopped;void 0!==oe&&e(ne,"cancelled"===oe&&z.get(O)?.retainCheckpoint?"cancelled-preserve":oe),!1===i.isOnline?.()&&ue(O,"offline");const re=()=>E()&&K.get(O)===ne,se=()=>{E()&&re()&&(j={...j,body:{mediaAlbum:V()}},i.domainState.upsertMessages([j],"live"))},le=u.items.reduce((e,t)=>e+t.data.size,0),ce=L.map((e,t)=>void 0!==e.uploaded?u.items[t].data.size:e.resume?.bytesUploaded??0),pe=()=>{if(!E()||!re()||ne.signal.aborted)return;const e=ce.reduce((e,t)=>e+t,0),t=Math.min(99,Math.max($.get(O)??0,Math.floor(e/le*100)));Y.set(O,{bytesTransferred:e,bytesTotal:le}),$.set(O,t),i.emitter.emit({type:"media:progress",conversation:C,messageId:O,percent:t}),!ne.signal.aborted&&re()&&ee(O,u,"running",t,void 0,"transferring")};let me;const fe=async()=>{let e=!0;return await Promise.all(L.map(async t=>{if(void 0!==t.resume)try{await i.mediaTransfer.abandonUpload(t.resume),delete t.resume}catch(a){e=!1,ae="cleanup-unconfirmed",i.onMediaTransferError?.({stage:"upload",kind:t.uploadKind,messageId:O,conversation:C,cause:a})}})),e},ve=e=>(te(O,{kind:"album",input:u,createdAt:F,message:j,failureReason:e,items:L,...!0===z.get(O)?.retainCheckpoint?{retainCheckpoint:!0}:{},..."cleanup-unconfirmed"===ae||"resume-unavailable"===ae?{restartRequired:!0}:{}}),ie(e,!0));try{if(k){const e=await fe();if(!E())return{ok:!1,reason:"cancelled"};if(!e)return ve("cancelled"===D.get(O)?"cancelled":"upload-failed");for(let e=0;e<L.length;e+=1)void 0===L[e].uploaded&&(ce[e]=0)}if(await Promise.all(u.items.map(async(n,o)=>{const r=L[o];if(void 0===r.uploaded)try{!1===i.isOnline?.()&&ue(O,"offline"),await(i.waitUntilOnline?.(ne.signal)),t(ne.signal);const e=await async function(e){const{conversation:t,encryptWith:n,isCurrentAttempt:o,item:r,onBytesUploaded:d,onPreviewReady:s,onSlotAcquired:l,signal:c,state:u}=e,p="video"===r.kind?h:y,m=a(e.itemCount),w=v(r.localPreviewMetadata,r.kind),b=void 0!==w?.thumbData&&w.thumbData.byteLength>m.maxBytes?{width:w.width,height:w.height,...void 0===w.duration?{}:{duration:w.duration}}:w;let T=b??{width:0,height:0};if("video"!==r.kind||void 0===b?.thumbData)try{T=g(await p.buildPreview(r.data,r.mimeType,i.mediaPreview,c,e.itemCount),b)}catch{}void 0===T.thumbData&&void 0!==u.preview?.thumbData&&u.preview.thumbData.byteLength<=m.maxBytes&&(T=u.preview),u.preview=T,s();const k=await f.acquire(I(r.kind,r.data.size),c);try{let a;l();let s=1;if(void 0!==n){u.teaKey??(u.teaKey=n.randomTeaKey());const e=u.teaKey;a=t=>n.encryptSymmetricChunked({teaKey:e,plain:t,signal:c}),s=3}return{url:(await i.mediaTransfer.upload({recoveryManaged:!0,forceRefreshCredentials:e.forceRefreshCredentials,data:r.data,...void 0===a?{}:{transformPart:a},kind:p.uploadKind,conversationType:t.conversationType,signal:c,...void 0===u.resume?{}:{resume:u.resume},onFailure:t=>{o()&&e.onFailure(t)},onResumeInvalidated:()=>{o()&&delete u.resume},onResumable:e=>{H&&o()&&(u.resume=e)},...void 0!==r.filename?{filename:r.filename}:{},...void 0!==r.mimeType?{mimeType:r.mimeType}:{},onProgress:e=>{H&&!c.aborted&&o()&&d(e.bytesTransferred)}})).url,meta:T,size:r.data.size,...void 0===u.teaKey?{}:{teaKey:u.teaKey},fileEncryptType:s}}finally{k()}}({item:n,itemCount:u.items.length,state:r,conversation:C,encryptWith:S,signal:ne.signal,isCurrentAttempt:re,onPreviewReady:se,onSlotAcquired:()=>{E()&&re()&&!ne.signal.aborted&&(q[o]={...q[o],state:"running"},ee(O,u,"running",$.get(O)??0))},forceRefreshCredentials:!0===z.get(O)?.refreshCredentials,onFailure:e=>{const t="cleanup-unconfirmed"===e||"resume-unavailable"===e;if(ne.signal.aborted&&!t)return;"cleanup-unconfirmed"!==e&&("cleanup-unconfirmed"===ae||"resume-unavailable"!==e&&"resume-unavailable"===ae)||(ae=e);const a=z.get(O);void 0!==a&&(a.failure=ae)},onBytesUploaded:e=>{ce[o]=e,q[o]={...q[o],bytesTransferred:e,percent:Math.min(99,Math.floor(e/n.data.size*100)),state:"running"},pe()}});if(!re())return;r.uploaded=e,q[o]={...q[o],bytesTransferred:n.data.size,percent:100,state:"completed"},ce[o]=n.data.size,pe()}catch(t){re()&&!ne.signal.aborted&&(q[o]={...q[o],state:"failed"}),((t,a)=>{void 0===me&&(me=ne.signal.aborted?D.get(O)??"cancelled":"upload-failed","upload-failed"===me&&i.onMediaTransferError?.({stage:"upload",kind:t,messageId:O,conversation:C,cause:a}),e(ne,"offline"))})(n.kind,t)}})),!E())return{ok:!1,reason:"cancelled"};if(!re())return{ok:!1,reason:"cancelled"};if("cancelled"===D.get(O))return"cleanup-unconfirmed"!==ae&&!0!==z.get(O)?.retainCheckpoint&&await fe(),E()?ve("cancelled"):{ok:!1,reason:"cancelled"};if(void 0!==me)return ve(me);if(ne.signal.aborted){return ve(D.get(O)??"cancelled")}const n=V();let o;try{o=d(s(n).content)}catch(e){return i.onMediaAlbumContentSize?.({messageId:O,conversation:C,itemCount:n.items.length,outcome:"rejected",cause:e}),ie("content-too-large",!1)}if(o>=l&&i.onMediaAlbumContentSize?.({messageId:O,conversation:C,itemCount:n.items.length,contentBytes:o,outcome:"warn"}),_===Q&&void 0!==i.mediaAssetCache){const e=i.mediaAssetCache;u.items.forEach((t,a)=>{const n=L[a].uploaded;void 0!==n&&e.put({kind:t.kind,messageId:O,resourceVersion:p(n.url,{conversation:C,itemIndex:a}),blob:t.data,...void 0===t.mimeType?{}:{mimeType:t.mimeType}}).catch(e=>{i.onMediaAssetCacheError?.({operation:"put",kind:t.kind,messageId:O,byteLength:t.data.size,cause:e})})})}return i.outbox.enqueueMedia({optimisticAlreadyCreated:!0,id:O,conversationId:u.conversationId,conversationType:u.conversationType,contentType:"mediaAlbum",body:{mediaAlbum:n},encryption:{encrypted:x},createdAt:F,...void 0!==u.refMessageId?{refMessageId:u.refMessageId}:{}}),ee(O,u,"completed",100),{ok:!0,messageId:O}}finally{E()||P(O,L),K.get(O)===ne&&(K.delete(O),R.delete(O),W.has(O)||$.delete(O),D.delete(O))}}function le(e,t,a,n=1){const{id:o,createdAt:r}=a??i.outbox.allocateMessageIdentity(X(e)),d={attempt:n};let s,l;G.delete(o),z.set(o,d);const c=new Promise((e,t)=>{s=e,l=t});return d.done=c,(async()=>{let e=await t(o,r);for(;z.get(o)===d&&void 0===d.stopped&&d.attempt<3;){const t=W.get(o);if(!H||e.ok||void 0===t||t.restartRequired||"network"!==d.failure&&"timeout"!==d.failure&&"credentials-expired"!==d.failure&&(e.ok||"offline"!==e.reason||void 0===i.waitUntilOnline))break;const a=new AbortController;if(d.waiting=a,await(i.waitUntilOnline?.(a.signal).catch(()=>{})),await new Promise(e=>{const t=setTimeout(i,1===d.attempt?1e3:3e3);function i(){clearTimeout(t),a.signal.removeEventListener("abort",i),e()}a.signal.addEventListener("abort",i,{once:!0}),a.signal.aborted&&i()}),await(i.waitUntilOnline?.(a.signal).catch(()=>{})),delete d.waiting,!H||void 0!==d.stopped||z.get(o)!==d)break;d.attempt+=1,d.refreshCredentials="credentials-expired"===d.failure,delete d.failure,W.delete(o),G.delete(o),e=await ce(o,t,!1)}const a=W.get(o),n="cancelled"!==d.stopped&&d.attempt>=3&&("network"===d.failure||"timeout"===d.failure||"credentials-expired"===d.failure);if(H&&z.get(o)===d&&void 0!==a&&n&&!0===i.retainFailedUploads){d.stopped="cancelled",d.retainCheckpoint=!0,a.retainCheckpoint=!0;const e={...C(a),displayCode:"timeout"===d.failure?"media.uploadTimeout":"media.uploadFailed",retryable:!0};i.domainState.upsertMessages([{...a.message,status:"failed",failure:e}],"live"),ee(o,a.input,"failed",$.get(o)??0,e)}else if(H&&z.get(o)===d&&void 0!==a&&("cancelled"===d.stopped||n)){d.stopped="cancelled";const t={...C(a),displayCode:"timeout"===d.failure?"media.uploadTimeout":"media.cancelled",retryable:!0===d.retainCheckpoint&&!n};(!0!==d.retainCheckpoint||n)&&await fe(o,a),H&&z.get(o)===d&&(i.domainState.upsertMessages([{...a.message,status:"failed",failure:t}],"live"),ee(o,a.input,"canceled",$.get(o)??0,t)),e={ok:!1,reason:"cancelled"}}return"paused"===d.stopped?{ok:!1,reason:"paused"}:e})().then(e=>{d.settled=!0,re(o),s(e)},e=>{d.settled=!0,re(o),l(e)}),c.then(()=>{z.get(o)===d&&"paused"!==d.stopped&&(z.delete(o),W.has(o)||($.delete(o),Y.delete(o),N.delete(o),S.delete(o),x.delete(o),j.delete(o)))},()=>{z.get(o)===d&&z.delete(o)}),c}function ce(e,t,a){return"album"===t.kind?se(t.input,e,t.createdAt,t.items,a):de(t.spec,t.input,e,t.createdAt,t.teaKey,t.resume,a)}function ue(t,a){const i=z.get(t);if(!H||void 0===i||"cancelled"===i.stopped)return;if("paused"===i.stopped)return void("pagehide"===a&&"offline"===i.pauseReason&&(i.pauseReason="pagehide"));i.stopped="paused",i.pauseReason=a;const n=K.get(t);i.waiting?.abort(),void 0!==n&&e(n,"paused");const o=j.get(t);void 0!==o&&z.get(t)===i&&"paused"===i.stopped&&ee(t,o.input,"paused",$.get(t)??o.percent)}async function pe(e,t="manual"){const a=z.get(e);if(!H||void 0===a||"cancelled"===a.stopped)return!1;if("paused"===a.stopped)return("manual"===t||"pagehide"===t&&"offline"===a.pauseReason)&&(a.pauseReason=t),await a.done,re(e),H&&z.get(e)===a&&W.has(e);ue(e,t),await a.done,await Promise.all(L(e));const i=W.get(e);return!(!H||z.get(e)!==a||"paused"!==a.stopped||void 0===i)&&(ee(e,i.input,"paused",$.get(e)??0),!0)}function me(e){oe();const t=z.get(e),a=W.get(e);if(!H||"paused"!==t?.stopped||!0!==t.settled||void 0===a||K.has(e))return!1;W.delete(e),G.delete(e);const n=J;return le(a.input,()=>ce(e,a,!1),{id:e,createdAt:a.createdAt},t.attempt).catch(t=>{H&&n===J&&i.onMediaTransferError?.({stage:"upload",kind:"media"===a.kind?a.spec.uploadKind:"image",messageId:e,conversation:X(a.input),cause:t})}),!0}async function fe(e,t){W.delete(e),G.delete(e),S.delete(e),x.delete(e),Y.delete(e),N.delete(e),V.add(e);try{await Promise.all(L(e)),await(i.recoveryPort?.remove(X(t.input),e).catch(a=>{i.onMediaTransferError?.({stage:"upload",kind:"media"===t.kind?t.spec.uploadKind:"image",messageId:e,conversation:X(t.input),cause:a})})),await Promise.all(E(t).map(async a=>{try{await i.mediaTransfer.abandonUpload(a.resume)}catch(n){i.onMediaTransferError?.({stage:"upload",kind:a.kind,messageId:e,conversation:X(t.input),cause:n})}}))}catch(a){i.onMediaTransferError?.({stage:"upload",kind:"media"===t.kind?t.spec.uploadKind:"image",messageId:e,conversation:X(t.input),cause:a})}finally{V.delete(e),S.delete(e),x.delete(e),Y.delete(e)}}function ve(t,a){if(oe(),!H)return!1;const n=z.get(t),o=K.get(t);if(!0!==a?.retainCheckpoint&&O.get(t)?.abort(),void 0!==n&&(n.stopped="cancelled",n.retainCheckpoint=!0===a?.retainCheckpoint,n.waiting?.abort()),void 0!==o){const n=R.get(t);return void 0!==n&&!0!==a?.retainCheckpoint&&function(e,t){if(void 0===i.recoveryPort)return;const a=L(e),n="video"===i.domainState.getConversationMessage?.(t,e)?.contentType?"video":"file",o=Promise.all(a).then(()=>i.recoveryPort.remove(t,e)).catch(a=>{i.onMediaTransferError?.({stage:"upload",kind:n,messageId:e,conversation:t,cause:a})});F(e,o)}(t,n),D.set(t,"cancelled"),e(o,!0===a?.retainCheckpoint?"cancelled-preserve":"cancelled"),!0}const r=W.get(t);if(void 0===r||void 0===n)return void 0!==n&&"queued"===j.get(t)?.state;if(!0===a?.retainCheckpoint)r.retainCheckpoint=!0,r.failureReason="cancelled";else{F(t,fe(t,r))}const d={...C(r),displayCode:"media.cancelled",retryable:!0===a?.retainCheckpoint};return i.domainState.upsertMessages([{...r.message,status:"failed",failure:d}],"live"),ee(t,r.input,"canceled",$.get(t)??0,d),z.get(t)===n&&z.delete(t),re(t),!0!==a?.retainCheckpoint&&($.delete(t),N.delete(t),j.delete(t)),!0}async function ge(e,t,a,i){oe();const n=J,o=L(t);return o.length>0&&await Promise.all(o),H&&n===J?(x.delete(t),le(i,()=>de(e,i,t,a,void 0,void 0,!0),{id:t,createdAt:a})):{ok:!1,reason:"cancelled"}}return{sendImage:e=>le(e,(t,a)=>de(y,e,t,a)),sendVideo:e=>le(e,(t,a)=>de(h,e,t,a)),replaceVideo:(e,t,a)=>ge(h,e,t,a),sendVoice:e=>{const t=e.durationMs;return void 0===t||!Number.isFinite(t)||t<1e3?Promise.resolve({ok:!1,reason:"invalid-duration"}):le(e,(t,a)=>de(w,e,t,a))},sendFile:e=>void 0!==e.caption&&Array.from(e.caption).length>n?Promise.resolve({ok:!1,reason:"content-too-large"}):le(e,(t,a)=>de(e.filesAlbum||e.caption?.trim()?k:T,e,t,a)),sendGif:e=>le(e,(t,a)=>de(b,{...e,encrypted:!1},t,a)),sendMediaAlbum:e=>le(e,(t,a)=>se(e,t,a)),replaceFile:(e,t,a)=>void 0!==a.caption&&Array.from(a.caption).length>n?Promise.resolve({ok:!1,reason:"content-too-large"}):ge(a.filesAlbum||a.caption?.trim()?k:T,e,t,a),cancel:ve,pause:pe,async pauseAll(e="pagehide"){for(const{controller:e}of q.values())e.abort();await Promise.all([...z.keys()].map(t=>pe(t,e)))},async resumePaused(e,t){await Promise.all([...z.entries()].map(async([a,i])=>{if(t?.aborted||"paused"!==i.stopped||"manual"===i.pauseReason)return;if(void 0===e&&"offline"!==i.pauseReason)return;const n=j.get(a)?.input;if(void 0!==e&&(n?.conversationType!==e.conversationType||n.conversationId!==e.conversationId))return;await i.done;const o=W.get(a);t?.aborted||z.get(a)!==i||void 0===o||void 0===e&&"offline"!==i.pauseReason||(void 0===e||o.input.conversationType===e.conversationType&&o.input.conversationId===e.conversationId)&&me(a)}))},resume:me,cancelConversation(t,a="offline"){for(const e of q.values())e.ref.conversationType===t.conversationType&&e.ref.conversationId===t.conversationId&&e.controller.abort();for(const[e,a]of W)if(a.input.conversationType===t.conversationType&&a.input.conversationId===t.conversationId){if(z.has(e))ve(e);else{for(const t of E(a))Z(t.resume,t.kind,e,X(a.input));i.recoveryPort?.remove(X(a.input),e).catch(n=>i.onMediaTransferError?.({stage:"upload",kind:"media"===a.kind?a.spec.uploadKind:"image",messageId:e,conversation:t,cause:n}))}W.delete(e),G.delete(e),N.delete(e),Y.delete(e),$.delete(e),j.delete(e)}if(H)for(const[i,n]of R){if(n.conversationType!==t.conversationType||n.conversationId!==t.conversationId)continue;const o=K.get(i);if(void 0===o)continue;const r=z.get(i);void 0!==r&&(r.stopped="cancelled"),D.set(i,a),O.get(i)?.abort(),e(o,a)}},cancelAll(t="offline"){if(H){if("offline"===t){const e=J;for(const t of z.keys()){const a=j.get(t)?.input;pe(t,"offline").catch(n=>{H&&e===J&&void 0!==a&&i.onMediaTransferError?.({stage:"upload",kind:"video"===i.domainState.getConversationMessage?.(a,t)?.contentType?"video":"file",messageId:t,conversation:a,cause:n})})}return}if("session-ended"===t){for(const{controller:e}of q.values())e.abort();for(const e of z.values())e.stopped="cancelled",e.waiting?.abort();J+=1,Q+=1}for(const a of O.values())e(a,t);for(const a of K.values())e(a,t)}},retry(e,t){if(oe(),V.has(e))return!1;if(!H)return!1;const a=W.get(e);if(void 0===a)return!1;if(!0===z.get(e)?.retainCheckpoint&&!0!==z.get(e)?.settled)return!1;if(a.restartRequired&&!0!==t?.restartUpload)return!1;const i=!0===t?.restartUpload||"cancelled"===a.failureReason&&!0!==a.retainCheckpoint;return W.delete(e),G.delete(e),le(a.input,()=>ce(e,a,i),{id:e,createdAt:a.createdAt}),!0},expireRetainedUploads:oe,invalidateAssetCacheWrites(){Q+=1},async dispose(t){if(!H)return;U=!0===t?.preserveRecovery;for(const{controller:e}of q.values())e.abort();const a=[...z.values()].flatMap(e=>void 0===e.done?[]:[e.done]);for(const e of z.values())e.stopped="cancelled",e.waiting?.abort();if(H=!1,Q+=1,!U)for(const e of O.values())e.abort();for(const t of K.values())e(t,U?"page-preserve":"cancelled");for(const[e,t]of W)if(!U||"available"!==S.get(e)?.recovery)for(const a of E(t))Z(a.resume,a.kind,e,X(t.input));W.clear(),G.clear(),await Promise.allSettled(a),await Promise.all([..._]),K.clear(),$.clear(),D.clear();for(const[e,t]of W)if(!U||"available"!==S.get(e)?.recovery)for(const a of E(t))Z(a.resume,a.kind,e,X(t.input));W.clear(),G.clear(),z.clear(),Y.clear(),N.clear(),S.clear(),x.clear(),j.clear(),await(i.recoveryPort?.drain())},async recoverUpload(e,t,a){oe();const n=i.recoveryPort;if(!H||void 0===n)throw new Error("IM_MEDIA_RECOVERY_UNAVAILABLE");if(z.has(t)||q.has(t))throw new Error("IM_MEDIA_RECOVERY_INVALID_STATE");const o=new AbortController;q.set(t,{controller:o,ref:e});const r=()=>{if(!H||o.signal.aborted||q.get(t)?.controller!==o)throw new Error("IM_MEDIA_RECOVERY_INVALID_STATE")},d=(e,t)=>{if(void 0===e||e.senderId!==i.getSelfId()||void 0!==e.recalled||void 0!==e.deletedForEveryone||"media.cancelled"===e.failure?.displayCode&&!0!==e.failure.retryable||"media.uploadTimeout"===e.failure?.displayCode&&!1===e.failure.retryable||"failed"!==e.status&&"uploading"!==e.status)return!1;const a="video"===e.contentType,n="file"===e.contentType||"filesAlbum"===e.contentType&&1===e.body.filesAlbum?.items.length;return(a||n)&&(void 0===t||e.contentType===t)};let s;try{s=await n.acquireLease(o.signal),r();const l=i.domainState.getConversationMessage?.(e,t);if(!d(l))throw new Error("IM_MEDIA_RECOVERY_INVALID_STATE");const c=await n.get(e,t);if(r(),void 0===c)throw new Error("IM_MEDIA_RECOVERY_NOT_FOUND");const u="video"===c.kind?"video":c.filesAlbum||c.caption?.trim()?"filesAlbum":"file";if(!d(l,u))throw new Error("IM_MEDIA_RECOVERY_INVALID_STATE");const p=await n.fingerprint(a,o.signal);if(r(),p.size!==c.source.size||p.sha256!==c.source.sha256)throw new Error("IM_MEDIA_RECOVERY_FILE_MISMATCH");const m=i.domainState.getConversationMessage?.(e,t);if(z.has(t)||!d(m,u))throw new Error("IM_MEDIA_RECOVERY_INVALID_STATE");const f={conversationId:e.conversationId,conversationType:e.conversationType,data:a,encrypted:c.encrypted,filename:c.source.filename,mimeType:c.source.mimeType,caption:c.caption,filesAlbum:c.filesAlbum,refMessageId:c.refMessageId,...void 0===c.preview?{}:{localPreviewMetadata:{width:c.preview.width,height:c.preview.height,duration:c.preview.duration,posterData:c.preview.thumbData}}};return x.set(t,c.savedAt),await le(f,()=>de("video"===c.kind?h:c.filesAlbum||c.caption?.trim()?k:T,f,t,c.createdAt,c.teaKey,c.resume),{id:t,createdAt:c.createdAt})}finally{q.get(t)?.controller===o&&q.delete(t),re(t),s?.release()}}}}export{K as createMediaSender};
1
+ import{throwIfAborted as e}from"../../abort.js";import{resolveMediaThumbnailPolicy as t,MEDIA_THUMBNAIL_MAX_BYTES as a}from"../../media-thumbnail-policy.js";import{MEDIA_ALBUM_CAPTION_MAX_LENGTH as i,MEDIA_ALBUM_MAX_ITEMS as n,resolveMediaAlbumSendContentType as o,measureMediaAlbumContentBytes as r,mediaAlbumBMessageFields as d,MEDIA_ALBUM_CONTENT_WARN_BYTES as s}from"../../mapping/media-album-body.js";import{computeSortKey as l}from"../../mapping/sort.js";import{SIMPLE_ENCRYPT_HEAD_BYTES as c}from"../../ports/crypto-port.js";import{mediaAssetResourceVersion as u}from"../../ports/media-asset-cache-port.js";import{LOCAL_MEDIA_ERROR_CODE as p}from"../../mapping/stored-message.js";function m(e){return Number.isFinite(e)&&e>0}function f(e,i,n=1){if(("video"===i||"image"===i)&&void 0!==e&&m(e.width)&&m(e.height)&&("video"!==i||void 0===e.duration||m(e.duration))&&("video"!==i||void 0===e.posterData||e.posterData instanceof Uint8Array&&0!==e.posterData.length&&!(e.posterData.length>a)))return{width:e.width,height:e.height,..."video"===i&&void 0!==e.duration?{duration:e.duration}:{},..."video"===i&&void 0!==e.posterData&&e.posterData.byteLength<=t(n).maxBytes?{thumbData:new Uint8Array(e.posterData)}:{}}}function v(e,t){return void 0===t?e:{...e,width:t.width,height:t.height,...void 0===t.thumbData?{}:{thumbData:t.thumbData},...void 0===e.duration&&void 0!==t.duration?{duration:t.duration}:{}}}const g={contentType:"image",uploadKind:"image",encryptMode:"integral",streamUpload:!0,async buildPreview(e,a,i,n,o=1){const r=await i.imageDimensions(e,a,n),d=await i.imageThumbnail(e,{mimeType:a,...t(o)},n);return{width:r.width,height:r.height,...d.data.byteLength<=t(o).maxBytes?{thumbData:d.data}:{}}},buildBody:({url:e,meta:t,size:a,teaKey:i,fileEncryptType:n})=>({image:{url:e,width:t.width,height:t.height,...void 0!==t.thumbData?{thumbData:t.thumbData}:{},...void 0!==a?{size:a}:{},...void 0!==n?{fileEncryptType:n}:{},...void 0!==i?{teaKey:i}:{}}})},y={contentType:"video",uploadKind:"video",encryptMode:"integral",streamUpload:!0,async buildPreview(e,a,i,n,o=1){const r=await i.videoPoster(e,{mimeType:a,...t(o)},n);return{width:r.width,height:r.height,...r.data.byteLength<=t(o).maxBytes?{thumbData:r.data}:{},duration:r.duration}},buildBody:({url:e,meta:t,size:a,teaKey:i,fileEncryptType:n},o)=>({video:{url:e,width:t.width,height:t.height,...void 0!==t.duration?{duration:t.duration}:{},...void 0!==o.caption&&""!==o.caption?{describe:o.caption}:{},...void 0!==t.thumbData?{thumbData:t.thumbData}:{},...void 0!==a?{size:a,sizeUnit:"bytes"}:{},...void 0!==n?{fileEncryptType:n}:{},...void 0!==i?{teaKey:i}:{}}})},h={contentType:"voice",uploadKind:"voice",encryptMode:"integral",buildPreview:()=>Promise.resolve({width:0,height:0}),buildBody:({url:e,size:t,teaKey:a,fileEncryptType:i},n)=>({voice:{url:e,durationMs:n.durationMs??0,...void 0!==n.waveform&&n.waveform.length>0?{waveform:n.waveform}:{},...void 0!==t?{size:t}:{},...void 0!==i?{fileEncryptType:i}:{},...void 0!==a?{teaKey:a}:{}}})},w={contentType:"sticker",uploadKind:"sticker",encryptMode:"none",async buildPreview(e,t,a,i){const n=await a.imageDimensions(e,t,i);return{width:n.width,height:n.height}},buildBody:({url:e,meta:t,size:a})=>({sticker:{url:e,width:t.width,height:t.height,exprType:2,imageType:1,...void 0===a?{}:{size:a}}})};const b={contentType:"file",uploadKind:"file",encryptMode:"simple",streamUpload:!0,buildPreview:()=>Promise.resolve({width:0,height:0}),buildBody({url:e,size:t,teaKey:a,fileEncryptType:i},n){const o=n.filename??"",r=function(e){const t=e.lastIndexOf(".");return t>-1&&t<e.length-1?e.slice(t+1).toLowerCase():""}(o),d=function(e,t){const a=t??"";return a.startsWith("image/")||["jpg","jpeg","png","gif","webp","bmp","heic","svg"].includes(e)?1:a.startsWith("video/")||["mp4","mov","m4v","3gp","avi","mkv","webm","flv"].includes(e)?2:a.startsWith("audio/")||["mp3","m4a","wav","aac","flac","ogg"].includes(e)?3:["pdf","doc","docx","xls","xlsx","ppt","pptx","txt","csv","zip","rar","7z","apk","json"].includes(e)?4:0}(r,n.mimeType);return{file:{url:e,fileName:o,...void 0!==t?{size:t}:{},...""!==r?{extension:r}:{},...0!==d?{fileType:d}:{},...void 0!==n.mimeType&&""!==n.mimeType?{mimeType:n.mimeType}:{},...void 0!==i?{fileEncryptType:i}:{},...void 0!==a?{teaKey:a}:{}}}}},T={...b,contentType:"filesAlbum",buildBody(e,t){const a=b.buildBody(e,t).file;return{filesAlbum:{...t.caption?.trim()?{caption:t.caption}:{},items:[{...a,extension:a.extension??"",fileType:a.fileType??0,...["zip","rar","torrent"].includes(a.extension??"")?{fileType:5}:{},...void 0===e.md5?{}:{md5:e.md5}}]}}}};function k(e){switch(e){case"empty":return"media.empty";case"no-crypto":return"media.noCrypto";case"preview-failed":return"media.previewFailed";case"encrypt-failed":return"media.encryptFailed";case"upload-failed":case"offline":return"media.uploadFailed";case"cancelled":return"media.cancelled";case"paused":throw new Error("暂停不是失败状态,不应生成失败文案");case"invalid-duration":return"media.invalidDuration";case"content-too-large":return"media.contentTooLarge"}}function M(e,t){return"video"===e||void 0===t||t>16777216?"large":"small"}function I(){return new DOMException("媒体上传已取消","AbortError")}function A(e){return"album"===e.kind?e.items.flatMap(e=>void 0===e.resume||void 0!==e.uploaded?[]:[{resume:e.resume,kind:e.uploadKind}]):void 0===e.resume?[]:[{resume:e.resume,kind:e.spec.uploadKind}]}function E(e){if("album"===e.kind)return{code:p,reason:"unknown",displayCode:k(e.failureReason),retryable:!1};const t="video"===e.spec.contentType||"file"===e.spec.contentType||"filesAlbum"===e.spec.contentType;return{code:p,reason:"unknown",displayCode:t?"media.uploadInterrupted":k(e.failureReason),mediaKind:e.spec.uploadKind,retryable:!1}}function C(e,t){if(!Number.isInteger(e)||e<1||e>6)throw new RangeError(`媒体上传并发数必须是 1-6 的整数(${t})`)}function P(a){const m=function(e){let t=0,a=0;const i=[];function n(i){return t<e.total&&("large"!==i||a<e.largeFiles)}function o(e){t+=1,"large"===e&&(a+=1);let i=!1;return()=>{i||(i=!0,t-=1,"large"===e&&(a-=1),r())}}function r(){let e=0;for(;e<i.length;){const t=i[e];t.signal.aborted?(i.splice(e,1),t.signal.removeEventListener("abort",t.onAbort),t.reject(I())):n(t.tier)?(i.splice(e,1),t.signal.removeEventListener("abort",t.onAbort),t.resolve(o(t.tier))):e+=1}}return{acquire:(e,t)=>t.aborted?Promise.reject(I()):new Promise((a,n)=>{const o={tier:e,signal:t,resolve:a,reject:n,onAbort:()=>{const e=i.indexOf(o);e>=0&&i.splice(e,1),n(I())}};i.push(o),t.addEventListener("abort",o.onAbort,{once:!0}),r()})}}(function(e){if(void 0===e)return{total:5,largeFiles:3};if("number"==typeof e)return C(e,"总数"),{total:e,largeFiles:e};const t=e.total??5;C(t,"total");const a=e.largeFiles??Math.min(3,t);if(C(a,"largeFiles"),a>t)throw new RangeError(`媒体上传大文件档并发数 ${a} 不能超过总并发数 ${t}`);return{total:t,largeFiles:a}}(a.maxConcurrentUploads)),P=/* @__PURE__ */new Map,K=/* @__PURE__ */new Map,R=/* @__PURE__ */new Map,D=/* @__PURE__ */new Map;let z=!1;const U=/* @__PURE__ */new Map,x=/* @__PURE__ */new Map,S=/* @__PURE__ */new Set,_=/* @__PURE__ */new Map,B=/* @__PURE__ */new Map;function O(e,t){const a=_.get(e)??/* @__PURE__ */new Set;_.set(e,a),a.add(t),S.add(t),t.finally(()=>{a.delete(t),S.delete(t),0===a.size&&_.get(e)===a&&_.delete(e),oe(e)})}function F(e){return[..._.get(e)??[]]}const L=/* @__PURE__ */new Map,q=/* @__PURE__ */new Set,V=/* @__PURE__ */new Map,j=/* @__PURE__ */new Map,N=/* @__PURE__ */new Map,Y=/* @__PURE__ */new Map,$=/* @__PURE__ */new Map,W=/* @__PURE__ */new Map;let G=!0,H=0,J=0;function Q(e){return{conversationType:e.conversationType,conversationId:e.conversationId}}function X(e,t,i,n){a.mediaTransfer.abandonUpload(e).catch(e=>{a.onMediaTransferError?.({stage:"upload",kind:t,messageId:i,conversation:n,cause:e})})}function Z(e,t,i,n,o,r){if(!G)return;const d=Q(t);V.set(e,{input:Q(t),state:i,percent:n,phase:r}),a.emitter.emit({type:"media-task:updated",conversation:d,task:{id:`upload:${e}`,messageId:e,ref:d,direction:"upload",state:i,percent:Math.max(0,Math.min(100,Math.round(n))),attempt:D.get(e)?.attempt??1,maxAttempts:3,...N.get(e),...j.has(e)?{items:Object.freeze(j.get(e).map(e=>Object.freeze({...e,state:"completed"===e.state?"completed":"canceled"===i||"failed"===i?i:e.state})))}:{},...x.get(e),...void 0===r?{}:{phase:r},...void 0===o?{}:{failure:o}}})}function ee(e,t){ne(),$.delete(e),W.delete(e),$.set(e,t),ie()}function te(e){const t=D.get(e);if(P.has(e)||L.has(e)||F(e).length>0||void 0!==t&&(!0!==t.settled||void 0!==t.waiting))return!1;const a=V.get(e)?.state;return"failed"===a||"canceled"===a||"paused"===a&&"manual"===t?.pauseReason}function ae(e,t){const i=Q(t.input),n=A(t),o="media"===t.kind?t.spec.uploadKind:"image",r={...E(t),displayCode:"media.uploadInterrupted",retryable:!1};$.delete(e),W.delete(e),D.delete(e),Y.delete(e),N.delete(e),j.delete(e),x.delete(e),U.delete(e),V.delete(e),R.delete(e);for(const t of n)X(t.resume,t.kind,e,i);if(function(e,t,i){const n=a.recoveryPort;if(void 0===n)return;const o=F(e),r=Promise.all(o).then(()=>n.remove(Q(t),e)).catch(n=>{a.onMediaTransferError?.({stage:"upload",kind:i,messageId:e,conversation:Q(t),cause:n})});O(e,r)}(e,i,o),!G)return;const d=a.domainState.getConversationMessage?.(i,e)??t.message;"sent"!==d.status&&(a.domainState.upsertMessages([{...d,status:"failed",failure:r}],"live"),Z(e,i,"failed",0,r))}function ie(){if(G)for(const[e,t]of $){if($.size<=3)break;te(e)&&ae(e,t)}}function ne(){if(!G)return;const e=Date.now();for(const[t,a]of $){const i=W.get(t);void 0!==i&&e-i>=864e5&&te(t)&&ae(t,a)}}function oe(e){G&&($.has(e)&&te(e)&&!W.has(e)&&W.set(e,Date.now()),ie())}async function re(t,i,n,o,r,d,s=!1){const g=H,y=()=>G&&g===H;if(!y())return void 0!==d&&void 0!==n&&X(d,t.uploadKind,n,Q(i)),{ok:!1,reason:"cancelled"};const h=J;let w,b,T=r,A=d,E=Promise.resolve(void 0);const C=/* @__PURE__ */new Set,S="function"==typeof i.data;const _=function(e){return"undefined"!=typeof Blob&&e instanceof Blob}(i.data)?i.data:void 0,F=S||void 0!==_?void 0:i.data,L=S||void 0!==_,q=!0===t.streamUpload&&void 0!==_,j=e=>{if(void 0!==_)return _;if(void 0===e)throw new Error("媒体预览缺少内容:非 Blob 输入必须先读出字节");return new Blob([e],void 0===i.mimeType?void 0:{type:i.mimeType})};if(0===F?.length||0===_?.size)return{ok:!1,reason:"empty"};const W=i.encrypted??!0;if(W&&void 0===a.crypto)return{ok:!1,reason:"no-crypto"};const te=f(i.localPreviewMetadata,t.contentType);if(("video"===t.contentType||"image"===t.contentType)&&void 0!==i.localPreviewMetadata&&void 0===te)return{ok:!1,reason:"preview-failed"};const ae=void 0===n||void 0===o?a.outbox.allocateMessageIdentity({conversationId:i.conversationId,conversationType:i.conversationType}):{id:n,createdAt:o},{id:ie,createdAt:ne}=ae,oe=a.getSelfId();let re=te??{width:0,height:0};if(!L)try{re=v(await t.buildPreview(j(F),i.mimeType,a.mediaPreview),te)}catch{}if(!y())return void 0!==A&&X(A,t.uploadKind,ie,Q(i)),{ok:!1,reason:"cancelled"};const de=_?.size??F?.byteLength,se={url:i.localPreviewUrl??"",...void 0===de?{}:{size:de}};let le={id:ie,conversationId:i.conversationId,conversationType:i.conversationType,senderId:oe,contentType:t.contentType,body:t.buildBody({...se,meta:re},i),createdAt:ne,sortKey:l(ne,ie),status:"uploading",receipt:"unread",encryption:{encrypted:W},...void 0!==i.refMessageId?{refMessageId:i.refMessageId}:{}};a.domainState.upsertMessages([le],"live",{newOutgoing:!0});const ue=s?0:Y.get(ie)??0;s&&N.delete(ie),Y.set(ie,ue),Z(ie,i,"queued",ue,void 0,"waiting-upload-slot");const pe=(e,n=!1)=>{const o={code:p,reason:"unknown",displayCode:"cleanup-unconfirmed"===w?"media.cleanupUnconfirmed":"resume-unavailable"===w?"media.resumeUnavailable":"timeout"===w?"media.uploadTimeout":k(e),mediaKind:t.uploadKind,retryable:n};if(!y())return{ok:!1,reason:e};const r=D.get(ie);return"paused"===r?.stopped?(Z(ie,i,"paused",Y.get(ie)??0),{ok:!1,reason:e}):void 0!==r&&void 0===r.stopped&&r.attempt<3&&("network"===r.failure||"timeout"===r.failure||"credentials-expired"===r.failure||"offline"===e&&void 0!==a.waitUntilOnline)?(Z(ie,i,"queued",Y.get(ie)??0,void 0,"waiting-retry"),{ok:!1,reason:e}):("cancelled"===r?.stopped||void 0!==r&&r.attempt>=3&&("network"===r.failure||"timeout"===r.failure||"credentials-expired"===r.failure)||(a.domainState.upsertMessages([{...le,status:"failed",failure:o}],"live"),Z(ie,i,"cancelled"===e?"canceled":"failed",Y.get(ie)??0,o)),{ok:!1,reason:e})},me=async()=>{if(void 0!==A)try{await a.mediaTransfer.abandonUpload(A),A=void 0}catch(e){throw w="cleanup-unconfirmed",a.onMediaTransferError?.({stage:"upload",kind:t.uploadKind,messageId:ie,conversation:Q(i),cause:e}),e}},fe=async e=>{if(await E,await Promise.all([...C]),"cancelled"===e&&"paused"!==D.get(ie)?.stopped&&!0!==D.get(ie)?.retainCheckpoint&&"cleanup-unconfirmed"!==w)try{await me()}catch{}return"cancelled"===e&&"paused"!==D.get(ie)?.stopped&&!0!==D.get(ie)?.retainCheckpoint&&void 0!==a.recoveryPort&&(await Promise.all([...C]),await a.recoveryPort.remove(Q(i),ie).catch(e=>a.onMediaTransferError?.({stage:"upload",kind:t.uploadKind,messageId:ie,conversation:Q(i),cause:e}))),y()?(ee(ie,{kind:"media",spec:t,input:i,createdAt:ne,message:le,failureReason:e,...!0===D.get(ie)?.retainCheckpoint?{retainCheckpoint:!0}:{},..."cleanup-unconfirmed"===w||"resume-unavailable"===w?{restartRequired:!0}:{},...void 0===T?{}:{teaKey:T},...void 0===A?{}:{resume:A}}),pe(e,!0)):{ok:!1,reason:"cancelled"}},ve=new AbortController;P.set(ie,ve),K.set(ie,Q(i));const ge=D.get(ie)?.stopped;void 0!==ge&&ve.abort("cancelled"===ge&&D.get(ie)?.retainCheckpoint?"cancelled-preserve":ge),!1===a.isOnline?.()&&ce(ie,"offline");try{if(s&&(await me(),!y()))return{ok:!1,reason:"cancelled"};if(void 0!==_&&("video"!==t.contentType||void 0===te?.thumbData)){try{re=v(await t.buildPreview(_,i.mimeType,a.mediaPreview,ve.signal),te)}catch{}if(!y())return{ok:!1,reason:"cancelled"};le={...le,body:t.buildBody({url:i.localPreviewUrl??"",meta:re,size:_.size},i)},a.domainState.upsertMessages([le],"live")}const n=await m.acquire(M(t.contentType,_?.size??F?.byteLength),ve.signal);try{let n;Z(ie,i,"running",Y.get(ie)??0);try{q||(n=S?await i.data():void 0!==_?new Uint8Array(await _.arrayBuffer()):F)}catch{return pe("upload-failed",!0)}const o=q?_.size:n.length;if(0===o)return pe("empty");if(S&&("video"!==t.contentType||void 0===te?.thumbData)){try{re=v(await t.buildPreview(j(n),i.mimeType,a.mediaPreview,ve.signal),te)}catch{}if(!y())return{ok:!1,reason:"cancelled"};le={...le,body:t.buildBody({url:i.localPreviewUrl??"",meta:re,size:o},i)},a.domainState.upsertMessages([le],"live")}if(e(ve.signal),("video"===t.contentType||"file"===t.contentType||"filesAlbum"===t.contentType)&&void 0!==a.recoveryPort&&!0===a.shouldPersistUpload?.(t.uploadKind,o)){b=new AbortController,B.set(ie,b);const e=b.signal;x.set(ie,{recovery:"session-only",recoveryReason:"fingerprint-pending"}),E=Promise.resolve().then(()=>a.recoveryPort.fingerprint(q?_:n,e)).catch(n=>{!e.aborted&&y()&&(x.set(ie,{recovery:"session-only",recoveryReason:"unavailable"}),a.onMediaTransferError?.({stage:"upload",kind:t.uploadKind,messageId:ie,conversation:Q(i),cause:n}))}),q||await E}if(ve.signal.aborted)throw I();let r,d,s=q?_:n,l=1;if(W&&void 0!==a.crypto&&"none"!==t.encryptMode){const e=a.crypto;try{T??(T=e.randomTeaKey());const a=T;"simple"===t.encryptMode?(s=q?new Blob([new Uint8Array(e.encryptFileSimple({teaKey:a,plain:new Uint8Array(await _.slice(0,c).arrayBuffer())})),_.slice(c)]):e.encryptFileSimple({teaKey:a,plain:n}),l=2):q?(r=t=>e.encryptSymmetricChunked({teaKey:a,plain:t,signal:ve.signal}),l=3):(s=e.encryptSymmetric({teaKey:a,plain:n}),l=3)}catch{return pe("encrypt-failed")}}try{!1===a.isOnline?.()&&ce(ie,"offline"),await(a.waitUntilOnline?.(ve.signal)),e(ve.signal);d=(await a.mediaTransfer.upload({recoveryManaged:!0,forceRefreshCredentials:!0===D.get(ie)?.refreshCredentials,data:s,...void 0===r?{}:{transformPart:r},kind:t.uploadKind,conversationType:i.conversationType,signal:ve.signal,...void 0===A?{}:{resume:A},onFailure:e=>{if(y()&&P.get(ie)===ve){w=e;const t=D.get(ie);void 0!==t&&(t.failure=e)}},onResumeInvalidated:()=>{y()&&P.get(ie)===ve&&(A=void 0)},onResumable:e=>{if(y()&&P.get(ie)===ve&&(A=e,!("cancelled"===D.get(ie)?.stopped&&!0!==D.get(ie)?.retainCheckpoint||void 0===b||void 0===a.recoveryPort||"video"!==t.contentType&&"file"!==t.contentType&&"filesAlbum"!==t.contentType))){const n=U.get(ie)??Date.now();U.set(ie,n);const o=E.then(async o=>{void 0===o||b?.signal.aborted||!y()&&!z||P.get(ie)!==ve||"cancelled"===D.get(ie)?.stopped&&!0!==D.get(ie)?.retainCheckpoint&&!z||(await a.recoveryPort.save({version:1,ref:Q(i),messageId:ie,kind:"video"===t.contentType?"video":"file",createdAt:ne,savedAt:n,source:{...o,...void 0===i.filename?{}:{filename:i.filename},...void 0===i.mimeType?{}:{mimeType:i.mimeType}},encrypted:W,...void 0===T?{}:{teaKey:T},resume:e,...void 0===i.caption?{}:{caption:i.caption},...void 0===i.filesAlbum?{}:{filesAlbum:i.filesAlbum},...void 0===i.refMessageId?{}:{refMessageId:i.refMessageId},..."video"===t.contentType?{preview:re}:{}}),P.get(ie)!==ve||b?.signal.aborted||x.set(ie,{recovery:"available"}))}).catch(e=>{const n="object"==typeof e&&null!==e&&"reason"in e?String(e.reason):"storage";(P.get(ie)===ve||$.has(ie))&&x.set(ie,{recovery:"session-only",recoveryReason:n}),a.onMediaTransferError?.({stage:"upload",kind:t.uploadKind,messageId:ie,conversation:Q(i),cause:e})});C.add(o),O(ie,o),o.finally(()=>{C.delete(o);const e=V.get(ie);!G||void 0===e||"running"!==e.state&&"paused"!==e.state&&"queued"!==e.state||Z(ie,e.input,e.state,e.percent,void 0,e.phase)})}},...void 0!==i.filename?{filename:i.filename}:{},...void 0!==i.mimeType?{mimeType:i.mimeType}:{},onProgress:e=>{if(!y()||ve.signal.aborted||P.get(ie)!==ve)return;const t=Number.isFinite(e.percent)?Math.max(0,Math.min(100,Math.round(e.percent))):0,n=Math.max(Y.get(ie)??0,t);N.set(ie,{bytesTransferred:e.bytesTransferred,bytesTotal:e.bytesTotal}),Y.set(ie,n),a.emitter.emit({type:"media:progress",conversation:Q(i),messageId:ie,percent:n}),ve.signal.aborted||P.get(ie)!==ve||Z(ie,i,"running",n,void 0,e.phase)}})).url}catch(e){if(ve.signal.aborted&&e instanceof Error&&"AbortError"===e.name||a.onMediaTransferError?.({stage:"upload",kind:t.uploadKind,messageId:ie,conversation:Q(i),cause:e}),!y())return{ok:!1,reason:"cancelled"};const n=ve.signal.aborted?R.get(ie)??"cancelled":"upload-failed";return await fe(n)}if(!y())return{ok:!1,reason:"cancelled"};if(ve.signal.aborted){const e=R.get(ie)??"cancelled";return await fe(e)}if(h===J&&("image"===t.contentType||"video"===t.contentType)&&void 0!==a.mediaAssetCache){const e=t.contentType,o=_??new Blob([n],void 0===i.mimeType?void 0:{type:i.mimeType}),r=o.size;a.mediaAssetCache.put({kind:e,messageId:ie,resourceVersion:u(d,{conversation:Q(i)}),blob:o,...void 0===i.mimeType?{}:{mimeType:i.mimeType}}).catch(t=>{a.onMediaAssetCacheError?.({operation:"put",kind:e,messageId:ie,byteLength:r,cause:t})})}const p="filesAlbum"===t.contentType?await(a.mediaPreview.fileMd5?.(j(n),ve.signal)):void 0;if(!y())return{ok:!1,reason:"cancelled"};if(e(ve.signal),"filesAlbum"===t.contentType&&void 0===p)throw new Error("FILES_ALBUM requires fileMd5");return await E,await Promise.all([...C]),y()?(e(ve.signal),a.outbox.enqueueMedia({optimisticAlreadyCreated:!0,id:ie,conversationId:i.conversationId,conversationType:i.conversationType,contentType:t.contentType,body:t.buildBody({url:d,meta:re,size:o,...void 0===p?{}:{md5:p},..."none"===t.encryptMode?{}:{teaKey:T,fileEncryptType:l}},i),encryption:{encrypted:W},createdAt:ne,...void 0!==i.refMessageId?{refMessageId:i.refMessageId}:{}}),await Promise.all([...C]),void 0!==a.recoveryPort&&await a.recoveryPort.remove(Q(i),ie).catch(e=>a.onMediaTransferError?.({stage:"upload",kind:t.uploadKind,messageId:ie,conversation:Q(i),cause:e})),Z(ie,i,"completed",100),{ok:!0,messageId:ie}):{ok:!1,reason:"cancelled"}}finally{n()}}catch{if(!y())return{ok:!1,reason:"cancelled"};const e=ve.signal.aborted?R.get(ie)??"cancelled":"upload-failed";return await fe(e)}finally{await E,await Promise.all([...C]),B.get(ie)===b&&B.delete(ie),!y()&&z&&await Promise.all([...C]),y()||void 0===A||z&&"available"===x.get(ie)?.recovery||X(A,t.uploadKind,ie,Q(i)),P.get(ie)===ve&&(P.delete(ie),K.delete(ie),$.has(ie)||Y.delete(ie),R.delete(ie))}}async function de(c,h,w,b,T=!1){const I=H,A=()=>G&&I===H,E=Q(c),C=(e,t)=>{for(const a of t)void 0!==a.resume&&X(a.resume,a.uploadKind,e,E)};if(!A())return void 0!==h&&void 0!==b&&C(h,b),{ok:!1,reason:"cancelled"};if(0===c.items.length)return{ok:!1,reason:"empty"};if(c.items.length>n)throw new RangeError(`媒体合集最多 ${n} 项,收到 ${c.items.length} 项`);const z=void 0!==c.caption&&""!==c.caption.trim()?c.caption:void 0;if(void 0!==z&&Array.from(z).length>i)throw new RangeError(`媒体合集配文最长 ${i} 字符,收到 ${Array.from(z).length}`);if(c.items.some(e=>0===e.data.size))return{ok:!1,reason:"empty"};if(void 0===b&&"mediaAlbum"!==o(c)){const e=c.items[0];return re("video"===e.kind?y:g,{conversationId:c.conversationId,conversationType:c.conversationType,data:e.data,...void 0!==e.mimeType?{mimeType:e.mimeType}:{},...void 0!==e.filename?{filename:e.filename}:{},...void 0!==e.localPreviewUrl?{localPreviewUrl:e.localPreviewUrl}:{},...void 0!==e.localPreviewMetadata?{localPreviewMetadata:e.localPreviewMetadata}:{},...void 0!==c.encrypted?{encrypted:c.encrypted}:{},...void 0!==c.refMessageId?{refMessageId:c.refMessageId}:{}},h,w)}const U=c.encrypted??!0;if(U&&void 0===a.crypto)return{ok:!1,reason:"no-crypto"};const x=U?a.crypto:void 0,S=J,_=void 0===h||void 0===w?a.outbox.allocateMessageIdentity(E):{id:h,createdAt:w},{id:B,createdAt:O}=_,F=c.items.map((e,t)=>{const a=b?.[t];return{uploadKind:e.kind,...void 0===a?.uploaded?{}:{uploaded:a.uploaded},...void 0===a?.preview?{}:{preview:a.preview},...void 0===a?.teaKey?{}:{teaKey:a.teaKey},...void 0===a?.resume?{}:{resume:a.resume}}}),L=F.map((e,t)=>{const a=c.items[t].data.size,i=void 0!==e.uploaded?a:T?0:e.resume?.bytesUploaded??0;return{itemIndex:t,bytesTransferred:i,bytesTotal:a,percent:void 0!==e.uploaded?100:Math.min(99,Math.floor(i/a*100)),state:void 0!==e.uploaded?"completed":"queued"}});j.set(B,L);const q=()=>({...void 0===z?{}:{caption:z},items:c.items.map((e,t)=>function(e,t,a){const i=t.uploaded,n=i?.meta??t.preview??f(e.localPreviewMetadata,e.kind)??{width:0,height:0};return{kind:e.kind,url:i?.url??e.localPreviewUrl??"",width:n.width,height:n.height,..."video"===e.kind&&void 0!==n.duration&&n.duration>0?{durationMs:Math.max(1,Math.round(1e3*n.duration))}:{},...void 0===n.thumbData?{}:{thumbData:n.thumbData},size:i?.size??e.data.size,...void 0===i?.teaKey?{}:{teaKey:i.teaKey},...void 0===i?{}:{fileEncryptType:i.fileEncryptType},...void 0===a?{}:{hd:a}}}(e,F[t],c.hd))});let V={id:B,conversationId:c.conversationId,conversationType:c.conversationType,senderId:a.getSelfId(),contentType:"mediaAlbum",body:{mediaAlbum:q()},createdAt:O,sortKey:l(O,B),status:"uploading",receipt:"unread",encryption:{encrypted:U},...void 0!==c.refMessageId?{refMessageId:c.refMessageId}:{}};a.domainState.upsertMessages([V],"live",{newOutgoing:!0});const W=T?0:Y.get(B)??0;let te;T&&N.delete(B),Y.set(B,W),Z(B,c,"queued",W,void 0,"waiting-upload-slot");const ae=(e,t)=>{const i={code:p,reason:"unknown",displayCode:"cleanup-unconfirmed"===te?"media.cleanupUnconfirmed":"resume-unavailable"===te?"media.resumeUnavailable":"timeout"===te?"media.uploadTimeout":k(e),retryable:t};if(!A())return{ok:!1,reason:e};const n=D.get(B);return"paused"===n?.stopped?(Z(B,c,"paused",Y.get(B)??0),{ok:!1,reason:e}):void 0!==n&&void 0===n.stopped&&n.attempt<3&&("network"===n.failure||"timeout"===n.failure||"credentials-expired"===n.failure||"offline"===e&&void 0!==a.waitUntilOnline)?(Z(B,c,"queued",Y.get(B)??0,void 0,"waiting-retry"),{ok:!1,reason:e}):("cancelled"===n?.stopped||void 0!==n&&n.attempt>=3&&("network"===n.failure||"timeout"===n.failure||"credentials-expired"===n.failure)||(a.domainState.upsertMessages([{...V,status:"failed",failure:i}],"live"),Z(B,c,"cancelled"===e?"canceled":"failed",Y.get(B)??0,i)),{ok:!1,reason:e})},ie=new AbortController;P.set(B,ie),K.set(B,E);const ne=D.get(B)?.stopped;void 0!==ne&&ie.abort("cancelled"===ne&&D.get(B)?.retainCheckpoint?"cancelled-preserve":ne),!1===a.isOnline?.()&&ce(B,"offline");const oe=()=>A()&&P.get(B)===ie,de=()=>{A()&&oe()&&(V={...V,body:{mediaAlbum:q()}},a.domainState.upsertMessages([V],"live"))},se=c.items.reduce((e,t)=>e+t.data.size,0),le=F.map((e,t)=>void 0!==e.uploaded?c.items[t].data.size:e.resume?.bytesUploaded??0),ue=()=>{if(!A()||!oe()||ie.signal.aborted)return;const e=le.reduce((e,t)=>e+t,0),t=Math.min(99,Math.max(Y.get(B)??0,Math.floor(e/se*100)));N.set(B,{bytesTransferred:e,bytesTotal:se}),Y.set(B,t),a.emitter.emit({type:"media:progress",conversation:E,messageId:B,percent:t}),!ie.signal.aborted&&oe()&&Z(B,c,"running",t,void 0,"transferring")};let pe;const me=async()=>{let e=!0;return await Promise.all(F.map(async t=>{if(void 0!==t.resume)try{await a.mediaTransfer.abandonUpload(t.resume),delete t.resume}catch(i){e=!1,te="cleanup-unconfirmed",a.onMediaTransferError?.({stage:"upload",kind:t.uploadKind,messageId:B,conversation:E,cause:i})}})),e},fe=e=>(ee(B,{kind:"album",input:c,createdAt:O,message:V,failureReason:e,items:F,...!0===D.get(B)?.retainCheckpoint?{retainCheckpoint:!0}:{},..."cleanup-unconfirmed"===te||"resume-unavailable"===te?{restartRequired:!0}:{}}),ae(e,!0));try{if(T){const e=await me();if(!A())return{ok:!1,reason:"cancelled"};if(!e)return fe("cancelled"===R.get(B)?"cancelled":"upload-failed");for(let e=0;e<F.length;e+=1)void 0===F[e].uploaded&&(le[e]=0)}if(await Promise.all(c.items.map(async(i,n)=>{const o=F[n];if(void 0===o.uploaded)try{!1===a.isOnline?.()&&ce(B,"offline"),await(a.waitUntilOnline?.(ie.signal)),e(ie.signal);const r=await async function(e){const{conversation:i,encryptWith:n,isCurrentAttempt:o,item:r,onBytesUploaded:d,onPreviewReady:s,onSlotAcquired:l,signal:c,state:u}=e,p="video"===r.kind?y:g,h=t(e.itemCount),w=f(r.localPreviewMetadata,r.kind,e.itemCount);let b=w??{width:0,height:0};if("video"!==r.kind||void 0===w?.thumbData)try{b=v(await p.buildPreview(r.data,r.mimeType,a.mediaPreview,c,e.itemCount),w)}catch{}void 0===b.thumbData&&void 0!==u.preview?.thumbData&&u.preview.thumbData.byteLength<=h.maxBytes&&(b=u.preview),u.preview=b,s();const T=await m.acquire(M(r.kind,r.data.size),c);try{let t;l();let s=1;if(void 0!==n){u.teaKey??(u.teaKey=n.randomTeaKey());const e=u.teaKey;t=t=>n.encryptSymmetricChunked({teaKey:e,plain:t,signal:c}),s=3}return{url:(await a.mediaTransfer.upload({recoveryManaged:!0,forceRefreshCredentials:e.forceRefreshCredentials,data:r.data,...void 0===t?{}:{transformPart:t},kind:p.uploadKind,conversationType:i.conversationType,signal:c,...void 0===u.resume?{}:{resume:u.resume},onFailure:t=>{o()&&e.onFailure(t)},onResumeInvalidated:()=>{o()&&delete u.resume},onResumable:e=>{G&&o()&&(u.resume=e)},...void 0!==r.filename?{filename:r.filename}:{},...void 0!==r.mimeType?{mimeType:r.mimeType}:{},onProgress:e=>{G&&!c.aborted&&o()&&d(e.bytesTransferred)}})).url,meta:b,size:r.data.size,...void 0===u.teaKey?{}:{teaKey:u.teaKey},fileEncryptType:s}}finally{T()}}({item:i,itemCount:c.items.length,state:o,conversation:E,encryptWith:x,signal:ie.signal,isCurrentAttempt:oe,onPreviewReady:de,onSlotAcquired:()=>{A()&&oe()&&!ie.signal.aborted&&(L[n]={...L[n],state:"running"},Z(B,c,"running",Y.get(B)??0))},forceRefreshCredentials:!0===D.get(B)?.refreshCredentials,onFailure:e=>{const t="cleanup-unconfirmed"===e||"resume-unavailable"===e;if(ie.signal.aborted&&!t)return;"cleanup-unconfirmed"!==e&&("cleanup-unconfirmed"===te||"resume-unavailable"!==e&&"resume-unavailable"===te)||(te=e);const a=D.get(B);void 0!==a&&(a.failure=te)},onBytesUploaded:e=>{le[n]=e,L[n]={...L[n],bytesTransferred:e,percent:Math.min(99,Math.floor(e/i.data.size*100)),state:"running"},ue()}});if(!oe())return;o.uploaded=r,L[n]={...L[n],bytesTransferred:i.data.size,percent:100,state:"completed"},le[n]=i.data.size,ue()}catch(e){oe()&&!ie.signal.aborted&&(L[n]={...L[n],state:"failed"}),((e,t)=>{void 0===pe&&(pe=ie.signal.aborted?R.get(B)??"cancelled":"upload-failed","upload-failed"===pe&&a.onMediaTransferError?.({stage:"upload",kind:e,messageId:B,conversation:E,cause:t}),ie.abort("offline"))})(i.kind,e)}})),!A())return{ok:!1,reason:"cancelled"};if(!oe())return{ok:!1,reason:"cancelled"};if("cancelled"===R.get(B))return"cleanup-unconfirmed"!==te&&!0!==D.get(B)?.retainCheckpoint&&await me(),A()?fe("cancelled"):{ok:!1,reason:"cancelled"};if(void 0!==pe)return fe(pe);if(ie.signal.aborted){return fe(R.get(B)??"cancelled")}const i=q();let n;try{n=r(d(i).content)}catch(e){return a.onMediaAlbumContentSize?.({messageId:B,conversation:E,itemCount:i.items.length,outcome:"rejected",cause:e}),ae("content-too-large",!1)}if(n>=s&&a.onMediaAlbumContentSize?.({messageId:B,conversation:E,itemCount:i.items.length,contentBytes:n,outcome:"warn"}),S===J&&void 0!==a.mediaAssetCache){const e=a.mediaAssetCache;c.items.forEach((t,i)=>{const n=F[i].uploaded;void 0!==n&&e.put({kind:t.kind,messageId:B,resourceVersion:u(n.url,{conversation:E,itemIndex:i}),blob:t.data,...void 0===t.mimeType?{}:{mimeType:t.mimeType}}).catch(e=>{a.onMediaAssetCacheError?.({operation:"put",kind:t.kind,messageId:B,byteLength:t.data.size,cause:e})})})}return a.outbox.enqueueMedia({optimisticAlreadyCreated:!0,id:B,conversationId:c.conversationId,conversationType:c.conversationType,contentType:"mediaAlbum",body:{mediaAlbum:i},encryption:{encrypted:U},createdAt:O,...void 0!==c.refMessageId?{refMessageId:c.refMessageId}:{}}),Z(B,c,"completed",100),{ok:!0,messageId:B}}finally{A()||C(B,F),P.get(B)===ie&&(P.delete(B),K.delete(B),$.has(B)||Y.delete(B),R.delete(B))}}function se(e,t,i,n=1){const{id:o,createdAt:r}=i??a.outbox.allocateMessageIdentity(Q(e)),d={attempt:n};let s,l;W.delete(o),D.set(o,d);const c=new Promise((e,t)=>{s=e,l=t});return d.done=c,(async()=>{let e=await t(o,r);for(;D.get(o)===d&&void 0===d.stopped&&d.attempt<3;){const t=$.get(o);if(!G||e.ok||void 0===t||t.restartRequired||"network"!==d.failure&&"timeout"!==d.failure&&"credentials-expired"!==d.failure&&(e.ok||"offline"!==e.reason||void 0===a.waitUntilOnline))break;const i=new AbortController;if(d.waiting=i,await(a.waitUntilOnline?.(i.signal).catch(()=>{})),await new Promise(e=>{const t=setTimeout(a,1===d.attempt?1e3:3e3);function a(){clearTimeout(t),i.signal.removeEventListener("abort",a),e()}i.signal.addEventListener("abort",a,{once:!0}),i.signal.aborted&&a()}),await(a.waitUntilOnline?.(i.signal).catch(()=>{})),delete d.waiting,!G||void 0!==d.stopped||D.get(o)!==d)break;d.attempt+=1,d.refreshCredentials="credentials-expired"===d.failure,delete d.failure,$.delete(o),W.delete(o),e=await le(o,t,!1)}const i=$.get(o),n="cancelled"!==d.stopped&&d.attempt>=3&&("network"===d.failure||"timeout"===d.failure||"credentials-expired"===d.failure);if(G&&D.get(o)===d&&void 0!==i&&n&&!0===a.retainFailedUploads){d.stopped="cancelled",d.retainCheckpoint=!0,i.retainCheckpoint=!0;const e={...E(i),displayCode:"timeout"===d.failure?"media.uploadTimeout":"media.uploadFailed",retryable:!0};a.domainState.upsertMessages([{...i.message,status:"failed",failure:e}],"live"),Z(o,i.input,"failed",Y.get(o)??0,e)}else if(G&&D.get(o)===d&&void 0!==i&&("cancelled"===d.stopped||n)){d.stopped="cancelled";const t={...E(i),displayCode:"timeout"===d.failure?"media.uploadTimeout":"media.cancelled",retryable:!0===d.retainCheckpoint&&!n};(!0!==d.retainCheckpoint||n)&&await me(o,i),G&&D.get(o)===d&&(a.domainState.upsertMessages([{...i.message,status:"failed",failure:t}],"live"),Z(o,i.input,"canceled",Y.get(o)??0,t)),e={ok:!1,reason:"cancelled"}}return"paused"===d.stopped?{ok:!1,reason:"paused"}:e})().then(e=>{d.settled=!0,oe(o),s(e)},e=>{d.settled=!0,oe(o),l(e)}),c.then(()=>{D.get(o)===d&&"paused"!==d.stopped&&(D.delete(o),$.has(o)||(Y.delete(o),N.delete(o),j.delete(o),x.delete(o),U.delete(o),V.delete(o)))},()=>{D.get(o)===d&&D.delete(o)}),c}function le(e,t,a){return"album"===t.kind?de(t.input,e,t.createdAt,t.items,a):re(t.spec,t.input,e,t.createdAt,t.teaKey,t.resume,a)}function ce(e,t){const a=D.get(e);if(!G||void 0===a||"cancelled"===a.stopped)return;if("paused"===a.stopped)return void("pagehide"===t&&"offline"===a.pauseReason&&(a.pauseReason="pagehide"));a.stopped="paused",a.pauseReason=t;const i=P.get(e);a.waiting?.abort(),i?.abort("paused");const n=V.get(e);void 0!==n&&D.get(e)===a&&"paused"===a.stopped&&Z(e,n.input,"paused",Y.get(e)??n.percent)}async function ue(e,t="manual"){const a=D.get(e);if(!G||void 0===a||"cancelled"===a.stopped)return!1;if("paused"===a.stopped)return("manual"===t||"pagehide"===t&&"offline"===a.pauseReason)&&(a.pauseReason=t),await a.done,oe(e),G&&D.get(e)===a&&$.has(e);ce(e,t),await a.done,await Promise.all(F(e));const i=$.get(e);return!(!G||D.get(e)!==a||"paused"!==a.stopped||void 0===i)&&(Z(e,i.input,"paused",Y.get(e)??0),!0)}function pe(e){ne();const t=D.get(e),i=$.get(e);if(!G||"paused"!==t?.stopped||!0!==t.settled||void 0===i||P.has(e))return!1;$.delete(e),W.delete(e);const n=H;return se(i.input,()=>le(e,i,!1),{id:e,createdAt:i.createdAt},t.attempt).catch(t=>{G&&n===H&&a.onMediaTransferError?.({stage:"upload",kind:"media"===i.kind?i.spec.uploadKind:"image",messageId:e,conversation:Q(i.input),cause:t})}),!0}async function me(e,t){$.delete(e),W.delete(e),x.delete(e),U.delete(e),N.delete(e),j.delete(e),q.add(e);try{await Promise.all(F(e)),await(a.recoveryPort?.remove(Q(t.input),e).catch(i=>{a.onMediaTransferError?.({stage:"upload",kind:"media"===t.kind?t.spec.uploadKind:"image",messageId:e,conversation:Q(t.input),cause:i})})),await Promise.all(A(t).map(async i=>{try{await a.mediaTransfer.abandonUpload(i.resume)}catch(n){a.onMediaTransferError?.({stage:"upload",kind:i.kind,messageId:e,conversation:Q(t.input),cause:n})}}))}catch(i){a.onMediaTransferError?.({stage:"upload",kind:"media"===t.kind?t.spec.uploadKind:"image",messageId:e,conversation:Q(t.input),cause:i})}finally{q.delete(e),x.delete(e),U.delete(e),N.delete(e)}}function fe(e,t){if(ne(),!G)return!1;const i=D.get(e),n=P.get(e);if(!0!==t?.retainCheckpoint&&B.get(e)?.abort(),void 0!==i&&(i.stopped="cancelled",i.retainCheckpoint=!0===t?.retainCheckpoint,i.waiting?.abort()),void 0!==n){const i=K.get(e);return void 0!==i&&!0!==t?.retainCheckpoint&&function(e,t){if(void 0===a.recoveryPort)return;const i=F(e),n="video"===a.domainState.getConversationMessage?.(t,e)?.contentType?"video":"file",o=Promise.all(i).then(()=>a.recoveryPort.remove(t,e)).catch(i=>{a.onMediaTransferError?.({stage:"upload",kind:n,messageId:e,conversation:t,cause:i})});O(e,o)}(e,i),R.set(e,"cancelled"),n.abort(!0===t?.retainCheckpoint?"cancelled-preserve":"cancelled"),!0}const o=$.get(e);if(void 0===o||void 0===i)return void 0!==i&&"queued"===V.get(e)?.state;if(!0===t?.retainCheckpoint)o.retainCheckpoint=!0,o.failureReason="cancelled";else{O(e,me(e,o))}const r={...E(o),displayCode:"media.cancelled",retryable:!0===t?.retainCheckpoint};return a.domainState.upsertMessages([{...o.message,status:"failed",failure:r}],"live"),Z(e,o.input,"canceled",Y.get(e)??0,r),D.get(e)===i&&D.delete(e),oe(e),!0!==t?.retainCheckpoint&&(Y.delete(e),j.delete(e),V.delete(e)),!0}async function ve(e,t,a,i){ne();const n=H,o=F(t);return o.length>0&&await Promise.all(o),G&&n===H?(U.delete(t),se(i,()=>re(e,i,t,a,void 0,void 0,!0),{id:t,createdAt:a})):{ok:!1,reason:"cancelled"}}return{sendImage:e=>se(e,(t,a)=>re(g,e,t,a)),sendVideo:e=>se(e,(t,a)=>re(y,e,t,a)),replaceVideo:(e,t,a)=>ve(y,e,t,a),sendVoice:e=>{const t=e.durationMs;return void 0===t||!Number.isFinite(t)||t<1e3?Promise.resolve({ok:!1,reason:"invalid-duration"}):se(e,(t,a)=>re(h,e,t,a))},sendFile:e=>void 0!==e.caption&&Array.from(e.caption).length>i?Promise.resolve({ok:!1,reason:"content-too-large"}):se(e,(t,a)=>re(e.filesAlbum||e.caption?.trim()?T:b,e,t,a)),sendGif:e=>se(e,(t,a)=>re(w,{...e,encrypted:!1},t,a)),sendMediaAlbum:e=>se(e,(t,a)=>de(e,t,a)),replaceFile:(e,t,a)=>void 0!==a.caption&&Array.from(a.caption).length>i?Promise.resolve({ok:!1,reason:"content-too-large"}):ve(a.filesAlbum||a.caption?.trim()?T:b,e,t,a),cancel:fe,pause:ue,async pauseAll(e="pagehide"){for(const{controller:e}of L.values())e.abort();await Promise.all([...D.keys()].map(t=>ue(t,e)))},async resumePaused(e,t){await Promise.all([...D.entries()].map(async([a,i])=>{if(t?.aborted||"paused"!==i.stopped||"manual"===i.pauseReason)return;if(void 0===e&&"offline"!==i.pauseReason)return;const n=V.get(a)?.input;if(void 0!==e&&(n?.conversationType!==e.conversationType||n.conversationId!==e.conversationId))return;await i.done;const o=$.get(a);t?.aborted||D.get(a)!==i||void 0===o||void 0===e&&"offline"!==i.pauseReason||(void 0===e||o.input.conversationType===e.conversationType&&o.input.conversationId===e.conversationId)&&pe(a)}))},resume:pe,cancelConversation(e,t="offline"){for(const t of L.values())t.ref.conversationType===e.conversationType&&t.ref.conversationId===e.conversationId&&t.controller.abort();for(const[t,i]of $)if(i.input.conversationType===e.conversationType&&i.input.conversationId===e.conversationId){if(D.has(t))fe(t);else{for(const e of A(i))X(e.resume,e.kind,t,Q(i.input));a.recoveryPort?.remove(Q(i.input),t).catch(n=>a.onMediaTransferError?.({stage:"upload",kind:"media"===i.kind?i.spec.uploadKind:"image",messageId:t,conversation:e,cause:n}))}$.delete(t),W.delete(t),j.delete(t),N.delete(t),Y.delete(t),V.delete(t)}if(G)for(const[a,i]of K){if(i.conversationType!==e.conversationType||i.conversationId!==e.conversationId)continue;const n=P.get(a);if(void 0===n)continue;const o=D.get(a);void 0!==o&&(o.stopped="cancelled"),R.set(a,t),B.get(a)?.abort(),n.abort(t)}},cancelAll(e="offline"){if(G){if("offline"===e){const e=H;for(const t of D.keys()){const i=V.get(t)?.input;ue(t,"offline").catch(n=>{G&&e===H&&void 0!==i&&a.onMediaTransferError?.({stage:"upload",kind:"video"===a.domainState.getConversationMessage?.(i,t)?.contentType?"video":"file",messageId:t,conversation:i,cause:n})})}return}if("session-ended"===e){for(const{controller:e}of L.values())e.abort();for(const e of D.values())e.stopped="cancelled",e.waiting?.abort();H+=1,J+=1}for(const t of B.values())t.abort(e);for(const t of P.values())t.abort(e)}},retry(e,t){if(ne(),q.has(e))return!1;if(!G)return!1;const a=$.get(e);if(void 0===a)return!1;if(!0===D.get(e)?.retainCheckpoint&&!0!==D.get(e)?.settled)return!1;if(a.restartRequired&&!0!==t?.restartUpload)return!1;const i=!0===t?.restartUpload||"cancelled"===a.failureReason&&!0!==a.retainCheckpoint;return $.delete(e),W.delete(e),se(a.input,()=>le(e,a,i),{id:e,createdAt:a.createdAt}),!0},expireRetainedUploads:ne,invalidateAssetCacheWrites(){J+=1},async dispose(e){if(!G)return;z=!0===e?.preserveRecovery;for(const{controller:e}of L.values())e.abort();const t=[...D.values()].flatMap(e=>void 0===e.done?[]:[e.done]);for(const e of D.values())e.stopped="cancelled",e.waiting?.abort();if(G=!1,J+=1,!z)for(const e of B.values())e.abort();for(const e of P.values())e.abort(z?"page-preserve":"cancelled");for(const[e,t]of $)if(!z||"available"!==x.get(e)?.recovery)for(const a of A(t))X(a.resume,a.kind,e,Q(t.input));$.clear(),W.clear(),await Promise.allSettled(t),await Promise.all([...S]),P.clear(),Y.clear(),R.clear();for(const[e,t]of $)if(!z||"available"!==x.get(e)?.recovery)for(const a of A(t))X(a.resume,a.kind,e,Q(t.input));$.clear(),W.clear(),D.clear(),N.clear(),j.clear(),x.clear(),U.clear(),V.clear(),await(a.recoveryPort?.drain())},async recoverUpload(e,t,i){ne();const n=a.recoveryPort;if(!G||void 0===n)throw new Error("IM_MEDIA_RECOVERY_UNAVAILABLE");if(D.has(t)||L.has(t))throw new Error("IM_MEDIA_RECOVERY_INVALID_STATE");const o=new AbortController;L.set(t,{controller:o,ref:e});const r=()=>{if(!G||o.signal.aborted||L.get(t)?.controller!==o)throw new Error("IM_MEDIA_RECOVERY_INVALID_STATE")},d=(e,t)=>{if(void 0===e||e.senderId!==a.getSelfId()||void 0!==e.recalled||void 0!==e.deletedForEveryone||"media.cancelled"===e.failure?.displayCode&&!0!==e.failure.retryable||"media.uploadTimeout"===e.failure?.displayCode&&!1===e.failure.retryable||"failed"!==e.status&&"uploading"!==e.status)return!1;const i="video"===e.contentType,n="file"===e.contentType||"filesAlbum"===e.contentType&&1===e.body.filesAlbum?.items.length;return(i||n)&&(void 0===t||e.contentType===t)};let s;try{s=await n.acquireLease(o.signal),r();const l=a.domainState.getConversationMessage?.(e,t);if(!d(l))throw new Error("IM_MEDIA_RECOVERY_INVALID_STATE");const c=await n.get(e,t);if(r(),void 0===c)throw new Error("IM_MEDIA_RECOVERY_NOT_FOUND");const u="video"===c.kind?"video":c.filesAlbum||c.caption?.trim()?"filesAlbum":"file";if(!d(l,u))throw new Error("IM_MEDIA_RECOVERY_INVALID_STATE");const p=await n.fingerprint(i,o.signal);if(r(),p.size!==c.source.size||p.sha256!==c.source.sha256)throw new Error("IM_MEDIA_RECOVERY_FILE_MISMATCH");const m=a.domainState.getConversationMessage?.(e,t);if(D.has(t)||!d(m,u))throw new Error("IM_MEDIA_RECOVERY_INVALID_STATE");const f={conversationId:e.conversationId,conversationType:e.conversationType,data:i,encrypted:c.encrypted,filename:c.source.filename,mimeType:c.source.mimeType,caption:c.caption,filesAlbum:c.filesAlbum,refMessageId:c.refMessageId,...void 0===c.preview?{}:{localPreviewMetadata:{width:c.preview.width,height:c.preview.height,duration:c.preview.duration,posterData:c.preview.thumbData}}};return U.set(t,c.savedAt),await se(f,()=>re("video"===c.kind?y:c.filesAlbum||c.caption?.trim()?T:b,f,t,c.createdAt,c.teaKey,c.resume),{id:t,createdAt:c.createdAt})}finally{L.get(t)?.controller===o&&L.delete(t),oe(t),s?.release()}}}}export{P as createMediaSender};
@@ -1 +1 @@
1
- import{encodeConversationKey as e,conversationRefFromMessage as t,conversationRefFromPinnedMessage as n,conversationRefFromSession as o}from"../conversation-identity.js";import{compareChannelReadPosition as r,getChannelReadOrder as s}from"../mapping/channel-read-position.js";import{computeSortKey as i,resolveMessageTimestamp as a,computeMessageSortKey as c,resolveMessageServerTime as d}from"../mapping/sort.js";import{collectTransferStatusBySerialNumber as u,synchronizeTransferStatusMessages as l,applyTransferStatusToBody as v}from"../mapping/transfer-status.js";import{parseChannelSyncCheckpoint as f,channelSyncCheckpointKey as p}from"../sync/channel-sync-checkpoint.js";import{parseConversationDeletionBoundary as y,isAfterConversationDeletion as m,captureConversationDeletionBoundary as g}from"./conversation-deletion-boundary.js";import{createDraftStore as h}from"./draft-store.js";import{rollbackMessageReaction as C,applyMessageReaction as w}from"./message-reactions.js";import{createMessageStore as I}from"./message-store.js";import{createMessageWindowStore as T}from"./message-window-store.js";import{createPinnedMessageStore as M}from"./pinned-message-store.js";import{createReadStore as S}from"./read-store.js";import{sortSessions as b}from"./session-sort.js";import{createSessionStore as E}from"./session-store.js";import{createImTextSearchMatcher as K,extractSearchText as U}from"../mapping/search-text.js";import{normalizeStoredMessageContent as A,LOCAL_MEDIA_ERROR_CODE as R,failInterruptedUpload as P}from"../mapping/stored-message.js";import{isMessageVisibleInTimeline as N,lastMessageSummaryEqual as x,sessionFromMessage as $}from"../mapping/session-mapper.js";import{isMessageEqual as D,isMessageRecoveryBodyEqual as B,dedupeById as j,mergeMessage as F}from"../mapping/merge.js";import{newClientMessageId as _}from"../mapping/message-id.js";import{backfillGroupMention as k}from"../mapping/group-message-mapper.js";import{isConversationUnreadMessage as L}from"../mapping/unread-divider.js";function O(e,t){for(let n=e.length-1;n>=0;n-=1){const o=e[n];if(t(o))return o}}function H(e){return"direct"===e||"robot"===e||"customerService"===e?"local":"server"}function z(e,t){const n=t?.includeMuted??!1;let o=0;for(const t of e)!n&&t.muted||(o+=t.unreadCount>0?t.unreadCount:!0===t.manuallyUnread?1:0);return o}const q="im:deleted-conversations",G="im:terminated-conversations",W="im:membership-reset-sort-keys",J="im:pending-message-reactions",Q="im:transfer-status-records",V=["sendMessages","mentionAll","editProfile","manageMembers","manageAdmins","moderateMessages","manageMute","dismissChannel","transferOwnership"];function X(e,t){return e===t||void 0!==e&&void 0!==t&&V.every(n=>e[n]===t[n])}function Y(e,t){return e===t||void 0!==e&&void 0!==t&&e.role===t.role&&e.baseState===t.baseState&&e.resolvedState===t.resolvedState&&e.allMembersMuted===t.allMembersMuted&&e.currentUserMuted===t.currentUserMuted&&e.mutePeriod===t.mutePeriod}function Z(e,t){return e.id===t.id&&e.type===t.type&&e.title===t.title&&e.avatar===t.avatar&&x(e.lastMessageSummary,t.lastMessageSummary)&&e.timestamp===t.timestamp&&e.unreadCount===t.unreadCount&&(e.manuallyUnread??!1)===(t.manuallyUnread??!1)&&(e.mentionUnreadCount??0)===(t.mentionUnreadCount??0)&&e.pinned===t.pinned&&e.muted===t.muted&&e.topTime===t.topTime&&e.lastMessageSendState===t.lastMessageSendState&&e.lastMessageReceipt===t.lastMessageReceipt&&e.readCursor===t.readCursor&&e.groupState===t.groupState&&e.channelState===t.channelState&&X(e.channelPermissions,t.channelPermissions)&&Y(e.channelAccessSnapshot,t.channelAccessSnapshot)&&e.sendDisabledReason===t.sendDisabledReason}function ee(x){const V=I({getSelfId:x.getSelfId}),ee=/* @__PURE__ */new Map,te=/* @__PURE__ */new Map,ne=E(),oe=E(),re=S(),se=h(),ie=M(),ae=/* @__PURE__ */new Map,ce=/* @__PURE__ */new Map;let de=0;function ue(e){ce.set(e,++de)}let le=1;const ve=/* @__PURE__ */new Set,fe=/* @__PURE__ */new Map,pe=/* @__PURE__ */new Set,ye=/* @__PURE__ */new Map,{storage:me}=x;let ge=Promise.resolve();const he=/* @__PURE__ */new Map,Ce=/* @__PURE__ */new Map,we=/* @__PURE__ */new Map;let Ie=0;const Te=x.unreadMode??H,Me=/* @__PURE__ */new Set;function Se(e={}){const t=T({storage:me,loadOlderFromRemote:x.loadOlderFromRemote,loadNewerFromRemote:x.loadNewerFromRemote,shouldIncludeMessage:et,normalizeStoredUpload:en,...e});return Me.add(t),t}const be=Se();function Ee(e,t){let n;for(const o of Me){const r=o.list().find(n=>n.id===e&&n.conversationId===t);if(void 0!==r){if(void 0!==n&&n.conversationType!==r.conversationType)throw new Error(`裸 conversationId 存在多类型消息歧义:${t}`);n=r}}return n}function Ke(e,t){const n=V.get(t,e);if(n?.conversationId===e.conversationId&&n.conversationType===e.conversationType)return n;for(const n of Me){const o=n.list().find(n=>n.id===t&&n.conversationId===e.conversationId&&n.conversationType===e.conversationType);if(void 0!==o)return o}}function Ue(e,n){const o=Ke(t(e),e.id);void 0===o||V.has(e.id,e)||V.upsert(o);const r=V.upsert(e,n);return{...r,previous:o,changed:void 0===o?r.changed:!D(o,r.message)}}function Ae(e){const t=new Map(V.getByConversation(e).map(e=>[e.id,e]));for(const n of Me)if(Re(n,e))for(const o of n.list())o.conversationType!==e.conversationType||o.conversationId!==e.conversationId||t.has(o.id)||t.set(o.id,o);return[...t.values()].sort((e,t)=>e.sortKey.localeCompare(t.sortKey))}function Re(t,n){const o=t.info();return void 0===o.conversation?o.conversationId===n.conversationId:e(o.conversation)===e(n)}let Pe=!1;function Ne(t){return`${e(t.conversation)}\0${t.parentMessageId}`}function xe(){if(void 0===me||Pe)return;const e=[...ee.values()].flat();Tt(()=>me.setMeta(J,e)).catch(e=>ot("保存待处理 Reaction 失败",e))}function $e(e){const t=e.body.transfer;if("transfer"!==e.contentType||void 0===t)return e;const n=te.get(t.serialNumber);if(void 0===n||0!==t.status&&0===n.status)return e;const o={...t,status:n.status,...1===n.status&&void 0!==n.occurredTime?{receiveTime:n.occurredTime}:{},...2===n.status||3===n.status?{returnTime:n.occurredTime??t.returnTime}:{}};return t.status===o.status&&t.receiveTime===o.receiveTime&&t.returnTime===o.returnTime&&t.isRead===o.isRead?e:{...e,body:{transfer:v(t,o)}}}function De(t,n){const o=`${e(t)}\0${n}`;return!!ee.delete(o)&&(xe(),!0)}function Be(t){const n=`${e(t)}\0`;let o=!1;for(const e of ee.keys())e.startsWith(n)&&(ee.delete(e),o=!0);return o&&xe(),o}function je(e,t){const n=Ke(e.conversation,e.parentMessageId);if(void 0===n){const t=Ne(e),n=ee.get(t)??[];return n.some(t=>t.id===e.id)?"duplicate":(ee.set(t,[...n,e]),xe(),"pending")}if(mt(n),void 0!==n.recalled||void 0!==n.deletedForEveryone)return"duplicate";const o=w(n.reactions,e,x.getSelfId?.()??"");return o===n.reactions?"duplicate":(on([{...n,reactions:o}],t),"applied")}function Fe(n,o){const r=t(n),s=`${e(r)}\0${n.id}`,i=ee.get(s);if(void 0!==i){ee.delete(s),xe();for(const e of i)je(e,o)}}function _e(e){for(const t of[...ee.values()]){const n=t[0];if(void 0===n)continue;const o=Ke(n.conversation,n.parentMessageId);void 0!==o&&(void 0!==o.recalled||void 0!==o.deletedForEveryone?De(n.conversation,n.parentMessageId):Fe(o,e))}}let ke=0;const Le=/* @__PURE__ */new Map,Oe=/* @__PURE__ */new Map,He=/* @__PURE__ */new Map,ze=/* @__PURE__ */new Map,qe=/* @__PURE__ */new Map;function Ge(t){return e(t)}function We(e){return Je(e)||ve.has(Ge(e))||ve.has(e.conversationId)}function Je(e){return pe.has(Ge(e))||pe.has(e.conversationId)}function Qe(t,n={}){return(!0===n.includeRestored||We(t))&&!Je(t)&&fe.has(e(t))}function Ve(){return[...ve,...fe.values()]}function Xe(e){const t=ve.delete(Ge(e)),n=ve.delete(e.conversationId);return t||n}function Ye(e){const t=Xe(e),n=pe.delete(Ge(e)),o=pe.delete(e.conversationId);return{deleted:t,terminal:n||o}}function Ze(e,t){if(""===t||"system"!==e.contentType)return!1;const n=e.body.system;return!0===n?.targetUserIds?.includes(t)&&("group"===e.conversationType?"group_member_joined"===n.eventType||"group_member_invited"===n.eventType:"channel"===e.conversationType&&("channel_member_joined"===n.eventType||"channel_member_invited"===n.eventType||"channel_created"===n.eventType))}function et(n){const o=t(n);if(Je(o)||We(o)&&void 0===oe.get(o))return!1;if("group"!==o.conversationType)return!0;const r=ye.get(e(o));return void 0===r||n.sortKey>=r}function tt(t){const n=e(t),o=(Oe.get(n)??0)+1;return Oe.set(n,o),o}function nt(t){const n=e(t),o=(Le.get(n)??0)+1;return Le.set(n,o),o}function ot(e,t){x.emitter.emit({type:"error",error:{scope:"storage",message:e,cause:t}})}function rt(e){x.emitter.emit({type:"session:updated",session:e,conversation:o(e)})}const st=/* @__PURE__ */new Set,it=/* @__PURE__ */new Set,at=/* @__PURE__ */new Map,ct=/* @__PURE__ */new Map;let dt=0,ut=Promise.resolve(),lt=0,vt=Promise.resolve(),ft=0;const pt=/* @__PURE__ */new Map;let yt;function mt(n){const o=e(t(n));yt?.keys.has(o)&&yt.messages.set(`${o}\0${n.id}`,n)}function gt(t){const n=e(t);pt.set(n,(pt.get(n)??0)+1)}function ht(e){return yt?.writes.push(e),void 0!==yt&&e.catch(()=>{}),e}async function Ct(e){const t=(await Promise.allSettled(e)).find(e=>"rejected"===e.status);if(void 0!==t)throw t.reason}function wt(e){const t=vt.then(e);return vt=t.then(()=>{},()=>{}),t}function It(t,n){const o=ft,r=t.map(t=>[e(t),pt.get(e(t))??0]);return()=>o===ft&&n()&&r.every(([e,t])=>(pt.get(e)??0)===t)}function Tt(e){const t=0===lt?(()=>{try{return e()}catch(e){return Promise.reject(e)}})():ut.then(e),n=t.then(()=>{},()=>{});st.add(n),n.finally(()=>st.delete(n));for(const e of it)e.writes.push(t);return ht(t)}function Mt(e){lt+=1;const t=Promise.all([...st]),n=ut.then(()=>t).then(e);return ut=n.then(()=>{},()=>{}),ut.finally(()=>{lt-=1}),ht(n)}function St(e){const t=e.body.system;if(void 0===t?.pinnedMessageAction)return e;const{pinnedMessageAction:n,...o}=t;return{...e,body:{...e.body,system:o}}}function bt(n){if(void 0!==me&&!Pe&&0!==n.length){for(const o of it)for(const r of n)o.messages.add(`${e(t(r))}\0${r.id}`);Tt(()=>me.saveMessages(n.map(St))).catch(e=>ot("消息落盘失败",e))}}function Et(e){const{lastMessageSendState:t,manuallyUnread:n,...o}=e;return o}function Kt(t){if(void 0!==me&&!Pe){for(const n of it)n.sessions.add(e(o(t)));Tt(()=>me.saveSessions([Et(t)])).catch(e=>ot("会话落盘失败",e))}}function Ut(e,t,n){if(void 0===me||Pe)return;const o=++dt;at.set(e,{version:o,persist:()=>Ut(e,t,n)});for(const t of it)t.metadata.add(e);const r=ct.get(e),s=Tt(()=>void 0===r?me.setMeta(e,t()):r.then(()=>me.setMeta(e,t()))),i=s.then(()=>{},()=>{});ct.set(e,i),i.then(()=>{ct.get(e)===i&&ct.delete(e)}),s.then(()=>{at.get(e)?.version===o&&at.delete(e)},e=>ot(n,e))}function At(){Ut(q,Ve,"删除会话标记保存失败")}function Rt(){Ut(G,()=>[...pe],"成员资格终止标记保存失败")}function Pt(){Ut(W,()=>[...ye.entries()],"重新入群的历史起点保存失败")}function Nt(t){if(void 0!==me&&!Pe){for(const n of it)void 0!==t.conversationType&&n.reads.add(e({conversationType:t.conversationType,conversationId:t.conversationId}));Tt(()=>me.saveReadState(t)).catch(e=>ot("已读态落盘失败",e))}}function xt(t){if(e(t),"supergroup"===t.conversationType)throw new Error("supergroup 草稿未实现,不得 fallback 到其他会话类型")}function $t(e){return xt(e),Object.freeze({conversationType:e.conversationType,conversationId:e.conversationId})}function Dt(e,t,n){if(xt(e),"string"!=typeof t.text)throw new TypeError("草稿 text 必须是字符串");if(void 0!==t.attachments&&t.attachments.length>0)throw new Error("草稿附件尚未支持:attachments 只接受空集合");if(void 0!==t.mentions&&!Array.isArray(t.mentions))throw new TypeError("草稿 mentions 必须是数组");const o=(t.mentions??[]).map(e=>{if("string"!=typeof e.userId||""===e.userId.trim()||"string"!=typeof e.displayName)throw new TypeError("草稿 mention 必须包含非空 userId 与字符串 displayName");return Object.freeze({userId:e.userId,displayName:e.displayName})}),r=Object.freeze({conversationType:e.conversationType,conversationId:e.conversationId});return Object.freeze({ref:r,text:t.text,mentions:Object.freeze(o),...void 0===t.replyToMessageId?{}:{replyToMessageId:t.replyToMessageId},attachments:Object.freeze([]),updatedAt:n})}function Bt(e,t){return e.text===t.text&&e.replyToMessageId===t.replyToMessageId&&e.mentions.length===t.mentions.length&&e.mentions.every((e,n)=>{const o=t.mentions[n];return void 0!==o&&e.userId===o.userId&&e.displayName===o.displayName})}function jt(t,n){xt(t);const o=e(t),r=(he.get(o)??Promise.resolve()).catch(()=>{}).then(n),s=r.then(()=>{},()=>{});return he.set(o,s),s.finally(()=>{he.get(o)===s&&he.delete(o)}),r}async function Ft(t,n){const o=$t(t),r=e(o);if(void 0!==n&&(!Number.isFinite(n)||n<0))throw new Error(`草稿 expectedUpdatedAt 非法:${n}`);const s=Ie,i=we.get(r)??0;return await jt(o,async()=>{const e=se.get(o);if(null===e||void 0!==n&&e.updatedAt!==n)return!1;if(void 0!==me&&await me.deleteDraft(o),s!==Ie||i!==(we.get(r)??0))throw new Error("草稿状态已失效,拒绝过期清理回灌内存");return se.delete(o),x.emitter.emit({type:"draft:cleared",conversation:o}),!0})}function _t(t,n,o,r,s){const i=gn(t);if(void 0===i)return;const a={...i,...void 0===s||s===Oe.get(e(t))?{title:n,avatar:o??i.avatar}:{},...void 0!==r?{muted:r}:{}};Z(i,a)||hn(a)}function kt(t,n){const o=x.profile;if(void 0===o)return Promise.resolve(null);const r={conversationType:"direct",conversationId:t},s=e(r),i=qe.get(t);if(!0!==n?.forceRefresh&&void 0!==i&&i.revision===Le.get(s))return i.promise;const a=ke,c=nt(r),d=tt(r),u=(async()=>{const e=await o.getUserProfile(t,n);if(null!==e&&e.id===t&&a===ke&&c===Le.get(s)){const n=e.remark?.trim()?e.remark:e.nickname||t;_t(r,n,e.avatar??"",e.muted,d)}return e})().finally(()=>{qe.get(t)?.promise===u&&qe.delete(t)});return qe.set(t,{revision:c,promise:u}),u}async function Lt(t,n){const{conversationId:o,conversationType:r}=t;if("direct"===r){try{await kt(o,!0===n?.force?{forceRefresh:!0}:void 0)}catch(e){x.emitter.emit({type:"error",error:{scope:"http",message:"会话资料补齐失败",cause:e}})}return!1}const s=e(t),i=!0===n?.force;if(!i&&(ze.has(s)||He.has(s)))return!1;const a=ke,c=nt(t),d=tt(t);i&&ze.set(s,c);const{profile:u,channelProfile:l}=x,v=i?{forceRefresh:!0}:void 0;try{if("group"===r){if(void 0===u)return!1;const e=await u.getGroupProfile(o,v);if(a!==ke||c!==Le.get(s))return!1;null!==e&&(_t(t,e.name,e.avatar??"",e.muted,d),3===e.status&&mn({conversationType:"group",conversationId:o},"group_dismissed"),i&&x.emitter.emit({type:"profile:updated",profileType:"group",id:o}))}else if("channel"===r){if(void 0===l)return!1;const e=await l.getProfile(o,v);if(a!==ke||c!==Le.get(s))return!1;if(null!==e){_t(t,e.name,e.avatar??"",e.muted,d);const r=gn(t)?.channelState,s="left"===r||"removed"===r||"dismissed"===r,a="left"===e.channelState||"removed"===e.channelState||"dismissed"===e.channelState;if(!0===n?.allowChannelRecovery&&s&&"dismissed"!==r&&"active"===e.channelState)return fn(o,"active",void 0,{permissions:e.permissions,...void 0===e.accessSnapshot?{}:{snapshot:e.accessSnapshot}}),i&&x.emitter.emit({type:"channel-profile:updated",channelId:o,conversation:{conversationType:"channel",conversationId:o}}),!0;const c=s&&(!a||"dismissed"===r||"dismissed"!==e.channelState);if(a&&!c)return mn({conversationType:"channel",conversationId:o},`channel_${e.channelState}`),i&&x.emitter.emit({type:"channel-profile:updated",channelId:o,conversation:{conversationType:"channel",conversationId:o}}),!1;if(!c){const t=e.permissions.sendMessages?void 0:`channel_${e.channelState}`;fn(o,e.channelState,t,{permissions:e.permissions,...void 0===e.accessSnapshot?{}:{snapshot:e.accessSnapshot}})}i&&x.emitter.emit({type:"channel-profile:updated",channelId:o,conversation:{conversationType:"channel",conversationId:o}})}}return!1}catch(e){return x.emitter.emit({type:"error",error:{scope:"http",message:"会话资料补齐失败",cause:e}}),!1}finally{i&&a===ke&&ze.get(s)===c&&ze.delete(s)}}function Ot(e){return L(e,x.getSelfId?.()??"")}function Ht(e){const t=re.get(e);if(void 0===t||""===t.readCursor)return;const n="string"==typeof e?t.conversationType:e.conversationType;if("channel"===n){const o={conversationType:n,conversationId:"string"==typeof e?e:e.conversationId};return Ae(o).find(e=>e.extensions?.historyCursor===t.readCursor)?.sortKey??t.readCursorSortKey}const o="string"==typeof e?V.getByConversation(e).find(e=>e.id===t.readCursor):Ke(e,t.readCursor);return o?.sortKey??t.readCursorSortKey}function zt(e,t){let n=0;for(const o of V.getByConversation(e))N(o)&&Ot(o)&&(void 0===t||o.sortKey>t)&&(n+=1);return n}function qt(e){const t=x.getSelfId?.();if(void 0===t||""===t||e.senderId===t)return!1;const{mention:n}=e;return void 0!==n&&(n.atAll||n.atUserIds.includes(t))}function Gt(e,t){let n=0;for(const o of V.getByConversation(e))!0!==o.readBySelf&&qt(o)&&(void 0===t||o.sortKey>t)&&(n+=1);return n}function Wt(e,t=!0){const n=void 0===e.conversationType?ne.get(e.conversationId):void 0,o=void 0===e.conversationType&&void 0!==n?{...e,conversationType:n.type}:e,r=void 0===o.conversationType?o.conversationId:{conversationType:o.conversationType,conversationId:o.conversationId},s=re.get(r);if("channel"===o.conversationType&&ue(o.conversationId),re.set(o),t&&Nt(o),void 0===s||s.readCursor!==o.readCursor||s.readCursorSortKey!==o.readCursorSortKey||s.unreadCount!==o.unreadCount||(s.manuallyUnread??!1)!==(o.manuallyUnread??!1)){if(void 0===o.conversationType)return void x.emitter.emit({type:"error",error:{scope:"storage",message:`已读状态缺少复合身份,拒绝发布 read:updated(conversationId=${o.conversationId})`}});x.emitter.emit({type:"read:updated",conversationId:o.conversationId,conversation:{conversationType:o.conversationType,conversationId:o.conversationId},readCursor:o.readCursor,unreadCount:o.unreadCount,...!0===o.manuallyUnread?{manuallyUnread:!0}:{}})}}function Jt(n,o){if(void 0===n||n.sortKey===o.sortKey)return;const r=t(o),s=re.get(r),i="channel"===o.conversationType?o.extensions?.historyCursor:void 0,a="direct"===o.conversationType||"group"===o.conversationType||"robot"===o.conversationType||"customerService"===o.conversationType;void 0!==s&&(a&&s.readCursor===o.id||"string"==typeof i&&""!==i&&s.readCursor===i||s.readCursorSortKey===n.sortKey)&&Wt({...s,readCursorSortKey:o.sortKey});const c=e(r);"group"===o.conversationType&&ye.get(c)===n.sortKey&&(ye.set(c,o.sortKey),Pt())}function Qt(e){const t=e?.channelAccessSnapshot?.role;return"owner"===t||"admin"===t}function Vt(e,t,n,o,r=gn(e)){const s=o??re.get(e);if(void 0===t){if(void 0===r){if("string"==typeof e||void 0===s||s.unreadCount<=0)return;return{id:e.conversationId,type:e.conversationType,title:"",lastMessagePreview:"",timestamp:0,unreadCount:s.unreadCount,mentionUnreadCount:s.mentionUnreadCount,readCursor:s.readCursor,pinned:!1,muted:!1}}const t={...r,..."clear"===n?{lastMessagePreview:"",timestamp:0}:{},...void 0===s?{}:{unreadCount:s.unreadCount,manuallyUnread:s.manuallyUnread,mentionUnreadCount:s.mentionUnreadCount,readCursor:s.readCursor||r.readCursor}};return"clear"===n&&(delete t.lastMessageSummary,delete t.lastMessageSenderId,delete t.lastMessageSystemEvent,delete t.lastMessageSystemTargetsSelf,delete t.lastMessageMention,delete t.lastMessageRecalled,delete t.lastMessageDeletedForEveryone,delete t.lastMessageSendState,delete t.lastMessageReceipt),t}const i=s?.unreadCount??r?.unreadCount??0,a=void 0===s?r?.manuallyUnread:s.manuallyUnread,c=$(t,{unreadCount:i,mentionUnreadCount:s?.mentionUnreadCount??r?.mentionUnreadCount??0,selfId:x.getSelfId?.(),showChannelModerationDeleted:Qt(r)});return void 0===r?{...c,...void 0===a?{}:{manuallyUnread:a},readCursor:(s?.readCursor??"")||c.readCursor}:{...c,title:r.title||c.title,avatar:r.avatar??c.avatar,pinned:r.pinned,muted:r.muted,topTime:r.topTime,...void 0===a?{}:{manuallyUnread:a},readCursor:(s?.readCursor??"")||r.readCursor,groupState:r.groupState,channelState:r.channelState,channelPermissions:r.channelPermissions,channelAccessSnapshot:r.channelAccessSnapshot,sendDisabledReason:r.sendDisabledReason}}function Xt(e,t){if(void 0===e)return;const n=ne.get({conversationType:e.type,conversationId:e.id});void 0!==n&&Z(n,e)||(ne.set(e),oe.delete({conversationType:e.type,conversationId:e.id}),rt(e),t&&Kt(e),""===e.title&&Lt({conversationType:e.type,conversationId:e.id}))}function Yt(e,t,n="preserve",o=gn(e)){const r=O(t,e=>function(e,t){return!!N(e)&&("channel"!==e.conversationType||void 0===e.deletedForEveryone||Qt(t))}(e,o)),s="string"==typeof e?o?.type:e.conversationType;return Vt(e,r,void 0===r&&"channel"===s&&!Qt(o)&&(t.some(e=>void 0!==e.deletedForEveryone)||"channel-moderation-deleted"===o?.lastMessageSummary?.kind||void 0!==o?.lastMessageDeletedForEveryone)?"clear":n,void 0,o)}function Zt(e,t=!1){(t||void 0!==ne.get(e))&&Xt(Yt(e,V.getByConversation(e)),!0)}function en(e){if("uploading"!==e.status&&("failed"!==e.status||e.failure?.code!==R))return e;const t=V.get(e.id,e);return void 0!==t&&t.conversationType===e.conversationType&&t.conversationId===e.conversationId?t:P(A(e))}function tn(n,o=()=>!0){const r=[],s=j(n,x.getSelfId?.()??"").map(e=>{const t=en(e);let n={...t,sortKey:c(t)};if(n=A(n),"group"===n.conversationType&&"text"===n.contentType){const e=k(n.body.text??"",n.mention);void 0!==e&&(n.mention=e)}return $e(n)}),i=/* @__PURE__ */new Map;for(const n of s){if("transfer"!==n.contentType||void 0===n.body.transfer)continue;const o=t(n);i.set(e(o),o)}const a=[...i.values()].flatMap(e=>Ae(e)),d=l(a,s),u=new Set(s.map(e=>e.id));for(const e of d){if(!o())break;const{previous:n,message:s,isNew:i,changed:a}=Ue(e);if(Jt(n,s),void 0!==n&&a)for(const e of Me){if(!o())return r;e.list().some(e=>e.id===s.id&&e.conversationType===s.conversationType&&e.conversationId===s.conversationId)&&e.applyIncoming([s])}if(!o())return r;i?x.emitter.emit({type:"message:received",message:s,conversation:t(s),source:"offline",channelLifecycleEffects:!1}):a&&x.emitter.emit({type:"message:updated",message:s,conversation:t(s),source:"offline",channelLifecycleEffects:!1}),u.has(s.id)&&r.push(s)}return r}function nn(e){const t=en(e);let n={...t,sortKey:c(t)};if(n=A(n),"group"===n.conversationType&&"text"===n.contentType){const e=k(n.body.text??"",n.mention);void 0!==e&&(n.mention=e)}return $e(n)}function on(n,o,r={}){const s=x.getSelfId?.()??"";if("offline"===o&&!0!==r.backfillOnly){let o=!1;for(const r of n){if(r.senderId===s||!N(r)||void 0!==r.recalled||void 0!==r.deletedForEveryone)continue;const n=t(r),i=fe.get(e(n));void 0!==i&&!Je(n)&&m(r,i)&&Xe(n)&&(o=!0)}o&&At(),n=n.filter(n=>{const o=fe.get(e(t(n)));return void 0===o||m(n,o)||void 0!==Ke(t(n),n.id)})}if("live"===o){let i=!1,a=!1;for(const c of n){const n=t(c);if(Ze(c,s)){const t=Ye(n);t.deleted&&(i=!0),t.terminal&&("group"===n.conversationType?(ye.set(e(n),c.sortKey),Pt()):"channel"===n.conversationType&&ye.delete(e(n)),x.diagnostics?.record("info","core","conversation","membership-termination-cleared",()=>({conversation:n,data:{source:o,eventType:c.body.system?.eventType,groupHistoryLowerBoundApplied:"group"===n.conversationType}})),a=!0)}else""!==s&&c.senderId===s&&!0!==r.newOutgoing||Je(n)||!Xe(n)||(i=!0)}i&&At(),a&&Rt()}const i=!0===x.diagnostics?.isEnabled("debug","conversation")?/* @__PURE__ */new Map:void 0,a=(n,o)=>{if(void 0===i)return;const r=t(n),s=e(r),a=i.get(s)??{ref:r,tombstone:0,groupLowerBound:0};"tombstone"===o?a.tombstone+=1:a.groupLowerBound+=1,i.set(s,a)},c=ve.size>0||pe.size>0?n.filter(e=>{const n=t(e),o=!We(n)||!0===r.backfillOnly&&void 0!==oe.get(n)&&!Je(n);return o||a(e,"tombstone"),o}):n,d=function(n){const o=/* @__PURE__ */new Map;if(0===ye.size)return o;for(const r of j(n,x.getSelfId?.()??"")){if("group"!==r.conversationType)continue;const n=t(r),s=e(n),i=ye.get(s);if(void 0===i)continue;const a=Ke(n,r.id);if(void 0===a||a.sortKey!==i)continue;const c=F(a,r,x.getSelfId?.()??"");c.sortKey!==i&&(ye.set(s,c.sortKey),o.set(s,c.id))}return o.size>0&&Pt(),o}(c),u=n=>d.get(e(t(n)))===n.id,v=ye.size>0?c.filter(e=>{const t=u(e)||et(e);return t||a(e,"groupLowerBound"),t}):c,f=0===d.size?v:[...v.filter(u),...v.filter(e=>!u(e))];for(const e of i?.values()??[])x.diagnostics?.record("debug","core","conversation","membership-filter-dropped",()=>({conversation:e.ref,data:{source:o,tombstoneDroppedCount:e.tombstone,groupHistoryLowerBoundDroppedCount:e.groupLowerBound}}));const p=/* @__PURE__ */new Map,y=/* @__PURE__ */new Map,g=/* @__PURE__ */new Map,h=/* @__PURE__ */new Map,C=/* @__PURE__ */new Map,w=/* @__PURE__ */new Set,I=j(f,s).map($e),T=/* @__PURE__ */new Map;for(const n of I){if("transfer"!==n.contentType||void 0===n.body.transfer)continue;const o=t(n);T.set(e(o),o)}const M=[...T.values()].flatMap(e=>Ae(e)),S=l(M,I),b=[],E=[];for(const n of S){if("channel"===n.conversationType&&yt?.keys.has(e(t(n)))&&!yt.current())continue;const{previous:s,message:i,isNew:a,changed:c}=Ue(n,{authoritativeFailure:!0===r.authoritativeOutboxFailure});if(mt(i),!0===r.backfillOnly&&!0===r.refreshSessionSummary){const n=t(i);p.set(e(n),n)}if(!a&&!c)continue;Jt(s,i);for(const e of Me)e.applyIncoming([i]);a?x.emitter.emit({type:"message:received",message:i,conversation:t(i),source:o,channelLifecycleEffects:!0===r.applyChannelLifecycleEffects}):x.emitter.emit({type:"message:updated",message:i,conversation:t(i),source:o,channelLifecycleEffects:!0===r.applyChannelLifecycleEffects});const d=t(i);if(!a&&void 0!==s&&!0!==s.readBySelf&&!0===i.readBySelf){const t=Ht(d),n=void 0===t||s.sortKey>t,o=e(d);n&&N(s)&&Ot(s)&&void 0===s.recalled&&void 0===s.deletedForEveryone&&g.set(o,(g.get(o)??0)-1),n&&qt(s)&&void 0===s.recalled&&void 0===s.deletedForEveryone&&C.set(o,(C.get(o)??0)-1)}Je(d)||(b.push(i),p.set(e(d),d),a&&!0!==r.backfillOnly&&E.push(i))}const K=/* @__PURE__ */new Map;for(const n of E){const r=t(n),s=e(r);Ot(n)&&w.add(s),K.has(s)||K.set(s,Ht(r));const i=K.get(s),a=void 0===i||n.sortKey>i;if(N(n)&&a&&Ot(n)&&!0!==n.readBySelf&&void 0===n.recalled&&void 0===n.deletedForEveryone){const e=Te(n.conversationType);("local"===e||"server"===e&&"live"===o)&&y.set(s,(y.get(s)??0)+1)}a&&!0!==n.readBySelf&&qt(n)&&void 0===n.recalled&&void 0===n.deletedForEveryone&&h.set(s,(h.get(s)??0)+1)}for(const t of p.values()){if(!0===r.backfillOnly){!0===r.refreshSessionSummary&&Zt(t);continue}const n=e(t),o=y.get(n)??0,s=h.get(n)??0,i=g.get(n)??0,a=C.get(n)??0,c=w.has(n),d=re.get(t);if(o>0||s>0||c||void 0!==d&&(0!==i||0!==a)){const e=d??{...t,readCursor:"",unreadCount:0},n={...e,unreadCount:Math.max(0,e.unreadCount+o+i),mentionUnreadCount:Math.max(0,(e.mentionUnreadCount??0)+s+a)};c&&delete n.manuallyUnread,Wt(n)}Zt(t,E.some(e=>e.conversationType===t.conversationType&&e.conversationId===t.conversationId&&N(e)))}bt(b.filter(e=>void 0!==Ke(t(e),e.id)));for(const e of b)void 0===e.recalled&&void 0===e.deletedForEveryone?Fe(e,o):De(t(e),e.id)}function rn(e,t,n=Date.now()){const o={conversationType:"direct",conversationId:e},r=Ke(o,t),s=O(V.getByConversation(o),e=>"direct_contact_established"===e.body.system?.eventType);if(void 0!==r&&void 0!==s&&a(s)>=a(r))return;const c=`${t}:contact-required`;if(void 0!==V.get(c,o))return;on([{id:c,conversationId:e,conversationType:"direct",senderId:e,contentType:"system",body:{system:{eventType:"direct_contact_required",targetUserIds:[e],action:{type:"request-contact",userId:e}}},createdAt:n,sortKey:i(n,c),status:"sent",receipt:"unread",encryption:{encrypted:!1,decryptFailed:!1}}],"live")}const sn=/* @__PURE__ */new Map;let an=0;function cn(e){const t=re.get(e);if(!0!==t?.manuallyUnread)return!1;const n={...t};return delete n.manuallyUnread,Wt(n),Zt(e),!0}function dn(e,t,n,r,s){const i="string"==typeof e?e:e.conversationId,a=gn(e),c="string"==typeof e?void 0===a?void 0:o(a):e;if(void 0!==a&&"server"!==Te(a.type))return void x.emitter.emit({type:"error",error:{scope:"unknown",message:`applyServerUnread 不应用于本地未读会话(conversationId=${i}, type=${a.type}),已忽略`}});if(!Number.isFinite(t))return void x.emitter.emit({type:"error",error:{scope:"unknown",message:`applyServerUnread 收到非法未读数(conversationId=${i}, count=${t}),已忽略`}});"channel"===c?.conversationType&&ae.delete(i);const d=re.get(e);let u=d?.readCursor??"",l=d?.readCursorSortKey;const v=void 0===n||""===n?void 0:void 0===c?V.getByConversation(i).find(e=>e.id===n)??Ee(n,i):Ke(c,n);void 0!==v&&v.conversationId===i&&(void 0===l||v.sortKey>l)&&(u=v.id,l=v.sortKey),void 0!==r&&(u=r),Wt({...void 0===c?{conversationId:i}:c,readCursor:u,readCursorSortKey:l,unreadCount:Math.max(0,Math.floor(t)),...t>0?{}:{manuallyUnread:d?.manuallyUnread},mentionUnreadCount:0===t||!1===s?0:!0===s?Math.max(1,d?.mentionUnreadCount??0):d?.mentionUnreadCount}),Zt(e,t>0&&void 0!==c&&!We(c))}function un(e){const t=ae.get(e.conversation.conversationId);return t?.handle.transactionId===e.transactionId?t:void 0}function ln(e,t,n,o=!1){const r=gn(e),s=Ke(e,t);if("channel"!==r?.type||"channel"!==s?.conversationType||s.conversationId!==e.conversationId||s.extensions?.historyCursor!==n)throw new Error(`CHANNEL 已读位置不可信(channelId=${e.conversationId}, messageId=${t})`);o||ae.delete(e.conversationId);const i=re.get(e),a=void 0===i?r.mentionUnreadCount:i.mentionUnreadCount;Wt({...e,readCursor:n,readCursorSortKey:s.sortKey,unreadCount:i?.unreadCount??r.unreadCount,...void 0===a?{}:{mentionUnreadCount:a}}),Zt(e)}function vn(e,t,n){const o=e.conversation,r=o.conversationId,i=un(e);if(void 0===i)throw new Error(`CHANNEL 乐观已读事务已失效(channelId=${r})`);const a=Ke(o,t);if(void 0===a||a.conversationId!==r||"channel"!==a.conversationType)throw new Error(`CHANNEL 乐观已读消息不可信(channelId=${r}, messageId=${t})`);if(a.extensions?.historyCursor!==n)throw new Error(`CHANNEL 乐观已读 cursor 与消息不一致(channelId=${r}, messageId=${t})`);i.steps.at(-1)?.readCursor!==n&&(i.steps.push({readCursor:n,messageId:t,...s(a)}),ln(o,t,n,!0))}function fn(t,n,o,r){const s={conversationType:"channel",conversationId:t},i=e(s);if(We(s)&&void 0===oe.get(s)&&!Qe(s))return;const a=gn(s);if(void 0===a){nt(s),ze.delete(i);return void hn({id:t,type:"channel",title:"",lastMessagePreview:"",timestamp:0,unreadCount:0,pinned:!1,muted:!1,channelState:n,channelPermissions:r?.permissions,channelAccessSnapshot:r?.snapshot,sendDisabledReason:o})}if("channel"!==a.type)throw new Error(`setChannelRestriction: 会话 ${t} 类型为 ${a.type},拒绝写入 CHANNEL 状态`);nt(s),ze.delete(i);const c=r?.permissions,d=r?.snapshot;if(a.channelState===n&&a.sendDisabledReason===o&&X(a.channelPermissions,c)&&Y(a.channelAccessSnapshot,d))return void(void 0!==ne.get(s)&&Zt(s));const u={...a,channelState:n,channelPermissions:c,channelAccessSnapshot:d,sendDisabledReason:o};void 0!==ne.get(s)?hn(Yt(s,V.getByConversation(s),"preserve",u)):hn(u)}async function pn(e,t){if(""===t.trim())throw new Error("本机删除消息需要非空 messageId");const n=()=>{if(ie.isPinnedMessage(e,t))throw Object.assign(new Error("置顶消息必须先取消置顶才能删除"),{code:"IM_MESSAGE_PINNED"})};n();const o=Ke(e,t),r=V.get(t,e),s=void 0!==r&&r.conversationType===e.conversationType&&r.conversationId===e.conversationId,i=V.getByConversation(e).filter(e=>e.id!==t),a=void 0===ne.get(e)?void 0:Yt(e,i,"clear"),c=void 0===a?void 0:Et(a);function d(e){return void 0!==e&&(void 0===r||!D(r,e))}const u=void 0===me?{deleted:!1,superseded:!1}:await Mt(async()=>{n();const r=Ke(e,t)??o??await me.getMessage(e,t)??void 0;if(n(),d(V.get(t,e)))return{deleted:!1,superseded:!0};const s=await me.deleteMessage(e,t,c);if(ie.isPinnedMessage(e,t)){const o=Ke(e,t)??r;void 0!==o&&await me.saveMessages([St(o)]);const s=ne.get(e);return void 0!==s&&await me.saveSessions([Et(s)]),n(),{deleted:!1,superseded:!0}}return{deleted:s,superseded:!1}});if(u.superseded||d(V.get(t,e)))return!1;const l=s&&V.delete(e,t);let v=!1;for(const n of Me)v=n.removeMessage(e,t)||v;if(!u.deleted&&!l&&!v)return!1;const f=void 0===ne.get(e)?void 0:Yt(e,V.getByConversation(e),"clear");return Xt(f,!1),void 0===f||void 0!==a&&Z(a,f)||Kt(f),De(e,t),x.emitter.emit({type:"message:removed",conversation:{...e},messageId:t,scope:"local-only"}),!0}function yn(t,o={}){const r="string"==typeof t?t:t.conversationId,s=ne.get(t),i=ie.get(t),a="string"==typeof t?void 0!==s?{conversationType:s.type,conversationId:r}:void 0===i?void 0:n(i):t;if(void 0===a)throw new Error(`裸 conversationId 无法确定删除类型:${r}`);if(tt(a),He.delete(e(a)),"direct"===a.conversationType&&(nt(a),qe.delete(a.conversationId)),gt(a),"direct"===a.conversationType||"group"===a.conversationType||"channel"===a.conversationType)if(!0===o.terminal)fe.delete(e(a));else{const t=g(a,Ae(a),fe.get(e(a)));void 0!==t&&fe.set(e(a),t)}const c=V.getByConversation(a).length;!function(t){const n=$t(t),o=e(n);we.set(o,(we.get(o)??0)+1),null!==se.get(n)&&(se.delete(n),x.emitter.emit({type:"draft:cleared",conversation:n})),jt(n,async()=>{void 0!==me&&await me.deleteDraft(n)}).catch(e=>ot("删会话草稿失败",e))}(a),Be(a),ne.delete(t),oe.delete(t),"channel"===a.conversationType&&(ue(a.conversationId),ae.delete(a.conversationId)),re.delete(t),V.deleteByConversation(t),ie.clear(t);const d=Ge(a);if(!0===o.terminal){pe.add(d);const e=ye.delete(d);ve.delete(d),ve.delete(r),e&&Pt(),x.diagnostics?.record("info","core","conversation","membership-terminated",()=>({conversation:a,data:{reason:o.terminalReason??"membership-terminated",removedMessageCount:c}}))}else ve.add(d);for(const e of Me)Re(e,a)&&e.reset();x.emitter.emit({type:"session:removed",conversationId:r,conversation:a}),At(),!0===o.terminal&&Rt(),void 0!==me&&Mt(async()=>{await Ct([me.deleteConversationMessages(a),me.deleteSession(a),me.deleteReadState(a),me.removePinnedMessage(a)])}).catch(e=>ot("删除会话持久数据失败",e))}function mn(e,t){yn(e,{terminal:!0,terminalReason:t})}function gn(e){if("string"==typeof e){const t=[...ne.getAll(),...oe.getAll()].filter(t=>t.id===e);if(t.length>1)throw new Error(`裸 conversationId 存在多类型歧义:${e}`);return t[0]}return ne.get(e)??oe.get(e)}function hn(e){const t=o(e);void 0!==ne.get(t)?(ne.set(e),rt(e),Kt(e)):(oe.set(e),x.emitter.emit({type:"conversation-context:updated",conversation:t}))}async function Cn(n,o){let r=await me.getMessages(n,{limit:50});const s=o=>o.filter(o=>e(t(o))===e(n)&&et(o)),a=s(r);if(!["direct","group","channel"].includes(n.conversationType)||!o())return a;let c=g(n,a);for(;o()&&50===r.length;){const e=r[0].sortKey;if(void 0!==c&&e<i(c.serverTime,""))break;if(r=await me.getMessages(n,{beforeSortKey:e,limit:50}),!o())return[];if(r.some(t=>t.sortKey>=e))throw new Error("会话本地历史游标没有向前推进");const t=s(r);c=g(n,t,c),a.push(...t.filter(e=>void 0!==c&&d(e)===c.serverTime))}return a}return{upsertMessages:on,commitReceivedMessages:function(n,o,r,s){if(void 0===me){for(const e of s?.events??[])s.apply(e);return void on(n,o,r)}const i={writes:[],messages:/* @__PURE__ */new Set,sessions:/* @__PURE__ */new Set,reads:/* @__PURE__ */new Set,metadata:/* @__PURE__ */new Set};it.add(i);try{const a=(s?.events??[]).filter(e=>"ignored"!==s.apply(e));on(n,o,r);const c=a.flatMap(e=>{const t=Ke(e.conversation,e.parentMessageId);return void 0===t?[]:[t]});a.length>0&&xe();const d=/* @__PURE__ */new Map,u=[];for(const o of[...n,...c]){const n=t(o),r=e(n),s=Ke(n,o.id);void 0!==s&&(d.set(r,n),i.messages.has(`${r}\0${s.id}`)||u.push(s))}bt(u);for(const[e,t]of d){const n=ne.get(t),o=re.get(t);void 0===n||i.sessions.has(e)||Kt(n),void 0===o||i.reads.has(e)||Nt(o)}for(const[e,t]of at)i.metadata.has(e)||t.persist()}finally{it.delete(i)}return Ct(i.writes)},prepareOfflineMessageUpdate:function(n,o){if(void 0===me)return!0;const r=t(n),s=fe.get(e(r));if(void 0===s||We(r)||m(n,s)||void 0!==Ke(r,n.id))return!0;const i=ft,a=e(r),c=pt.get(a)??0;o();let d=!1,u=Ke(r,n.id);const l=x.emitter.subscribe(o=>{"message:received"!==o.type&&"message:updated"!==o.type||o.message.id!==n.id||e(t(o.message))!==a||("live"!==o.source||void 0!==u&&B(u,o.message)||(d=!0),u=o.message)});return me.getMessage(r,n.id).then(s=>{if(o(),i!==ft||(pt.get(a)??0)!==c)throw new DOMException("消息提交前的本地历史读取已失效","AbortError");return!d&&(void 0===Ke(r,n.id)&&null!==s&&s.id===n.id&&e(t(s))===a&&et(s)&&V.upsert(s),!0)}).finally(l)},applyReaction:je,rollbackReaction:function(t,n,o){const r=Ke(t,n);if(void 0===r){const r=`${e(t)}\0${n}`,s=ee.get(r);if(void 0===s)return!1;const i=s.filter(e=>e.id!==o);return i.length!==s.length&&(0===i.length?ee.delete(r):ee.set(r,i),xe(),!0)}const s=C(r.reactions,o,x.getSelfId?.()??"");if(s===r.reactions)return!1;const i={...r};return void 0===s?delete i.reactions:i.reactions=s,on([i],"live"),!0},appendDirectContactRequiredNotice:rn,appendDirectMessageRefusedNotice:function(e,t,n=Date.now()){const o={conversationType:"direct",conversationId:e},r=`${t}:message-refused`;if(void 0!==V.get(r,o))return;const s=V.get(t,o),c="direct"===s?.conversationType&&s.conversationId===e?a(s):n;on([{id:r,conversationId:e,conversationType:"direct",senderId:e,contentType:"system",body:{system:{eventType:"direct_message_refused",targetUserIds:[e]}},createdAt:c,sortKey:i(c,r),status:"sent",receipt:"unread",encryption:{encrypted:!1,decryptFailed:!1}}],"live")},appendDirectContactRequiredTextFailure:function(e,t=Date.now()){const n=_(),o={id:n,conversationId:e.conversationId,conversationType:"direct",senderId:e.senderId,contentType:"text",body:{text:e.text},createdAt:t,sortKey:i(t,n),status:"failed",receipt:"unread",encryption:{encrypted:!1,decryptFailed:!1},failure:{code:33281,reason:"rejected",displayCode:"contactRequired",retryable:!1},...void 0===e.refMessageId?{}:{refMessageId:e.refMessageId}};return on([o],"live"),rn(e.conversationId,n,t+1),o},reconcileDirectContactEstablishedNotice:function(e,t,n=Date.now()){const o=sn.get(e);if(void 0!==o)return o;const r={conversationType:"direct",conversationId:e},s=an,a=(async()=>{const o=V.getByConversation(r).filter(e=>{const t=e.body.system?.eventType;return"direct_contact_required"===t||"direct_contact_established"===t}),a=o.filter(e=>"direct_contact_required"===e.body.system?.eventType),c=a.at(-1)?.createdAt??0,d=O(o,e=>"direct_contact_established"===e.body.system?.eventType)?.createdAt??0,u=d>=c&&d>0;if(0===a.length&&u)return;const l=Ht(r);for(const e of a)try{const t=await pn(r,e.id),n=Ke(r,e.id);t||"direct_contact_required"!==n?.body.system?.eventType||x.emitter.emit({type:"error",error:{scope:"storage",message:"联系人关系已建立,但旧的申请添加提示未能删除",cause:{conversation:r,messageId:e.id}}})}catch(t){x.emitter.emit({type:"error",error:{scope:"storage",message:"联系人关系已建立,但删除旧的申请添加提示失败",cause:{conversation:r,messageId:e.id,error:t}}})}if(s!==an)return;const v=re.get(r);if(void 0!==v&&(Wt({...v,...void 0===v.readCursorSortKey&&void 0!==l?{readCursorSortKey:l}:{},unreadCount:zt(r,l)}),Zt(r)),u)return;const f=Number.isFinite(n)&&n>0?n:Date.now(),p=Math.max(f,c+1);!function(e,t,n=Date.now(),o=n){const r=function(e,t){return`${""===e.trim()?`contact-established:${t}`:e}:contact-established`}(t,o);if(void 0!==V.get(r,{conversationType:"direct",conversationId:e}))return;on([{id:r,conversationId:e,conversationType:"direct",senderId:e,contentType:"system",body:{system:{eventType:"direct_contact_established",targetUserIds:[e]}},createdAt:n,sortKey:i(n,r),status:"sent",receipt:"unread",encryption:{encrypted:!1}}],"live")}(e,t,p,f)})().finally(()=>{sn.get(e)===a&&sn.delete(e)});return sn.set(e,a),a},recallMessage:function(e,t,n){const o=Ke(e,t);void 0!==o&&on([{...o,recalled:n,body:{}}],"live")},deleteChannelMessageForEveryone:function(e,t,n){const o=Ke(e,t);void 0!==o&&"channel"===o.conversationType&&on([{...o,recalled:void 0,deletedForEveryone:n,body:{}}],"live")},editMessage:function(e,t,n,o){const r=Ke(e,t);if(void 0===r)return;const s={...r,body:n,edited:!0};void 0!==o?s.mention=o:delete s.mention,on([s],"live")},applyTransferStatusBySerialNumber:async function(e,t,n){const o=function(e,t){if(void 0===e)return t;if(0===e.status&&0!==t.status)return t;if(0===t.status&&0!==e.status)return e;const n=e.occurredTime??0,o=t.occurredTime??0;return n!==o?o>n?t:e:t.status>e.status?t:e}(te.get(e),{serialNumber:e,status:t,...void 0===n?{}:{occurredTime:n}});te.set(o.serialNumber,o),await async function(){if(void 0===me)return;const e=[...te.values()],t=ge.then(()=>me.setMeta(Q,e));ht(t),ge=t.catch(()=>{});try{await t}catch(e){throw ot("保存转账状态记录失败",e),e}}();const r=/* @__PURE__ */new Map;for(const t of u(V.getAll(),e,o.status,o.occurredTime))r.set(t.id,t);for(const t of ne.getAll()){const n=Ae({conversationType:t.type,conversationId:t.id});for(const t of u(n,e,o.status,o.occurredTime))r.set(t.id,t)}0!==r.size&&on([...r.values()],"live")},getMessage:e=>V.get(e),getMessagesById:e=>V.getById(e),getConversationMessage:Ke,getLoadedMessagesByConversation:Ae,hasRecoverableConversationDeletion:Qe,resolveConversationMessage:async function(n,o,r={}){const s=Ke(n,o);if(void 0!==s||void 0===me)return s;try{const r=await me.getMessage(n,o);if(null===r||e(t(r))!==e(n))return;return nn(r)}catch(e){if(ot("按消息 ID 读取本地历史失败",e),!0===r.throwOnStorageError)throw e;return}},getMessages:()=>V.getAll(),getMessagesByConversation:e=>V.getByConversation(e),deleteLocalMessage:pn,clearLocalConversationHistory:async function(e){gt(e);const t={...e},n=new Map(V.getByConversation(t).map(e=>[e.id,e])),o=ne.get(t),r=re.get(t),s=void 0===r&&void 0===o?void 0:{...t,readCursor:r?.readCursor??o?.readCursor??"",...void 0===r?.readCursorSortKey?{}:{readCursorSortKey:r.readCursorSortKey},unreadCount:0,mentionUnreadCount:0},i=void 0===o?void 0:Vt(t,void 0,"clear",s);if(void 0!==me){if(void 0===me.clearConversationHistory)throw new Error("当前 storage 未实现 clearConversationHistory,拒绝非原子清空本机会话历史");await Mt(()=>me.clearConversationHistory(t,void 0===i?void 0:Et(i),s))}const a=re.get(t);void 0!==s&&(a?.conversationType===r?.conversationType&&a?.conversationId===r?.conversationId&&a?.readCursor===r?.readCursor&&a?.readCursorSortKey===r?.readCursorSortKey&&a?.unreadCount===r?.unreadCount&&a?.mentionUnreadCount===r?.mentionUnreadCount)&&Wt(s,!1);for(const[e,o]of n){const n=V.get(e,t);void 0!==n&&D(o,n)&&V.delete(t,e)}const c=V.getByConversation(t);for(const e of Me)e.clearConversation(t)&&e.applyIncoming(c);Be(t),void 0!==ne.get(t)&&Xt(Yt(t,c,"clear"),!1),x.emitter.emit({type:"conversation-history:cleared",conversation:t,scope:"local-only"})},commitChannelSyncPage:function(n,o,r,s){const i=It(n,r);return wt(async()=>{if(!i())return!1;if(void 0===me)throw new Error("CHANNEL 严格同步提交需要 storage");const r={writes:[],messages:/* @__PURE__ */new Map,keys:new Set(n.map(e)),current:i};let a;yt=r;try{const e=o();if(e instanceof Promise)throw e.catch(()=>{}),new Error("CHANNEL 页 mutation 必须同步执行")}catch(e){a={cause:e}}finally{yt=void 0}if(await Ct(r.writes),void 0!==a)throw a.cause;if(!i())return!1;const c=[...r.messages.values()].flatMap(e=>{const n=Ke(t(e),e.id);return void 0===n?[]:[St(n)]}),d=[];c.length>0&&d.push(Tt(()=>me.saveMessages(c)));for(const e of n){const t=ne.get(e),n=re.get(e),o=ie.get(e);void 0!==t&&d.push(Tt(()=>me.saveSessions([Et(t)]))),void 0!==n&&d.push(Tt(()=>me.saveReadState(n))),d.push(Tt(()=>void 0===o?me.removePinnedMessage(e):me.savePinnedMessage(o)))}const u=[[J,[...ee.values()].flat()],[Q,[...te.values()]],[q,Ve()],[G,[...pe]],[W,[...ye.entries()]]];for(const[e,t]of u)d.push(Tt(()=>me.setMeta(e,t)));return void 0!==s&&d.push(Tt(async()=>{i()&&await s()})),await Ct(d),i()})},saveChannelSyncCheckpoint:function(e,t){const n=f(e,e.conversation);if(void 0===n)return Promise.reject(new Error("CHANNEL 同步位置无效"));const o=It([n.conversation],t);return wt(async()=>{if(!o())return!1;if(void 0===me)throw new Error("CHANNEL 同步位置保存需要 storage");let e=!1;return await Tt(async()=>{o()&&(await me.setMeta(p(n.conversation),n),e=!0)}),e&&o()})},waitForChannelSyncPersistence:async function(){for(;;){const e=vt,t=ut;if(await Promise.all([e,t,...st]),e===vt&&t===ut&&0===st.size)return}},getSession:e=>ne.get(e),getConversationContext:gn,isMembershipTerminated:Je,prepareConversation:function(e,t={}){const n=o(e);if("supergroup"===n.conversationType)throw new Error("prepareConversation:supergroup 未实现");const r=gn(n);if(void 0!==r){const t=r.title||e.title,n=r.avatar??e.avatar;return void(t===r.title&&n===r.avatar||hn({...r,title:t,avatar:n}))}if(Je(n)){if(!0!==t.membershipConfirmed)throw new Error("准备聊天失败:需要重新确认成员资格");pe.delete(Ge(n)),pe.delete(n.conversationId),Rt()}hn({...e,...void 0===e.channelPermissions?{}:{channelPermissions:{...e.channelPermissions}},...void 0===e.channelAccessSnapshot?{}:{channelAccessSnapshot:{...e.channelAccessSnapshot}}}),(re.get(n)?.unreadCount??0)>0&&!We(n)&&Zt(n,!0)},ensureConversation:function(t){const n=o(t);if(e(n),"supergroup"===n.conversationType)throw new Error("ensureConversation:supergroup 未实现");const r=ne.get(n);if(void 0!==r)return r;const s={...t,id:n.conversationId,type:n.conversationType,...void 0===t.channelPermissions?{}:{channelPermissions:{...t.channelPermissions}},...void 0===t.channelAccessSnapshot?{}:{channelAccessSnapshot:{...t.channelAccessSnapshot}},...void 0===t.extensions?{}:{extensions:{...t.extensions}}},i=Ye(n);return i.deleted&&At(),i.terminal&&Rt(),ne.set(s),oe.delete(n),rt(s),Kt(s),s},getSessions:()=>ne.getAll(),getConversationList:function(){const e=[];for(const t of ne.getAll()){const n=o(t);e.push({...t,draft:se.get(n)})}return b(e)},getReadState:e=>re.get(e),getPinnedMessage:e=>ie.get(e),setPinnedMessage:function(e,t){const o=function(e){const t=Ke(n(e),e.messageId);return void 0===t?e:{...e,preview:{state:"ready",message:t}}}(e);ie.set(o)&&(x.emitter.emit({type:"pinned-message:updated",conversationId:o.conversationId,conversation:{conversationType:o.conversationType,conversationId:o.conversationId},pinnedMessage:o,reason:t}),function(e){void 0===me||Pe||Tt(()=>me.savePinnedMessage(e)).catch(e=>ot("置顶消息落盘失败",e))}(o))},clearPinnedMessage:function(e,t){const o="string"==typeof e?e:e.conversationId,r=ie.get(e);if(!ie.clear(e))return;const s="string"==typeof e?void 0===r?void 0:n(r):e;if(void 0===s)throw new Error(`置顶消息清理缺少复合身份:${o}`);x.emitter.emit({type:"pinned-message:updated",conversationId:o,conversation:s,pinnedMessage:null,reason:t}),function(e){void 0===me||Pe||Tt(()=>me.removePinnedMessage(e)).catch(e=>ot("置顶消息删除失败",e))}(e)},isPinnedMessage:(e,t)=>ie.isPinnedMessage(e,t),setReadState:e=>{const t=void 0===e.conversationType?ne.get(e.conversationId):void 0,n=void 0===e.conversationType&&void 0!==t?{...e,conversationType:t.type}:e;"channel"===n.conversationType&&ue(n.conversationId),re.set(n),Nt(n)},markConversationUnread:function(e){const t=ne.get(e);if(void 0===t)return!1;const n=re.get(e)??{...e,readCursor:t.readCursor??"",unreadCount:t.unreadCount,mentionUnreadCount:t.mentionUnreadCount};return!(n.unreadCount>0||!0===n.manuallyUnread)&&(Wt({...n,manuallyUnread:!0}),Zt(e),!0)},clearConversationManualUnread:cn,advanceRead:function(e,n){const o="string"==typeof e?V.getByConversation(e).find(e=>e.id===n)??Ee(n,e):Ke(e,n);if(void 0===o)return;const r="string"==typeof e?t(o):e,s="string"==typeof e?e:e.conversationId;if(o.conversationId!==s||o.conversationType!==r.conversationType)return;const i=Ht(r);if(void 0!==i&&i>=o.sortKey)return void("string"!=typeof e&&cn(e));const a={...r,readCursor:n,readCursorSortKey:o.sortKey,unreadCount:zt(r,o.sortKey),mentionUnreadCount:Gt(r,o.sortKey)};return Wt(a),Zt(r),a},applyServerUnread:dn,applyChannelReadPosition:ln,getChannelReadRevision:e=>ce.get(e.conversationId)??de,hasPendingChannelRead:e=>ae.has(e.conversationId),applyChannelReadSummary:(e,t)=>dn(e,t.unreadCount,void 0,t.readCursor,t.hasUnreadMention),beginChannelReadTransaction:function(e){const t=e.conversationId,n=gn(e);if(void 0===n||"channel"!==n.type)throw new Error(`CHANNEL 乐观已读事务要求 channel 会话(conversationId=${t}, type=${n?.type??"missing"})`);if(ae.has(t))throw new Error(`CHANNEL 乐观已读事务已存在(channelId=${t})`);const o={conversation:e,transactionId:le++},r=re.get(e)??{conversationId:t,readCursor:n.readCursor??"",unreadCount:n.unreadCount,...void 0===n.mentionUnreadCount?{}:{mentionUnreadCount:n.mentionUnreadCount}};return ae.set(t,{handle:o,baseReadState:{...r},steps:[],committedThrough:-1}),ue(t),o},applyChannelReadOptimistically:vn,applyChannelConversationReadOptimistically:function(e,t,n){vn(e,t,n);const o=un(e).steps.at(-1);if(void 0!==o.clearedCounts)return;const i=re.get(e.conversation),a=Ae(e.conversation).filter(e=>r(s(e),o)>0&&Ot(e)&&N(e)&&!0!==e.readBySelf&&void 0===e.recalled&&void 0===e.deletedForEveryone),c=Math.min(i.unreadCount,a.length),d=Math.min(i.mentionUnreadCount??0,a.filter(qt).length);o.clearedCounts={unread:i.unreadCount-c,mention:(i.mentionUnreadCount??0)-d},Wt({...i,unreadCount:c,mentionUnreadCount:d}),Zt(e.conversation)},commitChannelReadTransaction:function(e,t){const n=un(e);if(void 0===n)return!1;let o=-1;for(let e=n.steps.length-1;e>=0;e-=1)if(n.steps[e].readCursor===t){o=e;break}if(o<0)throw new Error(`CHANNEL 已确认 cursor 不属于乐观事务(channelId=${e.conversation.conversationId}, cursor=${t})`);return n.committedThrough=Math.max(n.committedThrough,o),ue(e.conversation.conversationId),n.committedThrough===n.steps.length-1&&ae.delete(e.conversation.conversationId),!0},rollbackChannelReadTransaction:function(e){const t=un(e);if(void 0===t)return!1;const n=e.conversation,o=n.conversationId,r=re.get(n),s=t.committedThrough>=0?t.steps[t.committedThrough]:void 0,i=void 0===s?t.baseReadState:void 0;let a=r?.unreadCount??i?.unreadCount??0,c=r?.mentionUnreadCount??i?.mentionUnreadCount??0;for(const e of t.steps.slice(t.committedThrough+1))a+=e.clearedCounts?.unread??0,c+=e.clearedCounts?.mention??0;const d=void 0!==i?.mentionUnreadCount||void 0!==r?.mentionUnreadCount,u={conversationId:o,conversationType:"channel",readCursor:s?.readCursor??i?.readCursor??"",readCursorSortKey:s?.sortKey??i?.readCursorSortKey,unreadCount:a,...d?{mentionUnreadCount:c}:{}};return ae.delete(o),Wt(u),Zt(n),!0},setGroupRestriction:function(e,t,n){const o=gn({conversationType:"group",conversationId:e});if(void 0===o){return void hn({id:e,type:"group",title:"",lastMessagePreview:"",timestamp:0,unreadCount:0,pinned:!1,muted:!1,groupState:t,sendDisabledReason:n})}if(o.groupState===t&&o.sendDisabledReason===n)return;hn({...o,groupState:t,sendDisabledReason:n})},setChannelRestriction:fn,setPinned:function(e,t){const n=ne.get(e);if(void 0===n||n.pinned===t)return;const o={...n,pinned:t,topTime:t?Date.now():void 0};ne.set(o),rt(o),Kt(o)},setMuted:function(e,t){const n=gn(e);if(void 0===n||n.muted===t)return;hn({...n,muted:t})},removeConversation:function(e){yn(e)},removeConversationForMembershipTermination:mn,refreshConversationProfile:function(e,t){Lt({conversationType:t,conversationId:e},{force:!0})},readDirectProfile:kt,beginConversationProfileRead:function(t,n){const o={...t},r=e(o),s=ke,i=!0!==n?.forceRefresh&&(ze.has(r)||He.has(r))?void 0:tt(o);void 0!==i&&!0===n?.forceRefresh&&He.set(r,i);const a=()=>{s===ke&&void 0!==i&&He.get(r)===i&&He.delete(r)};return Object.assign(e=>{try{if(void 0===i||e.id!==o.conversationId||s!==ke)return;_t(o,e.title,e.avatar??"",void 0,i)}finally{a()}},{finish:a})},recoverChannelFromProfile:function(e){return Lt({conversationType:"channel",conversationId:e},{force:!0,allowChannelRecovery:!0})},updateConversationProfile:function(e,t){const n=gn(e);if(void 0===n)return;tt(o(n));const r={...n,...void 0!==t.title?{title:t.title}:{},...void 0!==t.avatar?{avatar:t.avatar}:{}};Z(n,r)||hn(r)},getTotalUnread:function(e){return z(ne.getAll(),e)},getDraft:function(e){return se.get($t(e))},saveDraft:async function(t,n){const o=$t(t),r=e(o),s=Dt(o,n,0),i=Ie,a=we.get(r)??0;return await jt(o,async()=>{const e=se.get(o),t=Math.max(Date.now(),(Ce.get(r)??e?.updatedAt??0)+1),n=Dt(o,s,t);if(null!==e&&Bt(e,n))return e;if(void 0!==me&&await me.saveDraft(n),i!==Ie||a!==(we.get(r)??0))throw new Error("草稿状态已失效,拒绝过期写入回灌内存");return se.set(n),Ce.set(r,t),x.emitter.emit({type:"draft:updated",conversation:n.ref,draft:n}),n})},clearDraft:async function(e){await Ft(e)},clearDraftIfUnchanged:async function(e,t){return await Ft(e,t)},invalidateAndDrainDraftOperations:async function(){for(Ie+=1;he.size>0;)await Promise.all([...he.values()])},clearSession(){ft+=1,ke+=1,Ie+=1,an+=1,sn.clear(),Le.clear(),Oe.clear(),He.clear(),ze.clear(),qe.clear(),V.clear(),ne.clear(),oe.clear(),re.clear(),se.clear(),he.clear(),Ce.clear(),we.clear(),ae.clear(),ce.clear(),de+=1,ie.clearAll(),ve.clear(),fe.clear(),pe.clear(),ye.clear(),at.clear(),ee.clear();for(const e of Me)e.reset()},hydrate:async function(t=()=>!0){if(void 0!==me&&t()){Pe=!0;try{const r=await me.getMeta(q);if(!t())return;if(null!==r)for(const t of r)if("string"==typeof t)ve.add(t);else{const n=y(t);fe.set(e(n.conversation),n)}const s=await me.getMeta(G);if(!t())return;if(null!==s)for(const e of s)pe.add(e);const i=await me.getMeta(W);if(!t())return;if(null!==i)for(const[e,t]of i)"string"==typeof e&&"string"==typeof t&&ye.set(e,t);const a=await me.getMeta(J);if(!t())return;if(null!==a)for(const e of a){const t=Ne(e);ee.set(t,[...ee.get(t)??[],e])}const c=await me.getMeta(Q);if(!t())return;if(Array.isArray(c))for(const e of c){if("object"!=typeof e||null===e)continue;const t=Reflect.get(e,"serialNumber"),n=Reflect.get(e,"status"),o=Reflect.get(e,"occurredTime");"string"!=typeof t||""===t.trim()||0!==n&&1!==n&&2!==n&&3!==n||void 0!==o&&("number"!=typeof o||!Number.isFinite(o)||o<=0)||te.set(t,{serialNumber:t,status:n,...void 0===o?{}:{occurredTime:o}})}const d=await me.getPinnedMessages();if(!t())return;for(const e of d){if(!t())return;We({conversationType:e.conversationType,conversationId:e.conversationId})||ie.set(e)&&x.emitter.emit({type:"pinned-message:updated",conversationId:e.conversationId,conversation:n(e),pinnedMessage:e,reason:"hydrate"})}const u=(await me.getSessions()).filter(e=>!We({conversationType:e.type,conversationId:e.id}));if(!t())return;for(const e of u){if(!t())return;const n=Yt(o(e),[],"preserve",e),r=o(n),s=ne.get(r);ne.set(n),oe.delete(r),void 0!==s&&Z(s,n)||rt(n)}const l=await me.getReadStates();if(!t())return;for(const e of l)"channel"===e.conversationType&&ue(e.conversationId),re.set(e);const v=Ie,f=await me.getDrafts();if(!t())return;if(v!==Ie)return;for(const n of f){if(!t())return;if(!Number.isFinite(n.updatedAt)||n.updatedAt<0)throw new Error(`草稿 updatedAt 非法:${n.updatedAt}`);const o=Dt(n.ref,n,n.updatedAt);if(We(o.ref)){try{if(await me.deleteDraft(o.ref),!t())return}catch(e){if(!t())return;ot("清理已删会话残留草稿失败",e)}continue}const r=e(o.ref);Ce.set(r,Math.max(Ce.get(r)??0,o.updatedAt));const s=se.get(o.ref);null!==s&&s.updatedAt===o.updatedAt&&Bt(s,o)||(se.set(o),x.emitter.emit({type:"draft:updated",conversation:o.ref,draft:o}))}for(const e of u){if(!t())return;const n=o(e),r=await Cn(n,t);if(!t())return;const s=[];if(tn(r.map(e=>{const t=en(A(e));return t!==e&&s.push(t),t}),t),!t())return;if(s.length>0)try{if(await me.saveMessages(s),!t())return}catch(e){if(!t())return;ot("本地消息修复态落盘失败",e)}if(!t())return;Zt(n)}}catch(e){t()&&ot("本地历史回读失败",e)}finally{Pe=!1,t()&&_e("offline")}}},loadOlderMessages:async function(n,o){if(void 0===me)return[];try{const r=await me.getMessages(n,o),s="string"==typeof n?r.filter(et):r.filter(o=>e(t(o))===e(n)).filter(et),i=Pe;let a;Pe=!0;try{a=tn(s)}finally{Pe=i}return Pe||_e("offline"),a.map(e=>Ke(t(e),e.id)??e)}catch(e){return ot("加载更早消息失败",e),[]}},searchMessages:async function(n,o){const r=o.keyword?.trim()??"",s=o.contentTypes;if(""===r&&(void 0===s||0===s.length))return{results:[],exhausted:!0};const i=""===r?void 0:await K(r),a=e=>{const t=void 0===s||s.includes(e.contentType),n=void 0===i||null!==i.match(U(e));return t&&n},c=(e,t)=>e.sortKey<t.sortKey?1:e.sortKey>t.sortKey?-1:0,d=e=>function(e,t){const n=t?.match(U(e));return{message:e,ranges:n?.ranges.map(({start:e,end:t})=>[e,t])??[]}}(e,i);if(void 0===me)return(()=>{const e=V.getByConversation(n).filter(a).sort(c),t=(void 0===o.beforeSortKey?e:e.filter(e=>e.sortKey<o.beforeSortKey)).slice(0,o.limit),r=t.length<o.limit;return{results:t.map(d),exhausted:r,...r?{}:{nextBeforeSortKey:t.at(-1)?.sortKey}}})();let u;try{u=await me.searchMessages(n,{...void 0!==o.keyword?{keyword:o.keyword}:{},...void 0!==s?{contentTypes:s}:{},limit:o.limit,...void 0!==o.beforeSortKey?{beforeSortKey:o.beforeSortKey}:{}})}catch(e){throw ot("会话内搜索失败",e),e}const l=u.exhausted?void 0:u.nextBeforeSortKey,v=new Map(V.getByConversation(n).map(e=>[e.id,e])),f=/* @__PURE__ */new Map;for(const o of u.items){const r=nn(o);e(t(r))===e(n)&&f.set(r.id,v.get(r.id)??r)}for(const e of v.values()){const t=void 0===o.beforeSortKey||e.sortKey<o.beforeSortKey,n=void 0===l||e.sortKey>=l;t&&n&&a(e)&&f.set(e.id,e)}return{results:[...f.values()].filter(a).sort(c).map(d),exhausted:u.exhausted,...u.exhausted?{}:{nextBeforeSortKey:u.nextBeforeSortKey}}},messageWindow:be,createMessageWindow:function(e={}){const t=Se(e);let n=!1;return{window:t,dispose(){n||(n=!0,t.reset(),Me.delete(t))}}}}}export{ee as createDomainState,H as defaultConversationUnreadMode,z as sumSessionsUnread};
1
+ import{encodeConversationKey as e,conversationRefFromMessage as t,conversationRefFromPinnedMessage as n,conversationRefFromSession as o}from"../conversation-identity.js";import{compareChannelReadPosition as r,getChannelReadOrder as s}from"../mapping/channel-read-position.js";import{computeSortKey as i,resolveMessageTimestamp as a,computeMessageSortKey as c,resolveMessageServerTime as d}from"../mapping/sort.js";import{collectTransferStatusBySerialNumber as u,synchronizeTransferStatusMessages as l,applyTransferStatusToBody as v}from"../mapping/transfer-status.js";import{parseChannelSyncCheckpoint as f,channelSyncCheckpointKey as p}from"../sync/channel-sync-checkpoint.js";import{parseConversationDeletionBoundary as y,isAfterConversationDeletion as m,captureConversationDeletionBoundary as g}from"./conversation-deletion-boundary.js";import{createDraftStore as h}from"./draft-store.js";import{rollbackMessageReaction as C,applyMessageReaction as w}from"./message-reactions.js";import{createMessageStore as I}from"./message-store.js";import{createMessageWindowStore as T}from"./message-window-store.js";import{createPinnedMessageStore as M}from"./pinned-message-store.js";import{createReadStore as S}from"./read-store.js";import{sortSessions as b}from"./session-sort.js";import{createSessionStore as E}from"./session-store.js";import{createImTextSearchMatcher as K,extractSearchText as U}from"../mapping/search-text.js";import{normalizeStoredMessageContent as A,LOCAL_MEDIA_ERROR_CODE as R,failInterruptedUpload as P}from"../mapping/stored-message.js";import{isMessageVisibleInTimeline as N,lastMessageSummaryEqual as x,sessionFromMessage as $}from"../mapping/session-mapper.js";import{isMessageEqual as D,isMessageRecoveryBodyEqual as B,dedupeById as j,mergeMessage as F}from"../mapping/merge.js";import{newClientMessageId as L}from"../mapping/message-id.js";import{backfillGroupMention as _}from"../mapping/group-message-mapper.js";import{isConversationUnreadMessage as k}from"../mapping/unread-divider.js";function O(e){return"direct"===e||"robot"===e||"customerService"===e?"local":"server"}function H(e,t){const n=t?.includeMuted??!1;let o=0;for(const t of e)!n&&t.muted||(o+=t.unreadCount>0?t.unreadCount:!0===t.manuallyUnread?1:0);return o}const z="im:deleted-conversations",q="im:terminated-conversations",G="im:membership-reset-sort-keys",W="im:pending-message-reactions",J="im:transfer-status-records",Q=["sendMessages","mentionAll","editProfile","manageMembers","manageAdmins","moderateMessages","manageMute","dismissChannel","transferOwnership"];function V(e,t){return e===t||void 0!==e&&void 0!==t&&Q.every(n=>e[n]===t[n])}function X(e,t){return e===t||void 0!==e&&void 0!==t&&e.role===t.role&&e.baseState===t.baseState&&e.resolvedState===t.resolvedState&&e.allMembersMuted===t.allMembersMuted&&e.currentUserMuted===t.currentUserMuted&&e.mutePeriod===t.mutePeriod}function Y(e,t){return e.id===t.id&&e.type===t.type&&e.title===t.title&&e.avatar===t.avatar&&x(e.lastMessageSummary,t.lastMessageSummary)&&e.timestamp===t.timestamp&&e.unreadCount===t.unreadCount&&(e.manuallyUnread??!1)===(t.manuallyUnread??!1)&&(e.mentionUnreadCount??0)===(t.mentionUnreadCount??0)&&e.pinned===t.pinned&&e.muted===t.muted&&e.topTime===t.topTime&&e.lastMessageSendState===t.lastMessageSendState&&e.lastMessageReceipt===t.lastMessageReceipt&&e.readCursor===t.readCursor&&e.groupState===t.groupState&&e.channelState===t.channelState&&V(e.channelPermissions,t.channelPermissions)&&X(e.channelAccessSnapshot,t.channelAccessSnapshot)&&e.sendDisabledReason===t.sendDisabledReason}function Z(x){const Q=I({getSelfId:x.getSelfId}),Z=/* @__PURE__ */new Map,ee=/* @__PURE__ */new Map,te=E(),ne=E(),oe=S(),re=h(),se=M(),ie=/* @__PURE__ */new Map,ae=/* @__PURE__ */new Map;let ce=0;function de(e){ae.set(e,++ce)}let ue=1;const le=/* @__PURE__ */new Set,ve=/* @__PURE__ */new Map,fe=/* @__PURE__ */new Set,pe=/* @__PURE__ */new Map,{storage:ye}=x;let me=Promise.resolve();const ge=/* @__PURE__ */new Map,he=/* @__PURE__ */new Map,Ce=/* @__PURE__ */new Map;let we=0;const Ie=x.unreadMode??O,Te=/* @__PURE__ */new Set;function Me(e={}){const t=T({storage:ye,loadOlderFromRemote:x.loadOlderFromRemote,loadNewerFromRemote:x.loadNewerFromRemote,shouldIncludeMessage:Ze,normalizeStoredUpload:Zt,...e});return Te.add(t),t}const Se=Me();function be(e,t){let n;for(const o of Te){const r=o.list().find(n=>n.id===e&&n.conversationId===t);if(void 0!==r){if(void 0!==n&&n.conversationType!==r.conversationType)throw new Error(`裸 conversationId 存在多类型消息歧义:${t}`);n=r}}return n}function Ee(e,t){const n=Q.get(t,e);if(n?.conversationId===e.conversationId&&n.conversationType===e.conversationType)return n;for(const n of Te){const o=n.list().find(n=>n.id===t&&n.conversationId===e.conversationId&&n.conversationType===e.conversationType);if(void 0!==o)return o}}function Ke(e,n){const o=Ee(t(e),e.id);void 0===o||Q.has(e.id,e)||Q.upsert(o);const r=Q.upsert(e,n);return{...r,previous:o,changed:void 0===o?r.changed:!D(o,r.message)}}function Ue(e){const t=new Map(Q.getByConversation(e).map(e=>[e.id,e]));for(const n of Te)if(Ae(n,e))for(const o of n.list())o.conversationType!==e.conversationType||o.conversationId!==e.conversationId||t.has(o.id)||t.set(o.id,o);return[...t.values()].sort((e,t)=>e.sortKey.localeCompare(t.sortKey))}function Ae(t,n){const o=t.info();return void 0===o.conversation?o.conversationId===n.conversationId:e(o.conversation)===e(n)}let Re=!1;function Pe(t){return`${e(t.conversation)}\0${t.parentMessageId}`}function Ne(){if(void 0===ye||Re)return;const e=[...Z.values()].flat();It(()=>ye.setMeta(W,e)).catch(e=>nt("保存待处理 Reaction 失败",e))}function xe(e){const t=e.body.transfer;if("transfer"!==e.contentType||void 0===t)return e;const n=ee.get(t.serialNumber);if(void 0===n||0!==t.status&&0===n.status)return e;const o={...t,status:n.status,...1===n.status&&void 0!==n.occurredTime?{receiveTime:n.occurredTime}:{},...2===n.status||3===n.status?{returnTime:n.occurredTime??t.returnTime}:{}};return t.status===o.status&&t.receiveTime===o.receiveTime&&t.returnTime===o.returnTime&&t.isRead===o.isRead?e:{...e,body:{transfer:v(t,o)}}}function $e(t,n){const o=`${e(t)}\0${n}`;return!!Z.delete(o)&&(Ne(),!0)}function De(t){const n=`${e(t)}\0`;let o=!1;for(const e of Z.keys())e.startsWith(n)&&(Z.delete(e),o=!0);return o&&Ne(),o}function Be(e,t){const n=Ee(e.conversation,e.parentMessageId);if(void 0===n){const t=Pe(e),n=Z.get(t)??[];return n.some(t=>t.id===e.id)?"duplicate":(Z.set(t,[...n,e]),Ne(),"pending")}if(yt(n),void 0!==n.recalled||void 0!==n.deletedForEveryone)return"duplicate";const o=w(n.reactions,e,x.getSelfId?.()??"");return o===n.reactions?"duplicate":(nn([{...n,reactions:o}],t),"applied")}function je(n,o){const r=t(n),s=`${e(r)}\0${n.id}`,i=Z.get(s);if(void 0!==i){Z.delete(s),Ne();for(const e of i)Be(e,o)}}function Fe(e){for(const t of[...Z.values()]){const n=t[0];if(void 0===n)continue;const o=Ee(n.conversation,n.parentMessageId);void 0!==o&&(void 0!==o.recalled||void 0!==o.deletedForEveryone?$e(n.conversation,n.parentMessageId):je(o,e))}}let Le=0;const _e=/* @__PURE__ */new Map,ke=/* @__PURE__ */new Map,Oe=/* @__PURE__ */new Map,He=/* @__PURE__ */new Map,ze=/* @__PURE__ */new Map;function qe(t){return e(t)}function Ge(e){return We(e)||le.has(qe(e))||le.has(e.conversationId)}function We(e){return fe.has(qe(e))||fe.has(e.conversationId)}function Je(t,n={}){return(!0===n.includeRestored||Ge(t))&&!We(t)&&ve.has(e(t))}function Qe(){return[...le,...ve.values()]}function Ve(e){const t=le.delete(qe(e)),n=le.delete(e.conversationId);return t||n}function Xe(e){const t=Ve(e),n=fe.delete(qe(e)),o=fe.delete(e.conversationId);return{deleted:t,terminal:n||o}}function Ye(e,t){if(""===t||"system"!==e.contentType)return!1;const n=e.body.system;return!0===n?.targetUserIds?.includes(t)&&("group"===e.conversationType?"group_member_joined"===n.eventType||"group_member_invited"===n.eventType:"channel"===e.conversationType&&("channel_member_joined"===n.eventType||"channel_member_invited"===n.eventType||"channel_created"===n.eventType))}function Ze(n){const o=t(n);if(We(o)||Ge(o)&&void 0===ne.get(o))return!1;if("group"!==o.conversationType)return!0;const r=pe.get(e(o));return void 0===r||n.sortKey>=r}function et(t){const n=e(t),o=(ke.get(n)??0)+1;return ke.set(n,o),o}function tt(t){const n=e(t),o=(_e.get(n)??0)+1;return _e.set(n,o),o}function nt(e,t){x.emitter.emit({type:"error",error:{scope:"storage",message:e,cause:t}})}function ot(e){x.emitter.emit({type:"session:updated",session:e,conversation:o(e)})}const rt=/* @__PURE__ */new Set,st=/* @__PURE__ */new Set,it=/* @__PURE__ */new Map,at=/* @__PURE__ */new Map;let ct=0,dt=Promise.resolve(),ut=0,lt=Promise.resolve(),vt=0;const ft=/* @__PURE__ */new Map;let pt;function yt(n){const o=e(t(n));pt?.keys.has(o)&&pt.messages.set(`${o}\0${n.id}`,n)}function mt(t){const n=e(t);ft.set(n,(ft.get(n)??0)+1)}function gt(e){return pt?.writes.push(e),void 0!==pt&&e.catch(()=>{}),e}async function ht(e){const t=(await Promise.allSettled(e)).find(e=>"rejected"===e.status);if(void 0!==t)throw t.reason}function Ct(e){const t=lt.then(e);return lt=t.then(()=>{},()=>{}),t}function wt(t,n){const o=vt,r=t.map(t=>[e(t),ft.get(e(t))??0]);return()=>o===vt&&n()&&r.every(([e,t])=>(ft.get(e)??0)===t)}function It(e){const t=0===ut?(()=>{try{return e()}catch(e){return Promise.reject(e)}})():dt.then(e),n=t.then(()=>{},()=>{});rt.add(n),n.finally(()=>rt.delete(n));for(const e of st)e.writes.push(t);return gt(t)}function Tt(e){ut+=1;const t=Promise.all([...rt]),n=dt.then(()=>t).then(e);return dt=n.then(()=>{},()=>{}),dt.finally(()=>{ut-=1}),gt(n)}function Mt(e){const t=e.body.system;if(void 0===t?.pinnedMessageAction)return e;const{pinnedMessageAction:n,...o}=t;return{...e,body:{...e.body,system:o}}}function St(n){if(void 0!==ye&&!Re&&0!==n.length){for(const o of st)for(const r of n)o.messages.add(`${e(t(r))}\0${r.id}`);It(()=>ye.saveMessages(n.map(Mt))).catch(e=>nt("消息落盘失败",e))}}function bt(e){const{lastMessageSendState:t,manuallyUnread:n,...o}=e;return o}function Et(t){if(void 0!==ye&&!Re){for(const n of st)n.sessions.add(e(o(t)));It(()=>ye.saveSessions([bt(t)])).catch(e=>nt("会话落盘失败",e))}}function Kt(e,t,n){if(void 0===ye||Re)return;const o=++ct;it.set(e,{version:o,persist:()=>Kt(e,t,n)});for(const t of st)t.metadata.add(e);const r=at.get(e),s=It(()=>void 0===r?ye.setMeta(e,t()):r.then(()=>ye.setMeta(e,t()))),i=s.then(()=>{},()=>{});at.set(e,i),i.then(()=>{at.get(e)===i&&at.delete(e)}),s.then(()=>{it.get(e)?.version===o&&it.delete(e)},e=>nt(n,e))}function Ut(){Kt(z,Qe,"删除会话标记保存失败")}function At(){Kt(q,()=>[...fe],"成员资格终止标记保存失败")}function Rt(){Kt(G,()=>[...pe.entries()],"重新入群的历史起点保存失败")}function Pt(t){if(void 0!==ye&&!Re){for(const n of st)void 0!==t.conversationType&&n.reads.add(e({conversationType:t.conversationType,conversationId:t.conversationId}));It(()=>ye.saveReadState(t)).catch(e=>nt("已读态落盘失败",e))}}function Nt(t){if(e(t),"supergroup"===t.conversationType)throw new Error("supergroup 草稿未实现,不得 fallback 到其他会话类型")}function xt(e){return Nt(e),Object.freeze({conversationType:e.conversationType,conversationId:e.conversationId})}function $t(e,t,n){if(Nt(e),"string"!=typeof t.text)throw new TypeError("草稿 text 必须是字符串");if(void 0!==t.attachments&&t.attachments.length>0)throw new Error("草稿附件尚未支持:attachments 只接受空集合");if(void 0!==t.mentions&&!Array.isArray(t.mentions))throw new TypeError("草稿 mentions 必须是数组");const o=(t.mentions??[]).map(e=>{if("string"!=typeof e.userId||""===e.userId.trim()||"string"!=typeof e.displayName)throw new TypeError("草稿 mention 必须包含非空 userId 与字符串 displayName");return Object.freeze({userId:e.userId,displayName:e.displayName})}),r=Object.freeze({conversationType:e.conversationType,conversationId:e.conversationId});return Object.freeze({ref:r,text:t.text,mentions:Object.freeze(o),...void 0===t.replyToMessageId?{}:{replyToMessageId:t.replyToMessageId},attachments:Object.freeze([]),updatedAt:n})}function Dt(e,t){return e.text===t.text&&e.replyToMessageId===t.replyToMessageId&&e.mentions.length===t.mentions.length&&e.mentions.every((e,n)=>{const o=t.mentions[n];return void 0!==o&&e.userId===o.userId&&e.displayName===o.displayName})}function Bt(t,n){Nt(t);const o=e(t),r=(ge.get(o)??Promise.resolve()).catch(()=>{}).then(n),s=r.then(()=>{},()=>{});return ge.set(o,s),s.finally(()=>{ge.get(o)===s&&ge.delete(o)}),r}async function jt(t,n){const o=xt(t),r=e(o);if(void 0!==n&&(!Number.isFinite(n)||n<0))throw new Error(`草稿 expectedUpdatedAt 非法:${n}`);const s=we,i=Ce.get(r)??0;return await Bt(o,async()=>{const e=re.get(o);if(null===e||void 0!==n&&e.updatedAt!==n)return!1;if(void 0!==ye&&await ye.deleteDraft(o),s!==we||i!==(Ce.get(r)??0))throw new Error("草稿状态已失效,拒绝过期清理回灌内存");return re.delete(o),x.emitter.emit({type:"draft:cleared",conversation:o}),!0})}function Ft(t,n,o,r,s){const i=mn(t);if(void 0===i)return;const a={...i,...void 0===s||s===ke.get(e(t))?{title:n,avatar:o??i.avatar}:{},...void 0!==r?{muted:r}:{}};Y(i,a)||gn(a)}function Lt(t,n){const o=x.profile;if(void 0===o)return Promise.resolve(null);const r={conversationType:"direct",conversationId:t},s=e(r),i=ze.get(t);if(!0!==n?.forceRefresh&&void 0!==i&&i.revision===_e.get(s))return i.promise;const a=Le,c=tt(r),d=et(r),u=(async()=>{const e=await o.getUserProfile(t,n);if(null!==e&&e.id===t&&a===Le&&c===_e.get(s)){const n=e.remark?.trim()?e.remark:e.nickname||t;Ft(r,n,e.avatar??"",e.muted,d)}return e})().finally(()=>{ze.get(t)?.promise===u&&ze.delete(t)});return ze.set(t,{revision:c,promise:u}),u}async function _t(t,n){const{conversationId:o,conversationType:r}=t;if("direct"===r){try{await Lt(o,!0===n?.force?{forceRefresh:!0}:void 0)}catch(e){x.emitter.emit({type:"error",error:{scope:"http",message:"会话资料补齐失败",cause:e}})}return!1}const s=e(t),i=!0===n?.force;if(!i&&(He.has(s)||Oe.has(s)))return!1;const a=Le,c=tt(t),d=et(t);i&&He.set(s,c);const{profile:u,channelProfile:l}=x,v=i?{forceRefresh:!0}:void 0;try{if("group"===r){if(void 0===u)return!1;const e=await u.getGroupProfile(o,v);if(a!==Le||c!==_e.get(s))return!1;null!==e&&(Ft(t,e.name,e.avatar??"",e.muted,d),3===e.status&&yn({conversationType:"group",conversationId:o},"group_dismissed"),i&&x.emitter.emit({type:"profile:updated",profileType:"group",id:o}))}else if("channel"===r){if(void 0===l)return!1;const e=await l.getProfile(o,v);if(a!==Le||c!==_e.get(s))return!1;if(null!==e){Ft(t,e.name,e.avatar??"",e.muted,d);const r=mn(t)?.channelState,s="left"===r||"removed"===r||"dismissed"===r,a="left"===e.channelState||"removed"===e.channelState||"dismissed"===e.channelState;if(!0===n?.allowChannelRecovery&&s&&"dismissed"!==r&&"active"===e.channelState)return vn(o,"active",void 0,{permissions:e.permissions,...void 0===e.accessSnapshot?{}:{snapshot:e.accessSnapshot}}),i&&x.emitter.emit({type:"channel-profile:updated",channelId:o,conversation:{conversationType:"channel",conversationId:o}}),!0;const c=s&&(!a||"dismissed"===r||"dismissed"!==e.channelState);if(a&&!c)return yn({conversationType:"channel",conversationId:o},`channel_${e.channelState}`),i&&x.emitter.emit({type:"channel-profile:updated",channelId:o,conversation:{conversationType:"channel",conversationId:o}}),!1;if(!c){const t=e.permissions.sendMessages?void 0:`channel_${e.channelState}`;vn(o,e.channelState,t,{permissions:e.permissions,...void 0===e.accessSnapshot?{}:{snapshot:e.accessSnapshot}})}i&&x.emitter.emit({type:"channel-profile:updated",channelId:o,conversation:{conversationType:"channel",conversationId:o}})}}return!1}catch(e){return x.emitter.emit({type:"error",error:{scope:"http",message:"会话资料补齐失败",cause:e}}),!1}finally{i&&a===Le&&He.get(s)===c&&He.delete(s)}}function kt(e){return k(e,x.getSelfId?.()??"")}function Ot(e){const t=oe.get(e);if(void 0===t||""===t.readCursor)return;const n="string"==typeof e?t.conversationType:e.conversationType;if("channel"===n){const o={conversationType:n,conversationId:"string"==typeof e?e:e.conversationId};return Ue(o).find(e=>e.extensions?.historyCursor===t.readCursor)?.sortKey??t.readCursorSortKey}const o="string"==typeof e?Q.getByConversation(e).find(e=>e.id===t.readCursor):Ee(e,t.readCursor);return o?.sortKey??t.readCursorSortKey}function Ht(e,t){let n=0;for(const o of Q.getByConversation(e))N(o)&&kt(o)&&(void 0===t||o.sortKey>t)&&(n+=1);return n}function zt(e){const t=x.getSelfId?.();if(void 0===t||""===t||e.senderId===t)return!1;const{mention:n}=e;return void 0!==n&&(n.atAll||n.atUserIds.includes(t))}function qt(e,t){let n=0;for(const o of Q.getByConversation(e))!0!==o.readBySelf&&zt(o)&&(void 0===t||o.sortKey>t)&&(n+=1);return n}function Gt(e,t=!0){const n=void 0===e.conversationType?te.get(e.conversationId):void 0,o=void 0===e.conversationType&&void 0!==n?{...e,conversationType:n.type}:e,r=void 0===o.conversationType?o.conversationId:{conversationType:o.conversationType,conversationId:o.conversationId},s=oe.get(r);if("channel"===o.conversationType&&de(o.conversationId),oe.set(o),t&&Pt(o),void 0===s||s.readCursor!==o.readCursor||s.readCursorSortKey!==o.readCursorSortKey||s.unreadCount!==o.unreadCount||(s.manuallyUnread??!1)!==(o.manuallyUnread??!1)){if(void 0===o.conversationType)return void x.emitter.emit({type:"error",error:{scope:"storage",message:`已读状态缺少复合身份,拒绝发布 read:updated(conversationId=${o.conversationId})`}});x.emitter.emit({type:"read:updated",conversationId:o.conversationId,conversation:{conversationType:o.conversationType,conversationId:o.conversationId},readCursor:o.readCursor,unreadCount:o.unreadCount,...!0===o.manuallyUnread?{manuallyUnread:!0}:{}})}}function Wt(n,o){if(void 0===n||n.sortKey===o.sortKey)return;const r=t(o),s=oe.get(r),i="channel"===o.conversationType?o.extensions?.historyCursor:void 0,a="direct"===o.conversationType||"group"===o.conversationType||"robot"===o.conversationType||"customerService"===o.conversationType;void 0!==s&&(a&&s.readCursor===o.id||"string"==typeof i&&""!==i&&s.readCursor===i||s.readCursorSortKey===n.sortKey)&&Gt({...s,readCursorSortKey:o.sortKey});const c=e(r);"group"===o.conversationType&&pe.get(c)===n.sortKey&&(pe.set(c,o.sortKey),Rt())}function Jt(e){const t=e?.channelAccessSnapshot?.role;return"owner"===t||"admin"===t}function Qt(e,t,n,o,r=mn(e)){const s=o??oe.get(e);if(void 0===t){if(void 0===r){if("string"==typeof e||void 0===s||s.unreadCount<=0)return;return{id:e.conversationId,type:e.conversationType,title:"",lastMessagePreview:"",timestamp:0,unreadCount:s.unreadCount,mentionUnreadCount:s.mentionUnreadCount,readCursor:s.readCursor,pinned:!1,muted:!1}}const t={...r,..."clear"===n?{lastMessagePreview:"",timestamp:0}:{},...void 0===s?{}:{unreadCount:s.unreadCount,manuallyUnread:s.manuallyUnread,mentionUnreadCount:s.mentionUnreadCount,readCursor:s.readCursor||r.readCursor}};return"clear"===n&&(delete t.lastMessageSummary,delete t.lastMessageSenderId,delete t.lastMessageSystemEvent,delete t.lastMessageSystemTargetsSelf,delete t.lastMessageMention,delete t.lastMessageRecalled,delete t.lastMessageDeletedForEveryone,delete t.lastMessageSendState,delete t.lastMessageReceipt),t}const i=s?.unreadCount??r?.unreadCount??0,a=void 0===s?r?.manuallyUnread:s.manuallyUnread,c=$(t,{unreadCount:i,mentionUnreadCount:s?.mentionUnreadCount??r?.mentionUnreadCount??0,selfId:x.getSelfId?.(),showChannelModerationDeleted:Jt(r)});return void 0===r?{...c,...void 0===a?{}:{manuallyUnread:a},readCursor:(s?.readCursor??"")||c.readCursor}:{...c,title:r.title||c.title,avatar:r.avatar??c.avatar,pinned:r.pinned,muted:r.muted,topTime:r.topTime,...void 0===a?{}:{manuallyUnread:a},readCursor:(s?.readCursor??"")||r.readCursor,groupState:r.groupState,channelState:r.channelState,channelPermissions:r.channelPermissions,channelAccessSnapshot:r.channelAccessSnapshot,sendDisabledReason:r.sendDisabledReason}}function Vt(e,t){if(void 0===e)return;const n=te.get({conversationType:e.type,conversationId:e.id});void 0!==n&&Y(n,e)||(te.set(e),ne.delete({conversationType:e.type,conversationId:e.id}),ot(e),t&&Et(e),""===e.title&&_t({conversationType:e.type,conversationId:e.id}))}function Xt(e,t,n="preserve",o=mn(e)){const r=t.findLast(e=>function(e,t){return!!N(e)&&("channel"!==e.conversationType||void 0===e.deletedForEveryone||Jt(t))}(e,o)),s="string"==typeof e?o?.type:e.conversationType;return Qt(e,r,void 0===r&&"channel"===s&&!Jt(o)&&(t.some(e=>void 0!==e.deletedForEveryone)||"channel-moderation-deleted"===o?.lastMessageSummary?.kind||void 0!==o?.lastMessageDeletedForEveryone)?"clear":n,void 0,o)}function Yt(e,t=!1){(t||void 0!==te.get(e))&&Vt(Xt(e,Q.getByConversation(e)),!0)}function Zt(e){if("uploading"!==e.status&&("failed"!==e.status||e.failure?.code!==R))return e;const t=Q.get(e.id,e);return void 0!==t&&t.conversationType===e.conversationType&&t.conversationId===e.conversationId?t:P(A(e))}function en(n,o=()=>!0){const r=[],s=j(n,x.getSelfId?.()??"").map(e=>{const t=Zt(e);let n={...t,sortKey:c(t)};if(n=A(n),"group"===n.conversationType&&"text"===n.contentType){const e=_(n.body.text??"",n.mention);void 0!==e&&(n.mention=e)}return xe(n)}),i=/* @__PURE__ */new Map;for(const n of s){if("transfer"!==n.contentType||void 0===n.body.transfer)continue;const o=t(n);i.set(e(o),o)}const a=[...i.values()].flatMap(e=>Ue(e)),d=l(a,s),u=new Set(s.map(e=>e.id));for(const e of d){if(!o())break;const{previous:n,message:s,isNew:i,changed:a}=Ke(e);if(Wt(n,s),void 0!==n&&a)for(const e of Te){if(!o())return r;e.list().some(e=>e.id===s.id&&e.conversationType===s.conversationType&&e.conversationId===s.conversationId)&&e.applyIncoming([s])}if(!o())return r;i?x.emitter.emit({type:"message:received",message:s,conversation:t(s),source:"offline",channelLifecycleEffects:!1}):a&&x.emitter.emit({type:"message:updated",message:s,conversation:t(s),source:"offline",channelLifecycleEffects:!1}),u.has(s.id)&&r.push(s)}return r}function tn(e){const t=Zt(e);let n={...t,sortKey:c(t)};if(n=A(n),"group"===n.conversationType&&"text"===n.contentType){const e=_(n.body.text??"",n.mention);void 0!==e&&(n.mention=e)}return xe(n)}function nn(n,o,r={}){const s=x.getSelfId?.()??"";if("offline"===o&&!0!==r.backfillOnly){let o=!1;for(const r of n){if(r.senderId===s||!N(r)||void 0!==r.recalled||void 0!==r.deletedForEveryone)continue;const n=t(r),i=ve.get(e(n));void 0!==i&&!We(n)&&m(r,i)&&Ve(n)&&(o=!0)}o&&Ut(),n=n.filter(n=>{const o=ve.get(e(t(n)));return void 0===o||m(n,o)||void 0!==Ee(t(n),n.id)})}if("live"===o){let i=!1,a=!1;for(const c of n){const n=t(c);if(Ye(c,s)){const t=Xe(n);t.deleted&&(i=!0),t.terminal&&("group"===n.conversationType?(pe.set(e(n),c.sortKey),Rt()):"channel"===n.conversationType&&pe.delete(e(n)),x.diagnostics?.record("info","core","conversation","membership-termination-cleared",()=>({conversation:n,data:{source:o,eventType:c.body.system?.eventType,groupHistoryLowerBoundApplied:"group"===n.conversationType}})),a=!0)}else""!==s&&c.senderId===s&&!0!==r.newOutgoing||We(n)||!Ve(n)||(i=!0)}i&&Ut(),a&&At()}const i=!0===x.diagnostics?.isEnabled("debug","conversation")?/* @__PURE__ */new Map:void 0,a=(n,o)=>{if(void 0===i)return;const r=t(n),s=e(r),a=i.get(s)??{ref:r,tombstone:0,groupLowerBound:0};"tombstone"===o?a.tombstone+=1:a.groupLowerBound+=1,i.set(s,a)},c=le.size>0||fe.size>0?n.filter(e=>{const n=t(e),o=!Ge(n)||!0===r.backfillOnly&&void 0!==ne.get(n)&&!We(n);return o||a(e,"tombstone"),o}):n,d=function(n){const o=/* @__PURE__ */new Map;if(0===pe.size)return o;for(const r of j(n,x.getSelfId?.()??"")){if("group"!==r.conversationType)continue;const n=t(r),s=e(n),i=pe.get(s);if(void 0===i)continue;const a=Ee(n,r.id);if(void 0===a||a.sortKey!==i)continue;const c=F(a,r,x.getSelfId?.()??"");c.sortKey!==i&&(pe.set(s,c.sortKey),o.set(s,c.id))}return o.size>0&&Rt(),o}(c),u=n=>d.get(e(t(n)))===n.id,v=pe.size>0?c.filter(e=>{const t=u(e)||Ze(e);return t||a(e,"groupLowerBound"),t}):c,f=0===d.size?v:[...v.filter(u),...v.filter(e=>!u(e))];for(const e of i?.values()??[])x.diagnostics?.record("debug","core","conversation","membership-filter-dropped",()=>({conversation:e.ref,data:{source:o,tombstoneDroppedCount:e.tombstone,groupHistoryLowerBoundDroppedCount:e.groupLowerBound}}));const p=/* @__PURE__ */new Map,y=/* @__PURE__ */new Map,g=/* @__PURE__ */new Map,h=/* @__PURE__ */new Map,C=/* @__PURE__ */new Map,w=/* @__PURE__ */new Set,I=j(f,s).map(xe),T=/* @__PURE__ */new Map;for(const n of I){if("transfer"!==n.contentType||void 0===n.body.transfer)continue;const o=t(n);T.set(e(o),o)}const M=[...T.values()].flatMap(e=>Ue(e)),S=l(M,I),b=[],E=[];for(const n of S){if("channel"===n.conversationType&&pt?.keys.has(e(t(n)))&&!pt.current())continue;const{previous:s,message:i,isNew:a,changed:c}=Ke(n,{authoritativeFailure:!0===r.authoritativeOutboxFailure});if(yt(i),!0===r.backfillOnly&&!0===r.refreshSessionSummary){const n=t(i);p.set(e(n),n)}if(!a&&!c)continue;Wt(s,i);for(const e of Te)e.applyIncoming([i]);a?x.emitter.emit({type:"message:received",message:i,conversation:t(i),source:o,channelLifecycleEffects:!0===r.applyChannelLifecycleEffects}):x.emitter.emit({type:"message:updated",message:i,conversation:t(i),source:o,channelLifecycleEffects:!0===r.applyChannelLifecycleEffects});const d=t(i);if(!a&&void 0!==s&&!0!==s.readBySelf&&!0===i.readBySelf){const t=Ot(d),n=void 0===t||s.sortKey>t,o=e(d);n&&N(s)&&kt(s)&&void 0===s.recalled&&void 0===s.deletedForEveryone&&g.set(o,(g.get(o)??0)-1),n&&zt(s)&&void 0===s.recalled&&void 0===s.deletedForEveryone&&C.set(o,(C.get(o)??0)-1)}We(d)||(b.push(i),p.set(e(d),d),a&&!0!==r.backfillOnly&&E.push(i))}const K=/* @__PURE__ */new Map;for(const n of E){const r=t(n),s=e(r);kt(n)&&w.add(s),K.has(s)||K.set(s,Ot(r));const i=K.get(s),a=void 0===i||n.sortKey>i;if(N(n)&&a&&kt(n)&&!0!==n.readBySelf&&void 0===n.recalled&&void 0===n.deletedForEveryone){const e=Ie(n.conversationType);("local"===e||"server"===e&&"live"===o)&&y.set(s,(y.get(s)??0)+1)}a&&!0!==n.readBySelf&&zt(n)&&void 0===n.recalled&&void 0===n.deletedForEveryone&&h.set(s,(h.get(s)??0)+1)}for(const t of p.values()){if(!0===r.backfillOnly){!0===r.refreshSessionSummary&&Yt(t);continue}const n=e(t),o=y.get(n)??0,s=h.get(n)??0,i=g.get(n)??0,a=C.get(n)??0,c=w.has(n),d=oe.get(t);if(o>0||s>0||c||void 0!==d&&(0!==i||0!==a)){const e=d??{...t,readCursor:"",unreadCount:0},n={...e,unreadCount:Math.max(0,e.unreadCount+o+i),mentionUnreadCount:Math.max(0,(e.mentionUnreadCount??0)+s+a)};c&&delete n.manuallyUnread,Gt(n)}Yt(t,E.some(e=>e.conversationType===t.conversationType&&e.conversationId===t.conversationId&&N(e)))}St(b.filter(e=>void 0!==Ee(t(e),e.id)));for(const e of b)void 0===e.recalled&&void 0===e.deletedForEveryone?je(e,o):$e(t(e),e.id)}function on(e,t,n=Date.now()){const o={conversationType:"direct",conversationId:e},r=Ee(o,t),s=Q.getByConversation(o).findLast(e=>"direct_contact_established"===e.body.system?.eventType);if(void 0!==r&&void 0!==s&&a(s)>=a(r))return;const c=`${t}:contact-required`;if(void 0!==Q.get(c,o))return;nn([{id:c,conversationId:e,conversationType:"direct",senderId:e,contentType:"system",body:{system:{eventType:"direct_contact_required",targetUserIds:[e],action:{type:"request-contact",userId:e}}},createdAt:n,sortKey:i(n,c),status:"sent",receipt:"unread",encryption:{encrypted:!1,decryptFailed:!1}}],"live")}const rn=/* @__PURE__ */new Map;let sn=0;function an(e){const t=oe.get(e);if(!0!==t?.manuallyUnread)return!1;const n={...t};return delete n.manuallyUnread,Gt(n),Yt(e),!0}function cn(e,t,n,r,s){const i="string"==typeof e?e:e.conversationId,a=mn(e),c="string"==typeof e?void 0===a?void 0:o(a):e;if(void 0!==a&&"server"!==Ie(a.type))return void x.emitter.emit({type:"error",error:{scope:"unknown",message:`applyServerUnread 不应用于本地未读会话(conversationId=${i}, type=${a.type}),已忽略`}});if(!Number.isFinite(t))return void x.emitter.emit({type:"error",error:{scope:"unknown",message:`applyServerUnread 收到非法未读数(conversationId=${i}, count=${t}),已忽略`}});"channel"===c?.conversationType&&ie.delete(i);const d=oe.get(e);let u=d?.readCursor??"",l=d?.readCursorSortKey;const v=void 0===n||""===n?void 0:void 0===c?Q.getByConversation(i).find(e=>e.id===n)??be(n,i):Ee(c,n);void 0!==v&&v.conversationId===i&&(void 0===l||v.sortKey>l)&&(u=v.id,l=v.sortKey),void 0!==r&&(u=r),Gt({...void 0===c?{conversationId:i}:c,readCursor:u,readCursorSortKey:l,unreadCount:Math.max(0,Math.floor(t)),...t>0?{}:{manuallyUnread:d?.manuallyUnread},mentionUnreadCount:0===t||!1===s?0:!0===s?Math.max(1,d?.mentionUnreadCount??0):d?.mentionUnreadCount}),Yt(e,t>0&&void 0!==c&&!Ge(c))}function dn(e){const t=ie.get(e.conversation.conversationId);return t?.handle.transactionId===e.transactionId?t:void 0}function un(e,t,n,o=!1){const r=mn(e),s=Ee(e,t);if("channel"!==r?.type||"channel"!==s?.conversationType||s.conversationId!==e.conversationId||s.extensions?.historyCursor!==n)throw new Error(`CHANNEL 已读位置不可信(channelId=${e.conversationId}, messageId=${t})`);o||ie.delete(e.conversationId);const i=oe.get(e),a=void 0===i?r.mentionUnreadCount:i.mentionUnreadCount;Gt({...e,readCursor:n,readCursorSortKey:s.sortKey,unreadCount:i?.unreadCount??r.unreadCount,...void 0===a?{}:{mentionUnreadCount:a}}),Yt(e)}function ln(e,t,n){const o=e.conversation,r=o.conversationId,i=dn(e);if(void 0===i)throw new Error(`CHANNEL 乐观已读事务已失效(channelId=${r})`);const a=Ee(o,t);if(void 0===a||a.conversationId!==r||"channel"!==a.conversationType)throw new Error(`CHANNEL 乐观已读消息不可信(channelId=${r}, messageId=${t})`);if(a.extensions?.historyCursor!==n)throw new Error(`CHANNEL 乐观已读 cursor 与消息不一致(channelId=${r}, messageId=${t})`);i.steps.at(-1)?.readCursor!==n&&(i.steps.push({readCursor:n,messageId:t,...s(a)}),un(o,t,n,!0))}function vn(t,n,o,r){const s={conversationType:"channel",conversationId:t},i=e(s);if(Ge(s)&&void 0===ne.get(s)&&!Je(s))return;const a=mn(s);if(void 0===a){tt(s),He.delete(i);return void gn({id:t,type:"channel",title:"",lastMessagePreview:"",timestamp:0,unreadCount:0,pinned:!1,muted:!1,channelState:n,channelPermissions:r?.permissions,channelAccessSnapshot:r?.snapshot,sendDisabledReason:o})}if("channel"!==a.type)throw new Error(`setChannelRestriction: 会话 ${t} 类型为 ${a.type},拒绝写入 CHANNEL 状态`);tt(s),He.delete(i);const c=r?.permissions,d=r?.snapshot;if(a.channelState===n&&a.sendDisabledReason===o&&V(a.channelPermissions,c)&&X(a.channelAccessSnapshot,d))return void(void 0!==te.get(s)&&Yt(s));const u={...a,channelState:n,channelPermissions:c,channelAccessSnapshot:d,sendDisabledReason:o};void 0!==te.get(s)?gn(Xt(s,Q.getByConversation(s),"preserve",u)):gn(u)}async function fn(e,t){if(""===t.trim())throw new Error("本机删除消息需要非空 messageId");const n=()=>{if(se.isPinnedMessage(e,t))throw Object.assign(new Error("置顶消息必须先取消置顶才能删除"),{code:"IM_MESSAGE_PINNED"})};n();const o=Ee(e,t),r=Q.get(t,e),s=void 0!==r&&r.conversationType===e.conversationType&&r.conversationId===e.conversationId,i=Q.getByConversation(e).filter(e=>e.id!==t),a=void 0===te.get(e)?void 0:Xt(e,i,"clear"),c=void 0===a?void 0:bt(a);function d(e){return void 0!==e&&(void 0===r||!D(r,e))}const u=void 0===ye?{deleted:!1,superseded:!1}:await Tt(async()=>{n();const r=Ee(e,t)??o??await ye.getMessage(e,t)??void 0;if(n(),d(Q.get(t,e)))return{deleted:!1,superseded:!0};const s=await ye.deleteMessage(e,t,c);if(se.isPinnedMessage(e,t)){const o=Ee(e,t)??r;void 0!==o&&await ye.saveMessages([Mt(o)]);const s=te.get(e);return void 0!==s&&await ye.saveSessions([bt(s)]),n(),{deleted:!1,superseded:!0}}return{deleted:s,superseded:!1}});if(u.superseded||d(Q.get(t,e)))return!1;const l=s&&Q.delete(e,t);let v=!1;for(const n of Te)v=n.removeMessage(e,t)||v;if(!u.deleted&&!l&&!v)return!1;const f=void 0===te.get(e)?void 0:Xt(e,Q.getByConversation(e),"clear");return Vt(f,!1),void 0===f||void 0!==a&&Y(a,f)||Et(f),$e(e,t),x.emitter.emit({type:"message:removed",conversation:{...e},messageId:t,scope:"local-only"}),!0}function pn(t,o={}){const r="string"==typeof t?t:t.conversationId,s=te.get(t),i=se.get(t),a="string"==typeof t?void 0!==s?{conversationType:s.type,conversationId:r}:void 0===i?void 0:n(i):t;if(void 0===a)throw new Error(`裸 conversationId 无法确定删除类型:${r}`);if(et(a),Oe.delete(e(a)),"direct"===a.conversationType&&(tt(a),ze.delete(a.conversationId)),mt(a),"direct"===a.conversationType||"group"===a.conversationType||"channel"===a.conversationType)if(!0===o.terminal)ve.delete(e(a));else{const t=g(a,Ue(a),ve.get(e(a)));void 0!==t&&ve.set(e(a),t)}const c=Q.getByConversation(a).length;!function(t){const n=xt(t),o=e(n);Ce.set(o,(Ce.get(o)??0)+1),null!==re.get(n)&&(re.delete(n),x.emitter.emit({type:"draft:cleared",conversation:n})),Bt(n,async()=>{void 0!==ye&&await ye.deleteDraft(n)}).catch(e=>nt("删会话草稿失败",e))}(a),De(a),te.delete(t),ne.delete(t),"channel"===a.conversationType&&(de(a.conversationId),ie.delete(a.conversationId)),oe.delete(t),Q.deleteByConversation(t),se.clear(t);const d=qe(a);if(!0===o.terminal){fe.add(d);const e=pe.delete(d);le.delete(d),le.delete(r),e&&Rt(),x.diagnostics?.record("info","core","conversation","membership-terminated",()=>({conversation:a,data:{reason:o.terminalReason??"membership-terminated",removedMessageCount:c}}))}else le.add(d);for(const e of Te)Ae(e,a)&&e.reset();x.emitter.emit({type:"session:removed",conversationId:r,conversation:a}),Ut(),!0===o.terminal&&At(),void 0!==ye&&Tt(async()=>{await ht([ye.deleteConversationMessages(a),ye.deleteSession(a),ye.deleteReadState(a),ye.removePinnedMessage(a)])}).catch(e=>nt("删除会话持久数据失败",e))}function yn(e,t){pn(e,{terminal:!0,terminalReason:t})}function mn(e){if("string"==typeof e){const t=[...te.getAll(),...ne.getAll()].filter(t=>t.id===e);if(t.length>1)throw new Error(`裸 conversationId 存在多类型歧义:${e}`);return t[0]}return te.get(e)??ne.get(e)}function gn(e){const t=o(e);void 0!==te.get(t)?(te.set(e),ot(e),Et(e)):(ne.set(e),x.emitter.emit({type:"conversation-context:updated",conversation:t}))}async function hn(n,o){let r=await ye.getMessages(n,{limit:50});const s=o=>o.filter(o=>e(t(o))===e(n)&&Ze(o)),a=s(r);if(!["direct","group","channel"].includes(n.conversationType)||!o())return a;let c=g(n,a);for(;o()&&50===r.length;){const e=r[0].sortKey;if(void 0!==c&&e<i(c.serverTime,""))break;if(r=await ye.getMessages(n,{beforeSortKey:e,limit:50}),!o())return[];if(r.some(t=>t.sortKey>=e))throw new Error("会话本地历史游标没有向前推进");const t=s(r);c=g(n,t,c),a.push(...t.filter(e=>void 0!==c&&d(e)===c.serverTime))}return a}return{upsertMessages:nn,commitReceivedMessages:function(n,o,r,s){if(void 0===ye){for(const e of s?.events??[])s.apply(e);return void nn(n,o,r)}const i={writes:[],messages:/* @__PURE__ */new Set,sessions:/* @__PURE__ */new Set,reads:/* @__PURE__ */new Set,metadata:/* @__PURE__ */new Set};st.add(i);try{const a=(s?.events??[]).filter(e=>"ignored"!==s.apply(e));nn(n,o,r);const c=a.flatMap(e=>{const t=Ee(e.conversation,e.parentMessageId);return void 0===t?[]:[t]});a.length>0&&Ne();const d=/* @__PURE__ */new Map,u=[];for(const o of[...n,...c]){const n=t(o),r=e(n),s=Ee(n,o.id);void 0!==s&&(d.set(r,n),i.messages.has(`${r}\0${s.id}`)||u.push(s))}St(u);for(const[e,t]of d){const n=te.get(t),o=oe.get(t);void 0===n||i.sessions.has(e)||Et(n),void 0===o||i.reads.has(e)||Pt(o)}for(const[e,t]of it)i.metadata.has(e)||t.persist()}finally{st.delete(i)}return ht(i.writes)},prepareOfflineMessageUpdate:function(n,o){if(void 0===ye)return!0;const r=t(n),s=ve.get(e(r));if(void 0===s||Ge(r)||m(n,s)||void 0!==Ee(r,n.id))return!0;const i=vt,a=e(r),c=ft.get(a)??0;o();let d=!1,u=Ee(r,n.id);const l=x.emitter.subscribe(o=>{"message:received"!==o.type&&"message:updated"!==o.type||o.message.id!==n.id||e(t(o.message))!==a||("live"!==o.source||void 0!==u&&B(u,o.message)||(d=!0),u=o.message)});return ye.getMessage(r,n.id).then(s=>{if(o(),i!==vt||(ft.get(a)??0)!==c)throw new DOMException("消息提交前的本地历史读取已失效","AbortError");return!d&&(void 0===Ee(r,n.id)&&null!==s&&s.id===n.id&&e(t(s))===a&&Ze(s)&&Q.upsert(s),!0)}).finally(l)},applyReaction:Be,rollbackReaction:function(t,n,o){const r=Ee(t,n);if(void 0===r){const r=`${e(t)}\0${n}`,s=Z.get(r);if(void 0===s)return!1;const i=s.filter(e=>e.id!==o);return i.length!==s.length&&(0===i.length?Z.delete(r):Z.set(r,i),Ne(),!0)}const s=C(r.reactions,o,x.getSelfId?.()??"");if(s===r.reactions)return!1;const i={...r};return void 0===s?delete i.reactions:i.reactions=s,nn([i],"live"),!0},appendDirectContactRequiredNotice:on,appendDirectMessageRefusedNotice:function(e,t,n=Date.now()){const o={conversationType:"direct",conversationId:e},r=`${t}:message-refused`;if(void 0!==Q.get(r,o))return;const s=Q.get(t,o),c="direct"===s?.conversationType&&s.conversationId===e?a(s):n;nn([{id:r,conversationId:e,conversationType:"direct",senderId:e,contentType:"system",body:{system:{eventType:"direct_message_refused",targetUserIds:[e]}},createdAt:c,sortKey:i(c,r),status:"sent",receipt:"unread",encryption:{encrypted:!1,decryptFailed:!1}}],"live")},appendDirectContactRequiredTextFailure:function(e,t=Date.now()){const n=L(),o={id:n,conversationId:e.conversationId,conversationType:"direct",senderId:e.senderId,contentType:"text",body:{text:e.text},createdAt:t,sortKey:i(t,n),status:"failed",receipt:"unread",encryption:{encrypted:!1,decryptFailed:!1},failure:{code:33281,reason:"rejected",displayCode:"contactRequired",retryable:!1},...void 0===e.refMessageId?{}:{refMessageId:e.refMessageId}};return nn([o],"live"),on(e.conversationId,n,t+1),o},reconcileDirectContactEstablishedNotice:function(e,t,n=Date.now()){const o=rn.get(e);if(void 0!==o)return o;const r={conversationType:"direct",conversationId:e},s=sn,a=(async()=>{const o=Q.getByConversation(r).filter(e=>{const t=e.body.system?.eventType;return"direct_contact_required"===t||"direct_contact_established"===t}),a=o.filter(e=>"direct_contact_required"===e.body.system?.eventType),c=a.at(-1)?.createdAt??0,d=o.findLast(e=>"direct_contact_established"===e.body.system?.eventType)?.createdAt??0,u=d>=c&&d>0;if(0===a.length&&u)return;const l=Ot(r);for(const e of a)try{const t=await fn(r,e.id),n=Ee(r,e.id);t||"direct_contact_required"!==n?.body.system?.eventType||x.emitter.emit({type:"error",error:{scope:"storage",message:"联系人关系已建立,但旧的申请添加提示未能删除",cause:{conversation:r,messageId:e.id}}})}catch(t){x.emitter.emit({type:"error",error:{scope:"storage",message:"联系人关系已建立,但删除旧的申请添加提示失败",cause:{conversation:r,messageId:e.id,error:t}}})}if(s!==sn)return;const v=oe.get(r);if(void 0!==v&&(Gt({...v,...void 0===v.readCursorSortKey&&void 0!==l?{readCursorSortKey:l}:{},unreadCount:Ht(r,l)}),Yt(r)),u)return;const f=Number.isFinite(n)&&n>0?n:Date.now(),p=Math.max(f,c+1);!function(e,t,n=Date.now(),o=n){const r=function(e,t){return`${""===e.trim()?`contact-established:${t}`:e}:contact-established`}(t,o);if(void 0!==Q.get(r,{conversationType:"direct",conversationId:e}))return;nn([{id:r,conversationId:e,conversationType:"direct",senderId:e,contentType:"system",body:{system:{eventType:"direct_contact_established",targetUserIds:[e]}},createdAt:n,sortKey:i(n,r),status:"sent",receipt:"unread",encryption:{encrypted:!1}}],"live")}(e,t,p,f)})().finally(()=>{rn.get(e)===a&&rn.delete(e)});return rn.set(e,a),a},recallMessage:function(e,t,n){const o=Ee(e,t);void 0!==o&&nn([{...o,recalled:n,body:{}}],"live")},deleteChannelMessageForEveryone:function(e,t,n){const o=Ee(e,t);void 0!==o&&"channel"===o.conversationType&&nn([{...o,recalled:void 0,deletedForEveryone:n,body:{}}],"live")},editMessage:function(e,t,n,o){const r=Ee(e,t);if(void 0===r)return;const s={...r,body:n,edited:!0};void 0!==o?s.mention=o:delete s.mention,nn([s],"live")},applyTransferStatusBySerialNumber:async function(e,t,n){const o=function(e,t){if(void 0===e)return t;if(0===e.status&&0!==t.status)return t;if(0===t.status&&0!==e.status)return e;const n=e.occurredTime??0,o=t.occurredTime??0;return n!==o?o>n?t:e:t.status>e.status?t:e}(ee.get(e),{serialNumber:e,status:t,...void 0===n?{}:{occurredTime:n}});ee.set(o.serialNumber,o),await async function(){if(void 0===ye)return;const e=[...ee.values()],t=me.then(()=>ye.setMeta(J,e));gt(t),me=t.catch(()=>{});try{await t}catch(e){throw nt("保存转账状态记录失败",e),e}}();const r=/* @__PURE__ */new Map;for(const t of u(Q.getAll(),e,o.status,o.occurredTime))r.set(t.id,t);for(const t of te.getAll()){const n=Ue({conversationType:t.type,conversationId:t.id});for(const t of u(n,e,o.status,o.occurredTime))r.set(t.id,t)}0!==r.size&&nn([...r.values()],"live")},getMessage:e=>Q.get(e),getMessagesById:e=>Q.getById(e),getConversationMessage:Ee,getLoadedMessagesByConversation:Ue,hasRecoverableConversationDeletion:Je,resolveConversationMessage:async function(n,o,r={}){const s=Ee(n,o);if(void 0!==s||void 0===ye)return s;try{const r=await ye.getMessage(n,o);if(null===r||e(t(r))!==e(n))return;return tn(r)}catch(e){if(nt("按消息 ID 读取本地历史失败",e),!0===r.throwOnStorageError)throw e;return}},getMessages:()=>Q.getAll(),getMessagesByConversation:e=>Q.getByConversation(e),deleteLocalMessage:fn,clearLocalConversationHistory:async function(e){mt(e);const t={...e},n=new Map(Q.getByConversation(t).map(e=>[e.id,e])),o=te.get(t),r=oe.get(t),s=void 0===r&&void 0===o?void 0:{...t,readCursor:r?.readCursor??o?.readCursor??"",...void 0===r?.readCursorSortKey?{}:{readCursorSortKey:r.readCursorSortKey},unreadCount:0,mentionUnreadCount:0},i=void 0===o?void 0:Qt(t,void 0,"clear",s);if(void 0!==ye){if(void 0===ye.clearConversationHistory)throw new Error("当前 storage 未实现 clearConversationHistory,拒绝非原子清空本机会话历史");await Tt(()=>ye.clearConversationHistory(t,void 0===i?void 0:bt(i),s))}const a=oe.get(t);void 0!==s&&(a?.conversationType===r?.conversationType&&a?.conversationId===r?.conversationId&&a?.readCursor===r?.readCursor&&a?.readCursorSortKey===r?.readCursorSortKey&&a?.unreadCount===r?.unreadCount&&a?.mentionUnreadCount===r?.mentionUnreadCount)&&Gt(s,!1);for(const[e,o]of n){const n=Q.get(e,t);void 0!==n&&D(o,n)&&Q.delete(t,e)}const c=Q.getByConversation(t);for(const e of Te)e.clearConversation(t)&&e.applyIncoming(c);De(t),void 0!==te.get(t)&&Vt(Xt(t,c,"clear"),!1),x.emitter.emit({type:"conversation-history:cleared",conversation:t,scope:"local-only"})},commitChannelSyncPage:function(n,o,r,s){const i=wt(n,r);return Ct(async()=>{if(!i())return!1;if(void 0===ye)throw new Error("CHANNEL 严格同步提交需要 storage");const r={writes:[],messages:/* @__PURE__ */new Map,keys:new Set(n.map(e)),current:i};let a;pt=r;try{const e=o();if(e instanceof Promise)throw e.catch(()=>{}),new Error("CHANNEL 页 mutation 必须同步执行")}catch(e){a={cause:e}}finally{pt=void 0}if(await ht(r.writes),void 0!==a)throw a.cause;if(!i())return!1;const c=[...r.messages.values()].flatMap(e=>{const n=Ee(t(e),e.id);return void 0===n?[]:[Mt(n)]}),d=[];c.length>0&&d.push(It(()=>ye.saveMessages(c)));for(const e of n){const t=te.get(e),n=oe.get(e),o=se.get(e);void 0!==t&&d.push(It(()=>ye.saveSessions([bt(t)]))),void 0!==n&&d.push(It(()=>ye.saveReadState(n))),d.push(It(()=>void 0===o?ye.removePinnedMessage(e):ye.savePinnedMessage(o)))}const u=[[W,[...Z.values()].flat()],[J,[...ee.values()]],[z,Qe()],[q,[...fe]],[G,[...pe.entries()]]];for(const[e,t]of u)d.push(It(()=>ye.setMeta(e,t)));return void 0!==s&&d.push(It(async()=>{i()&&await s()})),await ht(d),i()})},saveChannelSyncCheckpoint:function(e,t){const n=f(e,e.conversation);if(void 0===n)return Promise.reject(new Error("CHANNEL 同步位置无效"));const o=wt([n.conversation],t);return Ct(async()=>{if(!o())return!1;if(void 0===ye)throw new Error("CHANNEL 同步位置保存需要 storage");let e=!1;return await It(async()=>{o()&&(await ye.setMeta(p(n.conversation),n),e=!0)}),e&&o()})},waitForChannelSyncPersistence:async function(){for(;;){const e=lt,t=dt;if(await Promise.all([e,t,...rt]),e===lt&&t===dt&&0===rt.size)return}},getSession:e=>te.get(e),getConversationContext:mn,isMembershipTerminated:We,prepareConversation:function(e,t={}){const n=o(e);if("supergroup"===n.conversationType)throw new Error("prepareConversation:supergroup 未实现");const r=mn(n);if(void 0!==r){const t=r.title||e.title,n=r.avatar??e.avatar;return void(t===r.title&&n===r.avatar||gn({...r,title:t,avatar:n}))}if(We(n)){if(!0!==t.membershipConfirmed)throw new Error("准备聊天失败:需要重新确认成员资格");fe.delete(qe(n)),fe.delete(n.conversationId),At()}gn({...e,...void 0===e.channelPermissions?{}:{channelPermissions:{...e.channelPermissions}},...void 0===e.channelAccessSnapshot?{}:{channelAccessSnapshot:{...e.channelAccessSnapshot}}}),(oe.get(n)?.unreadCount??0)>0&&!Ge(n)&&Yt(n,!0)},ensureConversation:function(t){const n=o(t);if(e(n),"supergroup"===n.conversationType)throw new Error("ensureConversation:supergroup 未实现");const r=te.get(n);if(void 0!==r)return r;const s={...t,id:n.conversationId,type:n.conversationType,...void 0===t.channelPermissions?{}:{channelPermissions:{...t.channelPermissions}},...void 0===t.channelAccessSnapshot?{}:{channelAccessSnapshot:{...t.channelAccessSnapshot}},...void 0===t.extensions?{}:{extensions:{...t.extensions}}},i=Xe(n);return i.deleted&&Ut(),i.terminal&&At(),te.set(s),ne.delete(n),ot(s),Et(s),s},getSessions:()=>te.getAll(),getConversationList:function(){const e=[];for(const t of te.getAll()){const n=o(t);e.push({...t,draft:re.get(n)})}return b(e)},getReadState:e=>oe.get(e),getPinnedMessage:e=>se.get(e),setPinnedMessage:function(e,t){const o=function(e){const t=Ee(n(e),e.messageId);return void 0===t?e:{...e,preview:{state:"ready",message:t}}}(e);se.set(o)&&(x.emitter.emit({type:"pinned-message:updated",conversationId:o.conversationId,conversation:{conversationType:o.conversationType,conversationId:o.conversationId},pinnedMessage:o,reason:t}),function(e){void 0===ye||Re||It(()=>ye.savePinnedMessage(e)).catch(e=>nt("置顶消息落盘失败",e))}(o))},clearPinnedMessage:function(e,t){const o="string"==typeof e?e:e.conversationId,r=se.get(e);if(!se.clear(e))return;const s="string"==typeof e?void 0===r?void 0:n(r):e;if(void 0===s)throw new Error(`置顶消息清理缺少复合身份:${o}`);x.emitter.emit({type:"pinned-message:updated",conversationId:o,conversation:s,pinnedMessage:null,reason:t}),function(e){void 0===ye||Re||It(()=>ye.removePinnedMessage(e)).catch(e=>nt("置顶消息删除失败",e))}(e)},isPinnedMessage:(e,t)=>se.isPinnedMessage(e,t),setReadState:e=>{const t=void 0===e.conversationType?te.get(e.conversationId):void 0,n=void 0===e.conversationType&&void 0!==t?{...e,conversationType:t.type}:e;"channel"===n.conversationType&&de(n.conversationId),oe.set(n),Pt(n)},markConversationUnread:function(e){const t=te.get(e);if(void 0===t)return!1;const n=oe.get(e)??{...e,readCursor:t.readCursor??"",unreadCount:t.unreadCount,mentionUnreadCount:t.mentionUnreadCount};return!(n.unreadCount>0||!0===n.manuallyUnread)&&(Gt({...n,manuallyUnread:!0}),Yt(e),!0)},clearConversationManualUnread:an,advanceRead:function(e,n){const o="string"==typeof e?Q.getByConversation(e).find(e=>e.id===n)??be(n,e):Ee(e,n);if(void 0===o)return;const r="string"==typeof e?t(o):e,s="string"==typeof e?e:e.conversationId;if(o.conversationId!==s||o.conversationType!==r.conversationType)return;const i=Ot(r);if(void 0!==i&&i>=o.sortKey)return void("string"!=typeof e&&an(e));const a={...r,readCursor:n,readCursorSortKey:o.sortKey,unreadCount:Ht(r,o.sortKey),mentionUnreadCount:qt(r,o.sortKey)};return Gt(a),Yt(r),a},applyServerUnread:cn,applyChannelReadPosition:un,getChannelReadRevision:e=>ae.get(e.conversationId)??ce,hasPendingChannelRead:e=>ie.has(e.conversationId),applyChannelReadSummary:(e,t)=>cn(e,t.unreadCount,void 0,t.readCursor,t.hasUnreadMention),beginChannelReadTransaction:function(e){const t=e.conversationId,n=mn(e);if(void 0===n||"channel"!==n.type)throw new Error(`CHANNEL 乐观已读事务要求 channel 会话(conversationId=${t}, type=${n?.type??"missing"})`);if(ie.has(t))throw new Error(`CHANNEL 乐观已读事务已存在(channelId=${t})`);const o={conversation:e,transactionId:ue++},r=oe.get(e)??{conversationId:t,readCursor:n.readCursor??"",unreadCount:n.unreadCount,...void 0===n.mentionUnreadCount?{}:{mentionUnreadCount:n.mentionUnreadCount}};return ie.set(t,{handle:o,baseReadState:{...r},steps:[],committedThrough:-1}),de(t),o},applyChannelReadOptimistically:ln,applyChannelConversationReadOptimistically:function(e,t,n){ln(e,t,n);const o=dn(e).steps.at(-1);if(void 0!==o.clearedCounts)return;const i=oe.get(e.conversation),a=Ue(e.conversation).filter(e=>r(s(e),o)>0&&kt(e)&&N(e)&&!0!==e.readBySelf&&void 0===e.recalled&&void 0===e.deletedForEveryone),c=Math.min(i.unreadCount,a.length),d=Math.min(i.mentionUnreadCount??0,a.filter(zt).length);o.clearedCounts={unread:i.unreadCount-c,mention:(i.mentionUnreadCount??0)-d},Gt({...i,unreadCount:c,mentionUnreadCount:d}),Yt(e.conversation)},commitChannelReadTransaction:function(e,t){const n=dn(e);if(void 0===n)return!1;const o=n.steps.findLastIndex(e=>e.readCursor===t);if(o<0)throw new Error(`CHANNEL 已确认 cursor 不属于乐观事务(channelId=${e.conversation.conversationId}, cursor=${t})`);return n.committedThrough=Math.max(n.committedThrough,o),de(e.conversation.conversationId),n.committedThrough===n.steps.length-1&&ie.delete(e.conversation.conversationId),!0},rollbackChannelReadTransaction:function(e){const t=dn(e);if(void 0===t)return!1;const n=e.conversation,o=n.conversationId,r=oe.get(n),s=t.committedThrough>=0?t.steps[t.committedThrough]:void 0,i=void 0===s?t.baseReadState:void 0;let a=r?.unreadCount??i?.unreadCount??0,c=r?.mentionUnreadCount??i?.mentionUnreadCount??0;for(const e of t.steps.slice(t.committedThrough+1))a+=e.clearedCounts?.unread??0,c+=e.clearedCounts?.mention??0;const d=void 0!==i?.mentionUnreadCount||void 0!==r?.mentionUnreadCount,u={conversationId:o,conversationType:"channel",readCursor:s?.readCursor??i?.readCursor??"",readCursorSortKey:s?.sortKey??i?.readCursorSortKey,unreadCount:a,...d?{mentionUnreadCount:c}:{}};return ie.delete(o),Gt(u),Yt(n),!0},setGroupRestriction:function(e,t,n){const o=mn({conversationType:"group",conversationId:e});if(void 0===o){return void gn({id:e,type:"group",title:"",lastMessagePreview:"",timestamp:0,unreadCount:0,pinned:!1,muted:!1,groupState:t,sendDisabledReason:n})}if(o.groupState===t&&o.sendDisabledReason===n)return;gn({...o,groupState:t,sendDisabledReason:n})},setChannelRestriction:vn,setPinned:function(e,t){const n=te.get(e);if(void 0===n||n.pinned===t)return;const o={...n,pinned:t,topTime:t?Date.now():void 0};te.set(o),ot(o),Et(o)},setMuted:function(e,t){const n=mn(e);if(void 0===n||n.muted===t)return;gn({...n,muted:t})},removeConversation:function(e){pn(e)},removeConversationForMembershipTermination:yn,refreshConversationProfile:function(e,t){_t({conversationType:t,conversationId:e},{force:!0})},readDirectProfile:Lt,beginConversationProfileRead:function(t,n){const o={...t},r=e(o),s=Le,i=!0!==n?.forceRefresh&&(He.has(r)||Oe.has(r))?void 0:et(o);void 0!==i&&!0===n?.forceRefresh&&Oe.set(r,i);const a=()=>{s===Le&&void 0!==i&&Oe.get(r)===i&&Oe.delete(r)};return Object.assign(e=>{try{if(void 0===i||e.id!==o.conversationId||s!==Le)return;Ft(o,e.title,e.avatar??"",void 0,i)}finally{a()}},{finish:a})},recoverChannelFromProfile:function(e){return _t({conversationType:"channel",conversationId:e},{force:!0,allowChannelRecovery:!0})},updateConversationProfile:function(e,t){const n=mn(e);if(void 0===n)return;et(o(n));const r={...n,...void 0!==t.title?{title:t.title}:{},...void 0!==t.avatar?{avatar:t.avatar}:{}};Y(n,r)||gn(r)},getTotalUnread:function(e){return H(te.getAll(),e)},getDraft:function(e){return re.get(xt(e))},saveDraft:async function(t,n){const o=xt(t),r=e(o),s=$t(o,n,0),i=we,a=Ce.get(r)??0;return await Bt(o,async()=>{const e=re.get(o),t=Math.max(Date.now(),(he.get(r)??e?.updatedAt??0)+1),n=$t(o,s,t);if(null!==e&&Dt(e,n))return e;if(void 0!==ye&&await ye.saveDraft(n),i!==we||a!==(Ce.get(r)??0))throw new Error("草稿状态已失效,拒绝过期写入回灌内存");return re.set(n),he.set(r,t),x.emitter.emit({type:"draft:updated",conversation:n.ref,draft:n}),n})},clearDraft:async function(e){await jt(e)},clearDraftIfUnchanged:async function(e,t){return await jt(e,t)},invalidateAndDrainDraftOperations:async function(){for(we+=1;ge.size>0;)await Promise.all([...ge.values()])},clearSession(){vt+=1,Le+=1,we+=1,sn+=1,rn.clear(),_e.clear(),ke.clear(),Oe.clear(),He.clear(),ze.clear(),Q.clear(),te.clear(),ne.clear(),oe.clear(),re.clear(),ge.clear(),he.clear(),Ce.clear(),ie.clear(),ae.clear(),ce+=1,se.clearAll(),le.clear(),ve.clear(),fe.clear(),pe.clear(),it.clear(),Z.clear();for(const e of Te)e.reset()},hydrate:async function(t=()=>!0){if(void 0!==ye&&t()){Re=!0;try{const r=await ye.getMeta(z);if(!t())return;if(null!==r)for(const t of r)if("string"==typeof t)le.add(t);else{const n=y(t);ve.set(e(n.conversation),n)}const s=await ye.getMeta(q);if(!t())return;if(null!==s)for(const e of s)fe.add(e);const i=await ye.getMeta(G);if(!t())return;if(null!==i)for(const[e,t]of i)"string"==typeof e&&"string"==typeof t&&pe.set(e,t);const a=await ye.getMeta(W);if(!t())return;if(null!==a)for(const e of a){const t=Pe(e);Z.set(t,[...Z.get(t)??[],e])}const c=await ye.getMeta(J);if(!t())return;if(Array.isArray(c))for(const e of c){if("object"!=typeof e||null===e)continue;const t=Reflect.get(e,"serialNumber"),n=Reflect.get(e,"status"),o=Reflect.get(e,"occurredTime");"string"!=typeof t||""===t.trim()||0!==n&&1!==n&&2!==n&&3!==n||void 0!==o&&("number"!=typeof o||!Number.isFinite(o)||o<=0)||ee.set(t,{serialNumber:t,status:n,...void 0===o?{}:{occurredTime:o}})}const d=await ye.getPinnedMessages();if(!t())return;for(const e of d){if(!t())return;Ge({conversationType:e.conversationType,conversationId:e.conversationId})||se.set(e)&&x.emitter.emit({type:"pinned-message:updated",conversationId:e.conversationId,conversation:n(e),pinnedMessage:e,reason:"hydrate"})}const u=(await ye.getSessions()).filter(e=>!Ge({conversationType:e.type,conversationId:e.id}));if(!t())return;for(const e of u){if(!t())return;const n=Xt(o(e),[],"preserve",e),r=o(n),s=te.get(r);te.set(n),ne.delete(r),void 0!==s&&Y(s,n)||ot(n)}const l=await ye.getReadStates();if(!t())return;for(const e of l)"channel"===e.conversationType&&de(e.conversationId),oe.set(e);const v=we,f=await ye.getDrafts();if(!t())return;if(v!==we)return;for(const n of f){if(!t())return;if(!Number.isFinite(n.updatedAt)||n.updatedAt<0)throw new Error(`草稿 updatedAt 非法:${n.updatedAt}`);const o=$t(n.ref,n,n.updatedAt);if(Ge(o.ref)){try{if(await ye.deleteDraft(o.ref),!t())return}catch(e){if(!t())return;nt("清理已删会话残留草稿失败",e)}continue}const r=e(o.ref);he.set(r,Math.max(he.get(r)??0,o.updatedAt));const s=re.get(o.ref);null!==s&&s.updatedAt===o.updatedAt&&Dt(s,o)||(re.set(o),x.emitter.emit({type:"draft:updated",conversation:o.ref,draft:o}))}for(const e of u){if(!t())return;const n=o(e),r=await hn(n,t);if(!t())return;const s=[];if(en(r.map(e=>{const t=Zt(A(e));return t!==e&&s.push(t),t}),t),!t())return;if(s.length>0)try{if(await ye.saveMessages(s),!t())return}catch(e){if(!t())return;nt("本地消息修复态落盘失败",e)}if(!t())return;Yt(n)}}catch(e){t()&&nt("本地历史回读失败",e)}finally{Re=!1,t()&&Fe("offline")}}},loadOlderMessages:async function(n,o){if(void 0===ye)return[];try{const r=await ye.getMessages(n,o),s="string"==typeof n?r.filter(Ze):r.filter(o=>e(t(o))===e(n)).filter(Ze),i=Re;let a;Re=!0;try{a=en(s)}finally{Re=i}return Re||Fe("offline"),a.map(e=>Ee(t(e),e.id)??e)}catch(e){return nt("加载更早消息失败",e),[]}},searchMessages:async function(n,o){const r=o.keyword?.trim()??"",s=o.contentTypes;if(""===r&&(void 0===s||0===s.length))return{results:[],exhausted:!0};const i=""===r?void 0:await K(r),a=e=>{const t=void 0===s||s.includes(e.contentType),n=void 0===i||null!==i.match(U(e));return t&&n},c=(e,t)=>e.sortKey<t.sortKey?1:e.sortKey>t.sortKey?-1:0,d=e=>function(e,t){const n=t?.match(U(e));return{message:e,ranges:n?.ranges.map(({start:e,end:t})=>[e,t])??[]}}(e,i);if(void 0===ye)return(()=>{const e=Q.getByConversation(n).filter(a).sort(c),t=(void 0===o.beforeSortKey?e:e.filter(e=>e.sortKey<o.beforeSortKey)).slice(0,o.limit),r=t.length<o.limit;return{results:t.map(d),exhausted:r,...r?{}:{nextBeforeSortKey:t.at(-1)?.sortKey}}})();let u;try{u=await ye.searchMessages(n,{...void 0!==o.keyword?{keyword:o.keyword}:{},...void 0!==s?{contentTypes:s}:{},limit:o.limit,...void 0!==o.beforeSortKey?{beforeSortKey:o.beforeSortKey}:{}})}catch(e){throw nt("会话内搜索失败",e),e}const l=u.exhausted?void 0:u.nextBeforeSortKey,v=new Map(Q.getByConversation(n).map(e=>[e.id,e])),f=/* @__PURE__ */new Map;for(const o of u.items){const r=tn(o);e(t(r))===e(n)&&f.set(r.id,v.get(r.id)??r)}for(const e of v.values()){const t=void 0===o.beforeSortKey||e.sortKey<o.beforeSortKey,n=void 0===l||e.sortKey>=l;t&&n&&a(e)&&f.set(e.id,e)}return{results:[...f.values()].filter(a).sort(c).map(d),exhausted:u.exhausted,...u.exhausted?{}:{nextBeforeSortKey:u.nextBeforeSortKey}}},messageWindow:Se,createMessageWindow:function(e={}){const t=Me(e);let n=!1;return{window:t,dispose(){n||(n=!0,t.reset(),Te.delete(t))}}}}}export{Z as createDomainState,O as defaultConversationUnreadMode,H as sumSessionsUnread};