• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 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 */
15import { Log } from '../utils/Log';
16import MediaLib from '@ohos.multimedia.mediaLibrary';
17import { ViewType } from '../data/ViewType';
18import mediaModel from '../model/MediaModel';
19import { MediaConstants } from '../constants/MediaConstants';
20import { setOrientation } from '../helper/MediaDataHelper';
21import selectManager from '../manager/SelectManager';
22import { ItemDataSource } from '../vm/ItemDataSource'
23const TAG = "MediaDataItem"
24
25const STATUS_UNDEFINED = -1
26const STATUS_FALSE = 0
27const STATUS_TRUE = 1
28
29export class MediaDataItem {
30    readonly viewType = ViewType.ITEM
31    readonly hashIndex: number
32    index: number
33    dateAdded: number
34    dateModified: number
35    dateTaken: number
36    status: number = MediaConstants.UNDEFINED
37    isSelect: boolean = false
38    id: number
39    uri: string
40    orientation: number
41    duration: number
42    size: number
43    width: number; // width changed by orientation
44    height: number; // height changed by orientation
45    imgWidth: number; // may be smaller than width, as width is too large
46    imgHeight: number; // may be smaller than height, as height is too large
47    path: string
48    title: string
49    displayName: string
50    mediaType: MediaLib.MediaType
51    favouriteStatus: number = STATUS_UNDEFINED
52    canRotate: number = STATUS_UNDEFINED
53    selections: string = ""
54    selectionArgs: Array<string> = new Array()
55    deviceId: string = ''
56
57    constructor(selections: string, selectionArgs: Array<string>, deviceId: string, index: number) {
58        this.selections = selections
59        this.selectionArgs = selectionArgs
60        this.deviceId = deviceId
61        this.hashIndex = index
62        this.index = index
63    }
64
65    getHashCode(): string {
66        //时间线界面角度,收藏状态变更,都需要刷新界面;大图浏览界面角度变更,需要刷新界面
67        return this.status == MediaConstants.UNDEFINED ?
68                `${this.hashIndex}` :
69                `${this.uri}${this.favouriteStatus} ${this.orientation} ${this.isSelect}`
70    }
71
72    async loadFileAsset(): Promise<MediaLib.FileAsset> {
73        let fetchOption: MediaLib.MediaFetchOptions
74        if (this.status == MediaConstants.UNDEFINED) {
75            fetchOption = {
76                selections: this.selections,
77                selectionArgs: this.selectionArgs,
78                order: `date_added DESC LIMIT ${this.index},1`
79            };
80        } else {
81            fetchOption = {
82                selections: `${MediaLib.FileKey.ID} = ?`,
83                selectionArgs: [this.id.toString()],
84                order: `date_added DESC`
85            }
86        }
87        if (this.deviceId.length > 0) {
88            fetchOption['networkId'] = this.deviceId
89        }
90        return (await mediaModel.getAllCommonMediaItem(fetchOption, false)).fileAsset
91    }
92
93    isLoad():boolean {
94        if (this.status > MediaConstants.UNDEFINED) {
95            return true
96        }
97        return false
98    }
99
100    async load(isForce: boolean): Promise<void> {
101        Log.info(TAG, `load ${this.status}`)
102        if (this.status > (isForce ? MediaConstants.PART_LOADED : MediaConstants.UNDEFINED)) {
103            return
104        }
105        let fileAsset = await this.loadFileAsset()
106        if (fileAsset) {
107            this.update(fileAsset)
108        }
109        return
110    }
111
112    update(fileAsset: MediaLib.FileAsset) {
113        this.id = fileAsset.id;
114        this.uri = fileAsset.uri;
115        this.orientation = fileAsset.orientation;
116        this.mediaType = fileAsset.mediaType;
117        this.duration = fileAsset.duration;
118        this.size = fileAsset.size;
119        if (this.orientation == MediaConstants.ROTATE_ONCE || this.orientation == MediaConstants.ROTATE_THIRD) {
120            this.width = fileAsset.height;
121            this.height = fileAsset.width;
122        } else {
123            this.width = fileAsset.width;
124            this.height = fileAsset.height;
125        }
126        this.imgWidth = this.width;
127        this.imgHeight = this.height;
128        this.path = fileAsset.relativePath;
129        this.title = fileAsset.title;
130        this.displayName = fileAsset.displayName;
131        this.dateAdded = fileAsset.dateAdded * 1000;
132        this.dateModified = fileAsset.dateModified * 1000;
133        this.dateTaken = fileAsset.dateTaken * 1000;
134        this.isSelect = selectManager.isSelect(this.uri, this.isSelect);
135
136        // may change
137        fileAsset.isFavorite().then((isFavor: boolean) => this.favouriteStatus = (isFavor) ? STATUS_TRUE : STATUS_FALSE);
138
139        if (this.width > 0 && this.height > 0) {
140            this.status = MediaConstants.LOADED;
141        } else {
142            this.status = MediaConstants.PART_LOADED;
143        }
144    }
145
146    getThumbnail(width: number, height: number): string {
147        Log.debug(TAG, `getThumbnail ${this.status}`);
148        if (this.status != MediaConstants.LOADED && this.status != MediaConstants.PART_LOADED) {
149            Log.warn(TAG, `getThumbnail fail as status: ${this.status}`);
150            return "";
151        }
152        Log.debug(TAG, `this.uri ${this.uri}`);
153        return this.uri + `/thumbnail/${width}/${height}`;
154    }
155
156    getAlt(): Resource {
157        if (this.mediaType == MediaLib.MediaType.VIDEO) {
158            return $r('app.media.alt_video_placeholder');
159        } else {
160            return $r('app.media.alt_placeholder');
161        }
162    }
163
164    setSelect(isSelect: boolean) {
165        this.isSelect = isSelect;
166        selectManager.setSelect(this.uri, this.isSelect);
167    }
168
169    async onDelete(): Promise<boolean> {
170        try {
171            let fileAsset = await this.loadFileAsset();
172            await fileAsset.trash(true);
173            selectManager.deleteSelect(this.uri);
174            this.status = MediaConstants.TRASHED;
175            return true;
176        } catch (err) {
177            Log.error(TAG, `onDelete ${this.index} error: ${JSON.stringify(err)}`);
178            return false;
179        }
180    }
181
182    isDeleted(): boolean {
183        return this.status == MediaConstants.TRASHED;
184    }
185
186    async isFavor(): Promise<boolean> {
187        if (this.favouriteStatus == STATUS_UNDEFINED) {
188            let fileAsset = await this.loadFileAsset();
189            this.favouriteStatus = (await fileAsset.isFavorite()) ? STATUS_TRUE : STATUS_FALSE;
190        }
191        return this.favouriteStatus == STATUS_TRUE;
192    }
193
194    async setFavor(): Promise<boolean> {
195        let status = !(await this.isFavor());
196        try {
197            let fileAsset = await this.loadFileAsset();
198            await fileAsset.favorite(status);
199            await fileAsset.commitModify();
200            this.favouriteStatus = status ? STATUS_TRUE : STATUS_FALSE;
201            return true;
202        } catch (err) {
203            return false;
204        }
205    }
206
207    async setOrientation(): Promise<void> {
208        let fileAsset = await this.loadFileAsset();
209        this.orientation = (this.orientation + MediaConstants.ROTATE_ONCE) % MediaConstants.ROTATE_AROUND;
210        await setOrientation(fileAsset, this.orientation);
211        let tmp = this.width;
212        this.width = this.height;
213        this.height = tmp;
214    }
215
216    async setName(name: string): Promise<void> {
217        let fileAsset = await this.loadFileAsset();
218        let displayName = fileAsset.displayName;
219        let index = displayName.lastIndexOf('.');
220        displayName = name + displayName.slice(index);
221
222        this.displayName = displayName;
223        fileAsset.displayName = displayName;
224
225        this.title = name;
226        fileAsset.title = name;;
227        await fileAsset.commitModify();
228    }
229}