1bea4f105Sopenharmony_ci/*
2bea4f105Sopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3bea4f105Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4bea4f105Sopenharmony_ci * you may not use this file except in compliance with the License.
5bea4f105Sopenharmony_ci * You may obtain a copy of the License at
6bea4f105Sopenharmony_ci *
7bea4f105Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8bea4f105Sopenharmony_ci *
9bea4f105Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10bea4f105Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11bea4f105Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12bea4f105Sopenharmony_ci * See the License for the specific language governing permissions and
13bea4f105Sopenharmony_ci * limitations under the License.
14bea4f105Sopenharmony_ci */
15bea4f105Sopenharmony_ci
16bea4f105Sopenharmony_ciimport { MILLISECOND } from '../../base/constants/Constant';
17bea4f105Sopenharmony_ciimport { formatSuffix, getResourceString } from '../../base/utils/Tools';
18bea4f105Sopenharmony_ciimport DateTimeUtil from '../../base/utils/DateTimeUtil';
19bea4f105Sopenharmony_ciimport { FileMimeTypeUtil } from '../../base/utils/FileMimeTypeUtil';
20bea4f105Sopenharmony_ciimport LanguageUtil from '../../base/utils/LanguageUtil';
21bea4f105Sopenharmony_ciimport { MimeType } from './MimeType';
22bea4f105Sopenharmony_ciimport { THUMBNAIL_SIZE } from '../../base/constants/UiConstant';
23bea4f105Sopenharmony_ciimport { BasicDataSource } from './BasicDataSource';
24bea4f105Sopenharmony_ciimport AbilityCommonUtil, { ResultCodePicker } from '../../base/utils/AbilityCommonUtil';
25bea4f105Sopenharmony_ciimport { StartModeOptions } from '../../base/model/StartModeOptions';
26bea4f105Sopenharmony_ciimport { photoAccessHelper } from '@kit.MediaLibraryKit';
27bea4f105Sopenharmony_ciimport { dataSharePredicates } from '@kit.ArkData';
28bea4f105Sopenharmony_ci
29bea4f105Sopenharmony_ciconst TAG = 'FileAssetModel';
30bea4f105Sopenharmony_ci
31bea4f105Sopenharmony_ciexport class FileAssetLazyModel extends BasicDataSource {
32bea4f105Sopenharmony_ci  private dataArray: FileAssetModel[] = [];
33bea4f105Sopenharmony_ci  public dataCount: number = 0;
34bea4f105Sopenharmony_ci
35bea4f105Sopenharmony_ci  public totalCount(): number {
36bea4f105Sopenharmony_ci    return this.dataArray.length;
37bea4f105Sopenharmony_ci  }
38bea4f105Sopenharmony_ci
39bea4f105Sopenharmony_ci  public getDataArray(): FileAssetModel[] {
40bea4f105Sopenharmony_ci    return this.dataArray;
41bea4f105Sopenharmony_ci  }
42bea4f105Sopenharmony_ci
43bea4f105Sopenharmony_ci  public setData(data: FileAssetModel[]): void {
44bea4f105Sopenharmony_ci    this.dataArray = [...data];
45bea4f105Sopenharmony_ci    this.dataCount = this.dataArray.length;
46bea4f105Sopenharmony_ci    this.notifyDataReload();
47bea4f105Sopenharmony_ci  }
48bea4f105Sopenharmony_ci
49bea4f105Sopenharmony_ci  public getData(index: number): FileAssetModel {
50bea4f105Sopenharmony_ci    return this.dataArray[index];
51bea4f105Sopenharmony_ci  }
52bea4f105Sopenharmony_ci
53bea4f105Sopenharmony_ci  public selectAll(isSelected: boolean): void {
54bea4f105Sopenharmony_ci    this.dataArray.forEach(item => {
55bea4f105Sopenharmony_ci      item.isChecked = isSelected;
56bea4f105Sopenharmony_ci    });
57bea4f105Sopenharmony_ci  }
58bea4f105Sopenharmony_ci
59bea4f105Sopenharmony_ci  public getIndex(uri): number {
60bea4f105Sopenharmony_ci    return this.dataArray.findIndex(item => item.uri === uri);
61bea4f105Sopenharmony_ci  }
62bea4f105Sopenharmony_ci
63bea4f105Sopenharmony_ci  public getSelectedFileList(): FileAssetModel[] {
64bea4f105Sopenharmony_ci    return this.dataArray.filter(item => item.isChecked);
65bea4f105Sopenharmony_ci  }
66bea4f105Sopenharmony_ci
67bea4f105Sopenharmony_ci  public replaceData(index, data: FileAssetModel): void {
68bea4f105Sopenharmony_ci    this.dataArray.splice(index, 1, data);
69bea4f105Sopenharmony_ci    this.notifyDataChange(index);
70bea4f105Sopenharmony_ci  }
71bea4f105Sopenharmony_ci
72bea4f105Sopenharmony_ci  public addData(index: number, data: FileAssetModel): void {
73bea4f105Sopenharmony_ci    this.dataArray.splice(index, 0, data);
74bea4f105Sopenharmony_ci    this.dataCount = this.dataArray.length;
75bea4f105Sopenharmony_ci    this.notifyDataAdd(index);
76bea4f105Sopenharmony_ci  }
77bea4f105Sopenharmony_ci
78bea4f105Sopenharmony_ci  public pushData(data: FileAssetModel): void {
79bea4f105Sopenharmony_ci    this.dataArray.push(data);
80bea4f105Sopenharmony_ci    this.dataCount = this.dataArray.length;
81bea4f105Sopenharmony_ci    this.notifyDataAdd(this.dataArray.length - 1);
82bea4f105Sopenharmony_ci  }
83bea4f105Sopenharmony_ci
84bea4f105Sopenharmony_ci  public deleteData(index: number): void {
85bea4f105Sopenharmony_ci    this.dataArray.splice(index, 1);
86bea4f105Sopenharmony_ci    this.dataCount = this.dataArray.length;
87bea4f105Sopenharmony_ci    this.notifyDataDelete(index);
88bea4f105Sopenharmony_ci  }
89bea4f105Sopenharmony_ci}
90bea4f105Sopenharmony_ci
91bea4f105Sopenharmony_ci/**
92bea4f105Sopenharmony_ci * 媒体文件信息类
93bea4f105Sopenharmony_ci */
94bea4f105Sopenharmony_ciexport class FileAssetModel {
95bea4f105Sopenharmony_ci  public id: number;
96bea4f105Sopenharmony_ci  public uri: string;
97bea4f105Sopenharmony_ci  public mimeType: string;
98bea4f105Sopenharmony_ci  public mediaType: number;
99bea4f105Sopenharmony_ci  public displayName: string;
100bea4f105Sopenharmony_ci  public title: string;
101bea4f105Sopenharmony_ci  public relativePath: string;
102bea4f105Sopenharmony_ci  public parent: number;
103bea4f105Sopenharmony_ci  public size: number;
104bea4f105Sopenharmony_ci  public dateAdded: number;
105bea4f105Sopenharmony_ci  public dateModified: number;
106bea4f105Sopenharmony_ci  public dateTaken: number;
107bea4f105Sopenharmony_ci  public artist: string;
108bea4f105Sopenharmony_ci  public audioAlbum: string;
109bea4f105Sopenharmony_ci  public width: number;
110bea4f105Sopenharmony_ci  public height: number;
111bea4f105Sopenharmony_ci  public orientation: number;
112bea4f105Sopenharmony_ci  public duration: number;
113bea4f105Sopenharmony_ci  public albumId: number;
114bea4f105Sopenharmony_ci  public albumUri: string;
115bea4f105Sopenharmony_ci  public albumName: string;
116bea4f105Sopenharmony_ci  // MediaLibrary.FileAsset对象外的属性
117bea4f105Sopenharmony_ci  public fileName: string;
118bea4f105Sopenharmony_ci  public fullPath: string;
119bea4f105Sopenharmony_ci  public isChecked: boolean = false;
120bea4f105Sopenharmony_ci  public suffix: string;
121bea4f105Sopenharmony_ci  public icon: Resource | PixelMap;
122bea4f105Sopenharmony_ci  public gridIcon: Resource | PixelMap;
123bea4f105Sopenharmony_ci  public localGridIcon: Resource | PixelMap;
124bea4f105Sopenharmony_ci  public lastModifiedDate: string | Resource;
125bea4f105Sopenharmony_ci  public thumbUri: string;
126bea4f105Sopenharmony_ci  public sortLabel: string = '';
127bea4f105Sopenharmony_ci  public mimeTypeObj: MimeType;
128bea4f105Sopenharmony_ci
129bea4f105Sopenharmony_ci  constructor(file) {
130bea4f105Sopenharmony_ci    this.id = file.id;
131bea4f105Sopenharmony_ci    this.uri = file.uri;
132bea4f105Sopenharmony_ci    this.mimeType = file.mimeType;
133bea4f105Sopenharmony_ci    this.mediaType = file.mediaType;
134bea4f105Sopenharmony_ci    this.displayName = file.displayName;
135bea4f105Sopenharmony_ci    this.title = file.title;
136bea4f105Sopenharmony_ci    this.relativePath = file.relativePath;
137bea4f105Sopenharmony_ci    this.parent = file.parent;
138bea4f105Sopenharmony_ci    this.size = file.size;
139bea4f105Sopenharmony_ci    this.dateAdded = file.dateAdded;
140bea4f105Sopenharmony_ci    this.dateModified = file.dateModified * MILLISECOND.ONE_SECOND;
141bea4f105Sopenharmony_ci    this.dateTaken = file.dateTaken;
142bea4f105Sopenharmony_ci    this.artist = file.artist;
143bea4f105Sopenharmony_ci    this.audioAlbum = file.audioAlbum;
144bea4f105Sopenharmony_ci    this.width = file.width;
145bea4f105Sopenharmony_ci    this.height = file.height;
146bea4f105Sopenharmony_ci    this.orientation = file.orientation;
147bea4f105Sopenharmony_ci    this.duration = file.duration;
148bea4f105Sopenharmony_ci    this.albumId = file.albumId;
149bea4f105Sopenharmony_ci    this.albumUri = file.albumUri;
150bea4f105Sopenharmony_ci    this.albumName = file.albumName;
151bea4f105Sopenharmony_ci
152bea4f105Sopenharmony_ci    this.fileName = file.displayName;
153bea4f105Sopenharmony_ci    this.mimeTypeObj = FileMimeTypeUtil.getFileMimeType(this.fileName);
154bea4f105Sopenharmony_ci    this.fullPath = getFullPath(this);
155bea4f105Sopenharmony_ci    this.suffix = formatSuffix(file.fileName);
156bea4f105Sopenharmony_ci    this.icon = this.mimeTypeObj.getResID();
157bea4f105Sopenharmony_ci    this.gridIcon = this.mimeTypeObj.getGridResID();
158bea4f105Sopenharmony_ci    this.localGridIcon = this.mimeTypeObj.getLocalGridResID();
159bea4f105Sopenharmony_ci    this.lastModifiedDate = DateTimeUtil.getDateStringForCategory(this.dateModified);
160bea4f105Sopenharmony_ci    this.sortLabel = file.sortLabel;
161bea4f105Sopenharmony_ci    if (this.mimeTypeObj.isMedia()) {
162bea4f105Sopenharmony_ci      this.thumbUri = `${this.uri}/thumbnail/${THUMBNAIL_SIZE.WIDTH}/${THUMBNAIL_SIZE.HEIGHT}`;
163bea4f105Sopenharmony_ci    }
164bea4f105Sopenharmony_ci  }
165bea4f105Sopenharmony_ci
166bea4f105Sopenharmony_ci  setFileName(fileName: string): void {
167bea4f105Sopenharmony_ci    this.fileName = fileName;
168bea4f105Sopenharmony_ci    this.mimeTypeObj = FileMimeTypeUtil.getFileMimeType(this.fileName);
169bea4f105Sopenharmony_ci    this.fullPath = getFullPath(this);
170bea4f105Sopenharmony_ci    this.icon = this.mimeTypeObj.getResID();
171bea4f105Sopenharmony_ci    this.gridIcon = this.mimeTypeObj.getGridResID();
172bea4f105Sopenharmony_ci    this.localGridIcon = this.mimeTypeObj.getLocalGridResID();
173bea4f105Sopenharmony_ci    if (this.mimeTypeObj.isMedia()) {
174bea4f105Sopenharmony_ci      this.thumbUri = `${this.uri}/thumbnail/${THUMBNAIL_SIZE.WIDTH}/${THUMBNAIL_SIZE.HEIGHT}`;
175bea4f105Sopenharmony_ci    }
176bea4f105Sopenharmony_ci  }
177bea4f105Sopenharmony_ci
178bea4f105Sopenharmony_ci  pickFile(startModeOptions: StartModeOptions): void {
179bea4f105Sopenharmony_ci    AbilityCommonUtil.terminateFilePicker([this.uri], ResultCodePicker.SUCCESS, startModeOptions);
180bea4f105Sopenharmony_ci  }
181bea4f105Sopenharmony_ci}
182bea4f105Sopenharmony_ci
183bea4f105Sopenharmony_ci/**
184bea4f105Sopenharmony_ci * 对媒体文件进行排序
185bea4f105Sopenharmony_ci * @param dataList 待排序数组
186bea4f105Sopenharmony_ci * @param order 排序规则
187bea4f105Sopenharmony_ci * @param isDesc 是否倒序
188bea4f105Sopenharmony_ci * @return 排序后的数组
189bea4f105Sopenharmony_ci */
190bea4f105Sopenharmony_cifunction sortFileAssetList(dataList) {
191bea4f105Sopenharmony_ci  const language = LanguageUtil.getSystemLanguage();
192bea4f105Sopenharmony_ci  return dataList.sort((a, b) => {
193bea4f105Sopenharmony_ci    if (b.dateModified !== a.dateModified) {
194bea4f105Sopenharmony_ci      return b.dateModified - a.dateModified;
195bea4f105Sopenharmony_ci    } else {
196bea4f105Sopenharmony_ci      return b.displayName.localeCompare(a.displayName, language);
197bea4f105Sopenharmony_ci    }
198bea4f105Sopenharmony_ci  })
199bea4f105Sopenharmony_ci}
200bea4f105Sopenharmony_ci
201bea4f105Sopenharmony_ci/**
202bea4f105Sopenharmony_ci * 媒体库查询条件类
203bea4f105Sopenharmony_ci */
204bea4f105Sopenharmony_ciexport class MediaFetchOptions {
205bea4f105Sopenharmony_ci  public selections: string = photoAccessHelper.PhotoKeys.PHOTO_TYPE + '=?';
206bea4f105Sopenharmony_ci  public selectionArgs: string[] = [];
207bea4f105Sopenharmony_ci  public order: string = photoAccessHelper.PhotoKeys.DATE_MODIFIED + ' DESC';
208bea4f105Sopenharmony_ci  public uri: string = '';
209bea4f105Sopenharmony_ci  public networkId: string = '';
210bea4f105Sopenharmony_ci  public extendArgs: string = '';
211bea4f105Sopenharmony_ci
212bea4f105Sopenharmony_ci  constructor(mediaTypeArg: string = '') {
213bea4f105Sopenharmony_ci    if (!mediaTypeArg) {
214bea4f105Sopenharmony_ci      this.selections = '';
215bea4f105Sopenharmony_ci    } else {
216bea4f105Sopenharmony_ci      this.selectionArgs.push(mediaTypeArg);
217bea4f105Sopenharmony_ci    }
218bea4f105Sopenharmony_ci  }
219bea4f105Sopenharmony_ci
220bea4f105Sopenharmony_ci  /**
221bea4f105Sopenharmony_ci   * 设置要查询文件的uri
222bea4f105Sopenharmony_ci   */
223bea4f105Sopenharmony_ci  setUri(uri: string): void {
224bea4f105Sopenharmony_ci    this.uri = uri;
225bea4f105Sopenharmony_ci  }
226bea4f105Sopenharmony_ci
227bea4f105Sopenharmony_ci  /**
228bea4f105Sopenharmony_ci   * 追加其他查询条件
229bea4f105Sopenharmony_ci   * @param selection 要查询的关键字
230bea4f105Sopenharmony_ci   * @param selectionArg 要查询的值
231bea4f105Sopenharmony_ci   */
232bea4f105Sopenharmony_ci  addSelection(selection: photoAccessHelper.PhotoKeys, selectionArg: string) {
233bea4f105Sopenharmony_ci    if (this.selections.length) {
234bea4f105Sopenharmony_ci      this.selections += ` AND ${selection} = ? `;
235bea4f105Sopenharmony_ci    } else {
236bea4f105Sopenharmony_ci      this.selections = `${selection} = ?`;
237bea4f105Sopenharmony_ci    }
238bea4f105Sopenharmony_ci    this.selectionArgs.push(selectionArg);
239bea4f105Sopenharmony_ci  }
240bea4f105Sopenharmony_ci}
241bea4f105Sopenharmony_ci
242bea4f105Sopenharmony_ci/**
243bea4f105Sopenharmony_ci * 查询媒体库内指定类型的文件
244bea4f105Sopenharmony_ci * @param mediaFetchOptions 媒体库查询条件
245bea4f105Sopenharmony_ci * @return 文件列表
246bea4f105Sopenharmony_ci */
247bea4f105Sopenharmony_ciexport async function getMediaFileDuration(mediaFetchOptions: MediaFetchOptions): Promise<number> {
248bea4f105Sopenharmony_ci  const photoManageHelper: photoAccessHelper.PhotoAccessHelper = AbilityCommonUtil.getPhotoManageHelper();
249bea4f105Sopenharmony_ci  let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates();
250bea4f105Sopenharmony_ci  let fetchOptions: photoAccessHelper.FetchOptions = {
251bea4f105Sopenharmony_ci    fetchColumns: mediaFetchOptions.selectionArgs,
252bea4f105Sopenharmony_ci    predicates: predicates
253bea4f105Sopenharmony_ci  };
254bea4f105Sopenharmony_ci  if (!photoManageHelper) {
255bea4f105Sopenharmony_ci    return 0;
256bea4f105Sopenharmony_ci  }
257bea4f105Sopenharmony_ci
258bea4f105Sopenharmony_ci  let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> =
259bea4f105Sopenharmony_ci    await photoManageHelper.getAssets(fetchOptions);
260bea4f105Sopenharmony_ci  let photoAsset: photoAccessHelper.PhotoAsset = await fetchResult.getFirstObject();
261bea4f105Sopenharmony_ci  let duration: photoAccessHelper.MemberType = photoAsset.get(photoAccessHelper.PhotoKeys.DURATION);
262bea4f105Sopenharmony_ci  return Number(duration) ?? 0;
263bea4f105Sopenharmony_ci}
264bea4f105Sopenharmony_ci
265bea4f105Sopenharmony_ciexport function getDurationByUri(mediaType: photoAccessHelper.PhotoType, uri: string): Promise<number> {
266bea4f105Sopenharmony_ci  const option = new MediaFetchOptions(mediaType.toString());
267bea4f105Sopenharmony_ci  option.setUri(uri);
268bea4f105Sopenharmony_ci  return getMediaFileDuration(option).then((res: number) => {
269bea4f105Sopenharmony_ci    return res;
270bea4f105Sopenharmony_ci  }).catch(() => {
271bea4f105Sopenharmony_ci    return 0;
272bea4f105Sopenharmony_ci  })
273bea4f105Sopenharmony_ci}
274bea4f105Sopenharmony_ci
275bea4f105Sopenharmony_ci/**
276bea4f105Sopenharmony_ci * 根据文件名(后缀)判断媒体类型
277bea4f105Sopenharmony_ci * @param fileName 文件名
278bea4f105Sopenharmony_ci * @return 媒体类型photoAccessHelper.PhotoType
279bea4f105Sopenharmony_ci */
280bea4f105Sopenharmony_ciexport function getMediaType(fileName: string): photoAccessHelper.PhotoType {
281bea4f105Sopenharmony_ci  const mimeType = FileMimeTypeUtil.getFileMimeType(fileName);
282bea4f105Sopenharmony_ci  if (mimeType.isImage()) {
283bea4f105Sopenharmony_ci    return photoAccessHelper.PhotoType.IMAGE;
284bea4f105Sopenharmony_ci  } else if (mimeType.isVideo()) {
285bea4f105Sopenharmony_ci    return photoAccessHelper.PhotoType.VIDEO;
286bea4f105Sopenharmony_ci  } else {
287bea4f105Sopenharmony_ci    return 0;
288bea4f105Sopenharmony_ci  }
289bea4f105Sopenharmony_ci}
290bea4f105Sopenharmony_ci
291bea4f105Sopenharmony_ci/**
292bea4f105Sopenharmony_ci * 获取文件的完整路径
293bea4f105Sopenharmony_ci * @param file 文件信息
294bea4f105Sopenharmony_ci * @return 完整路径
295bea4f105Sopenharmony_ci */
296bea4f105Sopenharmony_ciexport function getFullPath(file: FileAssetModel): string {
297bea4f105Sopenharmony_ci  return getResourceString($r('app.string.myPhone')) + '/' + file.relativePath + file.fileName;
298bea4f105Sopenharmony_ci}
299bea4f105Sopenharmony_ci
300bea4f105Sopenharmony_ci/**
301bea4f105Sopenharmony_ci * 设置文件列表排序后需要显示的label
302bea4f105Sopenharmony_ci * @param fileAssetList 文件列表
303bea4f105Sopenharmony_ci * @param order 排序规则
304bea4f105Sopenharmony_ci * @return 设置了label的文件数组
305bea4f105Sopenharmony_ci */
306bea4f105Sopenharmony_ciexport function addSortLabel(fileAssetList): FileAssetModel[] {
307bea4f105Sopenharmony_ci  fileAssetList.forEach((fileAsset: FileAssetModel) => {
308bea4f105Sopenharmony_ci    fileAsset.sortLabel = DateTimeUtil.getDateStringForCategory(fileAsset.dateModified);
309bea4f105Sopenharmony_ci  });
310bea4f105Sopenharmony_ci  return fileAssetList;
311bea4f105Sopenharmony_ci}
312bea4f105Sopenharmony_ci
313bea4f105Sopenharmony_ci
314