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 { AlbumDefine } from '../AlbumDefine'; 17import { AlbumInfo } from './AlbumInfo'; 18import type { AsyncCallback } from '../../common/AsyncCallback'; 19import { BrowserDataImpl } from '../BrowserDataImpl'; 20import type { Album, FetchOptions } from '../../../access/UserFileManagerAccess'; 21import { UserFileManagerAccess } from '../../../access/UserFileManagerAccess'; 22import { Log } from '../../../utils/Log'; 23import { Constants } from '../../common/Constants'; 24import { MediaItem } from '../photo/MediaItem'; 25import { ImageUtil } from '../../../utils/ImageUtil'; 26 27const TAG: string = 'common_AlbumDataImpl'; 28 29type AlbumInfoEx = { 30 relativePath?: string 31}; 32 33type QueryAlbumParam = { 34 filterMediaType?: string; 35 uris?: string[] 36}; 37 38export type InitAlbumParam = { 39 deviceId?: string, 40 deviceName?: string, 41 moreInfo?: boolean 42}; 43 44export type AlbumSimpleInfo = { 45 uris: string[], 46 count: number, 47 videoCount: number, 48}; 49 50export class AlbumDataImpl extends BrowserDataImpl { 51 private moreInfo: boolean = false; 52 53 constructor(param: InitAlbumParam) { 54 super(); 55 56 if (param && param.moreInfo) { 57 this.moreInfo = param.moreInfo 58 } 59 } 60 61 getDataByUri(uri: unknown) { 62 } 63 64 getData(callback: AsyncCallback<unknown>, param: QueryAlbumParam): void { 65 Log.info(TAG, 'load data getData start : ' + param); 66 if (param == null) { 67 this.buildAlbums(callback); 68 } else if (param?.filterMediaType != undefined) { 69 this.buildAlbums(callback, param.filterMediaType); 70 } else { 71 // 删除相册时,计算图片视频数量 72 this.genAlbumsInfo(callback, param.uris); 73 } 74 } 75 76 async getDataByName(name: string, albumUri?: string): Promise<Album> { 77 let albums = await UserFileManagerAccess.getInstance().getUserAlbums(AlbumDefine.getAlbumFetchOptByName(name)); 78 if (albums && albums.length > 0) { 79 let opt: FetchOptions = AlbumDefine.getFileFetchOpt(); 80 let fileResult = await albums[0].getPhotoAssets(opt); 81 if (fileResult == null || fileResult == undefined) { 82 Log.warn(TAG, `not valid fileResult`); 83 return null; 84 } 85 let count = fileResult.getCount(); 86 fileResult.close(); 87 if (count <= 0) { 88 Log.warn(TAG, `Not valid album Name: ${albums[0].albumName}, URI: ${albums[0].albumUri}`); 89 return null; 90 } 91 return albums[0]; 92 } else { 93 return null; 94 } 95 } 96 97 getDataCount(callback: AsyncCallback<unknown>, albumInfo: AlbumInfo): void { 98 } 99 100 getDataIndexByUri(callback: AsyncCallback<unknown>, param: QueryAlbumParam, uri: string): void { 101 } 102 103 getDataIndexById(callback: AsyncCallback<unknown>, param: QueryAlbumParam, id: number): void { 104 } 105 106 private async genAlbumsInfo(cb: AsyncCallback<AlbumSimpleInfo>, uris: string[]): Promise<void> { 107 Log.info(TAG, `genAlbumsInfo uris: ${JSON.stringify(uris)}`); 108 Log.info(TAG, 'load data genAlbumsInfo start'); 109 110 let res = { 111 uris: [], 112 count: 0, 113 videoCount: 0, 114 }; 115 116 for (let uri of uris) { 117 let objects = await super.getItems(uri, Constants.INVALID, Constants.INVALID); 118 Log.info(TAG, `get album objects: uri: ${uri} length: ${objects.length}`); 119 120 res.count += objects.length; 121 for (let item of objects) { 122 if (item.fileType === UserFileManagerAccess.MEDIA_TYPE_VIDEO) { 123 res.videoCount++; 124 } 125 res.uris.push(item.uri); 126 } 127 } 128 129 Log.info(TAG, `genAlbumsInfo done`); 130 cb.callback(res); 131 } 132 133 private async buildAlbums(callback: AsyncCallback<AlbumInfo[]>, filterMediaType?: string) { 134 Log.debug(TAG, `buildAlbums`); 135 let sourceData = new Array<AlbumInfo>(); 136 await this.getSystemAlbumsInfo(sourceData, filterMediaType); 137 await this.getUserAlbumsInfo(sourceData, filterMediaType); 138 await this.getTrashAlbumInfo(sourceData, filterMediaType); 139 callback.callback(sourceData); 140 } 141 142 private async getUserAlbumsInfo(albumArray: Array<AlbumInfo>, filterMediaType?: string): Promise<void> { 143 Log.info(TAG, 'getUserAlbumsInfo start'); 144 let albums: Album[] = await UserFileManagerAccess.getInstance().getUserAlbums(); 145 if (!albums) { 146 Log.error(TAG, 'getUserAlbumsInfo, albums undefined'); 147 } 148 Log.info(TAG, `getUserAlbumsInfo fetch albums length : ${albums.length}`); 149 try { 150 for (let album of albums) { 151 let albumInfo: AlbumInfo = new AlbumInfo(album); 152 let albumName: string = await UserFileManagerAccess.getInstance().getAlbumName(album); 153 albumInfo.setAlbumName(albumName); 154 albumInfo.setFilterMediaType(filterMediaType as string); 155 let count = albumInfo.count; 156 albumInfo.setCount(count); // Waiting: album.count不为0时,在构造函数里直接获取 157 let videoCount = 0; 158 if (count > 0) { 159 // 没有相册,设置为第一张 160 let hasCoverUri: Boolean = false; 161 if (album.coverUri) { 162 await UserFileManagerAccess.getInstance().getFirstObject(AlbumDefine.getFileFetchOptByUri(album.coverUri)).then((obj) => { 163 if (obj && obj.obj) { 164 let mediaItem = new MediaItem(obj.obj); 165 mediaItem.setThumbnail(this.getThumbnailSafe(obj.obj.uri, String(obj.obj.get(Constants.KEY_FILE_DATA)))); 166 albumInfo.setMediaItem(mediaItem); 167 albumInfo.setCoverUri(ImageUtil.calcThumbnail(obj.obj.uri, mediaItem.height, mediaItem.width)); 168 hasCoverUri = true; 169 } 170 }); 171 } 172 if (!hasCoverUri) { 173 await UserFileManagerAccess.getInstance().getAlbumFirstObject(album).then((obj) => { 174 if (obj) { 175 let mediaItem = new MediaItem(obj); 176 mediaItem.setThumbnail(this.getThumbnailSafe(obj.uri, String(obj.get(Constants.KEY_FILE_DATA)))); 177 albumInfo.setMediaItem(mediaItem); 178 albumInfo.setCoverUri(ImageUtil.calcThumbnail(obj.uri, mediaItem.height, mediaItem.width)); 179 } 180 }); 181 } 182 // 相册的视频数量 183 videoCount = await this.getItemsCountOfAlbum(album, AlbumDefine.FILTER_MEDIA_TYPE_VIDEO); 184 } 185 albumInfo.setVideoCount(videoCount); 186 albumArray.push(albumInfo); 187 Log.info(TAG, `getUserAlbumsInfo done, albumInfo : ${JSON.stringify(albumInfo)}, albumArray length: ${albumArray.length}`); 188 } 189 } catch (error) { 190 Log.error(TAG, `getUserAlbumsInfo error occured: ${error}`); 191 } 192 Log.info(TAG, 'getUserAlbumsInfo done'); 193 } 194 195 private async getSystemAlbumsInfo(albumArray: Array<AlbumInfo>, filterMediaType?: string): Promise<void> { 196 Log.debug(TAG, 'getSystemAlbumsInfo'); 197 198 let albums: Album[] = await UserFileManagerAccess.getInstance().getSystemAlbums(); 199 Log.debug(TAG, `getSystemAlbumsInfo albums is : ${albums}`); 200 201 if (albums) { 202 for (let album of albums) { 203 Log.info(TAG, `album ${JSON.stringify(album)}`) 204 let albumInfo: AlbumInfo = new AlbumInfo(album); 205 let count = await this.getItemsCount(album.albumUri); 206 // 系统相册为空时不展示 207 if (count === 0) { 208 continue; 209 } 210 albumInfo.setCount(count); // TODO album.count不为0时,在构造函数里直接获取 211 // 相册的视频数量 212 let videoCount = await this.getItemsCount(album.albumUri, AlbumDefine.FILTER_MEDIA_TYPE_VIDEO); 213 albumInfo.setVideoCount(videoCount); 214 let albumName: string = await UserFileManagerAccess.getInstance().getAlbumName(album); 215 albumInfo.setAlbumName(albumName); 216 albumInfo.setFilterMediaType(filterMediaType); 217 if (!album.coverUri) { 218 await UserFileManagerAccess.getInstance().getAlbumFirstObject(album).then((obj) => { 219 if (obj) { 220 let mediaItem = new MediaItem(obj); 221 mediaItem.setThumbnail(this.getThumbnailSafe(obj.uri, String(obj.get(Constants.KEY_FILE_DATA)))); 222 albumInfo.setMediaItem(mediaItem); 223 albumInfo.setCoverUri(this.getThumbnailSafe(obj.uri, String(obj.get(Constants.KEY_FILE_DATA)))); 224 } 225 }); 226 } else { 227 await UserFileManagerAccess.getInstance().getFirstObject(AlbumDefine.getFileFetchOptByUri(album.coverUri)).then((obj) => { 228 if (obj) { 229 let mediaItem = new MediaItem(obj.obj); 230 mediaItem.setThumbnail(this.getThumbnailSafe(obj.obj.uri, String(obj.obj.get(Constants.KEY_FILE_DATA)))); 231 albumInfo.setMediaItem(mediaItem); 232 albumInfo.setCoverUri(this.getThumbnailSafe(obj.obj.uri, String(obj.obj.get(Constants.KEY_FILE_DATA)))); 233 } 234 }); 235 } 236 Log.debug(TAG, `getSystemAlbumsInfo albumInfo is : ${albumInfo}`); 237 albumArray.push(albumInfo); 238 Log.debug(TAG, `getSystemAlbumsInfo albumArray length is : ${albumArray.length}`); 239 } 240 } else { 241 Log.error(TAG, 'Failed getSystemAlbumsInfo'); 242 } 243 244 Log.debug(TAG, 'getSystemAlbumsInfo done'); 245 } 246 247 private async getTrashAlbumInfo(albumArray: Array<AlbumInfo>, filterMediaType?: string): Promise<void> { 248 Log.info(TAG, 'getTrashAlbumInfo start'); 249 let album: Album = await UserFileManagerAccess.getInstance().getTrashAlbum() as Album; 250 if (!album) { 251 Log.error(TAG, 'getTrashAlbumInfo, get album undefined'); 252 } 253 let albumInfo: AlbumInfo = new AlbumInfo(album); 254 let count = albumInfo.count; 255 // 系统相册为空时不展示 256 if (count === 0) { 257 Log.warn(TAG, 'getTrashAlbumInfo count is 0'); 258 return; 259 } 260 albumInfo.setCount(count); 261 let albumName: string = await UserFileManagerAccess.getInstance().getAlbumName(album) as string; 262 albumInfo.setAlbumName(albumName); 263 albumInfo.setFilterMediaType(filterMediaType as string); 264 albumArray.push(albumInfo); 265 Log.info(TAG, `getTrashAlbumInfo done, albumInfo : ${JSON.stringify(albumInfo)}, albumArray length: ${albumArray.length}`); 266 } 267}