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}