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