• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
15import MediaLib from '@ohos.multimedia.mediaLibrary';
16import type { AsyncCallback } from '../interface/AsyncCallback';
17import { Log } from '../utils/Log';
18import type { MenuOperationCallback } from './MenuOperationCallback';
19import type { MenuOperation } from './MenuOperation';
20import { MenuContext } from './MenuContext';
21import { BroadcastConstants } from '../constants/BroadcastConstants';
22import { startTraceWithTaskId, finishTraceWithTaskId } from '../utils/TraceControllerUtils';
23import { getFetchOptionsByItem } from '../helper/MediaDataHelper';
24import { SimpleAlbumDataItem } from '../data/SimpleAlbumDataItem';
25import mediaModel from '../model/MediaModel';
26
27export enum FindSameOperation {
28    NONE,
29    REPLACE,
30    SKIP
31}
32
33const TAG = "ProcessMenuOperation"
34
35export class ProcessMenuOperation implements MenuOperation, AsyncCallback<String[]>, MenuOperationCallback {
36    // Number of data operated in a batch
37    readonly BATCH_SIZE: number = 1;
38
39    // Maximum progress
40    readonly MAX_PROGRESS: number = 100;
41    items: any[] = [];
42    menuContext: MenuContext;
43    uris: string[];
44    count: number;
45    onOperationEnd: Function;
46
47    // Total batches operated
48    totalBatches: number;
49
50    // Currently operated batch
51    currentBatch: number = 0;
52    successBatch: number = 0;
53    isCancelled: boolean = false;
54    startTime: number;
55    isPause: boolean = false;
56    isError: boolean = false;
57    findSameOperation: number = FindSameOperation.NONE;
58    requestTime: number;
59
60    constructor(menuContext: MenuContext) {
61        this.menuContext = menuContext;
62        this.requestTime = Date.now();
63    }
64
65    doAction(): void {
66    }
67
68    // Asynchronous callback for getSelection
69    callback(uris: string[]): void {
70
71    }
72
73    onCompleted(): void {
74        Log.info(TAG, `onCompleted ${this.isPause}`);
75        this.successBatch++;
76        if (!this.isPause) {
77            this.cyclicOperation();
78        }
79    }
80
81    onError(): void {
82        Log.error(TAG, `Operate the ${this.currentBatch} batch data error, total ${this.totalBatches} batches`);
83        this.isError = true;
84        this.cyclicOperation();
85    }
86
87    // Start processing operation
88    processOperation(): void {
89        Log.info(TAG, 'processOperation start');
90        startTraceWithTaskId('ProgressOperation', this.requestTime);
91        let length = this.items.length;
92        Log.info(TAG, `selected count: ${this.count}, uris's length: ${length}`);
93        // Batch deletion
94        this.totalBatches = Math.floor(length / this.BATCH_SIZE) + ((length % this.BATCH_SIZE) ? 1 : 0);
95        Log.info(TAG, `The count to be operate is ${length}, operate in ${this.totalBatches} batches`);
96        if (this.isCancelled) {
97            this.isCancelled = false;
98        }
99        this.startTime = Date.now();
100
101        this.requestOneBatchOperation()
102    }
103
104    // Batch circular deletion
105    cyclicOperation() {
106        Log.info(TAG, 'cyclicOperation');
107        this.menuContext.broadCast.emit(BroadcastConstants.UPDATE_PROGRESS, [this.getExpectProgress(), this.currentBatch]);
108
109        if (this.isCancelled) {
110            this.onProcessDone();
111        }
112
113        if (this.currentBatch >= this.totalBatches || this.isError) {
114            this.onProcessDone();
115        } else {
116            this.requestOneBatchOperation();
117        }
118    }
119
120    // Operate a batch of data
121    requestOneBatchOperation(): void {
122    }
123
124    onProcessDone(): void {
125        this.menuContext.broadCast.emit(BroadcastConstants.UPDATE_PROGRESS, [100]);
126        this.findSameOperation = FindSameOperation.NONE;
127        if (this.startTime != null) {
128            let operateCount = this.currentBatch >= this.totalBatches ? this.count : this.currentBatch * this.BATCH_SIZE;
129            let costTime = Date.now() - this.startTime;
130            Log.debug(TAG, `process data operate done, operate ${operateCount} items, cost time ${costTime} ms,\
131            average ${(costTime / operateCount)} ms/item.`);
132        }
133        this.isCancelled = false;
134        finishTraceWithTaskId('ProgressOperation', this.requestTime);
135        this.onOperationEnd && this.onOperationEnd(this.isError, this.successBatch, this.count);
136    }
137
138    // Operate cancel callback
139    onOperateCancelled(): void {
140        Log.info(TAG, 'Operate Cancel');
141        this.isCancelled = true;
142        this.onProcessDone();
143    }
144
145    // Operate cancel callback
146    onOperatePause(): void {
147        Log.info(TAG, 'Operate Pause');
148        this.isPause = true;
149    }
150
151    // Calculate the operation progress according to the batch
152    getExpectProgress(): number {
153        Log.info(TAG, 'getExpectProgress');
154        let progress = Math.min(
155        Math.floor(this.MAX_PROGRESS * this.currentBatch * this.BATCH_SIZE / this.count), this.MAX_PROGRESS);
156        return progress;
157    }
158
159    setFindSameOperation(newOperation: number): void {
160        Log.info(TAG, `setFindSameOperation ${newOperation}`);
161        this.findSameOperation = newOperation;
162    }
163
164    async getFileCopyOrMoveInfo(fileAsset: MediaLib.FileAsset, albumInfo: SimpleAlbumDataItem) {
165        Log.debug(TAG, 'getFileCopyOrMoveInfo start');
166        let item: SimpleAlbumDataItem = new SimpleAlbumDataItem("", fileAsset.displayName, albumInfo.relativePath, "", "");
167        let fetchOptions = await getFetchOptionsByItem(item);
168        let targetAsset = (await mediaModel.getAllCommonMediaItem(fetchOptions, false)).fileAsset;
169        if (targetAsset == null || targetAsset == undefined) {
170            Log.debug(TAG, 'targetAsset not found');
171        }
172
173        return { sourceAsset: fileAsset, targetAsset: targetAsset };
174    }
175}