Merge pull request !94 from 朱铖丰/master
This commit is contained in:
openharmony_ci 2022-09-20 01:55:12 +00:00 committed by Gitee
commit 69aabb8734
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
340 changed files with 9709 additions and 13057 deletions

View File

@ -57,10 +57,18 @@
<filefilter name="binaryFileTypePolicyFilter" desc="Filters for binary file policies">
<filteritem type="filepath" name="demos/.*.png" desc="self developed image"/>
<filteritem type="filepath" name="demos/.*.jpg" desc="self developed image"/>
<filteritem type="filepath" name="common/.*/src/main/resources/base/media/.*.png" desc="self developed image"/>
<filteritem type="filepath" name="common/.*/src/main/js/default/common/image/icon/.*.png" desc="self developed image"/>
<filteritem type="filepath" name="common/.*/src/main/js/default/common/image/icon/.*.jpg" desc="self developed image"/>
<filteritem type="filepath" name="common/.*/src/main/js/default/common/image/svg/.*.svg" desc="self developed image"/>
<filteritem type="filepath" name="entry/src/main/resources/base/media/.*.png" desc="self developed image"/>
<filteritem type="filepath" name="entry/src/main/js/default/common/image/icon/.*.png" desc="self developed image"/>
<filteritem type="filepath" name="entry/src/main/js/default/common/image/icon/.*.jpg" desc="self developed image"/>
<filteritem type="filepath" name="entry/src/main/js/default/common/image/svg/.*.svg" desc="self developed image"/>
<filteritem type="filepath" name="features/.*/src/main/resources/base/media/.*.png" desc="self developed image"/>
<filteritem type="filepath" name="features/.*/src/main/js/default/common/image/icon/.*.png" desc="self developed image"/>
<filteritem type="filepath" name="features/.*/src/main/js/default/common/image/icon/.*.jpg" desc="self developed image"/>
<filteritem type="filepath" name="features/.*/src/main/js/default/common/image/svg/.*.svg" desc="self developed image"/>
<filteritem type="filepath" name="figures/.*.png" desc="self developed image"/>
</filefilter>

View File

@ -1,17 +1,3 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
{
"app": {
"signingConfigs": [],
@ -37,5 +23,45 @@
},
],
},
{
"name": "base",
"srcPath": "./common/base"
},
{
"name": "timeline",
"srcPath": "./features/timeline"
},
{
"name": "browser",
"srcPath": "./features/browser"
},
{
"name": "grid",
"srcPath": "./features/grid"
},
{
"name": "album",
"srcPath": "./features/album"
},
{
"name": "selectAlbum",
"srcPath": "./features/selectAlbum"
},
{
"name": "third",
"srcPath": "./features/third"
},
{
"name": "mediaOperation",
"srcPath": "./features/mediaOperation"
},
{
"name": "distributed",
"srcPath": "./features/distributed"
},
{
"name": "formEditor",
"srcPath": "./features/formEditor"
}
],
}

3
common/base/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/node_modules
/.preview
/build

View File

@ -0,0 +1,5 @@
{
"apiType": "stageMode",
"buildOption": {
}
}

View File

@ -0,0 +1,3 @@
// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
module.exports = require('@ohos/hvigor-ohos-plugin').harTasks

View File

@ -12,9 +12,4 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export enum SelectionState {
NONE,
SELECTED,
NOT_SELECTED,
}
export { MainPage } from './src/main/ets/components/MainPage/MainPage'

5
common/base/package-lock.json generated Normal file
View File

@ -0,0 +1,5 @@
{
"name": "@ohos/base",
"version": "1.0.0",
"lockfileVersion": 1
}

14
common/base/package.json Normal file
View File

@ -0,0 +1,14 @@
{
"license": "ISC",
"types": "",
"devDependencies": {},
"name": "@ohos/base",
"description": "a npm package which contains arkUI2.0 page",
"ohos": {
"org": ""
},
"main": "src/main/ets/components/MainPage/MainPage.ets",
"repository": {},
"version": "1.0.0",
"dependencies": {}
}

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Constants } from '../model/common/Constants'
import { WindowConstants } from '../constants/WindowConstants'
// New style
@Component
@ -20,12 +20,12 @@ export struct EmptyAlbumComponent {
@Consume gridHeight: number;
@Consume isBigCard: boolean;
@State icHeight: number = 0;
gridAspectRatio = Constants.CARD_ASPECT_RATIO;
gridAspectRatio = WindowConstants.CARD_ASPECT_RATIO;
aboutToAppear(): void {
let numberHeight = px2vp(fp2px(Constants.TEXT_SIZE_BODY2));
let nameHeight = px2vp(fp2px(Constants.TEXT_SIZE_SUB_TITLE1));
this.icHeight = this.gridHeight - Constants.ALBUM_SET_NEW_ICON_MARGIN - numberHeight - nameHeight;
let numberHeight = px2vp(fp2px(WindowConstants.TEXT_SIZE_BODY2));
let nameHeight = px2vp(fp2px(WindowConstants.TEXT_SIZE_SUB_TITLE1));
this.icHeight = this.gridHeight - WindowConstants.ALBUM_SET_NEW_ICON_MARGIN - numberHeight - nameHeight;
}
build() {

View File

@ -0,0 +1,244 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import MediaLib from '@ohos.multimedia.mediaLibrary';
import { logDebug, logInfo, logError } from '../utils/LoggerUtils'
import { AnimationConstants } from '../constants/AnimationConstants'
import { MediaDataItem } from '../data/MediaDataItem'
import { DateUtil } from '../utils/DateUtil'
import { Broadcast } from '../utils/Broadcast'
import { BroadcastConstants } from '../constants/BroadcastConstants'
import { startTrace } from '../utils/TraceControllerUtils'
import { MediaConstants } from '../constants/MediaConstants'
import { startTraceWithTaskId, finishTraceWithTaskId } from '../utils/TraceControllerUtils'
const TAG = "ImageGridItemComponent"
// General grid picture control
@Component
export struct ImageGridItemComponent {
@Consume broadCast: Broadcast;
@Consume isSelectedMode: boolean;
@Consume @Watch('onShow') isShow: boolean;
@State thumbnail: string = ""
@State isFavourite: boolean = false
@State pressAnimScale: number = 1.0;
@State isError: boolean = false
pageName = '';
mediaItem: MediaDataItem;
isThird = false;
private isEnteringPhoto = false;
private resetPressAnim(): void {
this.pressAnimScale = 1;
this.isEnteringPhoto = false;
}
aboutToAppear(): void {
logDebug(TAG, 'aboutToAppear');
this.resetShow();
}
private resetShow() {
startTraceWithTaskId("load MediaItem", this.mediaItem.index)
this.mediaItem.load(false).then(() => {
finishTraceWithTaskId("load MediaItem", this.mediaItem.index)
this.thumbnail = this.mediaItem.getThumbnail(MediaConstants.DEFAULT_SIZE, MediaConstants.DEFAULT_SIZE)
this.isError = false
logDebug(TAG, `getThumbnail ${this.thumbnail}`)
this.mediaItem.isFavor().then((status: boolean) => {
this.isFavourite = status
})
})
this.resetPressAnim();
}
aboutToDisappear(): void {
logDebug(TAG, `aboutToDisappear`);
this.resetPressAnim();
}
private onShow(): void {
this.resetShow();
}
async routePage(isError: boolean) {
logInfo(TAG, `routePage ${isError}`);
try {
startTrace('enterPhotoBrowser');
if (this.isThird) {
this.broadCast.emit(BroadcastConstants.JUMP_THIRD_PHOTO_BROWSER, [this.pageName, this.mediaItem]);
} else {
this.broadCast.emit(BroadcastConstants.JUMP_PHOTO_BROWSER, [this.pageName, this.mediaItem]);
}
} catch (err) {
logError(TAG, `fail callback, code: ${err.code}, msg: ${err.msg}`);
}
}
async routeToPreviewPage() {
try {
logInfo(TAG, 'routeToPreviewPage');
this.broadCast.emit(BroadcastConstants.JUMP_THIRD_PHOTO_BROWSER, [this.pageName, this.mediaItem]);
} catch (err) {
logError(TAG, `fail callback, code: ${err.code}, msg: ${err.msg}`);
}
}
private onSelected() {
logInfo(TAG, 'onSelected');
this.mediaItem.setSelect(!this.mediaItem.isSelect)
this.broadCast.emit(BroadcastConstants.SELECT, [this.mediaItem.index])
}
private selectStateChange() {
logInfo(TAG, `change selected ${this.isSelectedMode}`);
if (this.isSelectedMode) {
this.onSelected()
} else {
this.isSelectedMode = true
this.pressAnimScale = 1;
}
}
build() {
Stack({ alignContent: Alignment.Start }) {
Image(this.isError ? this.mediaItem.getAlt() : this.thumbnail)
.aspectRatio(1)
.rotate({ x: 0, y: 0, z: 1, angle: this.isError ? 0 : this.mediaItem.orientation })
.objectFit(ImageFit.Cover)
.autoResize(false)
.onComplete(() => {
logDebug(TAG, `Draw the image! ${this.thumbnail}`);
})
.onError(() => {
logError(TAG, `alt Image ${this.mediaItem.index} error :${this.thumbnail}`);
if (this.thumbnail.length == 0 || this.mediaItem.width == 0 || this.mediaItem.height == 0) {
this.resetShow()
} else {
this.isError = true
}
})
.sharedTransition(this.pageName + this.mediaItem.getHashCode(), {
duration: AnimationConstants.SHARE_TRANSITION_DURATION
})
if (this.mediaItem.mediaType == MediaLib.MediaType.VIDEO) {
Column()
.position({ x: '0%', y: '50%' })
.height('50%')
.width('100%')
.linearGradient({
angle: 0,
colors: [[$r('app.color.album_cover_gradient_start_color'), 0], [$r('app.color.transparent'), 1.0]]
})
Text(DateUtil.getFormattedDuration(this.mediaItem.duration))
.fontSize($r('sys.float.ohos_id_text_size_caption'))
.fontFamily($r('app.string.id_text_font_family_regular'))
.fontColor($r('app.color.text_color_above_picture'))
.lineHeight($r('app.float.grid_item_text_line_height'))
.position({ x: '0%', y: '100%' })
.markAnchor({
x: $r('app.float.grid_item_duration_markAnchor_x'),
y: $r('app.float.grid_item_duration_markAnchor_y')
})
.margin({ right: $r('app.float.grid_item_duration_margin_right') })
}
if (this.isFavourite) {
Image($r('app.media.ic_favorite_overlay'))
.height($r('app.float.icon_size'))
.width($r('app.float.icon_size'))
.objectFit(ImageFit.Contain)
.position({ x: '100%', y: '0%' })
.markAnchor({
x: $r('app.float.grid_item_favor_markAnchor_x'),
y: $r('app.float.grid_item_favor_markAnchor_y')
})
}
Column()
.height('100%')
.width('100%')
.backgroundColor(this.isSelectedMode && this.mediaItem.isSelect ?
$r('app.color.item_selection_bg_color') : $r('app.color.transparent'))
.onClick(() => {
if (this.isSelectedMode) {
this.onSelected();
} else {
logInfo(TAG, 'item onClick loadBmp');
if (this.isThird) {
this.broadCast.emit(BroadcastConstants.JUMP_THIRD_PHOTO_BROWSER, [this.pageName, this.mediaItem]);
} else {
this.broadCast.emit(BroadcastConstants.JUMP_PHOTO_BROWSER, [this.pageName, this.mediaItem]);
}
this.isEnteringPhoto = true;
}
})
if (this.isSelectedMode) {
Image($r('app.media.ic_photo_preview'))
.onClick(() => {
this.routeToPreviewPage();
logInfo(TAG, 'expand.');
})
.height($r('app.float.icon_size_hot'))
.width($r('app.float.icon_size_hot'))
.position({ x: '0%', y: '0%' })
.markAnchor({ x: 0, y: 0 })
.padding($r('app.float.grid_item_preview_padding'))
Image(this.mediaItem.isSelect
? $r('app.media.ic_gallery_public_checkbox_filled') : $r('app.media.ic_checkbox_off_overlay'))
.height($r('app.float.icon_size'))
.width($r('app.float.icon_size'))
.position({ x: '100%', y: '100%' })
.markAnchor({
x: $r('app.float.grid_item_checkbox_markAnchor'),
y: $r('app.float.grid_item_checkbox_markAnchor')
})
.onClick(() => {
this.onSelected();
})
}
}
.scale({
x: this.pressAnimScale,
y: this.pressAnimScale
})
.animation({
duration: AnimationConstants.PRESS_ANIM_DURATION,
curve: Curve.Ease
})
.onTouch(event => {
logInfo(TAG, `onTouch trigger: isSelectedMode: ${this.isSelectedMode},
isEnteringPhoto: ${this.isEnteringPhoto}, ${JSON.stringify(event)}`);
if (this.isSelectedMode) {
return;
}
// Press animation
if (event.type == TouchType.Down) {
this.pressAnimScale = AnimationConstants.PRESS_ANIM_SCALE;
}
if (event.type == TouchType.Up && !this.isEnteringPhoto && this.pressAnimScale != 1) {
this.pressAnimScale = 1;
}
})
.gesture(LongPressGesture().onAction((event: GestureEvent) => {
if (!this.isThird) {
logInfo(TAG, `LongPressGesture ${this.isSelectedMode}`);
this.selectStateChange();
}
}))
}
}

View File

@ -12,17 +12,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@Entry
@Component
export struct MainPage {
@State message: string = 'Hello World'
export class PeerInfo {
coverUri: any;
deviceName: string;
count: number; // the count of photos
networkId: string;
constructor(uri, name, count, networkId) {
this.coverUri = uri;
this.deviceName = name;
this.count = count;
this.networkId = networkId;
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}
}

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export class AnimationConstants {
static readonly SHARE_TRANSITION_DURATION = 200;
static readonly DELETE_ANIMATE_DURATION: number = 150;
// Press animation duration
static readonly PRESS_ANIM_DURATION = 100;
// Press to scale the value at the end of the animation
static readonly PRESS_ANIM_SCALE = 0.9;
}

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
export class BroadCastConstants {
export class BroadcastConstants {
static readonly SELECT = 'select';
static readonly GROUP_SELECT = 'groupSelect';
static readonly JUMP_PHOTO_BROWSER = 'JumpPhotoPage';
@ -24,7 +24,6 @@ export class BroadCastConstants {
static readonly BACK_PRESS_EVENT = 'back';
static readonly RESET_STATE_EVENT = 'resetState';
static readonly ON_TAB_CHANGED = 'onTabChanged';
static readonly PHOTO_BROWSER_ACTIVE = 'photoBrowserActive';
static readonly RESET_ZERO = 'resetZero';
static readonly SHOW_DETAIL_DIALOG = 'showDetailDialog';
static readonly SHOW_MULTI_SELECT_DIALOG = 'showMultiSelectDialog';
@ -51,7 +50,8 @@ export class BroadCastConstants {
static readonly INIT_DATE_TEXT = 'init_date_text';
static readonly THIRD_ROUTE_PAGE = 'third_route_page';
static readonly ON_DATA_RELOADED_WITH_EDIT = 'on_data_reloaded_with_edit';
static readonly PHOTO_EDIT_SAVE_ID: string = 'photo_edit_save_id';
static readonly PHOTO_EDIT_SAVE_COMPLETE: string = 'photo_edit_save_complete';
static readonly CHANGE_SWIPER_DURATION = 'change_swiper_duration';
// USED for AppStorage
static readonly LEFT_BLANK: string = 'leftBlank';
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export class MediaConstants {
// Media item status
static readonly UNDEFINED = 0;
static readonly PART_LOADED = 1
static readonly LOADED = 2;
static readonly TRASHED = 3;
// Media type
static readonly MEDIA_TYPE_IMAGE: string = 'image';
static readonly MEDIA_TYPE_VIDEO: string = 'video';
static readonly MEDIA_TYPE_ALBUM: string = 'album';
static readonly MEDIA_TYPE_DEVICE: string = 'device';
static readonly MEDIA_TYPE_REMOTE: string = 'remote';
static readonly DEVICE_STATE_ONLINE: string = 'online';
static readonly DEVICE_STATE_OFFLINE: string = 'offline';
static readonly DEVICE_STATE_CHANGE: string = 'change';
static readonly ROTATE_NONE = 0;
static readonly ROTATE_ONCE = 90;
static readonly ROTATE_TWICE = 180;
static readonly ROTATE_THIRD = 270;
static readonly ROTATE_AROUND = 360;
static readonly DEFAULT_SIZE = 256;
// select type
static readonly SELECT_TYPE_ALL = 0;
static readonly SELECT_TYPE_VIDEO = 1;
static readonly SELECT_TYPE_IMAGE = 2;
// album id
static readonly ALBUM_ID_ALL = 'default_all';
static readonly ALBUM_ID_CAMERA = 'default_camera';
static readonly ALBUM_ID_VIDEO = 'default_video';
static readonly ALBUM_ID_RECYCLE = 'default_recycle';
static readonly ALBUM_ID_FAVOR = 'default_favor';
static readonly ALBUM_ID_SNAPSHOT = 'default_snapshot';
static readonly ALBUM_ID_REMOTE = 'default_remote';
static readonly ALBUM_DISABLE_COPY_LIST = new Set([
MediaConstants.ALBUM_ID_ALL,
MediaConstants.ALBUM_ID_VIDEO,
MediaConstants.ALBUM_ID_RECYCLE,
MediaConstants.ALBUM_ID_FAVOR
]);
static readonly ALBUM_DISABLE_DELETE_LIST = new Set([
MediaConstants.ALBUM_ID_ALL,
MediaConstants.ALBUM_ID_CAMERA,
MediaConstants.ALBUM_ID_VIDEO,
MediaConstants.ALBUM_ID_RECYCLE,
MediaConstants.ALBUM_ID_FAVOR
]);
static readonly ALBUM_DISABLE_NEW_LIST = new Set([
MediaConstants.ALBUM_ID_ALL,
MediaConstants.ALBUM_ID_CAMERA,
MediaConstants.ALBUM_ID_VIDEO,
MediaConstants.ALBUM_ID_RECYCLE,
MediaConstants.ALBUM_ID_FAVOR,
MediaConstants.ALBUM_ID_SNAPSHOT
]);
static readonly ALBUM_DISABLE_RENAME_LIST = new Set([
MediaConstants.ALBUM_ID_ALL,
MediaConstants.ALBUM_ID_CAMERA,
MediaConstants.ALBUM_ID_VIDEO,
MediaConstants.ALBUM_ID_RECYCLE,
MediaConstants.ALBUM_ID_FAVOR,
MediaConstants.ALBUM_ID_SNAPSHOT
]);
static readonly ALBUM_DEFAULT_SORT_LIST = [
MediaConstants.ALBUM_ID_CAMERA,
MediaConstants.ALBUM_ID_ALL,
MediaConstants.ALBUM_ID_VIDEO,
MediaConstants.ALBUM_ID_SNAPSHOT,
MediaConstants.ALBUM_ID_FAVOR
];
static readonly CAMERA_ALBUM_PATH = 'Camera'
static readonly REMOTE_ALBUM_PATH = 'FromOtherDevices'
static readonly SNAPSHOT_ALBUM_PATH = 'Screenshots'
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export class RouterConstants {
static readonly ENTRY_FROM_NONE = 0;
static readonly ENTRY_FROM_CAMERA = 1;
static readonly ENTRY_FROM_SINGLE_SELECT = 2;
static readonly ENTRY_FROM_MULTIPLE_SELECT = 3;
static readonly ENTRY_FROM_RECYCLE = 4;
static readonly ENTRY_FROM_DISTRIBUTED = 5;
static readonly ENTRY_FROM_NORMAL = 6;
static readonly ENTRY_FROM_FORM_ABILITY = 7;
static readonly ENTRY_FROM_FORM_FORM_EDITOR = 8;
static readonly ENTRY_FROM_VIEW_DATA = 9;
static readonly ENTRY_FROM_FORM_ABILITY_NONE = 12;
static readonly ENTRY_FROM = {
NORMAL: 0,
CAMERA: 1,
SINGLE_SELECT: 2,
MULTIPLE_SELECT: 3,
RECYCLE: 4,
DISTRIBUTED: 5,
CARD: 6,
VIEW_DATA: 7
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export class WindowConstants {
static readonly MAIN_WINDOW: string = 'mainWindow';
static readonly TOP_BAR_SIZE: number = 56;
static readonly TOOL_BAR_SIZE: number = 72;
static readonly BOTTOM_TOOL_BAR_SIZE: number = 196;
static readonly FILTER_BOTTOM_TOOL_BAR_SIZE: number = 232;
// Grid Constants
static readonly ACTION_BAR_HEIGHT: number = 56;
static readonly TAB_BAR_WIDTH: number = 96;
static readonly GRID_GUTTER: number = 2;
static readonly GRID_IMAGE_SIZE: number = 256;
static readonly GRID_MAX_SIZE_RATIO: number = 1.2;
static readonly GRID_MIN_COUNT: number = 4;
static readonly SCROLL_BAR_SIDE_MIN_GAP: number = 12;
static readonly SCROLL_MARGIN: number = 24;
static readonly SCROLL_BAR_VISIBLE_THRESHOLD: number = 50;
static readonly CARD_ASPECT_RATIO: number = 0.75;
static readonly TEXT_SIZE_SUB_TITLE1: number = 18; // ohos_id_text_size_sub_title1
static readonly TEXT_SIZE_BODY2: number = 14; // ohos_id_text_size_body2
static readonly TEXT_SIZE_SUB_TITLE2: number = 16; // ohos_id_text_size_sub_title2
static readonly ALBUM_SET_NEW_ICON_SIZE: number = 22;
static readonly ALBUM_SET_NEW_ICON_MARGIN: number = 8;
static readonly ALBUM_SET_MARGIN: number = 24;
static readonly ALBUM_SET_GUTTER: number = 12;
static readonly ALBUM_SET_COVER_SIZE: number = 150;
}

View File

@ -0,0 +1,110 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import MediaLib from '@ohos.multimedia.mediaLibrary';
import mediaModel from '../model/MediaModel'
import { logDebug, logError } from '../utils/LoggerUtils'
import selectManager from '../manager/SelectManager'
import { MediaConstants } from '../constants/MediaConstants'
import { getFetchOptions } from '../helper/MediaDataHelper';
const TAG = "AlbumDataItem"
export class AlbumDataItem {
index: number;
id: string;
uri: string;
orientation: number;
displayName: string;
count: number;
isDisableRename: boolean;
isDisableDelete: boolean;
relativePath: string;
innerId: number;
selectType: number = MediaConstants.SELECT_TYPE_ALL
deviceId: string = ""
isSelect: boolean = false
status: number = MediaConstants.UNDEFINED
constructor(id: string, count: number, displayName: string, selectType: number, deviceId: string) {
this.id = id
this.displayName = displayName
this.count = count
this.isDisableRename = MediaConstants.ALBUM_DISABLE_RENAME_LIST.has(id)
this.isDisableDelete = MediaConstants.ALBUM_DISABLE_DELETE_LIST.has(id)
this.selectType = selectType
this.deviceId = deviceId
}
getHashCode(): string {
return `${this.id} ${this.orientation}`
}
async load(): Promise<void> {
if (this.status >= MediaConstants.LOADED) {
return
}
let fetchOption: MediaLib.MediaFetchOptions = await getFetchOptions(this.selectType, this.id, this.deviceId)
let fileAsset = (await mediaModel.getAllMediaItem(this.id, fetchOption, false)).fileAsset
this.update(fileAsset)
}
update(fileAsset: MediaLib.FileAsset) {
this.uri = fileAsset.uri
this.orientation = fileAsset.orientation
this.relativePath = fileAsset.relativePath
this.status = MediaConstants.LOADED
}
async getRelativePath(): Promise<string> {
await this.load()
return this.relativePath
}
getThumbnail(): string{
logDebug(TAG, `this.uri ${this.uri}`)
return this.uri + `/thumbnail/256/256`
}
async getVideoCount(): Promise<number> {
if (this.selectType == MediaConstants.SELECT_TYPE_IMAGE) {
return 0
}
let videoFetchOption: MediaLib.MediaFetchOptions = await getFetchOptions(MediaConstants.SELECT_TYPE_VIDEO, this.id, this.deviceId)
return (await mediaModel.getAllMediaItem(this.id, videoFetchOption, true)).counts
}
setSelect(isSelect: boolean) {
this.isSelect = isSelect
selectManager.setSelect(this.uri, this.isSelect)
}
async onDelete(): Promise<boolean> {
try {
let fetchOption: MediaLib.MediaFetchOptions = await getFetchOptions(this.selectType, this.id, "")
await mediaModel.deleteAll(fetchOption)
selectManager.deleteSelect(this.uri)
this.status = MediaConstants.TRASHED
return true
} catch (err) {
logError(TAG, `onDelete error: ${JSON.stringify(err)}`)
return false
}
}
isDeleted(): boolean {
return this.status == MediaConstants.TRASHED
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import MediaLib from '@ohos.multimedia.mediaLibrary';
import mediaModel from '../model/MediaModel'
import { MediaConstants } from '../constants/MediaConstants'
import { MediaDataItem } from './MediaDataItem'
export class FavorMediaDataItem extends MediaDataItem {
constructor(selections: string, selectionArgs: Array<string>, index: number) {
super(selections, selectionArgs, "", index)
}
async loadFileAsset(): Promise<MediaLib.FileAsset> {
let fetchOption: MediaLib.MediaFetchOptions = {
selections: this.selections,
selectionArgs: this.selectionArgs,
order: `date_added DESC LIMIT ${this.index},1`
};
return (await mediaModel.getAllFavorMediaItem(fetchOption, false)).fileAsset
}
async setFavor(): Promise<boolean> {
let isSuccess: boolean = await super.setFavor()
let isFavor: boolean = await super.isFavor()
this.status = isFavor ? this.status : MediaConstants.TRASHED
return isSuccess
}
}

View File

@ -0,0 +1,211 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import MediaLib from '@ohos.multimedia.mediaLibrary';
import { logDebug, logInfo, logWarn, logError } from '../utils/LoggerUtils'
import { ViewType } from '../data/ViewType'
import mediaModel from '../model/MediaModel'
import { MediaConstants } from '../constants/MediaConstants'
import { setOrientation } from '../helper/MediaDataHelper'
import selectManager from '../manager/SelectManager'
const TAG = "MediaDataItem"
const STATUS_UNDEFINED = -1
const STATUS_FALSE = 0
const STATUS_TRUE = 1
export class MediaDataItem {
readonly viewType = ViewType.ITEM
readonly hashIndex: number
index: number
dateAdded: number
dateModified: number
dateTaken: number
status: number = MediaConstants.UNDEFINED
isSelect: boolean = false
id: number
uri: string
orientation: number
duration: number
size: number
width: number; // width changed by orientation
height: number; // height changed by orientation
imgWidth: number; // may be smaller than width, as width is too large
imgHeight: number; // may be smaller than height, as height is too large
path: string
title: string
displayName: string
mediaType: MediaLib.MediaType
favouriteStatus: number = STATUS_UNDEFINED
canRotate: number = STATUS_UNDEFINED
selections: string = ""
selectionArgs: Array<string> = new Array()
deviceId: string = ''
constructor(selections: string, selectionArgs: Array<string>, deviceId: string, index: number) {
this.selections = selections
this.selectionArgs = selectionArgs
this.deviceId = deviceId
this.hashIndex = index
this.index = index
}
getHashCode(): string {
return this.status == MediaConstants.UNDEFINED ? `${this.hashIndex}` : `${this.uri} ${this.orientation}`
}
async loadFileAsset(): Promise<MediaLib.FileAsset> {
let fetchOption: MediaLib.MediaFetchOptions = {
selections: this.selections,
selectionArgs: this.selectionArgs,
order: `date_added DESC LIMIT ${this.index},1`
};
if (this.deviceId.length > 0) {
fetchOption['networkId'] = this.deviceId
}
return (await mediaModel.getAllCommonMediaItem(fetchOption, false)).fileAsset
}
async load(isForce: boolean): Promise<void> {
logInfo(TAG, `load ${this.status}`)
if (this.status > (isForce ? MediaConstants.PART_LOADED : MediaConstants.UNDEFINED)) {
return
}
let fileAsset = await this.loadFileAsset()
if (fileAsset) {
this.update(fileAsset)
}
return
}
update(fileAsset: MediaLib.FileAsset) {
this.id = fileAsset.id
this.uri = fileAsset.uri
this.orientation = fileAsset.orientation
this.mediaType = fileAsset.mediaType
this.duration = fileAsset.duration
this.size = fileAsset.size;
if (this.orientation == MediaConstants.ROTATE_ONCE || this.orientation == MediaConstants.ROTATE_THIRD) {
this.width = fileAsset.height;
this.height = fileAsset.width;
} else {
this.width = fileAsset.width;
this.height = fileAsset.height;
}
this.imgWidth = this.width;
this.imgHeight = this.height;
this.path = fileAsset.relativePath
this.title = fileAsset.title;
this.displayName = fileAsset.displayName
this.dateAdded = fileAsset.dateAdded * 1000
this.dateModified = fileAsset.dateModified * 1000
this.dateTaken = fileAsset.dateTaken * 1000
this.isSelect = selectManager.isSelect(this.uri, this.isSelect)
// may change
fileAsset.isFavorite().then((isFavor: boolean) => this.favouriteStatus = (isFavor) ? STATUS_TRUE : STATUS_FALSE)
if (this.width > 0 && this.height > 0) {
this.status = MediaConstants.LOADED
} else {
this.status = MediaConstants.PART_LOADED
}
}
getThumbnail(width: number, height: number): string{
logDebug(TAG, `getThumbnail ${this.status}`)
if (this.status != MediaConstants.LOADED) {
logWarn(TAG, `getThumbnail fail as status: ${this.status}`)
return ""
}
logDebug(TAG, `this.uri ${this.uri}`)
return this.uri + `/thumbnail/${width}/${height}`
}
getAlt(): Resource{
if (this.mediaType == MediaLib.MediaType.VIDEO) {
return $r('app.media.alt_video_placeholder')
} else {
return $r('app.media.alt_placeholder')
}
}
setSelect(isSelect: boolean) {
this.isSelect = isSelect
selectManager.setSelect(this.uri, this.isSelect)
}
async onDelete(): Promise<boolean> {
try {
let fileAsset = await this.loadFileAsset()
await fileAsset.trash(true)
selectManager.deleteSelect(this.uri)
this.status = MediaConstants.TRASHED
return true
} catch (err) {
logError(TAG, `onDelete error: ${JSON.stringify(err)}`)
return false
}
}
isDeleted(): boolean {
return this.status == MediaConstants.TRASHED
}
async isFavor(): Promise<boolean> {
if (this.favouriteStatus == STATUS_UNDEFINED) {
let fileAsset = await this.loadFileAsset()
this.favouriteStatus = (await fileAsset.isFavorite()) ? STATUS_TRUE : STATUS_FALSE
}
return this.favouriteStatus == STATUS_TRUE
}
async setFavor(): Promise<boolean> {
let status = !(await this.isFavor())
try {
let fileAsset = await this.loadFileAsset()
await fileAsset.favorite(status)
await fileAsset.commitModify()
this.favouriteStatus = status ? STATUS_TRUE : STATUS_FALSE
return true
} catch (err) {
return false
}
}
async setOrientation(): Promise<void> {
let fileAsset = await this.loadFileAsset()
this.orientation = (this.orientation + MediaConstants.ROTATE_ONCE) % MediaConstants.ROTATE_AROUND
await setOrientation(fileAsset, this.orientation)
let tmp = this.width
this.width = this.height
this.height = tmp
}
async setName(name: string): Promise<void> {
let fileAsset = await this.loadFileAsset()
let displayName = fileAsset.displayName;
let index = displayName.lastIndexOf('.');
displayName = name + displayName.slice(index);
this.displayName = displayName
fileAsset.displayName = displayName;
this.title = name
fileAsset.title = name;
await fileAsset.commitModify()
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import MediaLib from '@ohos.multimedia.mediaLibrary';
import { logDebug } from '../utils/LoggerUtils'
import selectManager from '../manager/SelectManager'
const TAG = "PeerDataItem"
export class PeerDataItem {
index: number;
uri: string;
orientation: number;
deviceName: string;
count: number;
networkId: string;
isSelect: boolean;
constructor(count: number, peer: MediaLib.PeerInfo, fileAsset: MediaLib.FileAsset) {
this.uri = fileAsset.uri
this.orientation = fileAsset.orientation
this.deviceName = peer.deviceName
this.count = count
this.networkId = peer.networkId
}
getHashCode() {
return `${this.networkId} ${this.orientation}`
}
getThumbnail(): string{
logDebug(TAG, `this.uri ${this.uri}`)
return this.uri + `/thumbnail/256/256`
}
setSelect(isSelect: boolean) {
this.isSelect = isSelect
selectManager.setSelect(this.uri, this.isSelect)
}
}

View File

@ -13,19 +13,18 @@
* limitations under the License.
*/
import i18n from '@ohos.i18n';
import { Logger } from './Logger'
export class SimpleAlbumDataItem {
readonly id: string
readonly displayName: string
readonly relativePath: string
readonly deviceId: string
readonly deviceName: string
export class SystemUtil {
static logger: Logger = new Logger('SystemUtil');
public static getSystemLanguage(): string {
let systemLocale = i18n.getSystemLanguage();
let localInfo = systemLocale.split('-')[0];
return localInfo;
}
public static is24HourClock(): boolean {
return i18n.is24HourClock();
constructor(id: string, displayName: string, relativePath: string, deviceId: string, deviceName: string) {
this.id = id
this.displayName = displayName
this.relativePath = relativePath
this.deviceId = deviceId
this.deviceName = deviceName
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import MediaLib from '@ohos.multimedia.mediaLibrary';
import { logError } from '../utils/LoggerUtils';
import selectManager from '../manager/SelectManager'
import mediaModel from '../model/MediaModel'
import { MediaConstants } from '../constants/MediaConstants'
import { MediaDataItem } from './MediaDataItem'
const TAG = "TrashMediaDataItem"
export class TrashMediaDataItem extends MediaDataItem {
constructor(selections: string, selectionArgs: Array<string>, index: number) {
super(selections, selectionArgs, "", index)
this.setSelect(true)
}
async loadFileAsset(): Promise<MediaLib.FileAsset> {
let fetchOption: MediaLib.MediaFetchOptions = {
selections: this.selections,
selectionArgs: this.selectionArgs,
order: `date_added DESC LIMIT ${this.index},1`
};
return (await mediaModel.getAllTrashMediaItem(fetchOption, false)).fileAsset
}
async onRecover(): Promise<boolean> {
try {
let fileAsset = await this.loadFileAsset()
await fileAsset.trash(false)
selectManager.deleteSelect(this.uri)
this.status = MediaConstants.TRASHED
return true
} catch (err) {
logError(TAG, `onRecover error: ${JSON.stringify(err)}`)
return false
}
}
async onDelete(): Promise<boolean> {
try {
await mediaModel.deleteOne(this.uri)
selectManager.deleteSelect(this.uri)
this.status = MediaConstants.TRASHED
return true
} catch (err) {
logError(TAG, `onDelete error: ${JSON.stringify(err)}`)
return false
}
}
}

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import image from '@ohos.multimedia.image'
import MediaLib from '@ohos.multimedia.mediaLibrary';
import { logInfo, logError } from '../utils/LoggerUtils'
import mediaModel from '../model/MediaModel'
import { MediaConstants } from '../constants/MediaConstants'
import { getResourceString } from '../utils/ResourceUtils'
import { SimpleAlbumDataItem } from '../data/SimpleAlbumDataItem';
const TAG = "MediaDataHelper"
export class Rotatable {
rotatable: boolean
orientation: number
}
export async function setOrientation(fileAsset: MediaLib.FileAsset, orientation: number): Promise<void> {
logInfo(TAG, `setOrientation`)
try {
let fd: number = await mediaModel.openAsset('RW', fileAsset);
let imageSourceApi: image.ImageSource = image.createImageSource(fd);
await imageSourceApi.modifyImageProperty("Orientation", getPropertyValidOrientation(orientation))
imageSourceApi.release()
mediaModel.closeAsset(fd, fileAsset)
} catch (err) {
logError(TAG, `setOrientation err ${JSON.stringify(err)}`)
fileAsset.orientation = orientation
await fileAsset.commitModify()
}
}
function getPropertyValidOrientation(orientation: number): string {
logInfo(TAG, `getPropertyValidOrientation ${orientation}`)
switch (orientation) {
case MediaConstants.ROTATE_NONE:
return "1";
case MediaConstants.ROTATE_THIRD:
return "8";
case MediaConstants.ROTATE_TWICE:
return "3";
case MediaConstants.ROTATE_ONCE:
return "6";
default:
return ""
}
}
export async function getAlbumDisplayName(name: string): Promise<string> {
switch (name) {
case MediaConstants.ALBUM_ID_ALL:
return await getResourceString($r('app.string.album_all'));
case MediaConstants.ALBUM_ID_VIDEO:
return await getResourceString($r('app.string.album_video'));
case MediaConstants.ALBUM_ID_RECYCLE:
return await getResourceString($r('app.string.album_recycle'));
case MediaConstants.ALBUM_ID_CAMERA:
return await getResourceString($r('app.string.album_camera'));
case MediaConstants.ALBUM_ID_FAVOR:
return await getResourceString($r('app.string.album_favor'));
case MediaConstants.ALBUM_ID_REMOTE:
return await getResourceString($r('app.string.album_remote_device'));
case MediaConstants.ALBUM_ID_SNAPSHOT:
return await getResourceString($r('app.string.album_screen_shot'));
default:
break;
}
return null;
}
export async function getFetchOptions(selectType: number, albumId: string, deviceId: string): Promise<MediaLib.MediaFetchOptions> {
let selections: string = ""
let selectionArgs: Array<string> = []
let order: string = `date_added DESC`
if (selectType == MediaConstants.SELECT_TYPE_VIDEO || albumId == MediaConstants.ALBUM_ID_VIDEO) {
selections = MediaLib.FileKey.MEDIA_TYPE + ' = ?'
selectionArgs = [MediaLib.MediaType.VIDEO.toString()]
} else if (selectType == MediaConstants.SELECT_TYPE_IMAGE && albumId != MediaConstants.ALBUM_ID_VIDEO) {
selections = MediaLib.FileKey.MEDIA_TYPE + ' = ?'
selectionArgs = [MediaLib.MediaType.IMAGE.toString()]
} else if (selectType == MediaConstants.SELECT_TYPE_IMAGE && albumId == MediaConstants.ALBUM_ID_VIDEO) {
return undefined
} else {
selections = MediaLib.FileKey.MEDIA_TYPE + ' = ? or ' + MediaLib.FileKey.MEDIA_TYPE + ' = ?'
selectionArgs = [MediaLib.MediaType.IMAGE.toString(), MediaLib.MediaType.VIDEO.toString()]
}
if (albumId == MediaConstants.ALBUM_ID_CAMERA) {
let path = await mediaModel.getPublicDirectory(MediaLib.DirectoryType.DIR_CAMERA)
selections = `(${selections}) and ${MediaLib.FileKey.ALBUM_NAME} = ?`
selectionArgs.push(path.substr(0, path.length - 1))
} else if (albumId == MediaConstants.ALBUM_ID_SNAPSHOT) {
let path = await mediaModel.getPublicDirectory(MediaLib.DirectoryType.DIR_IMAGE) + "Screenshots/"
selections = `(${selections}) and ${MediaLib.FileKey.RELATIVE_PATH} = ?`
selectionArgs.push(path)
} else if ((new Number(albumId).valueOf() || 0) > 0) {
selections = `(${selections}) and ${MediaLib.FileKey.ALBUM_ID} = ?`
selectionArgs.push(albumId)
}
let fetchOption: MediaLib.MediaFetchOptions = {
selections: selections,
selectionArgs: selectionArgs,
order: order
};
if (deviceId.length > 0) {
fetchOption['networkId'] = deviceId
}
return fetchOption
}
export async function getFetchOptionsByItem(item: SimpleAlbumDataItem): Promise<MediaLib.MediaFetchOptions> {
let selections: string = `${MediaLib.FileKey.MEDIA_TYPE} = ? or ${MediaLib.FileKey.MEDIA_TYPE} = ?`
let selectionArgs: string[] = [MediaLib.MediaType.IMAGE.toString(), MediaLib.MediaType.VIDEO.toString()]
if (item.displayName.length > 0) {
selections = `(${selections}) and ${MediaLib.FileKey.DISPLAY_NAME} = ?`
selectionArgs.push(item.displayName)
}
if (item.relativePath.length > 0) {
selections = `(${selections}) and ${MediaLib.FileKey.RELATIVE_PATH} = ?`
selectionArgs.push(item.relativePath)
}
let fetchOption: MediaLib.MediaFetchOptions = {
selections: selections,
selectionArgs: selectionArgs,
order: `date_added DESC`
};
return fetchOption
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { logInfo } from '../utils/LoggerUtils'
import { Broadcast } from '../utils/Broadcast'
import createOrGet from '../utils/SingleInstanceUtils';
const TAG = "BroadcastManager"
export class BroadcastManager {
// The global Broadcast of the application process. Event registration and destruction should be paired
private appBroadcast: Broadcast;
constructor() {
logInfo(TAG, 'constructor');
this.appBroadcast = new Broadcast();
}
public getBroadcast(): Broadcast {
return this.appBroadcast;
}
}
let broadcastManager = createOrGet(BroadcastManager, TAG);
export default broadcastManager as BroadcastManager;

View File

@ -13,10 +13,11 @@
* limitations under the License.
*/
import inputConsumer from '@ohos.multimodalInput.inputConsumer';
import { Logger } from '../../utils/Logger';
import { logDebug } from '../utils/LoggerUtils';
const TAG = "MultimodalInputManager"
export class MultimodalInputManager {
logger: Logger = new Logger('MultimodalInputManager');
//win + N
leftKeyOptions: any = {
@ -41,34 +42,34 @@ export class MultimodalInputManager {
};
async registerListener(callback) {
this.logger.debug(`registerListener start`);
logDebug(TAG, `registerListener start`);
inputConsumer.on('key', this.leftKeyOptions, (data) => {
this.logger.debug(`notificationRegister data: ${JSON.stringify(data)}`);
logDebug(TAG, `notificationRegister data: ${JSON.stringify(data)}`);
callback(0);
});
inputConsumer.on('key', this.rightKeyOptions, (data) => {
this.logger.debug(`controlRegister data: ${JSON.stringify(data)}`);
logDebug(TAG, `controlRegister data: ${JSON.stringify(data)}`);
callback(1);
});
inputConsumer.on('key', this.escKeyOptions, (data) => {
this.logger.debug(`escRegister data: ${JSON.stringify(data)}`);
logDebug(TAG, `escRegister data: ${JSON.stringify(data)}`);
callback(2);
});
this.logger.debug(`registerListener end`);
logDebug(TAG, `registerListener end`);
}
async unregisterListener() {
this.logger.debug(`unregisterListener start`);
logDebug(TAG, `unregisterListener start`);
inputConsumer.off('key', this.leftKeyOptions, (data) => {
this.logger.debug(`notificationUnregister data: ${JSON.stringify(data)}`);
logDebug(TAG, `notificationUnregister data: ${JSON.stringify(data)}`);
});
inputConsumer.off('key', this.rightKeyOptions, (data) => {
this.logger.debug(`controlUnregister data: ${JSON.stringify(data)}`);
logDebug(TAG, `controlUnregister data: ${JSON.stringify(data)}`);
});
inputConsumer.off('key', this.escKeyOptions, (data) => {
this.logger.debug(`escUnregister data: ${JSON.stringify(data)}`);
logDebug(TAG, `escUnregister data: ${JSON.stringify(data)}`);
});
this.logger.debug(`unregisterListener end`);
logDebug(TAG, `unregisterListener end`);
}
}

View File

@ -0,0 +1,404 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import deviceInfo from '@ohos.deviceInfo';
import window from '@ohos.window';
import createOrGet from '../utils/SingleInstanceUtils';
import { logDebug, logInfo, logError } from '../utils/LoggerUtils'
import { BroadcastConstants } from '../constants/BroadcastConstants';
import { WindowConstants } from '../constants/WindowConstants'
import { getResourceString } from '../utils/ResourceUtils'
export enum ColumnSize {
COLUMN_TWO = 2,
COLUMN_FOUR = 4,
COLUMN_SIX = 6,
COLUMN_EIGHT = 8,
COLUMN_TWELVE = 12
}
enum ScreenWidth {
WIDTH_MEDIUM = 520,
WIDTH_LARGE = 840
}
enum WindowMode {
UNDEFINED = 1,
FULL_SCREEN,
PRIMARY,
SECONDARY,
FLOATING
}
const TAG = "ScreenManager"
const APP_KEY_SCREEN_MANAGER = 'app_key_screen_manager';
const SCREEN_ORIENTATION_HORIZONTAL: string = 'isHorizontal';
const SCREEN_SIDEBAR: string = 'isSidebar';
const COLUMN_MARGIN: number = 12;
const COLUMN_GUTTER: number = 12;
class ScreenManager {
readonly ON_WIN_SIZE_CHANGED = 'on_win_size_changed';
readonly ON_LEFT_BLANK_CHANGED = 'on_left_blank_changed';
readonly DEFAULT_WIDTH: number = 1920;
readonly DEFAULT_HEIGHT: number = 1080;
readonly SPLIT_THRESHOLD = 1.7;
private winWidth = 0.0;
private winHeight = 0.0;
private statusBarHeight = 0;
private naviBarHeight = 0;
private leftBlank: [number, number, number, number] = [0, 0, 0, 0];
private events = [];
private mainWindow: window.Window = undefined;
// Default orientation
private horizontal = deviceInfo.deviceType != ('phone' || 'default')
// Default sidebar
private sidebar = deviceInfo.deviceType != ('phone' || 'default')
private windowMode = WindowMode.UNDEFINED;
constructor() {
logInfo(TAG, 'constructor');
}
async initializationSize(win): Promise<void> {
this.mainWindow = win;
this.setMainWindow(win)
await this.checkWindowMode();
}
/**
* Add Listeners
*
* @param event
* @param fn
*/
on(event, fn) {
if (Array.isArray(event)) {
for (let i = 0, l = event.length; i < l; i++) {
this.on(event[i], fn);
}
} else {
(this.events[event] || (this.events[event] = [])).push(fn);
}
}
/**
* Delete Listeners
*
* @param event
* @param fn
*/
off(event, fn) {
if (event == null || event == undefined) {
return;
}
if (Array.isArray(event)) {
for (let i = 0, l = event.length; i < l; i++) {
this.off(event[i], fn);
}
}
const cbs = this.events[event];
if (!cbs) {
return;
}
if (fn == null || fn == undefined) {
return;
}
let cb;
let i = cbs.length;
while (i--) {
cb = cbs[i];
if (cb === fn || cb.fn === fn) {
cbs.splice(i, 1);
break;
}
}
}
private emit(event, argument: any[]) {
let _self = this;
if (!this.events[event]) {
return;
}
let cbs = [...this.events[event]];
if (cbs) {
for (let i = 0, l = cbs.length; i < l; i++) {
let ref = cbs[i];
if (ref) {
try {
ref.apply(_self, argument);
} catch (e) {
new Error(e);
}
}
}
}
}
private isLeftBlankInitialized(): boolean {
return this.leftBlank[0] != 0 || this.leftBlank[1] != 0 || this.leftBlank[2] != 0 || this.leftBlank[3] != 0;
}
// Unitvp
getWinWidth(): number {
return px2vp(this.winWidth);
}
// Unitvp
getWinHeight(): number {
return px2vp(this.winHeight);
}
getStatusBarHeight(): number {
return px2vp(this.statusBarHeight);
}
getNaviBarHeight(): number {
return px2vp(this.naviBarHeight);
}
async initWindowMode() {
logDebug(TAG, `start to initialize photos application window mode: ${this.windowMode}`);
}
isSplitMode(): boolean {
return (WindowMode.PRIMARY == this.windowMode || WindowMode.SECONDARY == this.windowMode)
}
async checkWindowMode() {
let before = this.windowMode;
let mode = await globalThis.photosWindowStage.getWindowMode();
logInfo(TAG, `photos application before/current window mode: ${before}/${mode}`);
if (before == mode) {
return;
}
this.windowMode = mode;
if (WindowMode.FULL_SCREEN == this.windowMode) {
await this.setFullScreen();
} else {
this.setSplitScreen();
}
}
private setMainWindow(win: window.Window) {
logDebug(TAG, 'setMainWindow');
win.on('windowSizeChange', (data) => {
logDebug(TAG, `windowSizeChange ${JSON.stringify(data)}`);
this.checkWindowMode()
this.onWinSizeChanged(data);
})
}
private async setFullScreen() {
let topWindow: any = AppStorage.Get(WindowConstants.MAIN_WINDOW);
logDebug(TAG, 'getTopWindow start');
try {
await topWindow.setLayoutFullScreen(true)
logDebug(TAG, 'setFullScreen true Succeeded');
await this.hideStatusBar(topWindow);
} catch (err) {
logError(TAG, `setFullScreen err: ${err}`);
}
}
setSplitScreen() {
try {
this.statusBarHeight = 0;
this.naviBarHeight = 0;
this.leftBlank = [0, 0, 0, 0];
AppStorage.SetOrCreate(BroadcastConstants.LEFT_BLANK, this.leftBlank);
} catch (err) {
logError(TAG, `setSplitScreen err: ${err}`);
}
}
private async hideStatusBar(topWindow: any) {
logDebug(TAG, 'hideStatusBar start');
let names = ['navigation'];
logDebug(TAG, `getTopWindow names: ${names} end`);
try {
await topWindow.setSystemBarEnable(names)
logDebug(TAG, 'hideStatusBar Succeeded');
let data = await topWindow.getAvoidArea(0)
logDebug(TAG, `Succeeded in obtaining the area. Data: ${JSON.stringify(data)}`);
this.onLeftBlankChanged(data);
let barColor = await getResourceString($r('app.color.default_background_color'));
let barContentColor = await getResourceString($r('app.color.default_bar_content_color'));
if (!barColor) {
barColor = '#00FFFFFF';
}
if (!barContentColor) {
barContentColor = '#FF000000';
}
await topWindow.setSystemBarProperties({
navigationBarColor: barColor,
navigationBarContentColor: barContentColor
});
logInfo(TAG, 'setStatusBarColor done');
} catch (err) {
logError(TAG, `hideStatusBar err: ${err}`);
}
}
async setNavigationBarColor(barColor: string, barContentColor: string) {
logDebug(TAG, 'setNavigationBarColor start');
let topWindow: any = AppStorage.Get(WindowConstants.MAIN_WINDOW);
try {
topWindow.setSystemBarProperties(
{
navigationBarColor: barColor,
navigationBarContentColor: barContentColor
},
() => logInfo(TAG, 'setStatusBarColor done')
);
} catch (err) {
logError(TAG, `setNavigationBarColor err: ${err}`);
}
}
setSystemUi(isShowBar: boolean): void {
logDebug(TAG, 'setSystemUi start');
let topWindow: any = AppStorage.Get(WindowConstants.MAIN_WINDOW);
logDebug(TAG, 'getTopWindow start');
let names = ["navigation"];
if (!isShowBar) {
names = [];
}
logDebug(TAG, `getTopWindow names: ${names} end`);
try {
topWindow.setSystemBarEnable(names, () => {
logDebug(TAG, 'setFullScreen Succeeded');
if (isShowBar) {
topWindow.getAvoidArea(0, (err, data) => {
logInfo(TAG, 'Succeeded in obtaining the area. Data:' + JSON.stringify(data));
this.onLeftBlankChanged(data);
});
}
})
} catch (err) {
logError(TAG, `setSystemUi err: ${err}`);
}
}
private onLeftBlankChanged(area) {
if (area == null || area == undefined || area.bottomRect.height == 0) {
return;
}
let leftBlankBefore = {
status: this.statusBarHeight,
navi: this.naviBarHeight
};
this.statusBarHeight = 0;
this.naviBarHeight = area.bottomRect.height;
this.leftBlank = [this.leftBlank[0], this.leftBlank[1], this.leftBlank[2], area.bottomRect.height];
if (leftBlankBefore.status != this.statusBarHeight || leftBlankBefore.navi != this.naviBarHeight) {
logInfo(TAG, `leftBlank changed: ${JSON.stringify(leftBlankBefore)}-${JSON.stringify(this.leftBlank)}`)
AppStorage.SetOrCreate(BroadcastConstants.LEFT_BLANK, this.leftBlank);
}
}
private onWinSizeChanged(size) {
logInfo(TAG, `onWinSizeChanged ${JSON.stringify(size)}`);
if (size == null || size == undefined) {
return;
}
let sizeBefore = {
width: this.winWidth,
height: this.winHeight
};
this.winWidth = size.width;
this.winHeight = size.height;
if (sizeBefore.width != this.winWidth || sizeBefore.height != this.winHeight) {
logInfo(TAG, `winSize changed: ${JSON.stringify(sizeBefore)} -> ${JSON.stringify(size)}`);
this.emit(screenManager.ON_WIN_SIZE_CHANGED, [size]);
}
}
private onRotationAngleChanged(angle) {
if (angle == null || angle == undefined) {
return;
}
if (angle == 0) {
this.horizontal = false;
} else {
this.horizontal = true;
}
AppStorage.SetOrCreate(SCREEN_ORIENTATION_HORIZONTAL, this.horizontal);
}
isHorizontal(): boolean {
if (AppStorage.Get(SCREEN_ORIENTATION_HORIZONTAL) == null) {
AppStorage.SetOrCreate(SCREEN_ORIENTATION_HORIZONTAL, this.horizontal);
}
return AppStorage.Get(SCREEN_ORIENTATION_HORIZONTAL);
}
isSidebar(): boolean {
if (AppStorage.Get(SCREEN_SIDEBAR) == null) {
AppStorage.SetOrCreate(SCREEN_SIDEBAR, this.sidebar);
}
return AppStorage.Get(SCREEN_SIDEBAR);
}
getColumnsWidth(count: number): number {
let columns = this.getScreenColumns()
logInfo(TAG, `getColumnsWidth count is ${count} colunms is ${columns}`);
let columnWidth = (px2vp(this.winWidth) - COLUMN_MARGIN) / columns;
return columnWidth * count - COLUMN_GUTTER;
}
getScreenColumns(): number {
let width = px2vp(this.winWidth)
if (width < ScreenWidth.WIDTH_MEDIUM) {
return ColumnSize.COLUMN_FOUR;
} else if (width >= ScreenWidth.WIDTH_MEDIUM && width < ScreenWidth.WIDTH_LARGE) {
return ColumnSize.COLUMN_EIGHT;
} else {
return ColumnSize.COLUMN_TWELVE;
}
}
setKeepScreenOn() {
logInfo(TAG, 'setKeepScreenOn start');
let topWindow: any = AppStorage.Get('mainWindow');
try {
topWindow.setKeepScreenOn(true, () => logInfo(TAG, 'setKeepScreenOn Succeeded'))
} catch (err) {
logError(TAG, `setKeepScreenOn err: ${err}`);
}
}
setKeepScreenOff() {
logInfo(TAG, 'setKeepScreenOff start');
let topWindow: any = AppStorage.Get('mainWindow');
try {
topWindow.setKeepScreenOn(false, () => logInfo(TAG, 'setKeepScreenOff Succeeded'))
} catch (err) {
logError(TAG, `setKeepScreenOff err: ${err}`);
}
}
}
let screenManager = createOrGet(ScreenManager, TAG);
export default screenManager as ScreenManager;

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import createOrGet from '../utils/SingleInstanceUtils';
const TAG = ""
class SelectManager {
private status: Map<string, boolean> = new Map()
isSelect(key: string, defaultValue: boolean): boolean{
if (this.status.has(key)) {
return this.status.get(key)
} else {
return defaultValue
}
}
setSelect(key: string, value: boolean) {
this.status.set(key, value)
}
deleteSelect(key: string) {
this.status.delete(key)
}
}
let selectManager = createOrGet(SelectManager, TAG);
export default selectManager as SelectManager;

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import MediaLib from '@ohos.multimedia.mediaLibrary';
import { logDebug, logWarn, logError } from '../utils/LoggerUtils';
import { AlbumDataItem } from '../data/AlbumDataItem'
import { MediaConstants } from '../constants/MediaConstants'
import mediaModel from '../model/MediaModel'
import { getAlbumDisplayName, getFetchOptions } from '../helper/MediaDataHelper'
const TAG = "AlbumDataImpl"
export class AlbumDataImpl {
private blackList: string[] = []
private selectType: number = MediaConstants.SELECT_TYPE_ALL
private deviceId: string = ''
setBlackList(blackList: string[]) {
this.blackList = blackList
}
setSelectType(selectType: number) {
this.selectType = selectType
}
setDeviceId(deviceId: string) {
this.deviceId = deviceId
}
async reloadAlbumItemData(): Promise<AlbumDataItem[]> {
let albumDataItems = []
for (let i = 0;i < MediaConstants.ALBUM_DEFAULT_SORT_LIST.length; i++) {
await this.getAlbumItem(MediaConstants.ALBUM_DEFAULT_SORT_LIST[i], albumDataItems)
}
await this.getCommonAlbumItem(albumDataItems)
await this.getAlbumItem(MediaConstants.ALBUM_ID_RECYCLE, albumDataItems)
return albumDataItems
}
private async getCommonAlbumItem(albumDataItems: AlbumDataItem[]): Promise<void> {
let fetchOption: MediaLib.MediaFetchOptions = await getFetchOptions(this.selectType, "", this.deviceId)
if (fetchOption == undefined) {
return
}
fetchOption.selections = `(${fetchOption.selections}) and (${MediaLib.FileKey.ALBUM_NAME} <> ? and ${MediaLib.FileKey.ALBUM_NAME} <> ?)`
fetchOption.selectionArgs.push('Camera', 'Screenshots')
let albums: MediaLib.Album[] = await mediaModel.getAlbums(fetchOption)
for (let i = 0;i < albums.length; i++) {
let album: MediaLib.Album = albums[i]
if (this.blackList.indexOf(album.albumId.toString()) >= 0) {
continue
}
let fetchFileResult: MediaLib.FetchFileResult = await album.getFileAssets()
try {
let count = fetchFileResult.getCount()
if (count == 0) {
continue
}
let item = new AlbumDataItem(album.albumId.toString(), count, album.albumName, this.selectType, this.deviceId)
item.update(await fetchFileResult.getFirstObject())
albumDataItems.push(item)
} catch (err) {
logError(TAG, `on err: ${JSON.stringify(err)}`)
} finally {
fetchFileResult.close()
}
}
}
private async getAlbumItem(id: string, albumDataItems: AlbumDataItem[]): Promise<void> {
if (this.blackList.indexOf(id) >= 0) {
logDebug(TAG, `no need as in black list`)
return
}
if (this.deviceId.length > 0 && (id != MediaConstants.ALBUM_ID_SNAPSHOT && id != MediaConstants.ALBUM_ID_CAMERA)) {
logDebug(TAG, `no need`)
return
}
let fetchOption: MediaLib.MediaFetchOptions = await getFetchOptions(this.selectType, id, this.deviceId)
if (fetchOption == undefined) {
logWarn(TAG, `${id} fetchOption is undefined`)
return
}
let item = await mediaModel.getAllMediaItem(id, fetchOption, false)
if (item.counts == 0) {
logWarn(TAG, `${id} is empty`)
return
}
let displayName = await getAlbumDisplayName(id)
let albumItem: AlbumDataItem = new AlbumDataItem(id, item.counts, displayName, this.selectType, this.deviceId)
albumItem.update(item.fileAsset)
albumDataItems.push(albumItem)
return
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import MediaLib from '@ohos.multimedia.mediaLibrary';
import { logInfo } from '../utils/LoggerUtils';
import { MediaConstants } from '../constants/MediaConstants';
import mediaModel from '../model/MediaModel'
import { PeerDataItem } from '../data/PeerDataItem'
const TAG = "DistributedDataImpl"
export class DistributedDataImpl {
async reloadAlbumItemData(): Promise<PeerDataItem[]> {
let peerDataItems = []
let peers: MediaLib.PeerInfo[] = await mediaModel.getActivePeers()
logInfo(TAG, `peers ${JSON.stringify(peers)}`)
for (let i = 0;i < peers.length; i++) {
let selections: string = `${MediaLib.FileKey.MEDIA_TYPE} = ? or ${MediaLib.FileKey.MEDIA_TYPE} = ?`
let selectionArgs: string[] = [MediaLib.MediaType.IMAGE.toString(), MediaLib.MediaType.VIDEO.toString()]
let fetchOption: MediaLib.MediaFetchOptions = {
selections: selections,
selectionArgs: selectionArgs,
networkId: peers[i].networkId,
order: `date_added DESC`
}
let item = await mediaModel.getAllCommonMediaItem(fetchOption, false)
if (item.counts == 0) {
continue
}
peerDataItems.push(new PeerDataItem(item.counts, peers[i], item.fileAsset))
}
return peerDataItems
}
}

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import MediaLib from '@ohos.multimedia.mediaLibrary';
import { logDebug, logInfo } from '../utils/LoggerUtils';
import { WindowConstants } from '../constants/WindowConstants';
import mediaModel from '../model/MediaModel'
import screenManager from '../manager/ScreenManager'
import { MediaConstants } from '../constants/MediaConstants';
import { getFetchOptions } from '../helper/MediaDataHelper';
import { MediaDataItem } from '../data/MediaDataItem';
import { FavorMediaDataItem } from '../data/FavorMediaDataItem'
import { TrashMediaDataItem } from '../data/TrashMediaDataItem'
const TAG = "GroupDataImpl"
export class GroupDataImpl {
private selectType: number = MediaConstants.SELECT_TYPE_ALL
private albumId: string = ""
private deviceId: string = ""
setSelectType(selectType: number) {
this.selectType = selectType
}
setAlbumId(id: string) {
logInfo(TAG, `setAlbumId: ${id}`)
this.albumId = id
}
setDeviceId(id: string) {
logInfo(TAG, `setDeviceId: ${id}`)
this.deviceId = id
}
async reloadGroupItemData(isGrid: boolean): Promise<MediaDataItem[]> {
if (isGrid) {
return this.reloadGridGroupItemData()
} else {
return this.reloadBrowserGroupItemData()
}
}
async reloadBrowserGroupItemData(): Promise<MediaDataItem[]> {
logDebug(TAG, `reloadGroupItemData`)
let groupDataItem = []
let fetchOption = await getFetchOptions(this.selectType, this.albumId, this.deviceId)
if (fetchOption == undefined) {
return []
}
let count: number = 0
if (this.albumId == MediaConstants.ALBUM_ID_FAVOR) {
count = (await mediaModel.getAllFavorMediaItem(fetchOption, true)).counts
for (let i = 0;i < count; i++) {
groupDataItem.push(new FavorMediaDataItem(fetchOption.selections, fetchOption.selectionArgs, i))
}
} else if (this.albumId == MediaConstants.ALBUM_ID_RECYCLE) {
count = (await mediaModel.getAllTrashMediaItem(fetchOption, true)).counts
for (let i = 0;i < count; i++) {
groupDataItem.push(new TrashMediaDataItem(fetchOption.selections, fetchOption.selectionArgs, i))
}
} else {
count = (await mediaModel.getAllCommonMediaItem(fetchOption, true)).counts
for (let i = 0;i < count; i++) {
groupDataItem.push(new MediaDataItem(fetchOption.selections, fetchOption.selectionArgs, this.deviceId, i))
}
}
logDebug(TAG, `reload finish count:${count}`)
return groupDataItem
}
async reloadGridGroupItemData(): Promise<MediaDataItem[]> {
logDebug(TAG, `reloadGroupItemData`)
let groupDataItem = []
let fetchOption = await getFetchOptions(this.selectType, this.albumId, this.deviceId)
if (fetchOption == undefined) {
return []
}
let groupCount: number = this.getCount()
let mediaFileAssets = await this.getMediaItemFileAssets(0, groupCount)
if (this.albumId == MediaConstants.ALBUM_ID_FAVOR) {
let count: number = (await mediaModel.getAllFavorMediaItem(fetchOption, true)).counts
for (let i = 0;i < count; i++) {
let item = new FavorMediaDataItem(fetchOption.selections, fetchOption.selectionArgs, i)
if (i < mediaFileAssets.length) {
item.update(mediaFileAssets[i])
}
groupDataItem.push(item)
}
} else if (this.albumId == MediaConstants.ALBUM_ID_RECYCLE) {
let count: number = (await mediaModel.getAllTrashMediaItem(fetchOption, true)).counts
for (let i = 0;i < count; i++) {
let item = new TrashMediaDataItem(fetchOption.selections, fetchOption.selectionArgs, i)
if (i < mediaFileAssets.length) {
item.update(mediaFileAssets[i])
}
groupDataItem.push(item)
}
} else {
let count: number = (await mediaModel.getAllCommonMediaItem(fetchOption, true)).counts
for (let i = 0;i < count; i++) {
let item = new MediaDataItem(fetchOption.selections, fetchOption.selectionArgs, this.deviceId, i)
if (i < mediaFileAssets.length) {
item.update(mediaFileAssets[i])
}
groupDataItem.push(item)
}
}
// do not use await to avoid load cost too much time
this.loadReset(groupDataItem, groupCount)
logDebug(TAG, `reload finish`)
return groupDataItem
}
private async getMediaItemFileAssets(start: number, count: number): Promise<MediaLib.FileAsset[]> {
let selections: string = MediaLib.FileKey.MEDIA_TYPE + ' = ? or ' + MediaLib.FileKey.MEDIA_TYPE + ' = ?'
let selectionArgs: Array<string> = [MediaLib.MediaType.IMAGE.toString(), MediaLib.MediaType.VIDEO.toString()]
let fetchOption: MediaLib.MediaFetchOptions = {
selections: selections,
selectionArgs: selectionArgs,
order: `date_added DESC LIMIT ${start},${count}`
};
if (this.albumId == MediaConstants.ALBUM_ID_FAVOR) {
return await mediaModel.getAllFavorMediaItems(fetchOption)
} else if (this.albumId == MediaConstants.ALBUM_ID_RECYCLE) {
return await mediaModel.getAllTrashMediaItems(fetchOption)
} else {
return await mediaModel.getAllMediaItems(fetchOption)
}
}
private getCount(): number {
let contentWidth = screenManager.getWinWidth();
let maxThumbWidth = px2vp(WindowConstants.GRID_IMAGE_SIZE) * WindowConstants.GRID_MAX_SIZE_RATIO;
let columns = Math.max(WindowConstants.GRID_MIN_COUNT, Math.ceil((contentWidth + WindowConstants.GRID_GUTTER) / (maxThumbWidth + WindowConstants.GRID_GUTTER)));
let contentHeight = screenManager.getWinHeight() - WindowConstants.ACTION_BAR_HEIGHT - screenManager.getNaviBarHeight()
let rows = Math.ceil((contentHeight + WindowConstants.GRID_GUTTER) / (maxThumbWidth + WindowConstants.GRID_GUTTER)) + 4
return columns * rows
}
private async loadReset(items: MediaDataItem[], count) {
let itemLen = items.length
let countLen = Math.ceil(itemLen / count)
for (let i = 1;i < countLen; i++) {
let mediaFileAsset: Array<MediaLib.FileAsset> = await this.getMediaItemFileAssets(i * count, count)
for (let j = 0;j < count; j++) {
if (i * count + j >= itemLen) {
return
}
items[i * count+j].update(mediaFileAsset[j])
}
}
}
}

View File

@ -0,0 +1,360 @@
// @ts-nocheck
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import fileIO from '@ohos.fileio';
import MediaLib from '@ohos.multimedia.mediaLibrary';
import { MediaConstants } from '../constants/MediaConstants'
import createOrGet from '../utils/SingleInstanceUtils';
import { logDebug, logInfo, logWarn, logError } from '../utils/LoggerUtils'
import { startTrace, finishTrace } from '../utils/TraceControllerUtils'
const TAG = "MediaModel"
export class MediaModelItem {
fileAsset: MediaLib.FileAsset
counts: number
}
class MediaModel {
private media: MediaLib.MediaLibrary = undefined
private imageDir: string = ""
private cameraDir: string = ""
constructor() {
}
onCreate(context) {
if (this.media == undefined) {
this.media = MediaLib.getMediaLibrary(context)
}
}
getMediaLibrary(): MediaLib.MediaLibrary{
return this.media
}
async getPublicDirectory(directoryType: MediaLib.DirectoryType): Promise<string> {
if (directoryType == MediaLib.DirectoryType.DIR_IMAGE) {
if (this.imageDir == "" || this.imageDir == undefined) {
this.imageDir = await this.media.getPublicDirectory(directoryType)
logDebug(TAG, `imageDir ${this.imageDir}`)
}
logDebug(TAG, `return imageDir ${this.imageDir}`)
return this.imageDir
} else if (directoryType == MediaLib.DirectoryType.DIR_CAMERA) {
if (this.cameraDir == "" || this.cameraDir == undefined) {
this.cameraDir = await this.media.getPublicDirectory(directoryType)
logDebug(TAG, `cameraDir ${this.cameraDir}`)
}
logDebug(TAG, `return cameraDir ${this.cameraDir}`)
return this.cameraDir
} else {
logWarn(TAG, `invaild directoryType: ${directoryType}`)
return ""
}
}
async createOne(mediaType: MediaLib.MediaType, displayName: string, relativePath: string): Promise<MediaLib.FileAsset> {
return await this.media.createAsset(mediaType, displayName, relativePath)
}
async copyOne(source: MediaLib.FileAsset, target: MediaLib.FileAsset) {
logInfo(TAG, `copy start: src:${source.uri} target: ${target.uri}`);
startTrace('openAssetR')
let fd = await this.openAsset('R', source);
finishTrace('openAssetR')
if (fd <= 0) {
throw 'fd is invalid'
return;
}
startTrace('openAssetRW')
let targetFd = await this.openAsset('RW', target);
finishTrace('openAssetRW')
if (targetFd <= 0) {
throw 'targetFd is invalid'
return;
}
startTrace('copyFile')
await fileIO.copyFile(fd, targetFd)
finishTrace('copyFile')
startTrace('sourceClose')
await this.closeAsset(fd, source)
finishTrace('sourceClose')
startTrace('targetClose')
await this.closeAsset(targetFd, target)
finishTrace('targetClose')
logDebug(TAG, 'copy end')
}
async deleteOne(uri: string) {
logDebug(TAG, `deleteAsset uri: ${uri}`);
await this.media.deleteAsset(uri);
}
async deleteAll(fetchOption: MediaLib.MediaFetchOptions) {
logInfo(TAG, 'deleteAll');
startTrace('deleteAll')
try {
let fetchFileResult: MediaLib.FetchFileResult = await this.media.getFileAssets(fetchOption);
logDebug(TAG, `deleteAll getFileAssets`);
let fileAssets: MediaLib.FileAsset[] = await fetchFileResult.getAllObject();
for (let i = 0;i < fileAssets.length; i++) {
await fileAssets[i].trash(true)
}
logDebug(TAG, `deleteAll getFirstObject`);
fetchFileResult.close()
} catch (err) {
logError(TAG, `deleteAll error:${JSON.stringify(err)}`);
}
finishTrace('deleteAll')
logDebug(TAG, 'deleteAll finish');
}
async getAllMediaItems(fetchOption: MediaLib.MediaFetchOptions): Promise<Array<MediaLib.FileAsset>> {
logInfo(TAG, 'getAllMediaItems');
startTrace('getAllMediaItems')
let fileAssets: Array<MediaLib.FileAsset> = []
try {
let fetchFileResult: MediaLib.FetchFileResult = await this.media.getFileAssets(fetchOption);
logDebug(TAG, `getAllMediaItems getFileAssets:${fetchFileResult.getCount()}`);
fileAssets = await fetchFileResult.getAllObject();
logDebug(TAG, `getAllMediaItems getAllObject:${fileAssets.length}`);
fetchFileResult.close()
} catch (err) {
logError(TAG, `getAllMediaItems error:${JSON.stringify(err)}`);
}
finishTrace('getAllMediaItems')
logDebug(TAG, 'getAllMediaItems finish');
return fileAssets
}
async getAllFavorMediaItems(fetchOption: MediaLib.MediaFetchOptions): Promise<Array<MediaLib.FileAsset>> {
logInfo(TAG, 'getAllFavorMediaItems');
startTrace('getAllFavorMediaItems')
let fileAssets: Array<MediaLib.FileAsset> = []
try {
let albums = await this.media.getPrivateAlbum(MediaLib.PrivateAlbumType.TYPE_FAVORITE);
if (albums.length > 0) {
let fetchFileResult: MediaLib.FetchFileResult = await albums[0].getFileAssets(fetchOption);
logDebug(TAG, `getAllFavorMediaItems getFileAssets`);
fileAssets = await fetchFileResult.getAllObject();
logDebug(TAG, `getAllFavorMediaItems getFirstObject`);
fetchFileResult.close()
}
fetchFileResult.close()
} catch (err) {
logError(TAG, `getAllFavorMediaItems error:${JSON.stringify(err)}`);
}
finishTrace('getAllFavorMediaItems')
logDebug(TAG, 'getAllFavorMediaItems finish');
return fileAssets
}
async getAllTrashMediaItems(fetchOption: MediaLib.MediaFetchOptions): Promise<Array<MediaLib.FileAsset>> {
logInfo(TAG, 'getAllTrashMediaItems');
startTrace('getAllTrashMediaItems')
let fileAssets: Array<MediaLib.FileAsset> = []
try {
let albums = await this.media.getPrivateAlbum(MediaLib.PrivateAlbumType.TYPE_TRASH);
if (albums.length > 0) {
let fetchFileResult: MediaLib.FetchFileResult = await albums[0].getFileAssets(fetchOption);
logDebug(TAG, `getAllTrashMediaItems getFileAssets`);
fileAssets = await fetchFileResult.getAllObject();
logDebug(TAG, `getAllTrashMediaItems getFirstObject`);
fetchFileResult.close()
}
fetchFileResult.close()
} catch (err) {
logError(TAG, `getAllTrashMediaItems error:${JSON.stringify(err)}`);
}
finishTrace('getAllTrashMediaItems')
logDebug(TAG, 'getAllTrashMediaItems finish');
return fileAssets
}
async getAllMediaItem(albumId: string, fetchOption: MediaLib.MediaFetchOptions, isCountOnly: boolean): Promise<MediaModelItem> {
if (albumId == MediaConstants.ALBUM_ID_FAVOR) {
return await this.getAllFavorMediaItem(fetchOption, isCountOnly)
} else if (albumId == MediaConstants.ALBUM_ID_RECYCLE) {
return await this.getAllTrashMediaItem(fetchOption, isCountOnly)
} else {
return await this.getAllCommonMediaItem(fetchOption, isCountOnly)
}
}
async getAllCommonMediaItem(fetchOption: MediaLib.MediaFetchOptions, isCountOnly: boolean): Promise<MediaModelItem> {
logInfo(TAG, 'getAllCommonMediaItem');
startTrace('getAllCommonMediaItem')
let item: MediaModelItem = new MediaModelItem()
try {
let fetchFileResult: MediaLib.FetchFileResult = await this.media.getFileAssets(fetchOption);
logDebug(TAG, `getAllCommonMediaItem getFileAssets`);
item.counts = await fetchFileResult.getCount();
if (!isCountOnly && item.counts > 0) {
item.fileAsset = await fetchFileResult.getFirstObject()
}
logDebug(TAG, `getAllCommonMediaItem getFirstObject`);
fetchFileResult.close()
} catch (err) {
logError(TAG, `getAllCommonMediaItem error:${JSON.stringify(err)}`);
}
finishTrace('getAllCommonMediaItem')
logDebug(TAG, 'getAllCommonMediaItem finish');
return item
}
async getAllFavorMediaItem(fetchOption: MediaLib.MediaFetchOptions, isCountOnly: boolean): Promise<MediaModelItem> {
logInfo(TAG, 'getAllFavorMediaItem');
startTrace('getAllFavorMediaItem')
let item: MediaModelItem = new MediaModelItem()
try {
let albums = await this.media.getPrivateAlbum(MediaLib.PrivateAlbumType.TYPE_FAVORITE);
if (albums.length > 0) {
let fetchFileResult: MediaLib.FetchFileResult = await albums[0].getFileAssets(fetchOption);
logDebug(TAG, `getAllFavorMediaItem getFileAssets`);
item.counts = await fetchFileResult.getCount();
if (!isCountOnly && item.counts > 0) {
item.fileAsset = await fetchFileResult.getFirstObject()
}
logDebug(TAG, `getAllFavorMediaItem getFirstObject`);
fetchFileResult.close()
}
} catch (err) {
logError(TAG, `getAllFavorMediaItem error:${JSON.stringify(err)}`);
}
finishTrace('getAllFavorMediaItem')
logDebug(TAG, 'getAllFavorMediaItem finish');
return item
}
async getAllTrashMediaItem(fetchOption: MediaLib.MediaFetchOptions, isCountOnly: boolean): Promise<MediaModelItem> {
logInfo(TAG, 'getAllTrashMediaItem');
startTrace('getAllTrashMediaItem')
let item: MediaModelItem = new MediaModelItem()
try {
let albums = await this.media.getPrivateAlbum(MediaLib.PrivateAlbumType.TYPE_TRASH);
if (albums.length > 0) {
let fetchFileResult: MediaLib.FetchFileResult = await albums[0].getFileAssets(fetchOption);
logDebug(TAG, `getAllTrashMediaItem getFileAssets`);
item.counts = await fetchFileResult.getCount();
if (!isCountOnly && item.counts > 0) {
item.fileAsset = await fetchFileResult.getFirstObject()
}
logDebug(TAG, `getAllTrashMediaItem getFirstObject`);
fetchFileResult.close()
}
} catch (err) {
logError(TAG, `getAllTrashMediaItem error:${JSON.stringify(err)}`);
}
finishTrace('getAllTrashMediaItem')
logDebug(TAG, 'getAllTrashMediaItem finish');
return item
}
async getAlbumCount(fetchOption: MediaLib.MediaFetchOptions): Promise<number> {
logInfo(TAG, 'getAlbumCount');
startTrace('getAlbumCount')
let count = 0
try {
let albums: Array<MediaLib.Album> = await this.media.getAlbums(fetchOption);
if (albums.length == 0) {
return count
}
let fetchFileResult: MediaLib.FetchFileResult = await albums[0].getFileAssets()
count = fetchFileResult.getCount()
fetchFileResult.close()
} catch (err) {
logError(TAG, `getAlbumCount error:${JSON.stringify(err)}`);
}
finishTrace('getAlbumCount')
logDebug(TAG, 'getAlbumCount finish');
return count
}
async getActivePeers(): Promise<Array<MediaLib.PeerInfo>> {
logInfo(TAG, 'getActivePeers');
startTrace('getActivePeers')
let peers: Array<MediaLib.PeerInfo> = undefined
try {
peers = await this.media.getActivePeers();
} catch (err) {
logError(TAG, `getActivePeers error:${JSON.stringify(err)}`);
}
finishTrace('getActivePeers')
logDebug(TAG, 'getActivePeers finish');
return peers
}
async getAlbums(fetchOption: MediaLib.MediaFetchOptions): Promise<Array<MediaLib.Album>> {
logInfo(TAG, 'getAlbums');
startTrace('getAlbums')
let albums: Array<MediaLib.Album> = undefined
try {
albums = await this.media.getAlbums(fetchOption);
logInfo(TAG, `getAlbums albums ${albums.length}`)
} catch (err) {
logError(TAG, `getAlbums error:${JSON.stringify(err)}`);
}
finishTrace('getAlbums')
logDebug(TAG, 'getAlbums finish');
return albums
}
async getTrashMedia(fetchOption: MediaLib.MediaFetchOptions): Promise<MediaLib.FileAsset> {
logInfo(TAG, 'getTrashMedia');
startTrace('getTrashMedia')
let fileAsset: MediaLib.FileAsset = undefined
try {
let albums = await this.media.getPrivateAlbum(MediaLib.PrivateAlbumType.TYPE_TRASH);
if (albums.length > 0) {
let fetchFileResult: MediaLib.FetchFileResult = await albums[0].getFileAssets(fetchOption);
logDebug(TAG, `getTrashMedia getFileAssets`);
if (fetchFileResult.getCount() > 0) {
fileAsset = await fetchFileResult.getFirstObject();
}
logDebug(TAG, `getTrashMedia getFirstObject`);
fetchFileResult.close()
}
} catch (err) {
logError(TAG, `getTrashMedia error:${JSON.stringify(err)}`);
}
finishTrace('getTrashMedia')
logDebug(TAG, 'getTrashMedia finish');
return fileAsset
}
async openAsset(mode: string, fileAsset: MediaLib.FileAsset) {
logDebug(TAG, 'openAsset start');
let fd: number = await fileAsset.open(mode);
logInfo(TAG, `openAsset end. fd: ${fd}`);
if (fd <= 0) {
logInfo(TAG, 'openAsset Fail');
}
return fd;
}
async closeAsset(fd: number, fileAsset: MediaLib.FileAsset) {
logDebug(TAG, 'closeAsset start');
await fileAsset.close(fd);
}
}
let mediaModel = createOrGet(MediaModel, TAG);
export default mediaModel as MediaModel;

View File

@ -13,10 +13,10 @@
* limitations under the License.
*/
import { MediaObserverCallback } from './dataObserver/MediaObserverCallback'
import { MediaObserverCallback } from '../interface/MediaObserverCallback'
export class CommonObserverCallback implements MediaObserverCallback {
source: any;
private source: any;
constructor(source: any) {
this.source = source;

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import createOrGet from '../utils/SingleInstanceUtils';
import { logInfo, logWarn } from '../utils/LoggerUtils'
import { MediaConstants } from '../constants/MediaConstants'
import mediaModel from '../model/MediaModel'
import { MediaObserverCallback } from '../interface/MediaObserverCallback';
const TAG = "MediaObserver"
class MediaObserver {
callbacks: MediaObserverCallback[] = [];
private static readonly OBSERVER_IMAGE_CHANGE: string = 'imageChange'
private static readonly OBSERVER_VIDEO_CHANGE: string = 'videoChange'
private static readonly OBSERVER_DEVICE_CHANGE: string = 'deviceChange'
private static readonly OBSERVER_ALBUM_CHANGE: string = 'albumChange'
private static readonly OBSERVER_REMOTE_FILE_CHANGE: string = 'remoteFileChange'
registerObserver(callback: MediaObserverCallback) {
logInfo(TAG, 'registerObserver');
if (callback == null) {
logWarn(TAG, 'registerObserver with empty callback');
return;
}
if (this.callbacks.indexOf(callback) < 0) {
this.callbacks.push(callback);
} else {
logInfo(TAG, 'registerObserver already exist');
return;
}
if (this.callbacks.length == 1) {
logInfo(TAG, 'registerObserver register media');
mediaModel.getMediaLibrary().on('imageChange', () => {
logInfo(TAG, 'registerObserver on image');
this.sendNotify(MediaConstants.MEDIA_TYPE_IMAGE);
})
mediaModel.getMediaLibrary().on('videoChange', () => {
logInfo(TAG, 'registerObserver on video');
this.sendNotify(MediaConstants.MEDIA_TYPE_VIDEO);
})
mediaModel.getMediaLibrary().on('deviceChange', () => {
logInfo(TAG, 'registerObserver on device');
this.sendNotify(MediaConstants.MEDIA_TYPE_DEVICE);
})
mediaModel.getMediaLibrary().on('albumChange', () => {
logInfo(TAG, 'registerObserver on album');
this.sendNotify(MediaConstants.MEDIA_TYPE_ALBUM);
})
mediaModel.getMediaLibrary().on('remoteFileChange', () => {
logInfo(TAG, 'registerObserver on remoteFile');
this.sendNotify(MediaConstants.MEDIA_TYPE_REMOTE);
})
}
}
sendNotify(mediaType: string) {
logInfo(TAG, `registerObserver sendNotify size: ${this.callbacks.length}`);
for (let callback of this.callbacks) {
callback.onChange(mediaType);
}
}
unregisterObserver(callback: MediaObserverCallback) {
logInfo(TAG, 'unregisterObserver');
const pos = this.callbacks.indexOf(callback);
if (pos >= 0) {
this.callbacks.splice(pos, 1);
}
}
}
let mediaObserver = createOrGet(MediaObserver, TAG);
export default mediaObserver as MediaObserver;

View File

@ -0,0 +1,155 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import router from '@system.router';
import MediaLib from '@ohos.multimedia.mediaLibrary';
import { logDebug, logInfo, logWarn, logError } from '../utils/LoggerUtils';
import { getResourceString } from '../utils/ResourceUtils';
import { BroadcastConstants } from '../constants/BroadcastConstants';
import { MenuOperationCallback } from './MenuOperationCallback'
import { MenuOperation } from './MenuOperation'
import { MenuContext } from './MenuContext'
import { JumpSourceToMain } from '../data/JumpSourceToMain'
import { SimpleAlbumDataItem } from '../data/SimpleAlbumDataItem';
import { getFetchOptionsByItem } from '../helper/MediaDataHelper';
import { showToast } from '../utils/UiUtil';
import mediaModel from '../model/MediaModel'
import { AlbumDataItem } from '../data/AlbumDataItem';
const TAG = "AlbumSetNewMenuOperation"
export class AlbumSetNewMenuOperation implements MenuOperation, MenuOperationCallback {
private menuContext: MenuContext;
private onOperationEnd: Function;
constructor(menuContext: MenuContext) {
this.menuContext = menuContext;
}
doAction() {
if (this.menuContext == null) {
logWarn(TAG, 'menuContext is null, return');
return;
}
getResourceString($r('app.string.album_new_album')).then((name: string) => {
logInfo(TAG, `The display name is ${name}`);
this.getNewAlbumDisplayName(name).then((newAlbumDisplayName: string) => {
logInfo(TAG, `The display name of new album is ${newAlbumDisplayName}`);
this.confirmCallback = this.confirmCallback.bind(this);
this.cancelCallback = this.cancelCallback.bind(this);
this.menuContext.broadCast.emit(BroadcastConstants.SHOW_NEW_ALBUM_PHOTO_DIALOG,
[newAlbumDisplayName, this.confirmCallback, this.cancelCallback]);
})
})
}
private async getNewAlbumDisplayName(name: string): Promise<string> {
let relativeRoot = await mediaModel.getPublicDirectory(MediaLib.DirectoryType.DIR_CAMERA)
return await this.getNewAlbumDefaultName(relativeRoot, name)
}
private async confirmCallback(displayName: string) {
logInfo(TAG, `AlbumSet new album confirm and the new name is: ${displayName}`);
let relativePath = await mediaModel.getPublicDirectory(MediaLib.DirectoryType.DIR_CAMERA) + displayName + "/"
let simpleAlbumDataItem: SimpleAlbumDataItem = new SimpleAlbumDataItem("", displayName, relativePath, "", "")
if (displayName != undefined && displayName != null) {
let isExit = await this.checkAlbumExit(simpleAlbumDataItem)
if (isExit) {
getResourceString($r('app.string.name_already_use')).then((message: string) => {
showToast(message)
})
return;
}
}
this.onOperationEnd = this.menuContext.onOperationEnd;
let onOperationStart: Function = this.menuContext.onOperationStart;
onOperationStart && onOperationStart();
if (this.menuContext.jumpSourceToMain == JumpSourceToMain.ALBUM) {
logInfo(TAG, 'go back to photo grid');
this.menuContext.broadCast.emit(BroadcastConstants.MEDIA_OPERATION, [simpleAlbumDataItem, this.onCompleted.bind(this)]);
} else {
router.push({
uri: 'feature/albumSelect/view/AlbumSelect',
params: {
albumInfo: JSON.stringify(simpleAlbumDataItem),
isNewAlbum: true
}
});
this.onCompleted();
}
}
private async checkAlbumExit(simpleAlbumDataItem: SimpleAlbumDataItem): Promise<boolean> {
let fetchOptions: MediaLib.MediaFetchOptions = await getFetchOptionsByItem(simpleAlbumDataItem)
return await mediaModel.getAlbumCount(fetchOptions) > 0
}
private cancelCallback(): void {
logInfo(TAG, 'AlbumSet new album cancel');
}
onCompleted(): void {
logInfo(TAG, 'new album data succeed!');
this.onOperationEnd && this.onOperationEnd();
}
onError(): void {
logError(TAG, 'new album data failed!');
this.onOperationEnd && this.onOperationEnd();
}
private async getNewAlbumDefaultName(root: string, prefixName: string): Promise<string> {
let numbers = [];
for (let i = 0; i < this.menuContext.dataSource.totalCount(); i++) {
let item = this.menuContext.dataSource.getData(i) as AlbumDataItem
let res = (await item.getRelativePath()).match(new RegExp(`^${root}${prefixName}[1-9][0-9]*${"/"}$`));
if (res != null) {
let number = res[0].match(new RegExp(`[1-9][0-9]*`));
numbers.push(parseInt(number[0]));
}
}
logDebug(TAG, `${JSON.stringify(numbers)}`);
if (numbers.length <= 0) {
return `${prefixName}1`;
} else if (numbers.length == 1) {
if (numbers[0] - 1 > 0) {
return `${prefixName}1`;
} else {
return `${prefixName}${numbers[0] + 1}`;
}
}
numbers.sort(function (a, b) {
return a - b;
});
if (numbers[0] - 1 > 0) {
return `${prefixName}1`;
}
for (let i = 1; i < numbers.length; i++) {
let res = numbers[i - 1] + 1;
if (res < numbers[i]) {
return `${prefixName}${res}`;
}
}
return `${prefixName}${numbers[numbers.length - 1] + 1}`;
}
}

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { logInfo, logWarn } from '../utils/LoggerUtils'
import { ItemDataSource } from '../vm/ItemDataSource';
import { MenuContext } from './MenuContext'
import { BroadcastConstants } from '../constants/BroadcastConstants';
import { ProcessMenuOperation } from './ProcessMenuOperation';
import { MediaDataItem } from '../data/MediaDataItem';
const TAG = "BatchDeleteMenuOperation"
export class BatchDeleteMenuOperation extends ProcessMenuOperation {
constructor(menuContext: MenuContext) {
super(menuContext);
}
doAction(): void{
logInfo(TAG, 'delete doAction');
if (this.menuContext == null) {
logWarn(TAG, 'menuContext is null, return');
return;
}
let dataSource: ItemDataSource = this.menuContext.dataSource;
if (dataSource == null) {
this.count = this.menuContext.items.length
} else {
this.count = dataSource.getSelectedCount();
}
if (this.count <= 0) {
logWarn(TAG, 'count <= 0, return');
return;
}
this.confirmCallback = this.confirmCallback.bind(this);
this.cancelCallback = this.cancelCallback.bind(this);
let resource: Resource = this.getDeleteMessageResource(dataSource)
this.menuContext.broadCast.emit(BroadcastConstants.SHOW_DELETE_DIALOG, [resource, this.confirmCallback, this.cancelCallback]);
}
getDeleteMessageResource(dataSource: ItemDataSource): Resource{
let resource: Resource
if (dataSource && dataSource.isSelect()) {
resource = $r('app.string.recycle_all_files_tips')
} else if (this.count == 1) {
resource = $r('app.string.recycle_single_file_tips')
} else {
resource = $r('app.string.recycle_files_tips', this.count)
}
return resource
}
confirmCallback(): void {
logInfo(TAG, 'Batch delete confirm');
// 1. Variable initialization
this.onOperationEnd = this.menuContext.onOperationEnd;
// 2. onDeleteStart exit selection mode
let onOperationStart: Function = this.menuContext.onOperationStart;
onOperationStart && onOperationStart();
this.menuContext.broadCast.emit(BroadcastConstants.DELETE_PROGRESS_DIALOG,
[$r('app.string.action_delete'), this.count]);
// 3. selectManager gets the URI of the data and starts processing deletion in the callback
let dataSource: ItemDataSource = this.menuContext.dataSource;
if (dataSource == null) {
this.items = this.menuContext.items
} else {
this.items = dataSource.getSelectedItems()
}
this.processOperation()
}
requestOneBatchOperation() {
let item = this.items[this.currentBatch] as MediaDataItem
item.onDelete().then(() => {
this.currentBatch++
this.menuContext.broadCast.emit(BroadcastConstants.UPDATE_PROGRESS, [this.getExpectProgress(), this.currentBatch]);
this.cyclicOperation()
})
}
cancelCallback(): void {
logInfo(TAG, 'Batch delete cancel');
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TrashMediaDataItem } from '../data/TrashMediaDataItem';
import { logInfo, logWarn } from '../utils/LoggerUtils'
import { ItemDataSource } from '../vm/ItemDataSource';
import { MenuContext } from './MenuContext'
import { ProcessMenuOperation } from './ProcessMenuOperation';
import { BroadcastConstants } from '../constants/BroadcastConstants';
const TAG = "BatchRecoverMenuOperation"
export class BatchRecoverMenuOperation extends ProcessMenuOperation {
constructor(menuContext: MenuContext) {
super(menuContext);
}
doAction(): void{
logInfo(TAG, 'delete doAction');
if (this.menuContext == null) {
logWarn(TAG, 'menuContext is null, return');
return;
}
let dataSource: ItemDataSource = this.menuContext.dataSource;
if (dataSource == null) {
this.count = this.menuContext.items.length
} else {
this.count = dataSource.getSelectedCount();
}
if (this.count <= 0) {
logWarn(TAG, 'count <= 0, return');
return;
}
this.onOperationEnd = this.menuContext.onOperationEnd;
let onOperationStart = this.menuContext.onOperationStart;
onOperationStart && onOperationStart();
this.menuContext.broadCast.emit(BroadcastConstants.DELETE_PROGRESS_DIALOG,
[$r('app.string.action_recover'), this.count]);
if (dataSource == null) {
this.items = this.menuContext.items
} else {
this.items = dataSource.getSelectedItems()
}
this.processOperation()
}
// Delete a batch of data
requestOneBatchOperation(): void {
let item = this.items[this.currentBatch] as TrashMediaDataItem
item.onRecover().then(() => {
this.currentBatch++
this.menuContext.broadCast.emit(BroadcastConstants.UPDATE_PROGRESS, [this.getExpectProgress(), this.currentBatch]);
this.cyclicOperation()
})
}
}

View File

@ -12,19 +12,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { OperationImpl } from '../model/browser/photo/OperationImpl'
import { AlbumOperationImpl } from '../model/browser/album/AlbumOperationImpl'
import { BrowserOperationInterface } from './BrowserOperationInterface'
import { ItemDataSource } from '../vm/ItemDataSource';
import { MenuContext } from './MenuContext'
import { BatchDeleteMenuOperation } from './BatchDeleteMenuOperation';
export class BrowserOperationFactory {
static readonly TYPE_PHOTO = 'photo';
static readonly TYPE_ALBUM = 'album';
export class ClearRecycleMenuOperation extends BatchDeleteMenuOperation {
constructor(menuContext: MenuContext) {
super(menuContext);
}
static getFeature(type: string): BrowserOperationInterface {
if (type == BrowserOperationFactory.TYPE_PHOTO) {
return new OperationImpl();
} else if (type == BrowserOperationFactory.TYPE_ALBUM) {
return new AlbumOperationImpl();
getDeleteMessageResource(dataSource: ItemDataSource): Resource{
if (dataSource && dataSource.isSelect()) {
return $r('app.string.recycleAlbum_clear_message')
} else {
return $r('app.plural.recycleAlbum_delete_message', this.count)
}
}
}

View File

@ -0,0 +1,182 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import MediaLib from '@ohos.multimedia.mediaLibrary';
import { MediaConstants } from '../constants/MediaConstants';
import { logInfo, logWarn, logError } from '../utils/LoggerUtils'
import { MenuContext } from './MenuContext'
import { ProcessMenuOperation, FindSameOperation } from './ProcessMenuOperation'
import { BroadcastConstants } from '../constants/BroadcastConstants';
import mediaModel from '../model/MediaModel'
import { MediaOperationType } from '../data/MediaOperationType'
import { startTraceWithTaskId, finishTraceWithTaskId } from '../utils/TraceControllerUtils';
import { ItemDataSource } from '../vm/ItemDataSource';
import { MediaDataItem } from '../data/MediaDataItem';
import { SimpleAlbumDataItem } from '../data/SimpleAlbumDataItem';
const TAG = "CopyMenuOperation"
export class CopyMenuOperation extends ProcessMenuOperation {
private albumInfo: SimpleAlbumDataItem;
constructor(menuContext: MenuContext) {
super(menuContext);
this.albumInfo = menuContext.albumInfo;
}
doAction(): void {
logInfo(TAG, 'copy doAction');
if (this.menuContext == null) {
logWarn(TAG, 'menuContext is null, return');
return;
}
let dataSource: ItemDataSource = this.menuContext.dataSource;
if (dataSource == null) {
this.count = this.menuContext.items.length
} else {
this.count = dataSource.getSelectedCount();
}
if (this.count <= 0) {
logWarn(TAG, 'count <= 0, return');
return;
}
this.onOperationEnd = this.menuContext.onOperationEnd;
let onOperationStart = this.menuContext.onOperationStart;
onOperationStart && onOperationStart();
if (this.menuContext.deviceId) {
this.menuContext.broadCast.emit(BroadcastConstants.SHOW_PROGRESS_DIALOG,
[$r('app.string.download_progress_message'),
MediaOperationType.Copy, this.cancelFunc.bind(this)]);
} else {
this.menuContext.broadCast.emit(BroadcastConstants.SHOW_PROGRESS_DIALOG,
[$r('app.string.copy_progress_message', this.albumInfo.displayName),
MediaOperationType.Copy, this.cancelFunc.bind(this)]);
}
if (dataSource == null) {
this.items = this.menuContext.items
} else {
this.items = dataSource.getSelectedItems()
}
this.processOperation();
}
requestOneBatchOperation() {
let item = this.items[this.currentBatch++] as MediaDataItem
this.copyOne(item)
}
private async copyOne(item: MediaDataItem) {
if (this.menuContext.deviceId) {
let path = await mediaModel.getPublicDirectory(MediaLib.DirectoryType.DIR_CAMERA) + MediaConstants.REMOTE_ALBUM_PATH + "/"
this.albumInfo = new SimpleAlbumDataItem("", "", path, "", "")
}
let fileAsset = await item.loadFileAsset()
let assets = await this.getFileCopyOrMoveInfo(fileAsset, this.albumInfo)
if (this.menuContext.deviceId) {
let displayName = assets.sourceAsset.displayName;
let index = displayName.lastIndexOf('.');
let start = displayName.lastIndexOf('_');
displayName = `${displayName.slice(0, start)}_${new Date().getTime()}${displayName.slice(index)}`;
this.copy(assets.sourceAsset, null, {
mediaType: assets.sourceAsset.mediaType,
name: displayName,
path: this.albumInfo.relativePath
});
return;
}
if (assets.targetAsset) {
if (assets.targetAsset.uri == assets.sourceAsset.uri) {
logInfo(TAG, 'copy same fileAsset');
this.onOperateContinue();
return;
}
logInfo(TAG, 'show find same file dialog');
switch (this.findSameOperation) {
case FindSameOperation.NONE:
this.menuContext.broadCast.emit(BroadcastConstants.FIND_SAME_FILE_DIALOG,
[assets, this.count, () => {
this.copy(assets.sourceAsset, assets.targetAsset);
}, this.onOperateContinue.bind(this), this.onOperateCancelled.bind(this),
this.setFindSameOperation.bind(this)]);
break;
case FindSameOperation.REPLACE:
this.copy(assets.sourceAsset, assets.targetAsset);
break;
case FindSameOperation.SKIP:
this.onOperateContinue();
break;
default:
logWarn(TAG, `findSameOperation is error ${this.findSameOperation}`);
break;
}
} else {
this.copy(assets.sourceAsset, null, {
mediaType: assets.sourceAsset.mediaType,
name: assets.sourceAsset.displayName,
path: this.albumInfo.relativePath
});
}
}
async copy(source, target, param?) {
try {
if (!target) {
startTraceWithTaskId('create', this.currentBatch)
target = await mediaModel.createOne(param.mediaType, param.name, param.path);
finishTraceWithTaskId('create', this.currentBatch);
if (target == null) {
logWarn(TAG, `Target file creat failed when copyFile!`);
this.onError();
return;
}
}
startTraceWithTaskId('openWriteClose', this.currentBatch)
await mediaModel.copyOne(source, target);
finishTraceWithTaskId('openWriteClose', this.currentBatch)
this.onCompleted();
} catch (error) {
finishTraceWithTaskId('create', this.currentBatch);
logError(TAG, `copyFile is error ${error}`);
this.onError();
}
}
cancelFunc(): void {
logInfo(TAG, `progress cancel`);
this.onOperatePause();
let cancelMessage = $r('app.string.copy_cancel_message', this.getExpectProgress().toString());
if (this.menuContext.deviceId) {
this.menuContext.broadCast && this.menuContext.broadCast.emit(BroadcastConstants.DOWNLOAD_CANCEL_OPERATE,
[cancelMessage, this.onOperateContinue.bind(this), this.onOperateCancelled.bind(this)]);
} else {
this.menuContext.broadCast && this.menuContext.broadCast.emit(BroadcastConstants.CANCEL_OPERATE,
[cancelMessage, this.onOperateContinue.bind(this), this.onOperateCancelled.bind(this)]);
}
}
// Copy cancel callback
onOperateContinue(): void {
logInfo(TAG, 'Operate Continue');
this.isPause = false;
this.cyclicOperation();
}
}

View File

@ -12,27 +12,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { MediaItem } from '../../model/browser/photo/MediaItem'
import { SelectManager } from '../../model/browser/SelectManager'
import { BroadCast } from '../../utils/BroadCast'
import { AlbumSetDataSource } from '../../model/browser/album/AlbumSetDataSource'
import { AlbumInfo } from '../../model/browser/album/AlbumInfo';
import { ItemDataSource } from '../vm/ItemDataSource';
import { MediaDataItem } from '../data/MediaDataItem'
import { Broadcast } from '../utils/Broadcast'
import { SimpleAlbumDataItem } from '../data/SimpleAlbumDataItem';
export class MenuContext {
mediaItem: MediaItem;
albumId: string;
selectManager: SelectManager;
items: any[] = [];
dataSource: ItemDataSource;
albumInfo: SimpleAlbumDataItem
broadCast: Broadcast
onOperationStart: Function;
onOperationEnd: Function;
broadCast: BroadCast
jumpSourceToMain: number;
albumSetDataSource: AlbumSetDataSource;
deviceId: string;
albumInfo: AlbumInfo
withMediaItem(mediaItem: MediaItem): MenuContext {
this.mediaItem = mediaItem;
jumpSourceToMain: number;
deviceId: string;
albumId: string;
withItems(items: MediaDataItem[]): MenuContext {
this.items = items;
return this;
}
@ -41,9 +42,9 @@ export class MenuContext {
return this;
}
withSelectManager(selectManager: SelectManager): MenuContext {
this.selectManager = selectManager;
return this;
withDataSource(dataSource): MenuContext{
this.dataSource = dataSource
return this
}
withOperationStartCallback(onOperationStart: Function): MenuContext {
@ -56,7 +57,7 @@ export class MenuContext {
return this;
}
withBroadCast(param: BroadCast): MenuContext {
withBroadCast(param: Broadcast): MenuContext {
this.broadCast = param;
return this;
}
@ -66,17 +67,12 @@ export class MenuContext {
return this;
}
withAlbumSetDataSource(albumSetDataSource: AlbumSetDataSource): MenuContext {
this.albumSetDataSource = albumSetDataSource;
return this;
}
withRemoteDevice(deviceId) {
this.deviceId = deviceId;
return this;
}
withAlbumInfo(albumInfo) {
withAlbumInfo(albumInfo: SimpleAlbumDataItem) {
this.albumInfo = albumInfo;
return this;
}

View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import MediaLib from '@ohos.multimedia.mediaLibrary';
import mediaModel from '../model/MediaModel'
import { logInfo, logWarn, logError } from '../utils/LoggerUtils'
import { MenuContext } from './MenuContext'
import { ProcessMenuOperation, FindSameOperation } from './ProcessMenuOperation'
import { MediaOperationType } from '../data/MediaOperationType'
import { BroadcastConstants } from '../constants/BroadcastConstants';
import { startTraceWithTaskId, finishTraceWithTaskId } from '../utils/TraceControllerUtils';
import { ItemDataSource } from '../vm/ItemDataSource';
import { MediaDataItem } from '../data/MediaDataItem';
import { SimpleAlbumDataItem } from '../data/SimpleAlbumDataItem';
const TAG = "MoveMenuOperation"
export class MoveMenuOperation extends ProcessMenuOperation {
albumInfo: SimpleAlbumDataItem;
constructor(menuContext: MenuContext) {
super(menuContext);
this.albumInfo = menuContext.albumInfo;
}
doAction(): void {
logInfo(TAG, 'move doAction');
if (this.menuContext == null) {
logWarn(TAG, 'menuContext is null, return');
return;
}
let dataSource: ItemDataSource = this.menuContext.dataSource;
if (dataSource == null) {
this.count = this.menuContext.items.length
} else {
this.count = dataSource.getSelectedCount();
}
if (this.count <= 0) {
logWarn(TAG, 'count <= 0, return');
return;
}
this.onOperationEnd = this.menuContext.onOperationEnd;
let onOperationStart = this.menuContext.onOperationStart;
onOperationStart && onOperationStart();
this.menuContext.broadCast.emit(
BroadcastConstants.SHOW_PROGRESS_DIALOG, [$r('app.string.move_progress_message', this.albumInfo.displayName),
MediaOperationType.Move, this.cancelFunc.bind(this)]);
if (dataSource == null) {
this.items = this.menuContext.items
} else {
this.items = dataSource.getSelectedItems()
}
this.processOperation()
}
requestOneBatchOperation() {
let item = this.items[this.currentBatch++] as MediaDataItem
this.moveOne(item)
}
private async moveOne(item: MediaDataItem) {
let fileAsset = await item.loadFileAsset()
let assets = await this.getFileCopyOrMoveInfo(fileAsset, this.albumInfo)
if (assets.targetAsset) {
if (assets.targetAsset.uri == assets.sourceAsset.uri) {
logInfo(TAG, 'move same fileAsset');
this.onOperateContinue();
return;
}
logInfo(TAG, 'show find same file dialog');
switch (this.findSameOperation) {
case FindSameOperation.NONE:
this.menuContext.broadCast.emit(BroadcastConstants.FIND_SAME_FILE_DIALOG,
[assets, this.count, () => {
this.move(assets.sourceAsset, this.albumInfo.relativePath, assets.targetAsset);
}, this.onOperateContinue.bind(this), this.onOperateCancelled.bind(this),
this.setFindSameOperation.bind(this)]);
break;
case FindSameOperation.REPLACE:
this.move(assets.sourceAsset, this.albumInfo.relativePath, assets.targetAsset);
break;
case FindSameOperation.SKIP:
this.onOperateContinue();
break;
default:
logWarn(TAG, `findSameOperation is error ${this.findSameOperation}`);
break;
}
} else {
this.move(assets.sourceAsset, this.albumInfo.relativePath)
}
}
async move(file: MediaLib.FileAsset, path: string, targetFile?) {
startTraceWithTaskId('move', this.currentBatch);
try {
if (targetFile) {
await mediaModel.deleteOne(targetFile.uri);
}
file.relativePath = path
file.commitModify()
finishTraceWithTaskId('move', this.currentBatch);
this.onCompleted();
} catch (error) {
logError(TAG, `move error: ${error}`)
this.onError();
}
}
cancelFunc(): void {
logInfo(TAG, `progress cancel`);
this.onOperatePause();
let cancelMessage = $r('app.string.move_cancel_message', this.getExpectProgress().toString());
this.menuContext.broadCast && this.menuContext.broadCast.emit(BroadcastConstants.CANCEL_OPERATE,
[cancelMessage, this.onOperateContinue.bind(this), this.onOperateCancelled.bind(this)]);
}
// Move cancel callback
onOperateContinue(): void {
logInfo(TAG, 'Operate Continue');
this.isPause = false;
this.cyclicOperation();
}
}

View File

@ -12,16 +12,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AsyncCallback } from '../../model/common/AsyncCallback'
import { Logger } from '../../utils/Logger'
import MediaLib from '@ohos.multimedia.mediaLibrary';
import { AsyncCallback } from '../interface/AsyncCallback'
import { logDebug, logInfo, logError } from '../utils/LoggerUtils'
import { MenuOperationCallback } from './MenuOperationCallback'
import { MenuOperation } from './MenuOperation'
import { MenuContext } from './MenuContext'
import { BroadCastConstants } from '../../model/common/BroadCastConstants';
import { BrowserDataFactory } from '../../interface/BrowserDataFactory'
import { StringUtil } from '../../utils/StringUtil'
import { TraceControllerUtils } from '../../utils/TraceControllerUtils';
import { BroadcastConstants } from '../constants/BroadcastConstants';
import { startTraceWithTaskId, finishTraceWithTaskId } from '../utils/TraceControllerUtils';
import { getFetchOptionsByItem } from '../helper/MediaDataHelper';
import { SimpleAlbumDataItem } from '../data/SimpleAlbumDataItem';
import mediaModel from '../model/MediaModel'
export enum FindSameOperation {
NONE,
@ -29,12 +30,15 @@ export enum FindSameOperation {
SKIP
}
const TAG = "ProcessMenuOperation"
export class ProcessMenuOperation implements MenuOperation, AsyncCallback<String[]>, MenuOperationCallback {
// Number of data operated in a batch
readonly BATCH_SIZE: number = 1;
// Maximum progress
readonly MAX_PROGRESS: number = 100;
items: any[] = []
menuContext: MenuContext;
uris: string[];
count: number;
@ -51,7 +55,6 @@ export class ProcessMenuOperation implements MenuOperation, AsyncCallback<String
isPause: boolean = false;
isError: boolean = false;
findSameOperation: number = FindSameOperation.NONE;
logger: Logger = new Logger('ProcessMenuOperation');
requestTime: number;
constructor(menuContext: MenuContext) {
@ -60,7 +63,6 @@ export class ProcessMenuOperation implements MenuOperation, AsyncCallback<String
}
doAction(): void {
}
// Asynchronous callback for getSelection
@ -69,7 +71,7 @@ export class ProcessMenuOperation implements MenuOperation, AsyncCallback<String
}
onCompleted(): void {
this.logger.info(`onCompleted ${this.isPause}`);
logInfo(TAG, `onCompleted ${this.isPause}`);
this.successBatch++;
if (!this.isPause) {
this.cyclicOperation();
@ -77,41 +79,32 @@ export class ProcessMenuOperation implements MenuOperation, AsyncCallback<String
}
onError(): void {
this.logger.error(`Operate the ${this.currentBatch} batch data error, total ${this.totalBatches} batches`);
logError(TAG, `Operate the ${this.currentBatch} batch data error, total ${this.totalBatches} batches`);
this.isError = true;
this.cyclicOperation();
}
// Operate a batch of data
requestOneBatchOperation(): void {
}
// Start processing operation
processOperation(): void {
this.logger.info('processOperation start');
TraceControllerUtils.startTraceWithTaskId('ProgressOperation', this.requestTime);
if (this.uris == null) {
this.logger.error('Invalid callback data, uris is null!');
return;
}
let length = this.uris.length;
this.logger.info(`selected count: ${this.count}, uris's length: ${length}`);
logInfo(TAG, 'processOperation start');
startTraceWithTaskId('ProgressOperation', this.requestTime);
let length = this.items.length;
logInfo(TAG, `selected count: ${this.count}, uris's length: ${length}`);
// Batch deletion
this.totalBatches = Math.floor(length / this.BATCH_SIZE) + ((length % this.BATCH_SIZE) ? 1 : 0);
this.logger.info(`The count to be operate is ${length}, operate in ${this.totalBatches} batches`);
logInfo(TAG, `The count to be operate is ${length}, operate in ${this.totalBatches} batches`);
if (this.isCancelled) {
this.isCancelled = false;
}
this.startTime = Date.now();
this.requestOneBatchOperation();
this.requestOneBatchOperation()
}
// Batch circular deletion
cyclicOperation() {
this.logger.info('cyclicOperation');
this.menuContext.broadCast.emit(BroadCastConstants.UPDATE_PROGRESS,
[this.getExpectProgress(), this.currentBatch]);
logInfo(TAG, 'cyclicOperation');
this.menuContext.broadCast.emit(BroadcastConstants.UPDATE_PROGRESS, [this.getExpectProgress(), this.currentBatch]);
if (this.isCancelled) {
this.onProcessDone();
@ -124,54 +117,57 @@ export class ProcessMenuOperation implements MenuOperation, AsyncCallback<String
}
}
// Operate a batch of data
requestOneBatchOperation(): void {
}
onProcessDone(): void {
this.menuContext.broadCast.emit(BroadCastConstants.UPDATE_PROGRESS, [100]);
this.menuContext.broadCast.emit(BroadcastConstants.UPDATE_PROGRESS, [100]);
this.findSameOperation = FindSameOperation.NONE
if (this.startTime != null) {
let operateCount = this.currentBatch >= this.totalBatches ? this.count : this.currentBatch * this.BATCH_SIZE;
let costTime = Date.now() - this.startTime;
this.logger.debug(`process data operate done, operate ${operateCount} items, cost time ${costTime} ms,\
logDebug(TAG, `process data operate done, operate ${operateCount} items, cost time ${costTime} ms,\
average ${(costTime / operateCount)} ms/item.`);
}
this.isCancelled = false;
TraceControllerUtils.finishTraceWithTaskId('ProgressOperation', this.requestTime);
finishTraceWithTaskId('ProgressOperation', this.requestTime);
this.onOperationEnd && this.onOperationEnd(this.isError, this.successBatch, this.count);
}
// Operate cancel callback
onOperateCancelled(): void {
this.logger.info('Operate Cancel');
logInfo(TAG, 'Operate Cancel');
this.isCancelled = true;
this.onProcessDone();
}
// Operate cancel callback
onOperatePause(): void {
this.logger.info('Operate Pause');
logInfo(TAG, 'Operate Pause');
this.isPause = true;
}
// Calculate the operation progress according to the batch
getExpectProgress(): number {
this.logger.info('getExpectProgress');
logInfo(TAG, 'getExpectProgress');
let progress = Math.min(
Math.floor(this.MAX_PROGRESS * this.currentBatch * this.BATCH_SIZE / this.count), this.MAX_PROGRESS);
return progress;
}
setFindSameOperation(newOperation: number): void {
this.logger.info(`setFindSameOperation ${newOperation}`);
logInfo(TAG, `setFindSameOperation ${newOperation}`);
this.findSameOperation = newOperation
}
async getFileCopyOrMoveInfo(uri: string, albumInfo: any, deviceId?) {
this.logger.debug('getFileCopyOrMoveInfo start');
let dataImpl = BrowserDataFactory.getFeature(BrowserDataFactory.TYPE_PHOTO);
let fileAsset = await dataImpl.getDataById(StringUtil.getIdFromUri(uri), deviceId);
let targetAsset = await dataImpl.getDataByName(fileAsset.displayName, albumInfo);
async getFileCopyOrMoveInfo(fileAsset: MediaLib.FileAsset, albumInfo: SimpleAlbumDataItem) {
logDebug(TAG, 'getFileCopyOrMoveInfo start');
let item: SimpleAlbumDataItem = new SimpleAlbumDataItem("", fileAsset.displayName, albumInfo.relativePath, "", "")
let fetchOptions = await getFetchOptionsByItem(item)
let targetAsset = (await mediaModel.getAllCommonMediaItem(fetchOptions, false)).fileAsset
if (targetAsset == null || targetAsset == undefined) {
this.logger.debug('targetAsset not found');
logDebug(TAG, 'targetAsset not found');
}
return { sourceAsset: fileAsset, targetAsset: targetAsset };

View File

@ -12,16 +12,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Logger } from '../../utils/Logger'
import Want from '@ohos.application.Want'
import { logDebug, logInfo, logWarn, logError } from '../utils/LoggerUtils'
import { startAbility } from '../utils/AbilityUtils';
import { MenuOperation } from './MenuOperation'
import { MenuContext } from './MenuContext'
import { AsyncCallback } from '../../model/common/AsyncCallback'
import { SelectManager } from '../../model/browser/SelectManager';
import { AsyncCallback } from '../interface/AsyncCallback'
const TAG = "ShareMenuOperation"
export class ShareMenuOperation implements MenuOperation, AsyncCallback<string[]> {
private menuContext: MenuContext;
private logger: Logger = new Logger('ShareMenuOperation');
private uris: string[];
constructor(menuContext: MenuContext) {
@ -30,21 +31,9 @@ export class ShareMenuOperation implements MenuOperation, AsyncCallback<string[]
doAction(): void {
if (this.menuContext == null) {
this.logger.error('menuContext is null, return');
logWarn(TAG, 'menuContext is null, return');
return;
}
let selectManager: SelectManager = this.menuContext.selectManager;
if (selectManager == null) {
this.logger.error('selectManager is null, return');
return;
}
let count = selectManager.getSelectedCount();
if (count <= 0) {
this.logger.error('count <= 0, return');
return;
}
selectManager.getSelection(this);
}
callback(uris: string[]): void {
@ -53,8 +42,8 @@ export class ShareMenuOperation implements MenuOperation, AsyncCallback<string[]
}
shareFileAsset() {
this.logger.info('shareFileAsset');
globalThis.photosAbilityContext.startAbility({
logInfo(TAG, 'shareFileAsset');
let want: Want = {
'action': 'com.huawei.intent.action.hwCHOOSER',
'parameters': {
'ability.want.params.INTENT': {
@ -65,10 +54,7 @@ export class ShareMenuOperation implements MenuOperation, AsyncCallback<string[]
}
}
}
}).then(() => {
this.logger.debug('raul startAbility complete');
}).catch((error) => {
this.logger.error(`raul startAbility failed, error: ${JSON.stringify(error)}`);
});
}
startAbility(want)
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Want from "@ohos.application.Want";
import { logDebug, logError } from './LoggerUtils'
const TAG = "AbilityUtils"
export async function startAbility(want: Want): Promise<void> {
try {
await globalThis.appContext.startAbility(want)
logDebug(TAG, 'raul startAbility complete');
} catch (error) {
logError(TAG, `raul startAbility failed, error: ${JSON.stringify(error)}`);
}
}
export async function terminateSelf(): Promise<void> {
await globalThis.appContext.terminateSelf()
}
export async function terminateSelfWithResult(parameter): Promise<void> {
await globalThis.appContext.terminateSelfWithResult(parameter)
}

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
export class BroadCast {
export class Broadcast {
private callBackArray = [];
constructor() {

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import preferences from '@ohos.data.preferences'
import { logDebug, logInfo, logWarn, logError } from './LoggerUtils'
import createOrGet from './SingleInstanceUtils';
const TAG = "DataStoreUtil"
class DataStoreUtil {
private preferences: preferences.Preferences = undefined;
private static readonly PREFERENCES_KEY_MY_FORM_STORE = 'myFormStore'
constructor() {
}
public async init(): Promise<void> {
logDebug(TAG, 'init start!');
if (this.preferences != undefined) {
logInfo(TAG, `init preferences before`);
return
}
try {
let context = globalThis.applicationContext
this.preferences = await preferences.getPreferences(context, DataStoreUtil.PREFERENCES_KEY_MY_FORM_STORE)
logInfo(TAG, `init preferences ${preferences}`)
} catch (err) {
logError(TAG, `init err ${err}`);
}
logDebug(TAG, 'init end!');
}
public async getData(key: string, defValue) {
logDebug(TAG, 'getData start!');
if (this.preferences == undefined) {
logWarn(TAG, `getData preferences is undefined`);
return defValue;
}
let temValue = defValue;
try {
temValue = await this.preferences.get(key, defValue)
logDebug(TAG, "The value of startup is " + temValue)
} catch (err) {
logError(TAG, `Get the value failed with err: ${err}`)
}
return temValue;
}
public async putData(key: string, value) {
logDebug(TAG, 'putData start!');
if (this.preferences == undefined) {
logWarn(TAG, 'putData preferences is undefined');
return
}
try {
await this.preferences.put(key, value)
logDebug(TAG, 'Put the value successfully.')
} catch (err) {
logError(TAG, `Put the value failed with err: ${err}`);
}
}
public async delData(key: string) {
logDebug(TAG, 'delData start!');
if (this.preferences == undefined) {
logWarn(TAG, `delData preferences is undefined`);
}
try {
await this.preferences.delete(key)
logDebug(TAG, "Delete the value successfully.");
} catch (err) {
logError(TAG, `Delete the value failed with err: ${err}`);
}
}
public async flush() {
logDebug(TAG, 'flush start!');
if (this.preferences == undefined) {
logWarn(TAG, `flush preferences is undefined`);
}
await this.preferences.flush();
}
public async hasData(key: string) {
logDebug(TAG, `hasData start! preferences ${this.preferences}`);
let ret = false;
if (this.preferences == undefined) {
logWarn(TAG, `hasData preferences is undefined`);
return ret;
}
try {
ret = await this.preferences.has(key)
logDebug(TAG, "hasData the value successfully.");
} catch (err) {
ret = false
logError(TAG, `hasData the value failed with err: ${err}`);
}
return ret;
}
}
let dataStore = createOrGet(DataStoreUtil, TAG);
export default dataStore as DataStoreUtil;

View File

@ -13,13 +13,13 @@
* limitations under the License.
*/
import { Logger } from './Logger'
import { logInfo, logWarn } from './LoggerUtils'
import i18n from '@ohos.i18n';
import Intl from '@ohos.intl';
const TAG = "DateUtil"
export class DateUtil {
// logger
private static logger: Logger = new Logger('DateUtil');
private static LANGUAGE_LOCALES_MAP = {
'zh': 'zh-CN',
'en': 'en-US'
@ -96,7 +96,7 @@ export class DateUtil {
public static getLocalizedTime(milliseconds: number): string {
let locales: string = this.getLocales();
let is24HourClock = i18n.is24HourClock();
this.logger.info(`get is24HourClock ${is24HourClock}`);
logInfo(TAG, `get is24HourClock ${is24HourClock}`);
return new Intl.DateTimeFormat(locales, this.buildDateTimeOpt('', '', '', (!is24HourClock ? '2-digit' : 'numeric'), '2-digit')).format(new Date(milliseconds));
}
@ -114,11 +114,11 @@ export class DateUtil {
// Format duration
public static getFormattedDuration(milliSecond: number): string {
if (milliSecond == null) {
this.logger.error('getFormattedDuration, input is null!');
logWarn(TAG, 'getFormattedDuration, input is null!');
return '00:00';
}
if (milliSecond <= 0) {
this.logger.error('getFormattedDuration, input is negative number!');
logWarn(TAG, 'getFormattedDuration, input is negative number!');
return '00:00';
}
if (milliSecond < this.MILLISECONDS_PER_SECOND) {
@ -137,7 +137,7 @@ export class DateUtil {
private static checkTime(time: number): string{
if (time < 0) {
this.logger.error('checkTime, input is negative number!');
logWarn(TAG, 'checkTime, input is negative number!');
return '00';
}
let formatTime: string = time.toString();

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { logInfo } from './LoggerUtils'
const TAG = "ImageUtil"
const MAX_BIT = 30;
const BIT_SIXTEEN = 16;
const BIT_EIGHT = 8;
const BIT_FOUR = 4;
const BIT_TWO = 2;
const BIT_ONE = 1;
export function computeSampleSize(width: number, height: number, minSideLength: number, maxNumOfPixels: number): number {
if (width == 0 || height == 0 || minSideLength == 0 || maxNumOfPixels == 0) {
return 2;
}
let initialSize = computeInitialSampleSize(width, height, minSideLength, maxNumOfPixels);
logInfo(TAG, `initialSize: ${initialSize}`);
return initialSize <= 8 ? nextPowerOf2(initialSize) : Math.floor((initialSize + 8 - 1) / 8) * 8;
}
function computeInitialSampleSize(width: number, height: number, minSideLength: number, maxNumOfPixels: number): number {
if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
return 1;
}
let lowerBound: number = (maxNumOfPixels == -1) ? 1 : Math.ceil(Math.sqrt((width * height) / maxNumOfPixels));
logInfo(TAG, `lowerBound: ${lowerBound}`);
if (minSideLength == -1) {
return lowerBound;
} else {
let sampleSize = Math.min(width / minSideLength, height / minSideLength);
return Math.max(sampleSize, lowerBound);
}
}
function nextPowerOf2(value: number): number {
let useValue = value;
if (useValue <= 0 || useValue > (1 << MAX_BIT)) {
}
useValue -= 1;
useValue |= useValue >> BIT_SIXTEEN;
useValue |= useValue >> BIT_EIGHT;
useValue |= useValue >> BIT_FOUR;
useValue |= useValue >> BIT_TWO;
useValue |= useValue >> BIT_ONE;
logInfo(TAG, `nextPowerOf2:${useValue}`);
return useValue + 1;
}

View File

@ -13,24 +13,18 @@
* limitations under the License.
*/
export interface LoadingListener {
export function logDebug(TAG: string, message: string | number): void {
console.debug('Photos_' + TAG + ': ' + message)
}
/**
* Quantity change notice
*
* @param size Total number of media
*/
onSizeLoadingFinished(size: number): void;
export function logInfo(TAG: string, message: string | number): void {
console.info('Photos_' + TAG + ': ' + message)
}
/**
* Data loading completion notification
*/
onDataLoadingFinished(): void;
export function logWarn(TAG: string, message: string | number): void {
console.warn('Photos_' + TAG + ': ' + message)
}
/**
* Data change notification
*
* @param dataIndex dataIndex
*/
onDataChanged(dataIndex: number): void;
export function logError(TAG: string, message: string | number): void {
console.error('Photos_' + TAG + ': ' + message)
}

View File

@ -13,12 +13,12 @@
* limitations under the License.
*/
export interface BrowserDataInterface {
getData(callback: any, param: any): void;
export function distance(x1: number, y1: number, x2: number, y2: number): number {
let dstX = x1 - x2;
let dstY = y1 - y2;
return Math.sqrt(dstX * dstX + dstY * dstY);
}
getDataCount(callback: any, param: any): void;
getDataById(id: any, deviceId?: any): any;
getDataByName(name: string, albumInfo: any): any;
export function clamp(num: number, min: number, max: number): number {
return Math.min(Math.max(num, min), max);
}

View File

@ -0,0 +1,35 @@
// @ts-nocheck
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import resourceManager from '@ohos.resourceManager';
import { logDebug, logWarn, logError } from './LoggerUtils'
const TAG = "ResourceUtils"
export async function getResourceString(resource: Resource): Promise<string> {
try {
logDebug(TAG, `getResourceString: ${JSON.stringify(resource)}`);
let mgr: resourceManager.ResourceManager = await resourceManager.getResourceManager(globalThis.appContext);
if (mgr != null || mgr != undefined) {
return await mgr.getString(resource.id);
} else {
logWarn(TAG, `getResourceManager instance is none`);
return null;
}
} catch (error) {
logError(TAG, `getResourceString error: ${error}`);
return null;
}
}

View File

@ -0,0 +1,26 @@
/**
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { logDebug } from './LoggerUtils';
const TAG = "SingleInstanceHelper";
export default function createOrGet<T>(objectClass: { new(): T }, storageKey: string): T {
if (!globalThis[storageKey]) {
globalThis[storageKey] = new objectClass();
logDebug(TAG, `Create key of ${storageKey}`);
}
return globalThis[storageKey];
}

View File

@ -13,12 +13,15 @@
* limitations under the License.
*/
import { Logger as RootLogger } from '../../../common/utils/Logger'
import { logInfo } from './LoggerUtils'
const MODULE_TIMELINE = 'Timeline_';
const TAG = "StringUtil"
export class Logger extends RootLogger {
constructor(module: string) {
super(MODULE_TIMELINE + module);
}
export function getIdFromUri(uri: string): number {
let srcIndex = uri.lastIndexOf('/');
let srcEnd = uri.length;
let srcId = uri.substring(srcIndex + 1, srcEnd);
let fileId = new Number(srcId);
logInfo(TAG, `getIdByUri fileId: ${fileId}`);
return fileId.valueOf();
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import bytrace from '@ohos.bytrace'
// Used to track the start of sequential tasks
export function startTrace(name: string): void {
bytrace.startTrace(name, 1);
}
// Used to track the end of sequential tasks. The name must be the same as that at start
export function finishTrace(name: string): void {
bytrace.finishTrace(name, 1);
}
// Used to track the start of cross tasks
// (scenarios where the next task starts before the previous task is finished)
export function startTraceWithTaskId(name: string, taskId: number): void {
bytrace.startTrace(name, taskId);
}
// Used to track the end of cross tasks. The name and taskId must be the same as at start
export function finishTraceWithTaskId(name: string, taskId: number): void {
bytrace.finishTrace(name, taskId);
}

View File

@ -12,23 +12,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import prompt from '@system.prompt';
import { logDebug } from './LoggerUtils';
import screenManager from '../manager/ScreenManager';
export interface BrowserOperationInterface {
create(param: any): any;
delete(uri: string): any;
trash(uri: string, isTrash: boolean): any;
copy(source: any, target: any): any;
favor(uri: string, isFavor: boolean): void;
setName(source: any, name: string): void;
setOrientation(source: any, orientation: number): void;
setRelativePath(source: any, relativePath: string): void;
commitChanges(source: any): any;
const TAG = "UiUtil"
const TOAST_DURATION = 3000;
export function showToast(message: string) {
let naviBarHeight = screenManager.getNaviBarHeight()
logDebug(TAG, `showToast: ${message}`);
prompt.showToast({
message: message,
duration: TOAST_DURATION,
bottom: `${64 + naviBarHeight}vp`
});
}

View File

@ -0,0 +1,129 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { logDebug, logWarn, logError } from '../utils/LoggerUtils';
import { AlbumDataImpl } from '../model/AlbumDataImpl'
import { ItemDataSource } from './ItemDataSource'
import { AlbumDataItem } from '../data/AlbumDataItem'
const TAG = "AlbumsDataSource"
export class AlbumsDataSource extends ItemDataSource {
private albumDataItems: AlbumDataItem[] = []
private albumDataImpl: AlbumDataImpl = new AlbumDataImpl()
setBlackList(blackList: string[]) {
this.albumDataImpl.setBlackList(blackList)
}
setSelectType(selectType: number) {
this.albumDataImpl.setSelectType(selectType)
}
setDeviceId(deviceId: string) {
this.albumDataImpl.setDeviceId(deviceId)
}
totalCount(): number {
return this.albumDataItems.length
}
getData(index: number): any{
if (index < 0 || index >= this.albumDataItems.length) {
logWarn(TAG, `${index}/${this.albumDataItems.length}`)
return undefined
}
this.albumDataItems[index].index = index
return this.albumDataItems[index]
}
isSelect(): boolean {
let isSelect = true
for (let i = 0;i < this.albumDataItems.length; i++) {
if (!this.albumDataItems[i].isSelect) {
isSelect = false
break
}
}
return isSelect
}
isDisableRename(): boolean {
let isDisableRename = false
for (let i = 0;i < this.albumDataItems.length; i++) {
if (this.albumDataItems[i].isSelect && this.albumDataItems[i].isDisableRename) {
isDisableRename = true
break
}
}
return isDisableRename
}
isDisableDelete(): boolean {
let isDisableDelete = false
for (let i = 0;i < this.albumDataItems.length; i++) {
if (this.albumDataItems[i].isSelect && this.albumDataItems[i].isDisableDelete) {
isDisableDelete = true
break
}
}
return isDisableDelete
}
setSelect(isSelect: boolean) {
this.albumDataItems.forEach((item: AlbumDataItem) => {
item.setSelect(isSelect)
})
}
getSelectedCount(): number {
let count = 0
for (let i = 0;i < this.albumDataItems.length; i++) {
if (this.albumDataItems[i].isSelect) {
count++
}
}
return count
}
getSelectedItems(): AlbumDataItem[]{
let items: AlbumDataItem[] = []
this.albumDataItems.forEach((item: AlbumDataItem) => {
if (item.isSelect) {
items.push(item)
}
})
return items
}
dataReload() {
this.reloadAlbumItemData().then((isEmpty: boolean) => {
this.notifyDataReload()
})
}
dataRemove() {
for (let i = this.albumDataItems.length - 1;i >= 0; i--) {
if (this.albumDataItems[i].isDeleted()) {
this.albumDataItems.splice(i, 1)
super.notifyDataDelete(i)
}
}
}
async reloadAlbumItemData(): Promise<boolean> {
this.albumDataItems = await this.albumDataImpl.reloadAlbumItemData()
return this.albumDataItems.length == 0
}
}

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { DistributedDataImpl } from '../model/DistributedDataImpl'
import { ItemDataSource } from './ItemDataSource'
import { PeerDataItem } from '../data/PeerDataItem'
export class DistributedDataSource extends ItemDataSource {
private peerDataItems: PeerDataItem[] = []
private distributedDataImpl: DistributedDataImpl = new DistributedDataImpl()
totalCount(): number {
return this.peerDataItems.length
}
getData(index: number): any{
this.peerDataItems[index].index = index
return this.peerDataItems[index]
}
isSelect(): boolean {
let isSelect = true
for (let i = 0;i < this.peerDataItems.length; i++) {
if (!this.peerDataItems[i].isSelect) {
isSelect = false
break
}
}
return isSelect
}
setSelect(isSelect: boolean) {
this.peerDataItems.forEach((item: PeerDataItem) => {
item.setSelect(isSelect)
})
}
getSelectedCount(): number {
let count = 0
for (let i = 0;i < this.peerDataItems.length; i++) {
if (this.peerDataItems[i].isSelect) {
count++
}
}
return count
}
getSelectedItems(): any[]{
return []
}
dataReload(): void {
this.reloadAlbumItemData().then((isEmpty: number) => {
this.notifyDataReload()
})
}
dataRemove(): void {
}
async reloadAlbumItemData(): Promise<number> {
let before = this.peerDataItems.length
this.peerDataItems = await this.distributedDataImpl.reloadAlbumItemData()
return this.peerDataItems.length - before
}
}

View File

@ -0,0 +1,143 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { logDebug, logInfo, logWarn } from '../utils/LoggerUtils'
import { GroupDataImpl } from '../model/GroupDataImpl'
import { ItemDataSource } from '../vm/ItemDataSource'
import { MediaDataItem } from '../data/MediaDataItem';
const TAG = "GroupItemDataSource"
export class GroupItemDataSource extends ItemDataSource {
groupDataItem: MediaDataItem[] = []
private groupDataImpl: GroupDataImpl = new GroupDataImpl()
constructor() {
super()
}
setSelectType(selectType: number) {
this.groupDataImpl.setSelectType(selectType)
}
setAlbumId(id: string) {
logInfo(TAG, `setAlbumId: ${id}`)
this.groupDataImpl.setAlbumId(id)
}
setDeviceId(id: string) {
logInfo(TAG, `setDeviceId: ${id}`)
this.groupDataImpl.setDeviceId(id)
}
totalCount(): number {
return this.groupDataItem.length
}
getIndexByItem(item: MediaDataItem): number{
let index = -1
let length = this.groupDataItem.length
for (let i = 0;i < length; i++) {
if (this.groupDataItem[i].uri == item.uri) {
index = i;
break
}
}
return index
}
getData(index: number): any{
if (index < 0 || index >= this.groupDataItem.length) {
logWarn(TAG, `${index}/${this.groupDataItem.length}`)
return undefined
}
this.groupDataItem[index].index = index
return this.groupDataItem[index]
}
isSelect(): boolean {
let isSelect = true
for (let i = 0;i < this.groupDataItem.length; i++) {
if (!this.groupDataItem[i].isSelect) {
isSelect = false
break
}
}
return isSelect
}
getSelectedCount(): number {
let count = 0
this.groupDataItem.forEach((item: MediaDataItem) => {
if (item.isSelect) {
count++
}
})
return count
}
getItems(): MediaDataItem[]{
let items: MediaDataItem[] = []
this.groupDataItem.forEach((item: MediaDataItem) => {
items.push(item)
})
return items
}
getSelectedItems(): MediaDataItem[]{
let items: MediaDataItem[] = []
this.groupDataItem.forEach((item: MediaDataItem) => {
if (item.isSelect) {
items.push(item)
}
})
return items
}
getSelectedUris(): string[]{
let uris: string[] = []
this.groupDataItem.forEach((item: MediaDataItem) => {
if (item.isSelect) {
uris.push(item.uri)
}
})
return uris
}
setSelect(isSelect: boolean) {
this.groupDataItem.forEach((item: MediaDataItem) => {
item.setSelect(isSelect)
})
}
async reloadGroupItemData(isGrid: boolean): Promise<boolean> {
this.groupDataItem = await this.groupDataImpl.reloadGroupItemData(isGrid)
return this.groupDataItem.length == 0
}
dataReload(isGrid: boolean) {
this.reloadGroupItemData(isGrid).then((isEmpty: boolean) => {
this.notifyDataReload()
})
}
dataRemove() {
for (let i = this.groupDataItem.length - 1;i >= 0; i--) {
if (this.groupDataItem[i].isDeleted()) {
this.groupDataItem.splice(i, 1)
super.notifyDataDelete(i)
}
}
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { logInfo } from '../utils/LoggerUtils'
import { MediaDataItem } from '../data/MediaDataItem'
const TAG = "ItemDataSource"
export abstract class ItemDataSource implements IDataSource {
private listeners: DataChangeListener[] = [];
abstract totalCount(): number
abstract getData(index: number): any
abstract isSelect(): boolean
abstract getSelectedCount(): number
abstract getSelectedItems(): any[]
abstract dataRemove(): void
registerDataChangeListener(listener: DataChangeListener): void{
logInfo(TAG, 'registerDataChangeListener');
if (this.listeners.indexOf(listener) < 0) {
this.listeners.push(listener);
logInfo(TAG, `registerDataChangeListener, add listener, length: ${this.listeners.length}`);
}
}
unregisterDataChangeListener(listener: DataChangeListener): void{
logInfo(TAG, 'unregisterDataChangeListener');
const pos = this.listeners.indexOf(listener);
if (pos >= 0) {
this.listeners.splice(pos, 1);
logInfo(TAG, `registerDataChangeListener, remove listener, length: ${this.listeners.length}`);
}
}
notifyDataChange(index: number): void {
this.listeners.forEach(listener => {
listener.onDataChange(index)
})
}
notifyDataReload(): void {
this.listeners.forEach(listener => {
listener.onDataReloaded()
})
}
notifyDataDelete(index: number): void {
this.listeners.forEach(listener => {
listener.onDataDelete(index)
})
}
}

View File

@ -0,0 +1,11 @@
{
"module": {
"name": "base",
"type": "har",
"deviceTypes": [
"default",
"tablet"
],
"uiSyntax": "ets"
}
}

View File

@ -0,0 +1,52 @@
{
"color": [
{
"name": "white",
"value": "#FFFFFF"
},
{
"name": "black",
"value": "#000000"
},
{
"name": "album_cover_stroke_color",
"value": "#14000000"
},
{
"name": "album_cover_gradient_start_color",
"value": "#33000000"
},
{
"name": "album_scrollbar_color",
"value": "#ffb3b3b3"
},
{
"name": "transparent",
"value": "#00000000"
},
{
"name": "text_color_above_picture",
"value": "#FFFFFF"
},
{
"name": "item_selection_bg_color",
"value": "#80FFFFFF"
},
{
"name": "default_background_color",
"value": "#FFF1F3F5"
},
{
"name": "empty_or_recycle_album_icon",
"value": "#99FFFFFF"
},
{
"name": "empty_or_recycle_album_back",
"value": "#9E9E9E"
},
{
"name": "color_control_highlight",
"value": "#007DFF"
}
]
}

View File

@ -0,0 +1,144 @@
{
"float": [
{
"name": "icon_size",
"value": "24vp"
},
{
"name": "icon_size_hot",
"value": "32vp"
},
{
"name": "max_padding_start",
"value": "24vp"
},
{
"name": "max_padding_end",
"value": "24vp"
},
{
"name": "grid_item_text_line_height",
"value": "12vp"
},
{
"name": "grid_item_duration_markAnchor_x",
"value": "-4vp"
},
{
"name": "grid_item_duration_markAnchor_y",
"value": "16vp"
},
{
"name": "grid_item_duration_margin_right",
"value": "32vp"
},
{
"name": "grid_item_favor_markAnchor_x",
"value": "28vp"
},
{
"name": "grid_item_favor_markAnchor_y",
"value": "-4vp"
},
{
"name": "grid_item_preview_padding",
"value": "4vp"
},
{
"name": "grid_item_checkbox_markAnchor",
"value": "28vp"
},
{
"name": "scroll_bar_margin_small",
"value": "48vp"
},
{
"name": "scroll_bar_small_width",
"value": "32vp"
},
{
"name": "scroll_bar_small_height",
"value": "56vp"
},
{
"name": "scroll_bar_big_width",
"value": "40vp"
},
{
"name": "scroll_bar_big_height",
"value": "69vp"
},
{
"name": "album_scrollbar_normal_size",
"value": "6vp"
},
{
"name": "album_scrollbar_select_size",
"value": "12vp"
},
{
"name": "album_scrollbar_height_size",
"value": "80vp"
},
{
"name": "album_scrollbar_radius",
"value": "50vp"
},
{
"name": "recycle_album_cover_icon_size",
"value": "48vp"
},
{
"name": "album_set_name_margin_right",
"value": "16vp"
},
{
"name": "album_set_count_margin_left",
"value": "8vp"
},
{
"name": "album_set_count_margin_bottom",
"value": "8vp"
},
{
"name": "album_set_new_style_icon",
"value": "22vp"
},
{
"name": "album_set_tab_bar_height",
"value": "56vp"
},
{
"name": "album_set_page_padding_end",
"value": "56vp"
},
{
"name": "album_set_page_padding_end_112",
"value": "112vp"
},
{
"name": "album_cover_stroke_width",
"value": "0.5vp"
},
{
"name": "crop_vertical_padding",
"value": "16vp"
},
{
"name": "dialog_border_radius",
"value": "36vp"
},
{
"name": "dialog_title_height",
"value": "56vp"
},
{
"name": "dialog_content_margin",
"value": "24vp"
},
{
"name": "details_dialog_button_height",
"value": "40vp"
}
]
}

View File

@ -0,0 +1,52 @@
{
"string": [
{
"name": "page_show",
"value": "page from npm package"
},
{
"name": "id_text_font_family_medium",
"value": "HwChinese-medium"
},
{
"name": "id_text_font_family_regular",
"value": "sans-serif"
},
{
"name": "album_all",
"value": "All photos"
},
{
"name": "album_camera",
"value": "Camera"
},
{
"name": "album_video",
"value": "Videos"
},
{
"name": "album_favor",
"value": "My favorites"
},
{
"name": "album_remote_device",
"value": "From other devices"
},
{
"name": "album_screen_shot",
"value": "Screenshots"
},
{
"name": "album_recycle",
"value": "Recently deleted"
},
{
"name": "yes",
"value": "OK"
},
{
"name": "no",
"value": "CANCEL"
}
]
}

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

View File

Before

Width:  |  Height:  |  Size: 489 B

After

Width:  |  Height:  |  Size: 489 B

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,48 @@
{
"string": [
{
"name": "id_text_font_family_medium",
"value": "中粗"
},
{
"name": "id_text_font_family_regular",
"value": "标准"
},
{
"name": "album_all",
"value": "所有照片"
},
{
"name": "album_camera",
"value": "相机"
},
{
"name": "album_video",
"value": "视频"
},
{
"name": "album_favor",
"value": "我的收藏"
},
{
"name": "album_screen_shot",
"value": "截屏录屏"
},
{
"name": "album_remote_device",
"value": "其他设备保存"
},
{
"name": "album_recycle",
"value": "最近删除"
},
{
"name": "yes",
"value": "确认"
},
{
"name": "no",
"value": "取消"
}
]
}

View File

@ -0,0 +1,12 @@
{
"string": [
{
"name": "yes",
"value": "[CJ_874431]_OK"
},
{
"name": "no",
"value": "[CJ_874432]_Cancel"
}
]
}

View File

@ -1,11 +1,22 @@
{
"devDependencies": {},
"name": "entry",
"ohos": {
"org": "huawei",
"directoryLevel": "module",
"buildTool": "hvigor"
},
"version": "1.0.0",
"dependencies": {}
"devDependencies": {},
"name": "entry",
"ohos": {
"org": "huawei",
"directoryLevel": "module",
"buildTool": "hvigor"
},
"version": "1.0.0",
"dependencies": {
"@ohos/base": "file:../common/base",
"@ohos/album": "file:../features/album",
"@ohos/browser": "file:../features/browser",
"@ohos/distributed": "file:../features/distributed",
"@ohos/formEditor": "file:../features/formEditor",
"@ohos/grid": "file:../features/grid",
"@ohos/mediaOperation": "file:../features/mediaOperation",
"@ohos/selectAlbums": "file:../features/selectAlbum",
"@ohos/third": "file:../features/third",
"@ohos/timeline": "file:../features/timeline"
}
}

View File

@ -2,6 +2,6 @@ import AbilityStage from "@ohos.application.AbilityStage"
export default class PhotosAbilityStage extends AbilityStage {
onCreate() {
globalThis.photosGlobalContext = this.context;
globalThis.applicationContext = this.context;
}
}

View File

@ -18,16 +18,19 @@ import { Logger } from './common/Logger'
import { FormControllerManager } from './controller/FormControllerManager'
import { FormController } from './controller/FormController'
import { Constants } from './common/Constants'
import mediaModel from '@ohos/base/src/main/ets/model/MediaModel'
export default class FormAbility extends FormExtension {
private logger: Logger = new Logger('FormAbility');
onCreate(want) {
this.logger.info(`form onCreate. want ${JSON.stringify(want)}`);
mediaModel.onCreate(this.context)
globalThis.appContext = this.context
let param = want.parameters;
let formId = param['ohos.extra.param.key.form_identity'];
this.logger.info(`form onCreate formId: ${formId}`);
let formControllerManager: FormControllerManager = FormControllerManager.getInstance(this.context);
let formControllerManager: FormControllerManager = FormControllerManager.getInstance();
formControllerManager.initData(formId, Constants.PHOTOS_FORM_OPERATION_MODE_NONE).then(() => {
let formController: FormController = formControllerManager.getController(formId);
this.logger.info(`form onCreate. formController ${formController}`);
@ -50,13 +53,13 @@ export default class FormAbility extends FormExtension {
onUpdate(formId) {
this.logger.info(`onUpdate, formId: ${formId} context ${JSON.stringify(this.context)}`);
let formControllerManager: FormControllerManager = FormControllerManager.getInstance(this.context);
let formControllerManager: FormControllerManager = FormControllerManager.getInstance();
formControllerManager.updateController(formId);
}
onVisibilityChange(newStatus) {
this.logger.info(`onVisibilityChange, newStatus: ${JSON.stringify(newStatus)}`);
let formControllerManager: FormControllerManager = FormControllerManager.getInstance(this.context);
let formControllerManager: FormControllerManager = FormControllerManager.getInstance();
for (let key in newStatus) {
this.logger.info(`onVisibilityChange, key:${key} value ${newStatus[key]}`);
let formId = key;
@ -66,13 +69,13 @@ export default class FormAbility extends FormExtension {
onEvent(formId, message) {
this.logger.info(`onEvent, formId: ${formId}, message: ${message}`);
let formControllerManager: FormControllerManager = FormControllerManager.getInstance(this.context);
let formControllerManager: FormControllerManager = FormControllerManager.getInstance();
formControllerManager.onEvent(formId, message);
}
onDestroy(formId) {
this.logger.info(`onDestroy, formId: ${formId}`);
let formControllerManager: FormControllerManager = FormControllerManager.getInstance(this.context);
let formControllerManager: FormControllerManager = FormControllerManager.getInstance();
formControllerManager.destroyController(formId);
}
};

View File

@ -31,7 +31,6 @@ export class Constants {
static readonly CURRENT_INDEX = 'currentIndex_';
static readonly FLEX_GROW = 2;
static readonly DIALOG_BOTTOM_OFFSET: number = 12;
static readonly DEFAULT_TIME = 30;
static readonly NUMBER_2 = 2;
static readonly NUMBER_3 = 3;
static readonly NUMBER_4: number = 4;
@ -40,6 +39,4 @@ export class Constants {
static readonly NUMBER_24: number = 24;
static readonly FROM_PLAYBACK_INTERVAL = 'form_playback_interval';
static readonly PHOTOS_FORM_DEFAULT_PERIOD = 30;
static readonly SELECT_ALBUM: string = 'selectAlbum';
static readonly SELECT_PHOTO: string = 'selectPhoto';
}

View File

@ -1,3 +1,4 @@
import { startAbility } from '../../../../../../common/base/src/main/ets/utils/AbilityUtils';
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
@ -12,18 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Want from '@ohos.application.Want'
import { MediaDataManager } from '../data/MediaDataManager'
import { Logger } from '../common/Logger'
import formBindingData from '@ohos.application.formBindingData';
import { Constants } from '../common/Constants'
import { DataStoreUtil } from '../../common/utils/DataStoreUtil'
import formProvider from '@ohos.application.formProvider';
import { MediaLibraryAccess } from '../../common/access/MediaLibraryAccess'
import { Constants as commonConstants } from '../../common/model/common/Constants'
export class FormController {
private context: any;
private formId: string;
private operationMode: number = Constants.PHOTOS_FORM_OPERATION_MODE_NONE;
private logger: Logger = new Logger('FormController');
@ -31,12 +29,11 @@ export class FormController {
private static readonly MSG_ROUTER_PHOTOS = 'routerPhotos'
mediaDataManager: MediaDataManager;
constructor(context: any, formId: string, operationMode: number, callback?: Function) {
this.context = context;
constructor(formId: string, operationMode: number, callback?: Function) {
this.formId = formId;
this.operationMode = operationMode;
this.callback = callback;
this.mediaDataManager = new MediaDataManager(context, formId, operationMode, this);
this.mediaDataManager = new MediaDataManager(formId, operationMode, this);
}
bindFormData(formId: string): any {
@ -89,7 +86,6 @@ export class FormController {
onDestroy() {
this.logger.info('onDestroy start!');
this.mediaDataManager.closeFd();
MediaLibraryAccess.getInstance().onDestroy();
this.callback = null;
this.logger.info('onDestroy done end!');
}
@ -101,7 +97,7 @@ export class FormController {
routerPhotoBrowser() {
this.logger.debug('routerPhotoBrowser start!');
let param = {
let param: Want = {
'bundleName': 'com.ohos.photos',
'abilityName': 'com.ohos.photos.MainAbility',
'parameters': {
@ -113,10 +109,9 @@ export class FormController {
}
};
this.logger.debug(`routerPhotoBrowser parm ${JSON.stringify(param)}`);
this.context.startAbility(param).then(() => {
this.logger.info(`raul startAbility complete`);
startAbility(param).then(() => {
AppStorage.Delete(Constants.FROM_CONTROLLER_MANAGER);
});
})
this.onDestroy();
this.logger.debug('routerPhotoBrowser end!');
}

View File

@ -15,22 +15,19 @@
import { Constants } from '../common/Constants'
import { FormController } from './FormController'
import { Logger } from '../common/Logger'
import { DataStoreUtil } from '../../common/utils/DataStoreUtil'
import dataStore from '../../../../../../common/base/src/main/ets/utils/DataStoreUtil'
export class FormControllerManager {
private context: any;
private formControllerMap = new Map();
private logger: Logger = new Logger('FormControllerManager');
private constructor(context) {
private constructor() {
this.logger.info('new FormControllerManager');
this.context = context;
DataStoreUtil.getInstance(globalThis.photosGlobalContext);
}
public static getInstance(context: any): FormControllerManager {
public static getInstance(): FormControllerManager {
if (AppStorage.Get(Constants.FROM_CONTROLLER_MANAGER) == null) {
AppStorage.SetOrCreate(Constants.FROM_CONTROLLER_MANAGER, new FormControllerManager(context));
AppStorage.SetOrCreate(Constants.FROM_CONTROLLER_MANAGER, new FormControllerManager());
}
return AppStorage.Get(Constants.FROM_CONTROLLER_MANAGER);
}
@ -41,7 +38,7 @@ export class FormControllerManager {
this.logger.info('formId is 0 or formName is null!');
return null;
}
let controller = new FormController(this.context, formId, operationMode, callback);
let controller = new FormController(formId, operationMode, callback);
if (controller == null || controller == undefined) {
this.logger.error('It is failed to create FormController!');
@ -54,16 +51,17 @@ export class FormControllerManager {
async initData(formId: string, operationMode: number, callback?: Function): Promise<void> {
this.logger.debug(`initData start! operationMode: ${operationMode}`);
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).init().then(async () => {
try {
await dataStore.init()
let formIdKey: string = 'formId_' + formId;
let hasFormId = await DataStoreUtil.getInstance(globalThis.photosGlobalContext).hasData(formIdKey);
let hasFormId = await dataStore.hasData(formIdKey);
this.logger.debug(`The value of hasFormId is ${hasFormId}`);
if (hasFormId) {
this.createFormController(formId, operationMode, callback);
}
}).catch((err) => {
} catch (err) {
this.logger.error(`init err ${err}`);
})
}
this.logger.debug('initData end!');
}

View File

@ -1,4 +1,3 @@
// @ts-nocheck
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
@ -15,11 +14,12 @@
*/
import { MediaData } from './MediaData'
import { Constants } from '../common/Constants'
import { MediaConstants } from '@ohos/base/src/main/ets/constants/MediaConstants';
import { Logger } from '../common/Logger'
import { AlbumDefine } from '../../common/model/browser/AlbumDefine'
import { DataStoreUtil } from '../../common/utils/DataStoreUtil'
import { MediaLibraryAccess } from '../../common/access/MediaLibraryAccess'
import resourceManager from '@ohos.resourceManager';
import dataStore from '../../../../../../common/base/src/main/ets/utils/DataStoreUtil'
import mediaModel from '@ohos/base/src/main/ets/model/MediaModel'
import { getResourceString } from '@ohos/base/src/main/ets/utils/ResourceUtils'
import { getAlbumDisplayName, getFetchOptions } from '@ohos/base/src/main/ets/helper/MediaDataHelper'
export class MediaDataManager {
private mediaData: MediaData = null;
@ -30,78 +30,37 @@ export class MediaDataManager {
private fd: number = -1;
private key: string = '';
private operationMode: number = Constants.PHOTOS_FORM_OPERATION_MODE_NONE;
private context: any;
private isNextFag: boolean = true;
private isUpdate: boolean = false;
constructor(context: any, formId: string, operationMode: number, formController: any) {
constructor(formId: string, operationMode: number, formController: any) {
this.formController = formController;
this.operationMode = operationMode;
this.context = context;
this.initData(formId);
}
async getResourceString(resource: Resource) {
try {
this.logger.info(`getResourceString: ${JSON.stringify(resource)}`);
let mgr: resourceManager.ResourceManager = await resourceManager.getResourceManager(this.context);
if (mgr != null || mgr != undefined) {
return await mgr.getString(resource.id);
} else {
this.logger.error(`getResourceManager instance is none`);
return null;
}
} catch (error) {
this.logger.error(`getResourceString error: ${error}`);
return null;
}
}
async initData(formId: string) {
this.logger.info(`initData formId ${formId}`);
MediaLibraryAccess.getInstance().onCreate(this.context);
MediaLibraryAccess.getInstance().getPublicDirectory().then(async () => {
await this.storageRead(formId);
if (this.mediaData == null || this.mediaData == undefined) {
this.logger.info('initData new MediaData!');
this.mediaData = new MediaData(formId,
await this.getResourceString($r('app.string.album_camera')),
Constants.PHOTOS_FORM_CAMERA_NAME, AlbumDefine.ALBUM_ID_CAMERA, '', 0,
Constants.PHOTOS_FORM_DEFAULT_PERIOD, 1, 0);
}
this.logger.info(`initData formId ${this.mediaData.formId}
albumName ${this.mediaData.albumName} currentIndex ${this.mediaData.currentIndex}`);
let displayName = await this.getAlbumDisplayName(this.mediaData.albumId);
if (displayName != null) {
this.mediaData.displayName = displayName;
this.logger.info('initData displayName' + this.mediaData.displayName)
}
await this.loadData();
});
}
private async getAlbumDisplayName(formId) {
this.logger.debug('getAlbumDisplayName name ' + formId)
switch (formId) {
case AlbumDefine.ALBUM_ID_ALL:
return await this.getResourceString($r('app.string.album_all'));
case AlbumDefine.ALBUM_ID_CAMERA:
return await this.getResourceString($r('app.string.album_camera'));
case AlbumDefine.ALBUM_ID_FAVOR:
return await this.getResourceString($r('app.string.album_favor'));
case AlbumDefine.ALBUM_ID_REMOTE:
return await this.getResourceString($r('app.string.album_remote_device'));
case AlbumDefine.ALBUM_ID_SNAPSHOT:
return await this.getResourceString($r('app.string.album_screen_shot'));
default:
break;
await this.storageRead(formId);
if (this.mediaData == null || this.mediaData == undefined) {
this.logger.info('initData new MediaData!');
this.mediaData = new MediaData(formId,
await getResourceString($r('app.string.album_camera')),
Constants.PHOTOS_FORM_CAMERA_NAME, MediaConstants.ALBUM_ID_CAMERA, '', 0,
Constants.PHOTOS_FORM_DEFAULT_PERIOD, 1, 0);
}
return null;
this.logger.info(`initData formId ${this.mediaData.formId}
albumName ${this.mediaData.albumName} currentIndex ${this.mediaData.currentIndex}`);
let displayName = await getAlbumDisplayName(this.mediaData.albumId);
if (displayName != null) {
this.mediaData.displayName = displayName;
this.logger.info('initData displayName' + this.mediaData.displayName)
}
await this.loadData();
}
async saveData() {
this.logger.debug('saveData');
this.filterOutVideoMediaData();
this.updateMediaData();
if (((this.operationMode != Constants.PHOTOS_FORM_OPERATION_MODE_EVENT)
&& (this.operationMode != Constants.PHOTOS_FORM_OPERATION_MODE_DESTROY)
@ -146,32 +105,32 @@ export class MediaDataManager {
async storageRead(formId: string) {
this.logger.debug('storageRead start!');
let formIdKey: string = 'formId_' + formId
let hasFormId = await DataStoreUtil.getInstance(globalThis.photosGlobalContext).hasData(formIdKey);
let hasFormId = await dataStore.hasData(formIdKey);
this.logger.debug(`The value of hasFormId is ${hasFormId}`)
if (hasFormId) {
let displayNameKey = 'displayName_' + formId;
let displayName = await DataStoreUtil.getInstance(globalThis.photosGlobalContext).getData(displayNameKey, '') as string;
let displayName = await dataStore.getData(displayNameKey, '') as string;
this.logger.debug(`The value of albumName is ${displayName}`);
let albumNameKey = 'albumName_' + formId;
let albumName = await DataStoreUtil.getInstance(globalThis.photosGlobalContext).getData(albumNameKey, '') as string;
let albumName = await dataStore.getData(albumNameKey, '') as string;
this.logger.debug(`The value of albumName is ${albumName}`);
let albumIdKey = 'albumId_' + formId;
let albumId = await DataStoreUtil.getInstance(globalThis.photosGlobalContext).getData(albumIdKey, '') as string;
let albumId = await dataStore.getData(albumIdKey, '') as string;
this.logger.debug(`The value of albumId is ${albumId}`);
let currentUriKey = 'currentUri_' + formId;
let currentUri = await DataStoreUtil.getInstance(globalThis.photosGlobalContext).getData(currentUriKey, '') as string;
let currentUri = await dataStore.getData(currentUriKey, '') as string;
this.logger.debug(`The value of currentUri is ${currentUri}`);
let currentIndexKey = 'currentIndex_' + formId;
let currentIndex = await DataStoreUtil.getInstance(globalThis.photosGlobalContext).getData(currentIndexKey, 0) as number;
let currentIndex = await dataStore.getData(currentIndexKey, 0) as number;
this.logger.debug(`The value of currentIndex is ${currentIndex}`);
let intervalTimeKey = 'intervalTime_' + formId;
let intervalTime = await DataStoreUtil.getInstance(globalThis.photosGlobalContext).getData(intervalTimeKey, 0) as number;
let intervalTime = await dataStore.getData(intervalTimeKey, 0) as number;
this.logger.debug(`The value of intervalTime is ${intervalTime}`);
let isShowKey = 'isShow_' + formId;
let isShow = await DataStoreUtil.getInstance(globalThis.photosGlobalContext).getData(isShowKey, 0) as number;
let isShow = await dataStore.getData(isShowKey, 0) as number;
this.logger.debug(`The value of isShow is ${isShow}`);
let arkUriKey = 'arkUri_' + formId;
let arkUri = await DataStoreUtil.getInstance(globalThis.photosGlobalContext).getData(arkUriKey, 0) as number;
let arkUri = await dataStore.getData(arkUriKey, 0) as number;
this.logger.debug(`The value of arkUri is ${arkUri}`);
if (arkUri == 0) {
arkUri = 1;
@ -187,107 +146,78 @@ export class MediaDataManager {
async storageSet() {
this.logger.debug('storageSet start!');
let formIdKey = 'formId_' + this.mediaData.formId;
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).putData(formIdKey, this.mediaData.formId);
await dataStore.putData(formIdKey, this.mediaData.formId);
let displayNameKey = 'displayName_' + this.mediaData.formId;
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).putData(displayNameKey, this.mediaData.displayName);
await dataStore.putData(displayNameKey, this.mediaData.displayName);
let albumNameKey = 'albumName_' + this.mediaData.formId;
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).putData(albumNameKey, this.mediaData.albumName);
await dataStore.putData(albumNameKey, this.mediaData.albumName);
let albumIdKey = 'albumId_' + this.mediaData.formId;
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).putData(albumIdKey, this.mediaData.albumId);
await dataStore.putData(albumIdKey, this.mediaData.albumId);
let currentUriKey = 'currentUri_' + this.mediaData.formId;
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).putData(currentUriKey, this.mediaData.currentUri);
await dataStore.putData(currentUriKey, this.mediaData.currentUri);
let currentIndexKey = 'currentIndex_' + this.mediaData.formId;
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).putData(currentIndexKey, this.mediaData.currentIndex);
await dataStore.putData(currentIndexKey, this.mediaData.currentIndex);
let intervalTimeKey = 'intervalTime_' + this.mediaData.formId;
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).putData(intervalTimeKey, this.mediaData.intervalTime);
await dataStore.putData(intervalTimeKey, this.mediaData.intervalTime);
let isShowKey = 'isShow_' + this.mediaData.formId;
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).putData(isShowKey, this.mediaData.isShowAlbumName);
await dataStore.putData(isShowKey, this.mediaData.isShowAlbumName);
let arkUriKey = 'arkUri_' + this.mediaData.formId;
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).putData(arkUriKey, this.mediaData.arkUri);
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).flush();
await dataStore.putData(arkUriKey, this.mediaData.arkUri);
await dataStore.flush();
this.logger.debug('storageSet end!');
}
async storageDelete() {
this.logger.debug('storageDelete start!');
let formIdKey = 'formId_' + this.mediaData.formId;
if (await DataStoreUtil.getInstance(globalThis.photosGlobalContext).hasData(formIdKey)) {
if (await dataStore.hasData(formIdKey)) {
this.logger.debug('storageDelete formId');
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).delData(formIdKey);
await dataStore.delData(formIdKey);
}
let displayNameKey = 'displayName_' + this.mediaData.formId;
if (await DataStoreUtil.getInstance(globalThis.photosGlobalContext).hasData(displayNameKey)) {
if (await dataStore.hasData(displayNameKey)) {
this.logger.debug('storageDelete displayName');
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).delData(displayNameKey);
await dataStore.delData(displayNameKey);
}
let albumNameKey = 'albumName_' + this.mediaData.formId;
if (await DataStoreUtil.getInstance(globalThis.photosGlobalContext).hasData(albumNameKey)) {
if (await dataStore.hasData(albumNameKey)) {
this.logger.debug('storageDelete albumName');
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).delData(albumNameKey);
await dataStore.delData(albumNameKey);
}
let albumIdKey = 'albumId_' + this.mediaData.formId;
if (await DataStoreUtil.getInstance(globalThis.photosGlobalContext).hasData(albumIdKey)) {
if (await dataStore.hasData(albumIdKey)) {
this.logger.debug('storageDelete albumId');
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).delData(albumIdKey);
await dataStore.delData(albumIdKey);
}
let currentUriKey = 'currentUri_' + this.mediaData.formId;
if (await DataStoreUtil.getInstance(globalThis.photosGlobalContext).hasData(currentUriKey)) {
if (await dataStore.hasData(currentUriKey)) {
this.logger.debug('storageDelete currentUri');
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).delData(currentUriKey);
await dataStore.delData(currentUriKey);
}
let currentIndexKey = 'currentIndex_' + this.mediaData.formId;
if (await DataStoreUtil.getInstance(globalThis.photosGlobalContext).hasData(currentIndexKey)) {
if (await dataStore.hasData(currentIndexKey)) {
this.logger.debug('storageDelete currentIndex');
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).delData(currentIndexKey);
await dataStore.delData(currentIndexKey);
}
let intervalTimeKey = 'intervalTime_' + this.mediaData.formId;
if (await DataStoreUtil.getInstance(globalThis.photosGlobalContext).hasData(intervalTimeKey)) {
if (await dataStore.hasData(intervalTimeKey)) {
this.logger.debug('storageDelete intervalTime');
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).delData(intervalTimeKey);
await dataStore.delData(intervalTimeKey);
}
let isShowKey = 'isShow_' + this.mediaData.formId;
if (await DataStoreUtil.getInstance(globalThis.photosGlobalContext).hasData(isShowKey)) {
if (await dataStore.hasData(isShowKey)) {
this.logger.debug('storageDelete isShowAlbumName');
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).delData(isShowKey);
await dataStore.delData(isShowKey);
}
let arkUriKey = 'arkUri_' + this.mediaData.formId;
if (await DataStoreUtil.getInstance(globalThis.photosGlobalContext).hasData(arkUriKey)) {
if (await dataStore.hasData(arkUriKey)) {
this.logger.debug('storageDelete arkUri');
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).delData(arkUriKey);
await dataStore.delData(arkUriKey);
}
await DataStoreUtil.getInstance(globalThis.photosGlobalContext).flush();
await dataStore.flush();
this.logger.debug('storageDelete end!');
}
filterOutVideoMediaData() {
this.logger.debug('filterOutVideoMediaData start!');
if (this.items.length == 0) {
return;
}
if (this.items[this.mediaData.currentIndex].mediaType == MediaLibraryAccess.MEDIA_TYPE_IMAGE) {
return;
}
let currentIndex = this.mediaData.currentIndex;
for (let i = currentIndex; i < this.items.length; i++) {
let type = this.items[i].mediaType;
if (type == MediaLibraryAccess.MEDIA_TYPE_IMAGE) {
this.mediaData.currentIndex = i;
return;
}
}
if (currentIndex != 0) {
for (let i = 0; i < this.items.length; i++) {
let type = this.items[i].mediaType;
if (type == MediaLibraryAccess.MEDIA_TYPE_IMAGE) {
this.mediaData.currentIndex = i;
return;
}
}
}
this.mediaData.currentIndex = 0;
this.logger.debug('filterOutVideoMediaData end!');
}
updateMediaData() {
this.logger.debug('updateMediaData start! index ${this.mediaData.currentIndex}');
if (this.mediaData.currentIndex == -1) {
@ -387,7 +317,7 @@ export class MediaDataManager {
async openCurrentFd(): Promise<number> {
let fileAsset = this.getCurrentItem();
this.logger.info(`openCurrentFd uri: ${this.mediaData.currentUri}`);
let fd = (fileAsset != null) ? await MediaLibraryAccess.getInstance().openAsset('R', fileAsset) : -1;
let fd = (fileAsset != null) ? await mediaModel.openAsset('R', fileAsset) : -1;
this.logger.info(`openCurrentFd the fd: ${fd}`);
return fd;
}
@ -400,7 +330,7 @@ export class MediaDataManager {
this.logger.info(`close the fd: ${this.fd}`);
let fileAsset = this.getCurrentItem();
if (fileAsset != null && this.fd != -1) {
await MediaLibraryAccess.getInstance().closeAsset(this.fd, fileAsset);
await mediaModel.closeAsset(this.fd, fileAsset);
this.fd = -1;
}
}
@ -416,18 +346,13 @@ export class MediaDataManager {
this.logger.debug('loadData end!');
}
async getItems(albumId: string, startIndex?: number, count?: number, deviceId?) {
async getItems(albumId: string) {
this.logger.info('getItems start!');
let fetchOpt = AlbumDefine.getFileFetchOpt(albumId, deviceId, startIndex, count);
switch (albumId) {
case AlbumDefine.ALBUM_ID_ALL:
let allObject = await MediaLibraryAccess.getInstance().getAllObject(fetchOpt);
return allObject;
break;
default:
return await MediaLibraryAccess.getInstance().getEntityAlbumObject(AlbumDefine.getAlbumFetchOpt(
albumId, deviceId), fetchOpt);
break;
let fetchOpt = await getFetchOptions(MediaConstants.SELECT_TYPE_IMAGE, albumId, "")
if (albumId == MediaConstants.ALBUM_ID_FAVOR) {
return await mediaModel.getAllFavorMediaItems(fetchOpt)
} else {
return await mediaModel.getAllMediaItems(fetchOpt)
}
}
}

View File

@ -14,25 +14,21 @@
*/
import deviceInfo from '@ohos.deviceInfo';
import window from '@ohos.window';
import Ability from '@ohos.application.Ability'
import wantConstant from '@ohos.ability.wantConstant'
import { Logger } from '../common/utils/Logger'
import { ScreenManager } from '../common/model/common/ScreenManager'
import { PixelMapManager } from '../common/model/common/PixelMapManager'
import { StatusBarColorController } from '../common/model/common/StatusBarColorController'
import { MediaLibraryAccess } from '../common/access/MediaLibraryAccess'
import { TimelineDataSourceManager } from '../feature/timeline/model/TimelineDataSourceManager'
import screenManager from '../../../../../common/base/src/main/ets/manager/ScreenManager'
import { Constants } from '../common/model/common/Constants'
import { MediaDataSource } from '../common/model/browser/photo/MediaDataSource'
import { BroadCastManager } from '../common/model/common/BroadCastManager';
import { TraceControllerUtils } from '../common/utils/TraceControllerUtils';
import { BroadCastConstants } from '../common/model/common/BroadCastConstants'
import broadcastManager from '../../../../../common/base/src/main/ets/manager/BroadcastManager';
import { startTrace, finishTrace } from '../../../../../common/base/src/main/ets/utils/TraceControllerUtils';
import { BroadcastConstants } from '../../../../../common/base/src/main/ets/constants/BroadcastConstants'
import mediaModel from '@ohos/base/src/main/ets/model/MediaModel'
import router from '@system.router'
const appLogger: Logger = new Logger('app');
let isFromCard = false;
let isFromCamera = false;
let appBroadCast = BroadCastManager.getInstance().getBroadCast();
let appBroadcast = broadcastManager.getBroadcast();
var pagePath: string = deviceInfo.deviceType == ('phone' || 'default') ? 'product/phone/view/index' : 'product/pad/view/index';
export default class MainAbility extends Ability {
@ -43,12 +39,12 @@ export default class MainAbility extends Ability {
onCreate(want, launchParam) {
appLogger.info('Application onCreate');
TraceControllerUtils.startTrace('onCreate');
startTrace('onCreate');
// Ability is creating, initialize resources for this ability
globalThis.photosAbilityContext = this.context;
globalThis.appContext = this.context;
mediaModel.onCreate(this.context)
let action = want.parameters;
if (action != null && action != undefined && action.uri == MainAbility.ACTION_URI_PHOTO_DETAIL) {
isFromCamera = true;
AppStorage.SetOrCreate(Constants.ENTRY_FROM_HAP, Constants.ENTRY_FROM_CAMERA);
} else if (action != null && action != undefined && action.uri == MainAbility.ACTION_URI_SINGLE_SELECT) {
AppStorage.SetOrCreate(Constants.ENTRY_FROM_HAP, Constants.ENTRY_FROM_SINGLE_SELECT);
@ -78,8 +74,8 @@ export default class MainAbility extends Ability {
"ohos.permission.MEDIA_LOCATION",
"ohos.permission.DISTRIBUTED_DATASYNC"
];
TraceControllerUtils.startTrace('requestPermissionsFromUser');
globalThis.photosAbilityContext.requestPermissionsFromUser(requestPermissionList).then(function (data) {
startTrace('requestPermissionsFromUser');
this.context.requestPermissionsFromUser(requestPermissionList).then(function (data) {
appLogger.info(`requestPermissionsFromUser data: ${JSON.stringify(data)}`)
let result = 0
for (let i = 0; i < data.authResults.length; i++) {
@ -88,14 +84,8 @@ export default class MainAbility extends Ability {
if (result >= 0) {
// Improve cold startup performance. Initialize the timeline in advance
AppStorage.SetOrCreate(Constants.PERMISSION_STATUS, true);
TraceControllerUtils.finishTrace('requestPermissionsFromUser');
MediaLibraryAccess.getInstance().onCreate(globalThis.photosAbilityContext)
if (!isFromCard && !isFromCamera) {
TraceControllerUtils.finishTrace('onCreate');
TimelineDataSourceManager.getInstance();
} else {
TraceControllerUtils.finishTrace('onCreate');
}
finishTrace('requestPermissionsFromUser');
finishTrace('onCreate');
} else {
AppStorage.SetOrCreate(Constants.PERMISSION_STATUS, false);
}
@ -103,12 +93,12 @@ export default class MainAbility extends Ability {
appLogger.error(`Failed to requestPermissionsFromUser, ${err.code}`);
});
appBroadCast.on(BroadCastConstants.THIRD_ROUTE_PAGE, this.thirdRouterPage.bind(this));
appBroadcast.on(BroadcastConstants.THIRD_ROUTE_PAGE, this.thirdRouterPage.bind(this));
appLogger.info('Application onCreate end');
}
onNewWant(want) {
TraceControllerUtils.startTrace('onNewWant');
startTrace('onNewWant');
let action = want.parameters;
if (action != null && action != undefined && action.uri == MainAbility.ACTION_URI_PHOTO_DETAIL) {
AppStorage.SetOrCreate(Constants.ENTRY_FROM_HAP, Constants.ENTRY_FROM_CAMERA);
@ -132,63 +122,33 @@ export default class MainAbility extends Ability {
} else {
AppStorage.SetOrCreate(Constants.ENTRY_FROM_HAP, Constants.ENTRY_FROM_NONE);
}
TraceControllerUtils.finishTrace('onNewWant');
finishTrace('onNewWant');
}
onDestroy() {
// Ability is creating, release resources for this ability
appLogger.info('Application onDestroy');
let pixelMapManager: PixelMapManager = PixelMapManager.getInstance();
pixelMapManager.release();
let statusBarColorController: StatusBarColorController = StatusBarColorController.getInstance();
statusBarColorController.release();
AppStorage.Delete(Constants.ENTRY_FROM_HAP);
MediaLibraryAccess.getInstance().onDestroy();
}
onWindowStageCreate(windowStage) {
TraceControllerUtils.startTrace('onWindowStageCreate');
startTrace('onWindowStageCreate');
// Main window is created, set main page for this ability
appLogger.info('Application onWindowStageCreate');
globalThis.photosWindowStage = windowStage;
ScreenManager.getInstance().on(ScreenManager.ON_LEFT_BLANK_CHANGED, data => {
appLogger.info(`onleftBlankChanged: ${data}`);
AppStorage.SetOrCreate(Constants.LEFT_BLANK, data);
});
ScreenManager.getInstance().on(ScreenManager.ON_SPLIT_MODE_CHANGED, mode => {
appLogger.info(`onSplitModeChanged: ${JSON.stringify(mode)}`);
AppStorage.SetOrCreate(Constants.IS_SPLIT_MODE, mode);
});
TraceControllerUtils.startTrace('getMainWindow');
windowStage.getMainWindow().then((win) => {
startTrace('getMainWindow');
windowStage.getMainWindow().then((win: window.Window) => {
AppStorage.SetOrCreate(Constants.MAIN_WINDOW, win);
TraceControllerUtils.finishTrace('getMainWindow');
TraceControllerUtils.startTrace('initializationSize');
ScreenManager.getInstance().initializationSize(win).then(() => {
TraceControllerUtils.finishTrace('initializationSize');
finishTrace('getMainWindow');
startTrace('initializationSize');
screenManager.initializationSize(win).then(() => {
finishTrace('initializationSize');
if (isFromCard) {
MediaLibraryAccess.getInstance().getPublicDirectory().then(() => {
let dataSource: MediaDataSource = new MediaDataSource(Constants.DEFAULT_SLIDING_WIN_SIZE);
dataSource.setAlbumId(AppStorage.Get(Constants.FROM_ALBUM_ID));
dataSource.initialize();
let times = 0;
//该场景是卡片跳转到大图指定图片,需要等大图数据获取完成再跳转,否则组件无法跳转。
let intervalId = setInterval(() => {
appLogger.info(`setInterval go`);
if (dataSource.getRawData(0) || times >= MainAbility.RETRY_MAX_TIMES) {
AppStorage.SetOrCreate(Constants.APP_KEY_PHOTO_BROWSER, dataSource);
windowStage.setUIContent(this.context, 'feature/browser/view/PhotoBrowser', null);
ScreenManager.getInstance().initWindowMode();
clearInterval(intervalId);
}
times++;
}, 50)
});
windowStage.setUIContent(this.context, 'feature/browser/view/PhotoBrowser', null);
} else {
windowStage.setUIContent(this.context, pagePath, null);
ScreenManager.getInstance().initWindowMode();
}
TraceControllerUtils.finishTrace('onWindowStageCreate');
finishTrace('onWindowStageCreate');
}).catch(() => {
appLogger.error(`get device screen info failed.`);
});
@ -205,7 +165,6 @@ export default class MainAbility extends Ability {
}
thirdRouterPage() {
TraceControllerUtils.startTrace('thirdRouterPage');
let entryFrom = AppStorage.Get(Constants.ENTRY_FROM_HAP);
let permission = AppStorage.Get(Constants.PERMISSION_STATUS);
appLogger.info(`thirdRouterPage entryFromHap: ${entryFrom} permission: ${permission}`);
@ -237,27 +196,10 @@ export default class MainAbility extends Ability {
};
router.replace(options);
} else if (entryFrom == Constants.ENTRY_FROM_FORM_ABILITY) {
let dataSource: MediaDataSource = new MediaDataSource(Constants.DEFAULT_SLIDING_WIN_SIZE);
dataSource.setAlbumId(AppStorage.Get(Constants.FROM_ALBUM_ID));
dataSource.initialize();
let times = 0;
//该场景是卡片跳转到大图指定图片,需要等大图数据获取完成再跳转,否则组件无法跳转。
let intervalId = setInterval(() => {
if (dataSource.getRawData(0) || times >= MainAbility.RETRY_MAX_TIMES) {
AppStorage.SetOrCreate(Constants.APP_KEY_PHOTO_BROWSER, dataSource);
let options = {
uri: 'feature/browser/view/PhotoBrowser',
params: {
pageFrom: Constants.ENTRY_FROM.CARD,
albumId: AppStorage.Get(Constants.FROM_ALBUM_ID),
position: AppStorage.Get(Constants.FROM_CURRENT_INDEX)
}
};
router.replace(options);
clearInterval(intervalId);
}
times++;
}, 50)
let options = {
uri: 'feature/browser/view/PhotoBrowser',
};
router.replace(options);
} else if (entryFrom == Constants.ENTRY_FROM_FORM_ABILITY_NONE) {
let options = {
uri: pagePath
@ -285,6 +227,5 @@ export default class MainAbility extends Ability {
router.clear();
AppStorage.SetOrCreate(Constants.ENTRY_FROM_HAP, 0)
}, 50);
TraceControllerUtils.finishTrace('thirdRouterPage');
}
}

View File

@ -1,504 +0,0 @@
// @ts-nocheck
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Logger } from '../utils/Logger'
import MediaLib from '@ohos.multimedia.mediaLibrary';
import { Constants } from '../model/common/Constants'
import { TraceControllerUtils } from '../utils/TraceControllerUtils';
export class MediaLibraryAccess {
private logger: Logger = new Logger('MediaLibraryAccess');
static readonly MEDIA_TYPE_IMAGE = MediaLib.MediaType.IMAGE;
static readonly MEDIA_TYPE_VIDEO = MediaLib.MediaType.VIDEO;
static readonly DIRECTORY_TYPE_IMAGE = MediaLib.DirectoryType.DIR_IMAGE;
static readonly DIRECTORY_TYPE_CAMERA = MediaLib.DirectoryType.DIR_CAMERA;
static readonly FILE_KEY_ID = MediaLib.FileKey.ID;
static readonly FILE_KEY_MEDIA_TYPE = MediaLib.FileKey.MEDIA_TYPE;
static readonly FILE_KEY_ALBUM_NAME = MediaLib.FileKey.ALBUM_NAME;
static readonly FILE_KEY_ALBUM_ID = MediaLib.FileKey.ALBUM_ID;
static readonly FILE_KEY_DISPLAY_NAME = MediaLib.FileKey.DISPLAY_NAME;
static readonly FILE_KEY_RELATIVE_PATH = MediaLib.FileKey.RELATIVE_PATH;
static readonly FILE_KEY_DATE_TAKEN = MediaLib.FileKey.DATE_ADDED; // TODO dateTaken is not supported, use dateAdded
static readonly FILE_KEY_DATE_TRASHED = 'date_trashed' //TODO dataTrashed is not define in FileKey
PUBLIC_PATH_IMAGE = '';
PUBLIC_PATH_CAMERA = '';
private media = null;
private requestTime: number;
public static getInstance(): MediaLibraryAccess {
if (AppStorage.Get(Constants.APP_KEY_INSTANCE_MEDIA_LIBRARY_ACCESS) == null) {
AppStorage.SetOrCreate(Constants.APP_KEY_INSTANCE_MEDIA_LIBRARY_ACCESS, new MediaLibraryAccess());
}
return AppStorage.Get(Constants.APP_KEY_INSTANCE_MEDIA_LIBRARY_ACCESS);
}
constructor() {
this.requestTime = Date.now();
}
onCreate(context) {
this.logger.debug(`Photos_MediaLibraryAccess onCreate ${context}`);
if (this.media) {
this.logger.debug(`Photos_MediaLibraryAccess onCreate already`);
return;
}
this.media = MediaLib.getMediaLibrary(context);
this.logger.debug('Photos_MediaLibraryAccess onCreate end');
if (this.media == null || this.media == undefined) {
this.logger.error('get media library instance failed!');
}
this.getPublicDirectory();
this.logger.info('onCreate done');
}
onDestroy() {
try {
this.media && this.media.release();
this.media = null;
this.logger.info('onDestroy done');
} catch (e) {
this.logger.error(`onDestroy error: ${e}`);
}
}
getMediaLibrary() {
return this.media;
}
async getAllObject(fetchOpt) {
this.logger.info(`getAllObject: ${JSON.stringify(fetchOpt)}`);
try {
TraceControllerUtils.startTraceWithTaskId('getAllObject', this.requestTime);
let dataList = await this.media.getFileAssets(fetchOpt);
if (dataList == null) {
this.logger.warn('get all Object Data with empty dataList');
return [];
}
this.logger.debug(`get all Object Data raw data size: ${dataList.getCount()}`);
if (dataList.getCount() <= 0) {
return [];
}
let result = await dataList.getAllObject();
dataList.close();
TraceControllerUtils.finishTraceWithTaskId('getAllObject', this.requestTime);
return result;
} catch (error) {
this.logger.error(`getAllObject error: ${error}`);
return [];
}
}
async getCount(fetchOpt) {
this.logger.info(`getCount: ${JSON.stringify(fetchOpt)}`);
try {
TraceControllerUtils.startTraceWithTaskId('getCount', this.requestTime);
let dataList = await this.media.getFileAssets(fetchOpt);
if (dataList == null) {
this.logger.warn('get count dataList is 0');
return 0;
}
this.logger.debug(`get count raw data size: ${dataList.getCount()}`);
let result = dataList.getCount();
dataList.close();
TraceControllerUtils.finishTraceWithTaskId('getCount', this.requestTime);
return result;
} catch (error) {
this.logger.error(`get Count error: ${error}`);
return 0;
}
}
async getFirstObject(fetchOpt) {
let result = {
count: 0,
obj: null,
}
this.logger.info(`getFirstObject: ${JSON.stringify(fetchOpt)}`);
try {
TraceControllerUtils.startTraceWithTaskId('getFirstObject', this.requestTime);
let fileResult = await this.media.getFileAssets(fetchOpt);
if (fileResult != undefined) {
result.count = fileResult.getCount();
this.logger.error(`getFirstObject count is ${result.count}`);
if (result.count <= 0) {
return result;
}
let file = await fileResult.getFirstObject();
if (file) {
result.obj = file;
return result;
} else {
this.logger.error('Failed getFirstObject');
}
fileResult.close();
}
TraceControllerUtils.finishTraceWithTaskId('getFirstObject', this.requestTime);
return result;
} catch (error) {
this.logger.error(`getFirstObject loadData error: ${error}`);
return result;
}
}
async deleteAsset(uri: string) {
this.logger.debug(`deleteAsset uri: ${uri}`);
await this.media.deleteAsset(uri);
}
async getPublicDirectory() {
this.PUBLIC_PATH_IMAGE =
await this.media.getPublicDirectory(MediaLibraryAccess.DIRECTORY_TYPE_IMAGE);
this.PUBLIC_PATH_CAMERA =
await this.media.getPublicDirectory(MediaLibraryAccess.DIRECTORY_TYPE_CAMERA);
}
async createAsset(mediaType: any, displayName: string, relativePath: string) {
this.logger.debug('createAsset start');
if (relativePath == null || relativePath == undefined) {
this.logger.error('createAsset with empty relativePath');
return null;
}
this.logger.info(`createAsset ${mediaType} ${displayName} ${relativePath}`);
let fileAsset = await this.media.createAsset(mediaType, displayName, relativePath);
this.logger.debug(`createAsset end. new fileAsset: ${fileAsset}`);
if (fileAsset == null || fileAsset == undefined) {
this.logger.error('createAsset Fail');
return null;
}
return fileAsset;
}
async openAsset(mode: string, fileAsset: any) {
this.logger.debug('openAsset start');
let fd = await fileAsset.open(mode);
this.logger.info(`openAsset end. fd: ${fd}`);
if (fd <= 0) {
this.logger.error('openAsset Fail');
return;
}
return fd;
}
async closeAsset(fd: number, fileAsset: any) {
this.logger.debug('closeAsset start');
await fileAsset.close(fd);
}
async trashAsset(isTrash: boolean, fileAsset: any) {
this.logger.debug('trashAsset start');
await fileAsset.trash(isTrash);
}
async getFavoriteObject(fetchOpt) {
this.logger.info(`Get favorite object: ${JSON.stringify(fetchOpt)}`);
try {
let albums = await this.media.getPrivateAlbum(MediaLib.PrivateAlbumType.TYPE_FAVORITE);
this.logger.debug(`[getFavoriteObject] get smart albums length:${albums.length} name:${albums[0].albumName}`);
let fileResult = await albums[0].getFileAssets(fetchOpt);
this.logger.debug(`[getFavoriteObject] object count :${fileResult.getCount()}`);
let objects = await fileResult.getAllObject();
this.logger.debug(`[getFavoriteObject] objects done`);
fileResult.close();
return objects;
} catch (err) {
this.logger.error(`Get favorite object exception! msg: ${err}`);
return [];
}
}
async getTrashObject(fetchOpt) {
this.logger.info(`Get trash object: ${JSON.stringify(fetchOpt)}`);
try {
let albums = await this.media.getPrivateAlbum(MediaLib.PrivateAlbumType.TYPE_TRASH);
this.logger.debug(`[getTrashObject] get smart albums length:${albums.length} name:${albums[0].albumName}`);
let fileResult = await albums[0].getFileAssets(fetchOpt);
this.logger.debug(`[getTrashObject] object count :${fileResult.getCount()}`);
let objects = await fileResult.getAllObject();
this.logger.debug(`[getTrashObject] get objects done`);
fileResult.close();
return objects;
} catch (err) {
this.logger.error(`Get Trash Object exception! msg: ${err}`);
return [];
}
}
async getEntityAlbumObject(fetchOpt, fileFetchOpt) {
this.logger.info(`getEntityAlbumObject opt${JSON.stringify(fetchOpt)} fileOpt${JSON.stringify(fileFetchOpt)}`);
try {
let albums = await this.media.getAlbums(fetchOpt);
this.logger.debug(`[getEntityAlbumObject]Get Albums done`);
this.logger.debug(`[getEntityAlbumObject]Album length:${albums.length}`);
if (albums.length == 0) {
return []
}
this.logger.debug(`[getEntityAlbumObject]Albums name:${albums[0].albumName}`);
let fileResult = await albums[0].getFileAssets(fileFetchOpt);
this.logger.debug(`[getEntityAlbumObject]objects count :${fileResult.getCount()}`);
if (fileResult.getCount() == 0) {
return []
}
let objects = await fileResult.getAllObject();
this.logger.debug(`[getEntityAlbumObject]Get objects done`);
fileResult.close();
return objects;
} catch (err) {
this.logger.error(`Get Entity Album Object exception! msg: ${err}`);
return []
}
}
async getFavoriteCount() {
this.logger.debug(`getFavoriteCount`);
let fetchOpt = {
selections: '',
selectionArgs: [],
order: ''
}
try {
let albums = await this.media.getPrivateAlbum(MediaLib.PrivateAlbumType.TYPE_FAVORITE);
this.logger.debug(`[getFavoriteCount]Get smart Albums length:${albums.length} name:${albums[0].albumName}`);
let fileResult = await albums[0].getFileAssets(fetchOpt);
this.logger.debug(`[getFavoriteCount]Get objects done`);
let count = fileResult.getCount();
fileResult.close();
return count;
} catch (err) {
this.logger.error(`Get Favorite count exception! msg: ${err}`);
return 0;
}
}
async getTrashCount() {
this.logger.debug(`getTrashCount`);
let fetchOpt = {
selections: '',
selectionArgs: [],
order: ''
}
try {
let albums = await this.media.getPrivateAlbum(MediaLib.PrivateAlbumType.TYPE_TRASH);
this.logger.debug(`[getTrashCount]Get smart Albums length:${albums.length} name:${albums[0].albumName}`);
let fileResult = await albums[0].getFileAssets(fetchOpt);
this.logger.debug(`[getTrashCount]Get objects done`);
let count = fileResult.getCount();
fileResult.close();
return count;
} catch (err) {
this.logger.error(`Get Trash count exception! msg: ${err}`);
return 0;
}
}
async getEntityAlbumCount(fetchOpt, fileFetchOpt?) {
this.logger.info(`getEntityAlbumCount opt: ${JSON.stringify(fetchOpt)}`);
try {
let albums = await this.media.getAlbums(fetchOpt);
this.logger.debug(`[getEntityAlbumCount]Get entity Albums length:${albums.length} name:${albums[0].albumName}`);
let fileFetchOp;
if (fileFetchOpt == undefined) {
fileFetchOp = {
selections: '',
selectionArgs: []
}
} else {
fileFetchOp = fileFetchOpt;
}
this.logger.debug(`[getEntityAlbumCount]file opt: ${JSON.stringify(fileFetchOp)}`);
let fileResult = await albums[0].getFileAssets(fileFetchOp);
this.logger.debug(`[getEntityAlbumCount]Get objects done`);
let count = fileResult.getCount();
fileResult.close();
return count;
} catch (err) {
this.logger.error(`Get Entity Album count exception! msg: ${err}`);
return 0;
}
}
async getAlbums(fetchOpt) {
this.logger.info(`getAlbums ${JSON.stringify(fetchOpt)}`);
try {
let albums = await this.media.getAlbums(fetchOpt);
this.logger.debug(`[getAlbums]Get Albums done`);
this.logger.debug(`[getAlbums]length :${albums.length}`);
return albums;
} catch (err) {
this.logger.error(`Get Album exception! msg: ${err}`);
return [];
}
}
async getFavoriteAlbum(fetchOpt) {
this.logger.debug(`getFavoriteObject`);
let result = {
count: 0,
file: undefined,
}
try {
let albums = await this.media.getPrivateAlbum(MediaLib.PrivateAlbumType.TYPE_FAVORITE);
this.logger.debug(`[getFavoriteAlbum]Get smart Albums done`);
this.logger.debug(`[getFavoriteAlbum]Albums length:${albums.length}`);
if (albums.length > 0) {
let fileResult = await albums[0].getFileAssets(fetchOpt);
result.count = fileResult.getCount();
this.logger.debug(`[getFavoriteAlbum]object count: ${result.count}`);
if (result.count > 0) {
result.file = await fileResult.getFirstObject();
}
fileResult.close();
}
return result;
} catch (err) {
this.logger.error(`Get Favorite album exception! msg: ${err}`);
return result;
}
}
async getTrashAlbum(fetchOpt) {
this.logger.debug(`getTrashAlbum`);
let result = {
count: 0,
file: undefined,
}
try {
let albums = await this.media.getPrivateAlbum(MediaLib.PrivateAlbumType.TYPE_TRASH);
this.logger.debug(`[getTrashAlbum]Get smart Albums done`);
this.logger.debug(`[getTrashAlbum]Albums length:${albums.length}`);
if (albums.length > 0) {
let fileResult = await albums[0].getFileAssets(fetchOpt);
result.count = fileResult.getCount();
this.logger.debug(`[getTrashAlbum]trash photo count ${result.count}`);
if (result.count > 0) {
result.file = await fileResult.getFirstObject();
}
fileResult.close();
}
return result;
} catch (err) {
this.logger.error(`Get Trash album exception! msg: ${err}`);
return result;
}
}
async getConnectedRemoteDevice() {
this.logger.debug(`getConnectedRemoteDevice`);
try {
let result = await this.media.getActivePeers();
this.logger.debug(`[getConnectedRemoteDevice]device count: ${result.length}`);
return result;
} catch (err) {
this.logger.error(`Get Connected Remote Device exception! msg: ${err}`);
return [];
}
}
}
export class FetchOptionBuilder {
private fetchOption = {
selections: '',
selectionArgs: [],
order: ''
}
constructor(fetchOpt?) {
if (fetchOpt) {
this.fetchOption = fetchOpt;
}
}
build(): any{
return this.fetchOption;
}
media(mediaType: string) {
this.fetchOption.selections = `${this.prefix(this.fetchOption.selections)}${MediaLibraryAccess.FILE_KEY_MEDIA_TYPE} =?`;
this.fetchOption.selectionArgs.push(mediaType);
return this;
}
order(key: string, isAsc = true) {
let order = isAsc ? '' : ' DESC';
this.fetchOption.order = `${this.prefix(this.fetchOption.order)}${key}${order}`;
return this;
}
select(start: number, count: number) {
this.fetchOption.order = `${this.prefix(this.fetchOption.order)}LIMIT ${start},${count}`
return this;
}
device(deviceId: string) {
this.fetchOption['networkId'] = deviceId;
return this;
}
fileId(id: string) {
this.fetchOption.selections = `${this.prefix(this.fetchOption.selections)}${MediaLibraryAccess.FILE_KEY_ID} =?`;
this.fetchOption.selectionArgs.push(id);
return this;
}
albumId(id: string) {
this.fetchOption.selections = `${this.prefix(this.fetchOption.selections)}${MediaLibraryAccess.FILE_KEY_ALBUM_ID} =?`;
this.fetchOption.selectionArgs.push(id);
return this;
}
relativePath(path: string) {
this.fetchOption.selections = `${this.prefix(this.fetchOption.selections)}${MediaLibraryAccess.FILE_KEY_RELATIVE_PATH} =?`;
this.fetchOption.selectionArgs.push(path);
return this;
}
albumName(name: string) {
this.fetchOption.selections = `${this.prefix(this.fetchOption.selections)}${MediaLibraryAccess.FILE_KEY_ALBUM_NAME} =?`;
this.fetchOption.selectionArgs.push(name);
return this;
}
displayName(name: string) {
this.fetchOption.selections = `${this.prefix(this.fetchOption.selections)}${MediaLibraryAccess.FILE_KEY_DISPLAY_NAME} =?`;
this.fetchOption.selectionArgs.push(name);
return this;
}
logicalAnd() {
this.fetchOption.selections = `${this.prefix(this.fetchOption.selections)}AND`;
return this;
}
logicalOr() {
this.fetchOption.selections = `${this.prefix(this.fetchOption.selections)}OR`;
return this;
}
parentheses() {
this.fetchOption.selections = `(${this.fetchOption.selections})`
return this;
}
private prefix(str: string) {
if (str.length > 0) {
return `${str} `;
}
return str;
}
}

View File

@ -1,39 +0,0 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TimelineDataImpl } from '../model/browser/photo/TimelineDataImpl';
import { PhotoDataImpl } from '../model/browser/photo/PhotoDataImpl';
import { AlbumDataImpl } from '../model/browser/album/AlbumDataImpl';
import { DistributedDataImpl } from '../model/browser/album/DistributedDataImpl'
import { BrowserDataInterface } from './BrowserDataInterface'
export class BrowserDataFactory {
static readonly TYPE_PHOTO = 'photo';
static readonly TYPE_ALBUM = 'album';
static readonly TYPE_GROUP = 'group';
static readonly TYPE_DISTRIBUTED = 'distributed';
static getFeature(type: string, param?: any): BrowserDataInterface {
if (type == BrowserDataFactory.TYPE_ALBUM) {
return new AlbumDataImpl(param);
} else if (type == BrowserDataFactory.TYPE_PHOTO) {
return new PhotoDataImpl();
} else if (type == BrowserDataFactory.TYPE_GROUP) {
return new TimelineDataImpl();
} else if (type == BrowserDataFactory.TYPE_DISTRIBUTED) {
return new DistributedDataImpl();
}
}
}

View File

@ -1,40 +0,0 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { MenuOperation } from '../view/browserOperation/MenuOperation'
import { MenuContext } from '../view/browserOperation/MenuContext'
import { Logger } from '../utils/Logger'
import { Constants } from '../model/common/Constants'
export class MenuOperationFactory {
private logger: Logger = new Logger('MenuOperationFactory');
private constructor() {
this.logger.info('constructor');
}
public static getInstance(): MenuOperationFactory {
if (AppStorage.Get(Constants.APP_KEY_MENU_OPERATION_FACTORY) == null) {
AppStorage.SetOrCreate(Constants.APP_KEY_MENU_OPERATION_FACTORY, new MenuOperationFactory());
}
return AppStorage.Get(Constants.APP_KEY_MENU_OPERATION_FACTORY);
}
public createMenuOperation<T extends MenuOperation>
(operation: { new(menuContext: MenuContext): T }, menuContext: MenuContext): T {
this.logger.info(`createMenuOperation: ${operation.name}`);
return new operation(menuContext);
}
}

View File

@ -1,221 +0,0 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Logger } from '../../utils/Logger'
import { LoadingListener } from './LoadingListener'
// Abs DataSource
export abstract class AbsDataSource implements IDataSource {
// logger
logger: Logger = new Logger('AbsDataSource');
// Last data change time
lastChangeTime = 0;
// Last refresh time
lastUpdateTime = 0;
// Data change monitoring
listeners: DataChangeListener[] = [];
// callbacks
mCallbacks = {};
// Is data initialized
isInitData: boolean;
// Are there any new data changes
hasNewChange = false;
// Freeze data refresh
isFreezeDataUpdate = false;
// Whether the page is in the foreground, and the data can be refreshed in the foreground
isActive = true;
// Data loading listener
private loadingListeners: Array<LoadingListener> = new Array<LoadingListener>();
constructor() {
this.registerObserver();
}
abstract initData(): void;
abstract loadData(): void;
abstract totalCount(): number;
abstract getData(index: number): any;
initialize(): void {
if (!this.isInitData) {
this.initData();
this.isInitData = true;
}
}
registerDataChangeListener(listener: DataChangeListener): void {
this.logger.info('registerDataChangeListener');
if (this.listeners.indexOf(listener) < 0) {
this.listeners.push(listener);
this.logger.info(`registerDataChangeListener, add listener, length: ${this.listeners.length}`);
}
this.initialize();
}
unregisterDataChangeListener(listener: DataChangeListener): void {
this.logger.info('unregisterDataChangeListener');
const pos = this.listeners.indexOf(listener);
if (pos >= 0) {
this.listeners.splice(pos, 1);
this.logger.info(`registerDataChangeListener, remove listener, length: ${this.listeners.length}`);
}
this.unregisterObserver();
}
/**
* Overall refresh of notification framework
*/
onDataReloaded(): void {
if (this.isFreezeDataUpdate) {
return;
}
this.logger.info(`onDataReloaded listeners size ${this.listeners.length}`)
this.listeners.forEach(listener => {
listener.onDataReloaded();
})
}
/**
* Notification frame refresh by index
*
* @param layoutIndex index
*/
onDataChanged(layoutIndex: number): void {
if (this.isFreezeDataUpdate) {
return;
}
this.listeners.forEach(listener => {
listener.onDataChanged(layoutIndex);
})
}
/**
* Delete frame refresh by index
*
* @param layoutIndex index
*/
onDataDeleted(layoutIndex: number): void {
if (this.isFreezeDataUpdate) {
return;
}
this.listeners.forEach(listener => {
listener.onDataDeleted(layoutIndex);
})
}
public registerObserver(): void {
}
public unregisterObserver(): void {
}
registerCallback(name: string, cb: Function) {
this.mCallbacks[name] = cb;
}
unregisterCallback(name) {
this.mCallbacks[name] = undefined;
}
addLoadingListener(listener: LoadingListener): void {
if (listener == null) {
this.logger.error('listener is null');
return;
}
if (this.loadingListeners.indexOf(listener) > -1) {
return;
}
this.loadingListeners.push(listener);
}
removeLoadingListener(listener: LoadingListener): void {
if (listener == null) {
this.logger.error('listener is null');
return;
}
let index = this.loadingListeners.indexOf(listener);
if (index > -1) {
this.loadingListeners.splice(index, 1);
}
}
notifyDataChanged(dataIndex: number): void {
this.logger.debug(`notifyDataChanged,loadingListeners size:${this.loadingListeners.length},index:${dataIndex}`);
for (let listener of this.loadingListeners) {
listener.onDataChanged(dataIndex);
}
}
notifyDataLoadingFinished(): void {
this.logger.info(`notifyDataLoadingFinished, loadingListeners size:${this.loadingListeners.length}`);
for (let listener of this.loadingListeners) {
listener.onDataLoadingFinished();
}
}
notifySizeLoadingFinished(size: number): void {
this.logger.info(`notifySizeLoadingFinished, loadingListeners size: ${this.loadingListeners.length}`);
for (let listener of this.loadingListeners) {
listener.onSizeLoadingFinished(size);
}
}
onActive(): void {
this.logger.info('onActive');
this.isActive = true;
if (this.lastUpdateTime < this.lastChangeTime) {
// Page back to the foreground, if there is a refresh media library reload refresh.
this.loadData();
}
}
onInActive(): void {
this.logger.info('onInActive');
this.isActive = false;
}
freeze(): void {
this.logger.info('freeze')
this.isFreezeDataUpdate = true;
}
unfreeze(): void {
this.logger.info('unfreeze')
this.isFreezeDataUpdate = false;
}
onChange(mediaType) {
this.lastChangeTime = Date.now();
this.logger.debug(`onChange mediaType: ${mediaType} ${this.hasNewChange} ${this.isActive}`);
if (!this.hasNewChange) {
this.hasNewChange = true;
if (this.isActive) {
this.loadData();
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More