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 = 62 AppStorage.get<common.UIAbilityContext>(contextName) as common.UIAbilityContext; 63 if (context == null || context === undefined) { 64 Log.info(TAG, 'context is null!'); 65 } else { 66 this.defaultAlbumName = await context.resourceManager.getString(a.id); 67 Log.info(TAG, `The display name is ${this.defaultAlbumName}`); 68 let newAlbumDisplayName = 69 this.getNewAlbumDefaultName(this.defaultAlbumName); 70 Log.info(TAG, `The display name of new album is ${newAlbumDisplayName}`); 71 72 this.menuContext.broadCast.emit(BroadCastConstants.SHOW_NEW_ALBUM_PHOTO_DIALOG, 73 [newAlbumDisplayName, async (displayName: string): Promise<boolean> => 74 await this.confirmCallbackBindImpl(displayName), 75 (): void => this.cancelCallbackBindImpl()]); 76 } 77 } catch (error) { 78 interface Msg2 { 79 type: string 80 errMsg: string 81 } 82 let msg: Msg2 = { 83 type: BigDataConstants.ALBUM_CREATE_ERROR, 84 errMsg: JSON.stringify(error) 85 }; 86 ReportToBigDataUtil.errEventReport(BigDataConstants.ALBUM_OPERATION_ERROR_ID, msg); 87 Log.info(TAG, `The display name error ${error}`); 88 } 89 } 90 91 onCompleted(): void { 92 Log.info(TAG, 'new album data succeed!'); 93 this.onOperationEnd && this.onOperationEnd(); 94 } 95 96 onError(): void { 97 Log.error(TAG, 'new album data failed!'); 98 this.onOperationEnd && this.onOperationEnd(); 99 } 100 101 private async confirmCallback(displayName: string): Promise<boolean> { 102 return await this.confirmCallbackBindImpl(displayName); 103 } 104 105 private async confirmCallbackBindImpl(displayName: string): Promise<boolean> { 106 Log.info(TAG, `AlbumSet new album confirm and the new name is: ${displayName}`); 107 if (displayName) { 108 // 过滤用户相册 109 let targetAlbum: Album = await UserFileManagerAccess.getInstance().getAlbumByName(displayName); 110 // 过滤系统相册 111 let isAlbumNameExistInSystemAlbums: boolean = await UserFileManagerAccess.getInstance() 112 .isAlbumNameExistInSystemAlbums(displayName); 113 if (targetAlbum || isAlbumNameExistInSystemAlbums) { 114 UiUtil.showToast($r('app.string.name_already_use')); 115 return false; 116 } 117 } 118 this.onOperationEnd = this.menuContext.onOperationEnd; 119 let onOperationStart: Function = this.menuContext.onOperationStart; 120 onOperationStart && onOperationStart(); 121 122 let album: Album = await UserFileManagerAccess.getInstance().createUserAlbum(displayName); 123 if (this.menuContext.jumpSourceToMain == JumpSourceToMain.ALBUM) { 124 Log.info(TAG, 'go back to photo grid'); 125 this.menuContext.broadCast.emit(BroadCastConstants.MEDIA_OPERATION, 126 [displayName, album.albumUri, (): void => this.onCompleted()]); 127 } else { 128 router.pushUrl({ 129 url: 'pages/AlbumSelect', 130 params: { 131 albumName: displayName, 132 albumUri: album.albumUri, 133 isNewAlbum: true 134 } 135 }); 136 this.onCompleted(); 137 } 138 return true; 139 } 140 141 private cancelCallback(): void { 142 this.cancelCallbackBindImpl(); 143 } 144 145 private cancelCallbackBindImpl(): void { 146 Log.info(TAG, 'AlbumSet new album cancel'); 147 } 148 149 private checkAndAddNumber(albumInfo: AlbumInfo, prefixName: string, numbers: number[]): void { 150 if (!albumInfo || !albumInfo.albumName) { 151 Log.warn(TAG, 'album is empty'); 152 return; 153 } 154 let res: string[] = albumInfo.albumName.match(new RegExp('^' + prefixName + '[1-9][0-9]*$')) as string[]; 155 Log.info(TAG, `check name res ${res}`) 156 if (res) { 157 let number: string[] = res[0].match(new RegExp('[1-9][0-9]*')) as string[]; 158 if (number != null && number[0] != null) { 159 numbers.push(Number.parseInt(number[0])); 160 } 161 } 162 } 163 164 private getNewAlbumDefaultName(prefixName: string): string { 165 let numbers: number[] = []; 166 for (let i = 0; i < this.menuContext.albumSetDataSource.totalCount(); i++) { 167 this.checkAndAddNumber(this.menuContext.albumSetDataSource.getData(i).data, prefixName, numbers); 168 } 169 let currentAlbum = this.menuContext.albumInfo; 170 if (currentAlbum != null) { 171 this.checkAndAddNumber(currentAlbum, prefixName, numbers); 172 } 173 174 Log.debug(TAG, `${JSON.stringify(numbers)}`); 175 176 if (numbers.length <= 0) { 177 return `${prefixName}1`; 178 } else if (numbers.length == 1) { 179 if (numbers[0] - 1 > 0) { 180 return `${prefixName}1`; 181 } else { 182 return `${prefixName}${numbers[0] + 1}`; 183 } 184 } 185 186 numbers.sort((a: number, b: number) => { 187 return a - b; 188 }); 189 190 if (numbers[0] - 1 > 0) { 191 return `${prefixName}1`; 192 } 193 194 for (let i = 1; i < numbers.length; i++) { 195 let res = numbers[i - 1] + 1; 196 if (res < numbers[i]) { 197 return `${prefixName}${res}`; 198 } 199 } 200 return `${prefixName}${numbers[numbers.length - 1] + 1}`; 201 } 202}