• 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 */
15
16import router from '@system.router';
17import MediaLib from '@ohos.multimedia.mediaLibrary';
18import { Log } from '../utils/Log';
19import { getResourceString } from '../utils/ResourceUtils';
20import { BroadcastConstants } from '../constants/BroadcastConstants';
21import type { MenuOperationCallback } from './MenuOperationCallback';
22import type { MenuOperation } from './MenuOperation';
23import { MenuContext } from './MenuContext';
24import { JumpSourceToMain } from '../data/JumpSourceToMain';
25import { SimpleAlbumDataItem } from '../data/SimpleAlbumDataItem';
26import { getFetchOptionsByItem } from '../helper/MediaDataHelper';
27import { showToast } from '../utils/UiUtil';
28import mediaModel from '../model/MediaModel';
29import { AlbumDataItem } from '../data/AlbumDataItem';
30import { LazyItem } from '../vm/ItemDataSource';
31import { MediaConstants } from '../constants/MediaConstants';
32
33const TAG = "AlbumSetNewMenuOperation"
34
35export class AlbumSetNewMenuOperation implements MenuOperation, MenuOperationCallback {
36    private menuContext: MenuContext;
37    private onOperationEnd: Function;
38
39    constructor(menuContext: MenuContext) {
40        this.menuContext = menuContext;
41    }
42
43    doAction() {
44        if (this.menuContext == null) {
45            Log.warn(TAG, 'menuContext is null, return');
46            return;
47        }
48        getResourceString($r('app.string.album_new_album')).then((name: string) => {
49            Log.info(TAG, `The display name is ${name}`);
50            this.getNewAlbumDisplayName(name).then((newAlbumDisplayName: string) => {
51                Log.info(TAG, `The display name of new album is ${newAlbumDisplayName}`);
52
53                this.confirmCallback = this.confirmCallback.bind(this);
54                this.cancelCallback = this.cancelCallback.bind(this);
55
56                this.menuContext.broadCast.emit(BroadcastConstants.SHOW_NEW_ALBUM_PHOTO_DIALOG,
57                    [newAlbumDisplayName, this.confirmCallback, this.cancelCallback]);
58            })
59        })
60    }
61
62    private async getNewAlbumDisplayName(name: string): Promise<string> {
63        let relativeRoot = await mediaModel.getPublicDirectory(MediaLib.DirectoryType.DIR_CAMERA);
64        return await this.getNewAlbumDefaultName(relativeRoot, name);
65    }
66
67    private async confirmCallback(displayName: string) {
68        Log.info(TAG, `AlbumSet new album confirm and the new name is: ${displayName}`);
69        let relativePath = await mediaModel.getPublicDirectory(MediaLib.DirectoryType.DIR_CAMERA) + displayName + "/";
70        let simpleAlbumDataItem: SimpleAlbumDataItem = new SimpleAlbumDataItem("", displayName, relativePath, "", "");
71        if (displayName != undefined && displayName != null) {
72            let isExit = await this.checkAlbumExit(simpleAlbumDataItem);
73            if (isExit) {
74                getResourceString($r('app.string.name_already_use')).then((message: string) => {
75                    showToast(message);
76                })
77                return;
78            }
79        }
80        this.onOperationEnd = this.menuContext.onOperationEnd;
81        let onOperationStart: Function = this.menuContext.onOperationStart;
82        onOperationStart && onOperationStart();
83
84        if (this.menuContext.jumpSourceToMain == JumpSourceToMain.ALBUM) {
85            Log.info(TAG, 'go back to photo grid');
86            this.menuContext.broadCast.emit(BroadcastConstants.MEDIA_OPERATION, [simpleAlbumDataItem, this.onCompleted.bind(this)]);
87        } else {
88            router.push({
89                uri: 'feature/albumSelect/view/AlbumSelect',
90                params: {
91                    albumInfo: JSON.stringify(simpleAlbumDataItem),
92                    isNewAlbum: true
93                }
94            });
95            this.onCompleted();
96        }
97    }
98
99    private async checkAlbumExit(simpleAlbumDataItem: SimpleAlbumDataItem): Promise<boolean> {
100        let fetchOptions: MediaLib.MediaFetchOptions = await getFetchOptionsByItem(simpleAlbumDataItem);
101        return await mediaModel.getAlbumCount(fetchOptions) > 0;
102    }
103
104    private cancelCallback(): void {
105        Log.info(TAG, 'AlbumSet new album cancel');
106    }
107
108    onCompleted(): void {
109        Log.info(TAG, 'new album data succeed!');
110        this.onOperationEnd && this.onOperationEnd();
111    }
112
113    onError(): void {
114        Log.error(TAG, 'new album data failed!');
115        this.onOperationEnd && this.onOperationEnd();
116    }
117
118    private matchAlbumDefaultName(albumInfo: string, numbers: Array<number>, root: string, prefixName: string) {
119        let res = albumInfo.match(new RegExp(`^${root}${prefixName}[1-9][0-9]*${"/"}$`));
120        if (res != null) {
121            let number = res[0].match(new RegExp(`[1-9][0-9]*`));
122            numbers.push(parseInt(number[0]));
123        }
124    }
125
126    private async getNewAlbumDefaultName(root: string, prefixName: string): Promise<string> {
127        let numbers = [];
128        for (let i = 0; i < this.menuContext.dataSource.totalCount(); i++) {
129            let item = (this.menuContext.dataSource.getData(i) as LazyItem<AlbumDataItem>).get();
130            if (MediaConstants.ALBUM_ID_RECYCLE == item.id) {
131                continue;
132            }
133            this.matchAlbumDefaultName(await item.getRelativePath(), numbers, root, prefixName);
134        }
135        if (this.menuContext.albumInfo) {
136            this.matchAlbumDefaultName(this.menuContext.albumInfo.relativePath, numbers, root, prefixName);
137        }
138        Log.debug(TAG, `${JSON.stringify(numbers)}`);
139
140        if (numbers.length <= 0) {
141            return `${prefixName}1`;
142        } else if (numbers.length == 1) {
143            if (numbers[0] - 1 > 0) {
144                return `${prefixName}1`;
145            } else {
146                return `${prefixName}${numbers[0] + 1}`;
147            }
148        }
149
150        numbers.sort(function (a, b) {
151            return a - b;
152        });
153
154        if (numbers[0] - 1 > 0) {
155            return `${prefixName}1`;
156        }
157
158        for (let i = 1; i < numbers.length; i++) {
159            let res = numbers[i - 1] + 1;
160            if (res < numbers[i]) {
161                return `${prefixName}${res}`;
162            }
163        }
164        return `${prefixName}${numbers[numbers.length - 1] + 1}`;
165    }
166}