1/* 2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import photoAccessHelper from '@ohos.file.photoAccessHelper'; 17import { AsyncCallback } from './AsyncCallback'; 18import { Log } from '../utils/Log'; 19import { MenuOperationCallback } from './MenuOperationCallback'; 20import { MenuOperation } from './MenuOperation'; 21import { MenuContext } from './MenuContext'; 22import { BroadcastConstants } from '../constants/BroadcastConstants'; 23import { SimpleAlbumDataItem } from '../common/SimpleAlbumDataItem'; 24import { userFileModel } from '../base/UserFileModel'; 25 26export enum FindSameOperation { 27 NONE, 28 REPLACE, 29 SKIP 30} 31 32export interface Assets { 33 sourceAsset: photoAccessHelper.PhotoAsset, 34 targetAsset: photoAccessHelper.PhotoAsset 35} 36 37const TAG = 'ProcessMenuOperation'; 38 39export class ProcessMenuOperation implements MenuOperation, AsyncCallback<String[]>, MenuOperationCallback { 40 // Number of data operated in a batch 41 readonly BATCH_SIZE: number = 1; 42 43 // Maximum progress 44 readonly MAX_PROGRESS: number = 100; 45 items: Object[] = []; 46 menuContext: MenuContext; 47 uris: string[]; 48 count: number; 49 onOperationEnd: Function; 50 51 // Total batches operated 52 totalBatches: number; 53 54 // Currently operated batch 55 currentBatch: number = 0; 56 successBatch: number = 0; 57 isCancelled: boolean = false; 58 startTime: number; 59 isPause: boolean = false; 60 isError: boolean = false; 61 findSameOperation: number = FindSameOperation.NONE; 62 requestTime: number; 63 64 constructor(menuContext: MenuContext) { 65 this.menuContext = menuContext; 66 this.requestTime = Date.now(); 67 } 68 69 doAction(): void { 70 } 71 72 // Asynchronous callback for getSelection 73 callback(uris: string[]): void { 74 this.callbackBindImpl(uris); 75 } 76 77 protected callbackBindImpl(uris: string[]): void { 78 } 79 80 onCompleted(): void { 81 Log.info(TAG, 'onCompleted ' + this.isPause); 82 this.successBatch++; 83 if (!this.isPause) { 84 this.cyclicOperation(); 85 } 86 } 87 88 onError(): void { 89 Log.error(TAG, 'Operate the ' + this.currentBatch + ' batch data error, total ' + this.totalBatches + ' batches'); 90 this.isError = true; 91 this.cyclicOperation(); 92 } 93 94 // Start processing operation 95 processOperation(): void { 96 Log.info(TAG, 'processOperation start'); 97 let length = this.items.length; 98 Log.info(TAG, 'selected count: ' + this.count + ', uris length: ' + length); 99 // Batch deletion 100 this.totalBatches = Math.floor(length / this.BATCH_SIZE) + (((length % this.BATCH_SIZE) ? 1 : 0) as number); 101 Log.info(TAG, 'The count to be operate is ' + length + ', operate in ' + this.totalBatches + ' batches'); 102 if (this.isCancelled) { 103 this.isCancelled = false; 104 } 105 this.startTime = Date.now(); 106 107 this.requestOneBatchOperation(); 108 } 109 110 // Batch circular deletion 111 cyclicOperation(): void { 112 Log.info(TAG, 'cyclicOperation'); 113 this.menuContext.broadCast.emit(BroadcastConstants.UPDATE_PROGRESS, [this.getExpectProgress(), this.currentBatch]); 114 115 if (this.isCancelled) { 116 this.onProcessDone(); 117 } 118 119 if (this.currentBatch >= this.totalBatches || this.isError) { 120 this.onProcessDone(); 121 } else { 122 this.requestOneBatchOperation(); 123 } 124 } 125 126 // Operate a batch of data 127 requestOneBatchOperation(): void { 128 } 129 130 onProcessDone(): void { 131 this.menuContext.broadCast.emit(BroadcastConstants.UPDATE_PROGRESS, [100]); 132 this.findSameOperation = FindSameOperation.NONE; 133 if (this.startTime != null) { 134 let operateCount = this.currentBatch >= this.totalBatches ? this.count : this.currentBatch * this.BATCH_SIZE; 135 let costTime = Date.now() - this.startTime; 136 Log.debug(TAG, 'process data operate done, operate ' + operateCount + ' items, cost time ' + costTime + 137 ' ms, average ' + (costTime / operateCount) + ' ms/item.'); 138 } 139 this.isCancelled = false; 140 if (this.onOperationEnd != null) this.onOperationEnd(this.isError, this.successBatch, this.count); 141 } 142 143 // Operate cancel callback 144 onOperateCancelled(): void { 145 this.onOperateCancelledBindImpl(); 146 } 147 148 protected onOperateCancelledBindImpl(): void { 149 Log.info(TAG, 'Operate Cancel'); 150 this.isCancelled = true; 151 this.onProcessDone(); 152 } 153 154 // Operate cancel callback 155 onOperatePause(): void { 156 Log.info(TAG, 'Operate Pause'); 157 this.isPause = true; 158 } 159 160 // Calculate the operation progress according to the batch 161 getExpectProgress(): number { 162 Log.info(TAG, 'getExpectProgress'); 163 let progress = Math.min( 164 Math.floor(this.MAX_PROGRESS * this.currentBatch * this.BATCH_SIZE / this.count), this.MAX_PROGRESS); 165 return progress; 166 } 167 168 setFindSameOperation(newOperation: number): void { 169 this.setFindSameOperationBindImpl(newOperation); 170 } 171 172 protected setFindSameOperationBindImpl(newOperation: number): void { 173 Log.info(TAG, 'setFindSameOperation ' + newOperation); 174 this.findSameOperation = newOperation; 175 } 176} 177