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 getMediaItemByUri(callback: AsyncCallback<unknown>, uri: string): void { 107 } 108 109 private async genAlbumsInfo(cb: AsyncCallback<AlbumSimpleInfo>, uris: string[]): Promise<void> { 110 Log.info(TAG, `genAlbumsInfo uris: ${JSON.stringify(uris)}`); 111 Log.info(TAG, 'load data genAlbumsInfo start'); 112 113 let res = { 114 uris: [], 115 count: 0, 116 videoCount: 0, 117 }; 118 119 for (let uri of uris) { 120 let objects = await super.getItems(uri, Constants.INVALID, Constants.INVALID); 121 Log.info(TAG, `get album objects: uri: ${uri} length: ${objects.length}`); 122 123 res.count += objects.length; 124 for (let item of objects) { 125 if (item.fileType === UserFileManagerAccess.MEDIA_TYPE_VIDEO) { 126 res.videoCount++; 127 } 128 res.uris.push(item.uri); 129 } 130 } 131 132 Log.info(TAG, `genAlbumsInfo done`); 133 cb.callback(res); 134 } 135 136 private async buildAlbums(callback: AsyncCallback<AlbumInfo[]>, filterMediaType?: string) { 137 Log.debug(TAG, `buildAlbums`); 138 let sourceData = new Array<AlbumInfo>(); 139 await this.getSystemAlbumsInfo(sourceData, filterMediaType); 140 await this.getUserAlbumsInfo(sourceData, filterMediaType); 141 await this.getTrashAlbumInfo(sourceData, filterMediaType); 142 callback.callback(sourceData); 143 } 144 145 private async getUserAlbumsInfo(albumArray: Array<AlbumInfo>, filterMediaType?: string): Promise<void> { 146 Log.info(TAG, 'getUserAlbumsInfo start'); 147 let albums: Album[] = await UserFileManagerAccess.getInstance().getUserAlbums(); 148 if (!albums) { 149 Log.error(TAG, 'getUserAlbumsInfo, albums undefined'); 150 } 151 Log.info(TAG, `getUserAlbumsInfo fetch albums length : ${albums.length}`); 152 try { 153 for (let album of albums) { 154 let albumInfo: AlbumInfo = new AlbumInfo(album); 155 let albumName: string = await UserFileManagerAccess.getInstance().getAlbumName(album); 156 albumInfo.setAlbumName(albumName); 157 albumInfo.setFilterMediaType(filterMediaType as string); 158 let count = albumInfo.count; 159 albumInfo.setCount(count); // Waiting: album.count不为0时,在构造函数里直接获取 160 let videoCount = 0; 161 if (count > 0) { 162 // 没有相册,设置为第一张 163 let hasCoverUri: Boolean = false; 164 if (album.coverUri) { 165 await UserFileManagerAccess.getInstance().getFirstObject(AlbumDefine.getFileFetchOptByUri(album.coverUri)).then((obj) => { 166 if (obj && obj.obj) { 167 let mediaItem = new MediaItem(obj.obj); 168 mediaItem.setThumbnail(this.getThumbnailSafe(obj.obj.uri, String(obj.obj.get(Constants.KEY_FILE_DATA)))); 169 albumInfo.setMediaItem(mediaItem); 170 albumInfo.setCoverUri(ImageUtil.calcThumbnail(obj.obj.uri, mediaItem.height, mediaItem.width)); 171 hasCoverUri = true; 172 } 173 }); 174 } 175 if (!hasCoverUri) { 176 await UserFileManagerAccess.getInstance().getAlbumFirstObject(album).then((obj) => { 177 if (obj) { 178 let mediaItem = new MediaItem(obj); 179 mediaItem.setThumbnail(this.getThumbnailSafe(obj.uri, String(obj.get(Constants.KEY_FILE_DATA)))); 180 albumInfo.setMediaItem(mediaItem); 181 albumInfo.setCoverUri(ImageUtil.calcThumbnail(obj.uri, mediaItem.height, mediaItem.width)); 182 } 183 }); 184 } 185 // 相册的视频数量 186 videoCount = await this.getItemsCountOfAlbum(album, AlbumDefine.FILTER_MEDIA_TYPE_VIDEO); 187 } 188 albumInfo.setVideoCount(videoCount); 189 albumArray.push(albumInfo); 190 Log.info(TAG, `getUserAlbumsInfo done, albumInfo : ${JSON.stringify(albumInfo)}, albumArray length: ${albumArray.length}`); 191 } 192 } catch (error) { 193 Log.error(TAG, `getUserAlbumsInfo error occured: ${error}`); 194 } 195 Log.info(TAG, 'getUserAlbumsInfo done'); 196 } 197 198 private async getSystemAlbumsInfo(albumArray: Array<AlbumInfo>, filterMediaType?: string): Promise<void> { 199 Log.debug(TAG, 'getSystemAlbumsInfo'); 200 201 let albums: Album[] = await UserFileManagerAccess.getInstance().getSystemAlbums(); 202 Log.debug(TAG, `getSystemAlbumsInfo albums is : ${albums}`); 203 204 if (albums) { 205 for (let album of albums) { 206 Log.info(TAG, `album ${JSON.stringify(album)}`) 207 let albumInfo: AlbumInfo = new AlbumInfo(album); 208 let count = await this.getItemsCount(album.albumUri); 209 // 系统相册为空时不展示 210 if (count === 0) { 211 continue; 212 } 213 albumInfo.setCount(count); // TODO album.count不为0时,在构造函数里直接获取 214 // 相册的视频数量 215 let videoCount = await this.getItemsCount(album.albumUri, AlbumDefine.FILTER_MEDIA_TYPE_VIDEO); 216 albumInfo.setVideoCount(videoCount); 217 let albumName: string = await UserFileManagerAccess.getInstance().getAlbumName(album); 218 albumInfo.setAlbumName(albumName); 219 albumInfo.setFilterMediaType(filterMediaType); 220 if (!album.coverUri) { 221 await UserFileManagerAccess.getInstance().getAlbumFirstObject(album).then((obj) => { 222 if (obj) { 223 let mediaItem = new MediaItem(obj); 224 mediaItem.setThumbnail(this.getThumbnailSafe(obj.uri, String(obj.get(Constants.KEY_FILE_DATA)))); 225 albumInfo.setMediaItem(mediaItem); 226 albumInfo.setCoverUri(this.getThumbnailSafe(obj.uri, String(obj.get(Constants.KEY_FILE_DATA)))); 227 } 228 }); 229 } else { 230 await UserFileManagerAccess.getInstance().getFirstObject(AlbumDefine.getFileFetchOptByUri(album.coverUri)).then((obj) => { 231 if (obj) { 232 let mediaItem = new MediaItem(obj.obj); 233 mediaItem.setThumbnail(this.getThumbnailSafe(obj.obj.uri, String(obj.obj.get(Constants.KEY_FILE_DATA)))); 234 albumInfo.setMediaItem(mediaItem); 235 albumInfo.setCoverUri(this.getThumbnailSafe(obj.obj.uri, String(obj.obj.get(Constants.KEY_FILE_DATA)))); 236 } 237 }); 238 } 239 Log.debug(TAG, `getSystemAlbumsInfo albumInfo is : ${albumInfo}`); 240 albumArray.push(albumInfo); 241 Log.debug(TAG, `getSystemAlbumsInfo albumArray length is : ${albumArray.length}`); 242 } 243 } else { 244 Log.error(TAG, 'Failed getSystemAlbumsInfo'); 245 } 246 247 Log.debug(TAG, 'getSystemAlbumsInfo done'); 248 } 249 250 private async getTrashAlbumInfo(albumArray: Array<AlbumInfo>, filterMediaType?: string): Promise<void> { 251 Log.info(TAG, 'getTrashAlbumInfo start'); 252 let album: Album = await UserFileManagerAccess.getInstance().getTrashAlbum() as Album; 253 if (!album) { 254 Log.error(TAG, 'getTrashAlbumInfo, get album undefined'); 255 } 256 let albumInfo: AlbumInfo = new AlbumInfo(album); 257 let count = albumInfo.count; 258 // 系统相册为空时不展示 259 if (count === 0) { 260 Log.warn(TAG, 'getTrashAlbumInfo count is 0'); 261 return; 262 } 263 albumInfo.setCount(count); 264 let albumName: string = await UserFileManagerAccess.getInstance().getAlbumName(album) as string; 265 albumInfo.setAlbumName(albumName); 266 albumInfo.setFilterMediaType(filterMediaType as string); 267 albumArray.push(albumInfo); 268 Log.info(TAG, `getTrashAlbumInfo done, albumInfo : ${JSON.stringify(albumInfo)}, albumArray length: ${albumArray.length}`); 269 } 270}