• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 { ViewType } from '../models/ViewType';
18import { userFileModel } from './UserFileModel';
19import { MediaConstants } from '../constants/MediaConstants';
20import { selectManager } from '../common/SelectManager';
21import photoAccessHelper from '@ohos.file.photoAccessHelper';
22import { screenManager } from '../common/ScreenManager';
23
24const TAG = 'UserFileDataItem';
25const STATUS_UNDEFINED = -1;
26const STATUS_FALSE = 0;
27const STATUS_TRUE = 1;
28
29export interface DateAdded {
30  dateAdded: number;
31  viewType: ViewType;
32}
33
34export class UserFileDataItem implements DateAdded {
35  viewType: ViewType = ViewType.ITEM;
36  readonly hashIndex: number;
37  index: number;
38  dateAdded: number = 0;
39  dateModified: number;
40  dateTaken: number;
41  status: number = MediaConstants.UNDEFINED;
42  isSelect: boolean = false;
43  uri: string;
44  orientation: number;
45  duration: number;
46  size: number;
47  width: number; // width changed by orientation
48  height: number; // height changed by orientation
49  imgWidth: number; // may be smaller than width, as width is too large
50  imgHeight: number; // may be smaller than height, as height is too large
51  path: string = '';
52  title: string;
53  displayName: string;
54  mediaType: photoAccessHelper.PhotoType;
55  favouriteStatus: number = STATUS_UNDEFINED;
56  canRotate: number = STATUS_UNDEFINED;
57  selections: string = '';
58  selectionArgs: string[] = [];
59  deviceId: string = '';
60  fileAsset: photoAccessHelper.PhotoAsset = undefined;
61  defaultThumbnail: PixelMap = undefined;
62  thumbnailArray: Map<string, PixelMap> = new Map<string, PixelMap>();
63
64  constructor(selections: string, selectionArgs: string[], deviceId: string, index: number) {
65    this.selections = selections;
66    this.selectionArgs = selectionArgs;
67    this.deviceId = deviceId;
68    this.hashIndex = index;
69    this.index = index;
70  }
71
72  getHashCode(): string {
73    // 时间线界面角度,收藏状态变更,都需要刷新界面;大图浏览界面角度变更,需要刷新界面
74    return this.status === MediaConstants.UNDEFINED ?
75      '' + this.hashIndex :
76      this.uri + this.favouriteStatus + ' ' + this.orientation + ' ' + this.isSelect;
77  }
78
79  async loadFileAsset(): Promise<photoAccessHelper.PhotoAsset> {
80    return await userFileModel.getMediaItemByUri(this.uri);
81  }
82
83  isLoad(): boolean {
84    if (this.status > MediaConstants.UNDEFINED) {
85      return true;
86    }
87    return false;
88  }
89
90  async load(isForce: boolean): Promise<void> {
91    Log.info(TAG, 'load ' + this.status);
92    if (this.status > (isForce ? MediaConstants.PART_LOADED : MediaConstants.UNDEFINED)) {
93      return;
94    }
95    let fileAsset = await this.loadFileAsset();
96    if (fileAsset != null) {
97      this.update(fileAsset);
98    }
99    return;
100  }
101
102  async update(fileAsset: photoAccessHelper.PhotoAsset): Promise<void> {
103    this.fileAsset = fileAsset;
104    this.uri = fileAsset.uri;
105    this.displayName = fileAsset.displayName;
106    this.mediaType = fileAsset.photoType;
107    this.width = screenManager.getWinWidth();
108    this.height = screenManager.getWinHeight();
109    this.orientation = MediaConstants.ROTATE_NONE;
110    try {
111      this.orientation = fileAsset.get(photoAccessHelper.PhotoKeys.ORIENTATION.toString()) as number;
112      Log.info(TAG, 'orientation ' + this.orientation);
113    } catch (err) {
114      Log.error(TAG, 'get orientation ' + JSON.stringify(err));
115    }
116    try {
117      this.duration = fileAsset.get(photoAccessHelper.PhotoKeys.DURATION.toString()) as number;
118      Log.info(TAG, 'duration ' + this.duration);
119    } catch (err) {
120      Log.error(TAG, 'get duration ' + JSON.stringify(err));
121    }
122    try {
123      if (this.orientation === MediaConstants.ROTATE_ONCE || this.orientation === MediaConstants.ROTATE_THIRD) {
124        this.width = fileAsset.get(photoAccessHelper.PhotoKeys.HEIGHT.toString()) as number;
125        this.height = fileAsset.get(photoAccessHelper.PhotoKeys.WIDTH.toString()) as number;
126      } else {
127        this.width = fileAsset.get(photoAccessHelper.PhotoKeys.WIDTH.toString()) as number;
128        this.height = fileAsset.get(photoAccessHelper.PhotoKeys.HEIGHT.toString()) as number;
129      }
130      Log.info(TAG, 'width ' + this.width);
131      Log.info(TAG, 'height ' + this.height);
132    } catch (err) {
133      Log.error(TAG, 'get width height ' + JSON.stringify(err));
134    }
135    try {
136      this.title = fileAsset.get(photoAccessHelper.PhotoKeys.TITLE.toString()) as string;
137      Log.info(TAG, 'title ' + this.title);
138    } catch (err) {
139      Log.error(TAG, 'get title ' + JSON.stringify(err));
140    }
141    try {
142      this.dateAdded = fileAsset.get(photoAccessHelper.PhotoKeys.DATE_ADDED.toString()) as number * 1000;
143      this.dateModified = fileAsset.get(photoAccessHelper.PhotoKeys.DATE_MODIFIED.toString()) as number * 1000;
144      this.dateTaken = fileAsset.get(photoAccessHelper.PhotoKeys.DATE_TAKEN.toString()) as number * 1000;
145      Log.info(TAG, 'dateAdded ' + this.dateAdded);
146    } catch (err) {
147      Log.error(TAG, 'get date ' + JSON.stringify(err));
148    }
149    try {
150      this.favouriteStatus = fileAsset.get(photoAccessHelper.PhotoKeys.FAVORITE.toString()) as boolean ? STATUS_TRUE : STATUS_FALSE
151      Log.info(TAG, 'favouriteStatus ' + this.favouriteStatus);
152    } catch (err) {
153      Log.error(TAG, 'get favouriteStatus ' + JSON.stringify(err));
154    }
155    try {
156      this.size = fileAsset.get(photoAccessHelper.PhotoKeys.SIZE.toString()) as number;
157      Log.info(TAG, 'size ' + this.size);
158    } catch (err) {
159      Log.error(TAG, 'get favouriteStatus ' + JSON.stringify(err));
160    }
161    let size = { width: MediaConstants.DEFAULT_SIZE, height: MediaConstants.DEFAULT_SIZE };
162    if (fileAsset != null && this.defaultThumbnail == undefined) {
163      try {
164        this.defaultThumbnail = await this.fileAsset.getThumbnail(size);
165      } catch (err) {
166        Log.error(TAG, 'getThumbnail error: ' + JSON.stringify(err));
167      }
168    }
169    this.isSelect = selectManager.isSelect(this.uri, this.isSelect);
170    this.imgWidth = this.width;
171    this.imgHeight = this.height;
172    if (this.width > 0 && this.height > 0) {
173      this.status = MediaConstants.LOADED;
174    } else {
175      this.status = MediaConstants.PART_LOADED;
176    }
177  }
178
179  async getThumbnail(width: number, height: number): Promise<PixelMap> {
180    Log.debug(TAG, 'getThumbnail ' + this.status);
181    if (this.status !== MediaConstants.LOADED && this.status !== MediaConstants.PART_LOADED) {
182      Log.warn(TAG, 'getThumbnail fail as status: ' + this.status);
183      return undefined;
184    }
185    if (width === MediaConstants.DEFAULT_SIZE && height === MediaConstants.DEFAULT_SIZE) {
186      return this.defaultThumbnail;
187    }
188    let newThumbnail: PixelMap = undefined;
189    let size = { width: width, height: height };
190    let cacheThumbnail = this.thumbnailArray.get(width.toString() + height.toString());
191    if (cacheThumbnail != null) {
192      return cacheThumbnail;
193    }
194    if (this.fileAsset != undefined) {
195      try {
196        newThumbnail = await this.fileAsset.getThumbnail(size);
197        this.thumbnailArray.set(width.toString() + height.toString(), newThumbnail);
198      } catch (err) {
199        Log.error(TAG, 'getThumbnail error: ' + JSON.stringify(err));
200      }
201    }
202    return newThumbnail;
203  }
204
205  getAlt(): Resource {
206    if (this.mediaType === photoAccessHelper.PhotoType.VIDEO) {
207      return $r('app.media.alt_video_placeholder');
208    } else {
209      return $r('app.media.alt_placeholder');
210    }
211  }
212
213  setSelect(isSelect: boolean): void {
214    this.isSelect = isSelect;
215    selectManager.setSelect(this.uri, this.isSelect);
216  }
217
218  async onDelete(): Promise<boolean> {
219    try {
220      await userFileModel.deleteOne(this.uri);
221      selectManager.deleteSelect(this.uri);
222      this.status = MediaConstants.TRASHED;
223      return true;
224    } catch (err) {
225      Log.error(TAG, 'onDelete ' + this.index + ' error: ' + JSON.stringify(err));
226      return false;
227    }
228  }
229
230  async addToAlbum(albumUri:string): Promise<boolean> {
231    try {
232      await userFileModel.addPhotoToAlbumByUserFileMgr(albumUri, this.uri);
233      selectManager.deleteSelect(this.uri);
234      this.status = MediaConstants.TRASHED;
235      return true;
236    } catch (err) {
237      Log.error(TAG, 'addToAlbum ' + this.index + ' error: ' + JSON.stringify(err));
238      return false;
239    }
240  }
241
242  isDeleted(): boolean {
243    return this.status === MediaConstants.TRASHED;
244  }
245
246  async isFavor(): Promise<boolean> {
247    if (this.favouriteStatus === STATUS_UNDEFINED) {
248      let fileAsset = await this.loadFileAsset();
249      try {
250        this.favouriteStatus = (fileAsset.get(photoAccessHelper.PhotoKeys.FAVORITE.toString()) as boolean) ? STATUS_TRUE : STATUS_FALSE;
251      } catch (err) {
252        Log.error(TAG, 'isFavor error: ' + JSON.stringify(err));
253      }
254    }
255    return this.favouriteStatus === STATUS_TRUE;
256  }
257
258  async setFavor(): Promise<boolean> {
259    let status = !(await this.isFavor());
260    try {
261      let fileAsset = await this.loadFileAsset();
262      await fileAsset.setFavorite(status);
263      this.favouriteStatus = status ? STATUS_TRUE : STATUS_FALSE;
264      return true;
265    } catch (err) {
266      return false;
267    }
268  }
269
270  async setName(name: string): Promise<void> {
271    let fileAsset = await this.loadFileAsset();
272    let displayName = fileAsset.displayName;
273    let index = displayName.lastIndexOf('.');
274    displayName = name + displayName.slice(index);
275    this.displayName = displayName;
276    this.title = name;
277    try {
278      fileAsset.set(photoAccessHelper.PhotoKeys.TITLE.toString(), name);
279      await fileAsset.commitModify();
280    } catch (err) {
281      Log.error(TAG, 'setName error: ' + JSON.stringify(err));
282    }
283  }
284}
285