66import type { IHistoryAPI } from '@/api/history' ;
77import { RecordNotFoundError } from '@/errors' ;
88import { HistoryStorage } from '../../storage/HistoryStorage' ;
9- import { HistorySyncStatus } from '@/types/clipboard' ;
9+ import { HistorySyncStatus , type ClipboardContent } from '@/types/clipboard' ;
1010import { getHistoryFileDir } from '@/utils/fileStorage' ;
11+ import { historyItemToContent } from '@/utils/clipboard/convert' ;
1112import { File } from 'expo-file-system' ;
1213
1314export type TransferType = 'upload' | 'download' ;
@@ -35,6 +36,7 @@ export interface TransferTask {
3536 isImmediateTask : boolean ;
3637 abortController : AbortController ;
3738 userCancelled ?: boolean ;
39+ awaiter : Promise < ClipboardContent > ;
3840}
3941
4042export interface TransferQueueConfig {
@@ -60,6 +62,10 @@ export class HistoryTransferQueue {
6062 private pendingTasks : TransferTask [ ] = [ ] ;
6163 private activeTasks : Map < string , TransferTask > = new Map ( ) ;
6264 private taskStatusCallbacks : Set < TaskStatusChangedCallback > = new Set ( ) ;
65+ private taskCompletionResolvers : Map <
66+ string ,
67+ { resolve : ( content : ClipboardContent ) => void ; reject : ( error : Error ) => void }
68+ > = new Map ( ) ;
6369
6470 private config : TransferQueueConfig ;
6571 private isRunning = false ;
@@ -167,6 +173,14 @@ export class HistoryTransferQueue {
167173 const item = parsed ? await this . historyStorage . getItem ( parsed . hash ) : null ;
168174 const displayName = item ?. text || profileId ;
169175
176+ const key = this . getTaskKey ( profileId , 'download' ) ;
177+ let resolveAwaiter : ( content : ClipboardContent ) => void ;
178+ let rejectAwaiter : ( error : Error ) => void ;
179+ const awaiter = new Promise < ClipboardContent > ( ( resolve , reject ) => {
180+ resolveAwaiter = resolve ;
181+ rejectAwaiter = reject ;
182+ } ) ;
183+
170184 const task : TransferTask = {
171185 profileId,
172186 displayName,
@@ -178,8 +192,10 @@ export class HistoryTransferQueue {
178192 failureCount : 0 ,
179193 isImmediateTask : isImmediate ,
180194 abortController : new AbortController ( ) ,
195+ awaiter,
181196 } ;
182197
198+ this . taskCompletionResolvers . set ( key , { resolve : resolveAwaiter ! , reject : rejectAwaiter ! } ) ;
183199 this . pendingTasks . push ( task ) ;
184200 this . notifyStatusChanged ( task ) ;
185201 this . signalQueue ( ) ;
@@ -205,6 +221,14 @@ export class HistoryTransferQueue {
205221 const item = parsed ? await this . historyStorage . getItem ( parsed . hash ) : null ;
206222 const displayName = item ?. text || profileId ;
207223
224+ const key = this . getTaskKey ( profileId , 'upload' ) ;
225+ let resolveAwaiter : ( content : ClipboardContent ) => void ;
226+ let rejectAwaiter : ( error : Error ) => void ;
227+ const awaiter = new Promise < ClipboardContent > ( ( resolve , reject ) => {
228+ resolveAwaiter = resolve ;
229+ rejectAwaiter = reject ;
230+ } ) ;
231+
208232 const task : TransferTask = {
209233 profileId,
210234 displayName,
@@ -216,8 +240,10 @@ export class HistoryTransferQueue {
216240 failureCount : 0 ,
217241 isImmediateTask : isImmediate ,
218242 abortController : new AbortController ( ) ,
243+ awaiter,
219244 } ;
220245
246+ this . taskCompletionResolvers . set ( key , { resolve : resolveAwaiter ! , reject : rejectAwaiter ! } ) ;
221247 this . pendingTasks . push ( task ) ;
222248 this . notifyStatusChanged ( task ) ;
223249 this . signalQueue ( ) ;
@@ -345,7 +371,6 @@ export class HistoryTransferQueue {
345371 * 执行任务
346372 */
347373 private async executeTask ( task : TransferTask ) : Promise < void > {
348- // 用户取消的任务不执行
349374 if ( task . userCancelled || task . status === 'cancelled' ) {
350375 console . log ( `[HistoryTransferQueue] Task was cancelled, skipping: ${ task . profileId } ` ) ;
351376 return ;
@@ -355,11 +380,13 @@ export class HistoryTransferQueue {
355380 task . startedTime = Date . now ( ) ;
356381 this . notifyStatusChanged ( task ) ;
357382
383+ let resultContent : ClipboardContent | undefined ;
384+
358385 try {
359386 if ( task . type === 'download' ) {
360- await this . executeDownloadTask ( task ) ;
387+ resultContent = await this . executeDownloadTask ( task ) ;
361388 } else {
362- await this . executeUploadTask ( task ) ;
389+ resultContent = await this . executeUploadTask ( task ) ;
363390 }
364391
365392 task . status = 'completed' ;
@@ -383,7 +410,6 @@ export class HistoryTransferQueue {
383410 error
384411 ) ;
385412
386- // 检查是否需要重试
387413 if (
388414 task . failureCount < this . config . maxConsecutiveFailures &&
389415 this . consecutiveFailures < this . config . maxConsecutiveFailures
@@ -403,13 +429,25 @@ export class HistoryTransferQueue {
403429 this . notifyStatusChanged ( task ) ;
404430 const key = this . getTaskKey ( task . profileId , task . type ) ;
405431 this . activeTasks . delete ( key ) ;
432+
433+ const resolver = this . taskCompletionResolvers . get ( key ) ;
434+ if ( resolver ) {
435+ this . taskCompletionResolvers . delete ( key ) ;
436+ if ( task . status === 'completed' && resultContent ) {
437+ resolver . resolve ( resultContent ) ;
438+ } else if ( task . status === 'failed' ) {
439+ resolver . reject ( new Error ( task . errorMessage || 'Task failed' ) ) ;
440+ } else {
441+ resolver . reject ( new Error ( `Task ${ task . status } ` ) ) ;
442+ }
443+ }
406444 }
407445 }
408446
409447 /**
410448 * 执行下载任务
411449 */
412- private async executeDownloadTask ( task : TransferTask ) : Promise < void > {
450+ private async executeDownloadTask ( task : TransferTask ) : Promise < ClipboardContent > {
413451 if ( ! this . historyAPI ) {
414452 throw new Error ( 'History API not initialized' ) ;
415453 }
@@ -472,11 +510,14 @@ export class HistoryTransferQueue {
472510 await this . historyStorage . updateItem ( parsed . hash , {
473511 fileUri : destinationUri ,
474512 isLocalFileReady : true ,
475- // dataName: item.dataName,
476- // text: item.text,
477513 } ) ;
478514
479515 console . log ( `[HistoryTransferQueue] Download task completed: ${ task . profileId } ` ) ;
516+
517+ return {
518+ ...historyItemToContent ( item ) ,
519+ fileUri : destinationUri ,
520+ } ;
480521 }
481522
482523 /**
@@ -486,7 +527,7 @@ export class HistoryTransferQueue {
486527 * 2. 如果存在,直接标记为已同步
487528 * 3. 如果不存在,执行上传
488529 */
489- private async executeUploadTask ( task : TransferTask ) : Promise < void > {
530+ private async executeUploadTask ( task : TransferTask ) : Promise < ClipboardContent > {
490531 if ( ! this . historyAPI ) {
491532 throw new Error ( 'History API not initialized' ) ;
492533 }
@@ -525,7 +566,7 @@ export class HistoryTransferQueue {
525566 console . log (
526567 `[HistoryTransferQueue] Record already exists on server: ${ task . profileId } , marked as synced`
527568 ) ;
528- return ;
569+ return historyItemToContent ( item ) ;
529570 }
530571 } catch ( error ) {
531572 // 如果是 404 错误,继续执行上传
@@ -543,7 +584,7 @@ export class HistoryTransferQueue {
543584 throw new Error ( `No file to upload: ${ task . profileId } ` ) ;
544585 }
545586
546- const { historyItemToDto } = await import ( '@/utils/clipboard/dtoConvert ' ) ;
587+ const { historyItemToDto } = await import ( '@/utils/clipboard/convert ' ) ;
547588 const dto = historyItemToDto ( item ) ;
548589
549590 await this . historyAPI . uploadRecord ( dto , item . fileUri , task . abortController . signal , ( info ) => {
@@ -558,6 +599,8 @@ export class HistoryTransferQueue {
558599 } ) ;
559600
560601 await this . historyStorage . updateSyncStatus ( parsed . hash , HistorySyncStatus . Synced ) ;
602+
603+ return historyItemToContent ( item ) ;
561604 }
562605
563606 /**
0 commit comments