1/* 2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 { RouterOptions } from '@system.router'; 18import { Log } from '../utils/Log'; 19import { getResourceString } from '../utils/ResourceUtils'; 20import { BroadcastConstants } from '../constants/BroadcastConstants'; 21import { MenuOperationCallback } from './MenuOperationCallback'; 22import { MenuOperation } from './MenuOperation'; 23import { MenuContext } from './MenuContext'; 24import { JumpSourceToMain } from '../models/JumpSourceToMain'; 25import { SimpleAlbumDataItem } from '../common/SimpleAlbumDataItem'; 26import { showToast } from '../utils/UiUtil'; 27import { userFileModel } from '../base/UserFileModel'; 28import { AlbumDataItem } from '../common/AlbumDataItem'; 29import { LazyItem } from '../common/ItemDataSource'; 30import { MediaConstants } from '../constants/MediaConstants'; 31import { AlbumsDataSource } from '../common/AlbumsDataSource'; 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(): void { 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<void, void>((name: string): void => { 49 Log.info(TAG, 'The display name is ' + name); 50 let newAlbumDisplayName = this.getNewAlbumDefaultName(name); 51 Log.info(TAG, `The display name of new album is ${newAlbumDisplayName}`); 52 this.confirmCallback = (displayName: string): Promise<void> => this.confirmCallbackBindImpl(displayName); 53 this.cancelCallback = (): void => this.cancelCallbackBindImpl(); 54 55 this.menuContext.broadCast.emit(BroadcastConstants.SHOW_NEW_ALBUM_PHOTO_DIALOG, 56 [newAlbumDisplayName, this.confirmCallback, this.cancelCallback]); 57 }) 58 } 59 60 private async confirmCallback(displayName: string): Promise<void> { 61 return await this.confirmCallbackBindImpl(displayName); 62 } 63 64 private async confirmCallbackBindImpl(displayName: string): Promise<void> { 65 Log.info(TAG, 'AlbumSet new album confirm and the new name is: ' + displayName); 66 let simpleAlbumDataItem: SimpleAlbumDataItem = new SimpleAlbumDataItem('', displayName, '', '', '', -1, -1); 67 if (displayName != undefined && displayName != null) { 68 let isExit = await this.checkAlbumExit(simpleAlbumDataItem); 69 if (isExit) { 70 getResourceString($r('app.string.name_already_use')).then<void, void>((message: string): void => { 71 showToast(message); 72 }) 73 return; 74 } 75 } 76 this.onOperationEnd = this.menuContext.onOperationEnd; 77 let onOperationStart: Function = this.menuContext.onOperationStart; 78 if (onOperationStart != null) onOperationStart(); 79 80 if (this.menuContext.jumpSourceToMain === JumpSourceToMain.ALBUM) { 81 Log.info(TAG, 'go back to photo grid'); 82 this.menuContext.broadCast.emit(BroadcastConstants.MEDIA_OPERATION, [simpleAlbumDataItem, (): void => this.onCompletedBindImpl()]); 83 } else { 84 let params: Object = { 85 albumInfo: JSON.stringify(simpleAlbumDataItem), 86 isNewAlbum: true 87 }; 88 let routerOptions: RouterOptions = { 89 uri: 'pages/AlbumSelect', 90 params: params 91 }; 92 router.push(routerOptions); 93 this.onCompleted(); 94 } 95 } 96 97 private async checkAlbumExit(simpleAlbumDataItem: SimpleAlbumDataItem): Promise<boolean> { 98 return await userFileModel.getUserAlbumCountByName(simpleAlbumDataItem.displayName) > 0; 99 } 100 101 private cancelCallback(): void { 102 this.cancelCallbackBindImpl(); 103 } 104 105 private cancelCallbackBindImpl(): void { 106 Log.info(TAG, 'AlbumSet new album cancel'); 107 } 108 109 onCompleted(): void { 110 this.onCompletedBindImpl(); 111 } 112 113 private onCompletedBindImpl(): void { 114 Log.info(TAG, 'new album data succeed!'); 115 if (this.onOperationEnd != null) this.onOperationEnd(); 116 } 117 118 onError(): void { 119 Log.error(TAG, 'new album data failed!'); 120 if (this.onOperationEnd != null) this.onOperationEnd(); 121 } 122 123 private checkAndAddNumber(albumInfo: AlbumDataItem, prefixName: string, numbers: number[]): void { 124 let res = albumInfo.displayName.match(new RegExp('^' + prefixName + '[1-9][0-9]*$')); 125 Log.info(TAG, `check name res ${res}`); 126 if (res) { 127 let number = res[0].match(new RegExp(`[1-9][0-9]*`)); 128 numbers.push(parseInt(number[0])); 129 } 130 } 131 132 private getNewAlbumDefaultName(prefixName: string): string { 133 let numbers: number[] = []; 134 for (let i = 0; i < this.menuContext.dataSource.totalCount(); i++) { 135 let album = this.menuContext.dataSource as AlbumsDataSource; 136 this.checkAndAddNumber(album.getDataByIndex(i), prefixName, numbers); 137 } 138 139 Log.debug(TAG, `${JSON.stringify(numbers)}`); 140 141 if (numbers.length <= 0) { 142 return `${prefixName}1`; 143 } else if (numbers.length === 1) { 144 if (numbers[0] - 1 > 0) { 145 return `${prefixName}1`; 146 } else { 147 return `${prefixName}${numbers[0] + 1}`; 148 } 149 } 150 151 numbers.sort(function (a, b) { 152 return a - b; 153 }); 154 155 if (numbers[0] - 1 > 0) { 156 return `${prefixName}1`; 157 } 158 159 for (let i = 1; i < numbers.length; i++) { 160 let res = numbers[i - 1] + 1; 161 if (res < numbers[i]) { 162 return `${prefixName}${res}`; 163 } 164 } 165 return `${prefixName}${numbers[numbers.length - 1] + 1}`; 166 } 167} 168