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 { Log } from '../../utils/Log'; 17import { BroadCastConstants } from '../../model/common/BroadCastConstants'; 18import { MenuOperationCallback } from './MenuOperationCallback'; 19import { MenuOperation } from './MenuOperation'; 20import { MenuContext, SourceSceneType } from './MenuContext'; 21import { JumpSourceToMain } from '../../model/browser/photo/JumpSourceToMain'; 22import { AlbumInfo } from '../../model/browser/album/AlbumInfo'; 23import router from '@ohos.router'; 24import { UiUtil } from '../../utils/UiUtil'; 25import { AlbumDefine } from '../../model/browser/AlbumDefine'; 26import { BrowserDataFactory } from '../../interface/BrowserDataFactory'; 27import { BigDataConstants, ReportToBigDataUtil } from '../../utils/ReportToBigDataUtil'; 28import { Album, UserFileManagerAccess } from '../../access/UserFileManagerAccess'; 29import common from '@ohos.app.ability.common'; 30 31const TAG: string = 'common_AlbumSetNewMenuOperation'; 32 33export class AlbumSetNewMenuOperation implements MenuOperation, MenuOperationCallback { 34 private menuContext: MenuContext; 35 private defaultAlbumName: string = ''; 36 private onOperationEnd: Function = (): void => {}; 37 38 constructor(menuContext: MenuContext) { 39 this.menuContext = menuContext; 40 } 41 42 async doAction(): Promise<void> { 43 if (this.menuContext == null) { 44 Log.error(TAG, 'menuContext is null, return'); 45 return; 46 } 47 interface Msg1 { 48 type: string 49 } 50 let msg: Msg1 = { 51 type: BigDataConstants.ALBUM_CREATE 52 }; 53 ReportToBigDataUtil.report(BigDataConstants.ALBUM_OPERATION_ID, msg); 54 55 let a = $r('app.string.album_new_album'); 56 Log.info(TAG, `The display name from resource ${JSON.stringify(a)}`); 57 this.defaultAlbumName = ''; 58 try { 59 let contextName: string = this.menuContext.sourceScene === SourceSceneType.BIG_PHOTO_COMPONENT ? 60 'photoLibraryContext' : 'photosAbilityContext'; 61 let context: common.UIAbilityContext = AppStorage.get<common.UIAbilityContext>(contextName) as common.UIAbilityContext; 62 if (context == null || context === undefined) { 63 Log.info(TAG, 'context is null!'); 64 } else { 65 this.defaultAlbumName = await context.resourceManager.getString(a.id); 66 Log.info(TAG, `The display name is ${this.defaultAlbumName}`); 67 let newAlbumDisplayName 68 = this.getNewAlbumDefaultName(this.defaultAlbumName); 69 Log.info(TAG, `The display name of new album is ${newAlbumDisplayName}`); 70 71 this.menuContext.broadCast.emit(BroadCastConstants.SHOW_NEW_ALBUM_PHOTO_DIALOG, 72 [newAlbumDisplayName, async (displayName: string): Promise<boolean> => await this.confirmCallbackBindImpl(displayName), 73 (): void => this.cancelCallbackBindImpl()]); 74 } 75 } catch (error) { 76 interface Msg2 { 77 type: string 78 errMsg: string 79 } 80 let msg: Msg2 = { 81 type: BigDataConstants.ALBUM_CREATE_ERROR, 82 errMsg: JSON.stringify(error) 83 }; 84 ReportToBigDataUtil.errEventReport(BigDataConstants.ALBUM_OPERATION_ERROR_ID, msg); 85 Log.info(TAG, `The display name error ${error}`); 86 } 87 } 88 89 onCompleted(): void { 90 Log.info(TAG, 'new album data succeed!'); 91 this.onOperationEnd && this.onOperationEnd(); 92 } 93 94 onError(): void { 95 Log.error(TAG, 'new album data failed!'); 96 this.onOperationEnd && this.onOperationEnd(); 97 } 98 99 private async confirmCallback(displayName: string): Promise<boolean> { 100 return await this.confirmCallbackBindImpl(displayName); 101 } 102 103 private async confirmCallbackBindImpl(displayName: string): Promise<boolean> { 104 Log.info(TAG, `AlbumSet new album confirm and the new name is: ${displayName}`); 105 if (displayName) { 106 // 过滤用户相册 107 let targetAlbum: Album = await UserFileManagerAccess.getInstance().getAlbumByName(displayName); 108 // 过滤系统相册 109 let isAlbumNameExistInSystemAlbums: boolean = await UserFileManagerAccess.getInstance() 110 .isAlbumNameExistInSystemAlbums(displayName); 111 if (targetAlbum || isAlbumNameExistInSystemAlbums) { 112 UiUtil.showToast($r('app.string.name_already_use')); 113 return false; 114 } 115 } 116 this.onOperationEnd = this.menuContext.onOperationEnd; 117 let onOperationStart: Function = this.menuContext.onOperationStart; 118 onOperationStart && onOperationStart(); 119 120 let album: Album = await UserFileManagerAccess.getInstance().createUserAlbum(displayName); 121 if (this.menuContext.jumpSourceToMain == JumpSourceToMain.ALBUM) { 122 Log.info(TAG, 'go back to photo grid'); 123 this.menuContext.broadCast.emit(BroadCastConstants.MEDIA_OPERATION, 124 [displayName, album.albumUri, (): void => this.onCompleted()]); 125 } else { 126 router.pushUrl({ 127 url: 'pages/AlbumSelect', 128 params: { 129 albumName: displayName, 130 albumUri: album.albumUri, 131 isNewAlbum: true 132 } 133 }); 134 this.onCompleted(); 135 } 136 return true; 137 } 138 139 private cancelCallback(): void { 140 this.cancelCallbackBindImpl(); 141 } 142 143 private cancelCallbackBindImpl(): void { 144 Log.info(TAG, 'AlbumSet new album cancel'); 145 } 146 147 private checkAndAddNumber(albumInfo: AlbumInfo, prefixName: string, numbers: number[]): void { 148 if (!albumInfo || !albumInfo.albumName) { 149 Log.warn(TAG, 'album is empty'); 150 return; 151 } 152 let res: string[] = albumInfo.albumName.match(new RegExp('^' + prefixName + '[1-9][0-9]*$')) as string[]; 153 Log.info(TAG, `check name res ${res}`) 154 if (res) { 155 let number: string[] = res[0].match(new RegExp('[1-9][0-9]*')) as string[]; 156 if (number != null && number[0] != null) { 157 numbers.push(Number.parseInt(number[0])); 158 } 159 } 160 } 161 162 private getNewAlbumDefaultName(prefixName: string): string { 163 let numbers: number[] = []; 164 for (let i = 0; i < this.menuContext.albumSetDataSource.totalCount(); i++) { 165 this.checkAndAddNumber(this.menuContext.albumSetDataSource.getData(i).data, prefixName, numbers); 166 } 167 let currentAlbum = this.menuContext.albumInfo; 168 if (currentAlbum != null) { 169 this.checkAndAddNumber(currentAlbum, prefixName, numbers); 170 } 171 172 Log.debug(TAG, `${JSON.stringify(numbers)}`); 173 174 if (numbers.length <= 0) { 175 return `${prefixName}1`; 176 } else if (numbers.length == 1) { 177 if (numbers[0] - 1 > 0) { 178 return `${prefixName}1`; 179 } else { 180 return `${prefixName}${numbers[0] + 1}`; 181 } 182 } 183 184 numbers.sort((a: number, b: number) => { 185 return a - b; 186 }); 187 188 if (numbers[0] - 1 > 0) { 189 return `${prefixName}1`; 190 } 191 192 for (let i = 1; i < numbers.length; i++) { 193 let res = numbers[i - 1] + 1; 194 if (res < numbers[i]) { 195 return `${prefixName}${res}`; 196 } 197 } 198 return `${prefixName}${numbers[numbers.length - 1] + 1}`; 199 } 200}