1/* 2 * Copyright (c) 2022 Huawei Device 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 MediaLib from '@ohos.multimedia.mediaLibrary'; 17import { MediaConstants } from '../constants/MediaConstants'; 18import { Log } from '../utils/Log'; 19import { MenuContext } from './MenuContext'; 20import { ProcessMenuOperation, FindSameOperation } from './ProcessMenuOperation'; 21import { BroadcastConstants } from '../constants/BroadcastConstants'; 22import mediaModel from '../model/MediaModel'; 23import { MediaOperationType } from '../data/MediaOperationType'; 24import { startTraceWithTaskId, finishTraceWithTaskId } from '../utils/TraceControllerUtils'; 25import { ItemDataSource } from '../vm/ItemDataSource'; 26import { MediaDataItem } from '../data/MediaDataItem'; 27import { SimpleAlbumDataItem } from '../data/SimpleAlbumDataItem'; 28 29const TAG = "CopyMenuOperation" 30 31export class CopyMenuOperation extends ProcessMenuOperation { 32 private albumInfo: SimpleAlbumDataItem; 33 34 constructor(menuContext: MenuContext) { 35 super(menuContext); 36 this.albumInfo = menuContext.albumInfo; 37 } 38 39 doAction(): void { 40 Log.info(TAG, 'copy doAction'); 41 if (this.menuContext == null) { 42 Log.warn(TAG, 'menuContext is null, return'); 43 return; 44 } 45 46 let dataSource: ItemDataSource = this.menuContext.dataSource; 47 if (dataSource == null) { 48 this.count = this.menuContext.items.length; 49 } else { 50 this.count = dataSource.getSelectedCount(); 51 } 52 if (this.count <= 0) { 53 Log.warn(TAG, 'count <= 0, return'); 54 return; 55 } 56 57 this.onOperationEnd = this.menuContext.onOperationEnd; 58 let onOperationStart = this.menuContext.onOperationStart; 59 60 onOperationStart && onOperationStart(); 61 62 if (this.menuContext.deviceId) { 63 this.menuContext.broadCast.emit(BroadcastConstants.SHOW_PROGRESS_DIALOG, 64 [$r('app.string.download_progress_message'), 65 MediaOperationType.Copy, this.cancelFunc.bind(this)]); 66 } else { 67 this.menuContext.broadCast.emit(BroadcastConstants.SHOW_PROGRESS_DIALOG, 68 [$r('app.string.copy_progress_message', this.albumInfo.displayName), 69 MediaOperationType.Copy, this.cancelFunc.bind(this)]); 70 } 71 72 if (dataSource == null) { 73 this.items = this.menuContext.items; 74 } else { 75 this.items = dataSource.getSelectedItems(); 76 } 77 this.processOperation(); 78 } 79 80 requestOneBatchOperation() { 81 let item = this.items[this.currentBatch++] as MediaDataItem; 82 this.copyOne(item); 83 } 84 85 private async copyOne(item: MediaDataItem) { 86 if (this.menuContext.deviceId) { 87 let path = await mediaModel.getPublicDirectory(MediaLib.DirectoryType.DIR_CAMERA) + MediaConstants.REMOTE_ALBUM_PATH + "/"; 88 this.albumInfo = new SimpleAlbumDataItem("", "", path, "", ""); 89 90 } 91 let fileAsset = await item.loadFileAsset(); 92 let assets = await this.getFileCopyOrMoveInfo(fileAsset, this.albumInfo); 93 if (this.menuContext.deviceId) { 94 let displayName = assets.sourceAsset.displayName; 95 let index = displayName.lastIndexOf('.'); 96 let start = displayName.lastIndexOf('_'); 97 displayName = `${displayName.slice(0, start)}_${new Date().getTime()}${displayName.slice(index)}`; 98 this.copy(assets.sourceAsset, null, { 99 mediaType: assets.sourceAsset.mediaType, 100 name: displayName, 101 path: this.albumInfo.relativePath 102 }); 103 return; 104 } 105 if (assets.targetAsset) { 106 if (assets.targetAsset.uri == assets.sourceAsset.uri) { 107 Log.info(TAG, 'copy same fileAsset'); 108 this.onOperateContinue(); 109 return; 110 } 111 Log.info(TAG, 'show find same file dialog'); 112 switch (this.findSameOperation) { 113 case FindSameOperation.NONE: 114 this.menuContext.broadCast.emit(BroadcastConstants.FIND_SAME_FILE_DIALOG, 115 [assets, this.count, () => { 116 this.copy(assets.sourceAsset, assets.targetAsset); 117 }, this.onOperateContinue.bind(this), this.onOperateCancelled.bind(this), 118 this.setFindSameOperation.bind(this)]); 119 break; 120 case FindSameOperation.REPLACE: 121 this.copy(assets.sourceAsset, assets.targetAsset); 122 break; 123 case FindSameOperation.SKIP: 124 this.onOperateContinue(); 125 break; 126 default: 127 Log.warn(TAG, `findSameOperation is error ${this.findSameOperation}`); 128 break; 129 } 130 } else { 131 this.copy(assets.sourceAsset, null, { 132 mediaType: assets.sourceAsset.mediaType, 133 name: assets.sourceAsset.displayName, 134 path: this.albumInfo.relativePath 135 }); 136 } 137 } 138 139 async copy(source, target, param?) { 140 try { 141 if (!target) { 142 startTraceWithTaskId('create', this.currentBatch); 143 target = await mediaModel.createOne(param.mediaType, param.name, param.path); 144 finishTraceWithTaskId('create', this.currentBatch); 145 if (target == null) { 146 Log.warn(TAG, `Target file creat failed when copyFile!`); 147 this.onError(); 148 return; 149 } 150 } 151 startTraceWithTaskId('openWriteClose', this.currentBatch); 152 await mediaModel.copyOne(source, target); 153 finishTraceWithTaskId('openWriteClose', this.currentBatch); 154 this.onCompleted(); 155 } catch (error) { 156 finishTraceWithTaskId('create', this.currentBatch); 157 Log.error(TAG, `copyFile is error ${error}`); 158 this.onError(); 159 } 160 } 161 162 cancelFunc(): void { 163 Log.info(TAG, `progress cancel`); 164 this.onOperatePause(); 165 let cancelMessage = $r('app.string.copy_cancel_message', this.getExpectProgress().toString()); 166 167 if (this.menuContext.deviceId) { 168 this.menuContext.broadCast && this.menuContext.broadCast.emit(BroadcastConstants.DOWNLOAD_CANCEL_OPERATE, 169 [cancelMessage, this.onOperateContinue.bind(this), this.onOperateCancelled.bind(this)]); 170 } else { 171 this.menuContext.broadCast && this.menuContext.broadCast.emit(BroadcastConstants.CANCEL_OPERATE, 172 [cancelMessage, this.onOperateContinue.bind(this), this.onOperateCancelled.bind(this)]); 173 } 174 } 175 176 // Copy cancel callback 177 onOperateContinue(): void { 178 Log.info(TAG, 'Operate Continue'); 179 this.isPause = false; 180 this.cyclicOperation(); 181 } 182}