mirror of
https://gitee.com/openharmony/applications_app_samples
synced 2024-11-27 02:30:43 +00:00
!4862 medialibrary sample
Merge pull request !4862 from lumingfei(zhouhui)/master
This commit is contained in:
commit
6e7c69efd0
@ -16,9 +16,9 @@
|
||||
1. 主界面:查询显示所有照片、系统相册(相机/视频/截屏录屏/动态照片/我的收藏/最近删除)、用户相册
|
||||
2. 主界面点击“+”,创建用户相册
|
||||
3. 创建用户相册时添加图片到用户相册
|
||||
4. 长按相册,删除相册
|
||||
5. 长按相册,重命名相册(不可重名)
|
||||
6. 长按相册,相册多选,批量删除
|
||||
4. 长按用户相册,删除相册
|
||||
5. 长按系统相册,重命名相册(不可重名)
|
||||
6. 长按用户相册,相册多选,批量删除
|
||||
7. 点击相册,查看相册中的图片列表
|
||||
8. 点击图片,查看单个图片大图
|
||||
9. 点击心形图标,收藏图片
|
||||
@ -29,7 +29,7 @@
|
||||
14. 点击视频,查看视频并播放
|
||||
15. 点击图片页面右上角叹号,查看图片详情
|
||||
16. 长按图片批量操作:多选/全选、删除、恢复
|
||||
17. 相册内图片列表界面点击“+”,从已有相册添加照片
|
||||
17. 用户相册内图片列表界面点击“+”,从已有相册添加照片
|
||||
18. 长按图片列表图片,更多菜单,从图片选择添加到已有相册
|
||||
19. 在相册图片列表界面,长按图片,选择图片,点击更多,可以将图片加入到其他相册(可多选)
|
||||
20. 在用户相册图片列表界面,长按图片,选择图片,点击更多,可以将图片从当前相册移除(可多选)
|
||||
|
@ -19,8 +19,8 @@
|
||||
{
|
||||
"name": "default",
|
||||
"signingConfig": "default",
|
||||
"compileSdkVersion": 12,
|
||||
"compatibleSdkVersion": 12,
|
||||
"compileSdkVersion": 14,
|
||||
"compatibleSdkVersion": 14,
|
||||
"runtimeOS": "OpenHarmony"
|
||||
}
|
||||
]
|
||||
|
@ -19,7 +19,9 @@ import { userFileModel } from './UserFileModel';
|
||||
import { MediaConstants } from '../constants/MediaConstants';
|
||||
import { selectManager } from '../common/SelectManager';
|
||||
import photoAccessHelper from '@ohos.file.photoAccessHelper';
|
||||
import fs from '@ohos.file.fs';
|
||||
import { screenManager } from '../common/ScreenManager';
|
||||
import image from '@ohos.multimedia.image';
|
||||
|
||||
const TAG = 'UserFileDataItem';
|
||||
const STATUS_UNDEFINED = -1;
|
||||
@ -57,6 +59,9 @@ export class UserFileDataItem implements DateAdded {
|
||||
selections: string = '';
|
||||
selectionArgs: string[] = [];
|
||||
deviceId: string = '';
|
||||
longitude: string = '';
|
||||
latitude: string = '';
|
||||
shootingParams: string = '';
|
||||
fileAsset: photoAccessHelper.PhotoAsset = undefined;
|
||||
defaultThumbnail: PixelMap = undefined;
|
||||
thumbnailArray: Map<string, PixelMap> = new Map<string, PixelMap>();
|
||||
@ -174,6 +179,21 @@ export class UserFileDataItem implements DateAdded {
|
||||
} else {
|
||||
this.status = MediaConstants.PART_LOADED;
|
||||
}
|
||||
this.getExif(fileAsset);
|
||||
}
|
||||
|
||||
async getExif(fileAsset: photoAccessHelper.PhotoAsset): Promise<void> {
|
||||
let file = await fs.open(fileAsset.uri);
|
||||
let imageSourceApi: image.ImageSource = image.createImageSource(file.fd);
|
||||
this.latitude = await imageSourceApi.getImageProperty(image.PropertyKey.GPS_LATITUDE);
|
||||
this.longitude = await imageSourceApi.getImageProperty(image.PropertyKey.GPS_LONGITUDE);
|
||||
let light = await imageSourceApi.getImageProperty(image.PropertyKey.EXPOSURE_TIME);
|
||||
let fNumber = await imageSourceApi.getImageProperty(image.PropertyKey.F_NUMBER);
|
||||
let photographicSensitivity = await imageSourceApi.getImageProperty(
|
||||
image.PropertyKey.PHOTOGRAPHIC_SENSITIVITY);
|
||||
this.shootingParams = 'F_NUMBER ' + fNumber +
|
||||
' PHOTOGRAPHIC_SENSITIVITY ' + photographicSensitivity +
|
||||
' EXPOSURE_TIME ' + light;
|
||||
}
|
||||
|
||||
async getThumbnail(width: number, height: number): Promise<PixelMap> {
|
||||
@ -255,6 +275,15 @@ export class UserFileDataItem implements DateAdded {
|
||||
return this.favouriteStatus === STATUS_TRUE;
|
||||
}
|
||||
|
||||
async isVideo(): Promise<boolean> {
|
||||
let fileAsset = await this.loadFileAsset();
|
||||
this.mediaType = fileAsset.photoType;
|
||||
if (this.mediaType === photoAccessHelper.PhotoType.VIDEO) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async setFavor(): Promise<boolean> {
|
||||
let status = !(await this.isFavor());
|
||||
try {
|
||||
|
@ -23,6 +23,7 @@ import dataSharePredicates from '@ohos.data.dataSharePredicates';
|
||||
import { MediaConstants } from '../constants/MediaConstants'
|
||||
import { getSystemAlbumDisplayName } from './UserFileDataHelper';
|
||||
import { SimpleAlbumDataItem } from '../common/SimpleAlbumDataItem';
|
||||
import bundleManager from '@ohos.bundle.bundleManager';
|
||||
|
||||
const TAG = 'UserFileModel';
|
||||
|
||||
@ -535,6 +536,15 @@ class UserFileModel {
|
||||
Log.error(TAG, 'addPhotoAssetsDemoPromise failed with error: ' + err);
|
||||
}
|
||||
}
|
||||
|
||||
async hideSensitives(type: number, uris: string[]): Promise<void> {
|
||||
let flags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_SIGNATURE_INFO;
|
||||
let bundleInfo = bundleManager.getBundleInfoForSelfSync(flags);
|
||||
let appId = bundleInfo.signatureInfo.appId;
|
||||
for (let uri of uris) {
|
||||
await this.userFileMgr.grantPhotoUriPermission(appId, uri, 1, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export let userFileModel: UserFileModel = stashOrGetObject<UserFileModel>(new UserFileModel(), TAG);
|
||||
|
@ -33,6 +33,8 @@ import { NewAlbumDialog } from './NewAlbumDialog';
|
||||
import { FindSameNameDialog, FindSameNameParam } from './FindSameNameDialog';
|
||||
import { screenManager } from '../common/ScreenManager';
|
||||
import { SaveImageDialog } from './SaveImageDialog';
|
||||
import { SelectSensitiveDialog } from './SelectSensitiveDialog';
|
||||
import { TransCodingDialog } from './TransCodingDialog';
|
||||
|
||||
const TAG: string = 'CustomDialogView'
|
||||
|
||||
@ -52,6 +54,7 @@ export struct CustomDialogView {
|
||||
@Provide findSameNameParam: FindSameNameParam = new FindSameNameParam();
|
||||
@Provide cancelMessage: Resource = $r('app.string.common_place_holder', String(''));
|
||||
@Provide renameFileName: string = '';
|
||||
@Provide uris: string[] = [];
|
||||
@Provide mediaDetails: MediaDetails = {
|
||||
mediaType: 0,
|
||||
height: 0,
|
||||
@ -64,7 +67,9 @@ export struct CustomDialogView {
|
||||
dateAdded: 0,
|
||||
uri: '',
|
||||
displayName: '',
|
||||
dateModified: 0
|
||||
dateModified: 0,
|
||||
location: '',
|
||||
shootingParams: ''
|
||||
};
|
||||
@Provide targetMediaDetails: MediaDetails = {
|
||||
mediaType: 0,
|
||||
@ -78,7 +83,9 @@ export struct CustomDialogView {
|
||||
dateAdded: 0,
|
||||
uri: '',
|
||||
displayName: '',
|
||||
dateModified: 0
|
||||
dateModified: 0,
|
||||
location: '',
|
||||
shootingParams: ''
|
||||
};
|
||||
@Provide multiSelectDetails: MultiSelectDetails = {
|
||||
count: 0,
|
||||
@ -98,6 +105,8 @@ export struct CustomDialogView {
|
||||
newAlbumDialogController?: CustomDialogController ;
|
||||
findSameNameDialog?: CustomDialogController ;
|
||||
saveImageDialogController?: CustomDialogController ;
|
||||
sensitiveDialogController?: CustomDialogController ;
|
||||
transCodingFileDialogController?: CustomDialogController ;
|
||||
|
||||
aboutToDisappear(): void {
|
||||
Log.info(TAG, 'aboutToDisappear');
|
||||
@ -113,6 +122,7 @@ export struct CustomDialogView {
|
||||
this.newAlbumDialogController = undefined;
|
||||
this.findSameNameDialog = undefined;
|
||||
this.saveImageDialogController = undefined;
|
||||
this.sensitiveDialogController = undefined;
|
||||
}
|
||||
|
||||
aboutToAppear(): void {
|
||||
@ -128,6 +138,16 @@ export struct CustomDialogView {
|
||||
},
|
||||
customStyle: true
|
||||
});
|
||||
this.sensitiveDialogController = new CustomDialogController({
|
||||
builder: SelectSensitiveDialog(),
|
||||
autoCancel: false,
|
||||
alignment: this.isHorizontal || this.isSidebar ? DialogAlignment.Center : DialogAlignment.Bottom,
|
||||
offset: {
|
||||
dx: 0,
|
||||
dy: this.isHorizontal || this.isSidebar ? 0 : $r('app.float.dialog_offset_bottom')
|
||||
},
|
||||
customStyle: true
|
||||
});
|
||||
this.multiSelectDialog = new CustomDialogController({
|
||||
builder: MultiSelectDialog(),
|
||||
autoCancel: false,
|
||||
@ -188,6 +208,16 @@ export struct CustomDialogView {
|
||||
},
|
||||
customStyle: true
|
||||
});
|
||||
this.transCodingFileDialogController = new CustomDialogController({
|
||||
builder: TransCodingDialog(),
|
||||
autoCancel: false,
|
||||
alignment: this.isHorizontal || this.isSidebar ? DialogAlignment.Center : DialogAlignment.Bottom,
|
||||
offset: {
|
||||
dx: 0,
|
||||
dy: this.isHorizontal || this.isSidebar ? 0 : $r('app.float.dialog_offset_bottom')
|
||||
},
|
||||
customStyle: true
|
||||
});
|
||||
this.saveDialogController = new CustomDialogController({
|
||||
builder: SaveDialog(),
|
||||
autoCancel: false,
|
||||
@ -231,6 +261,16 @@ export struct CustomDialogView {
|
||||
this.showDetailDialog(item)
|
||||
});
|
||||
|
||||
this.broadCast.on(BroadcastConstants.SHOW_SENSITIVE_DIALOG,
|
||||
(items: UserFileDataItem[]): void => {
|
||||
let uris: string[] = [];
|
||||
for (let item of items) {
|
||||
uris.push(item.uri);
|
||||
}
|
||||
self.uris = uris;
|
||||
self.sensitiveDialogController?.open();
|
||||
});
|
||||
|
||||
this.broadCast.on(BroadcastConstants.SHOW_MULTI_SELECT_DIALOG,
|
||||
(count: number, size: number): void => {
|
||||
Log.info(TAG, 'SHOW_MULTI_SELECT_DIALOG ');
|
||||
@ -258,6 +298,13 @@ export struct CustomDialogView {
|
||||
self.renameFileDialogController?.open();
|
||||
});
|
||||
|
||||
this.broadCast.on(BroadcastConstants.SHOW_TRANS_CODING_DIALOG,
|
||||
(fileName: string, confirmCallback: Function, cancelCallback?: Function): void => {
|
||||
Log.info(TAG, 'SHOW_TRANS_CODING_DIALOG ');
|
||||
self.renameFileName = fileName;
|
||||
self.dialogCallback = { confirmCallback: confirmCallback, cancelCallback: cancelCallback };
|
||||
self.transCodingFileDialogController?.open();
|
||||
});
|
||||
this.broadCast.on(BroadcastConstants.SHOW_ADD_NOTES_PHOTO_DIALOG,
|
||||
(confirmCallback: Function, cancelCallback?: Function): void => {
|
||||
Log.info(TAG, 'SHOW_ADD_NOTES_PHOTO_DIALOG ');
|
||||
@ -365,7 +412,9 @@ export struct CustomDialogView {
|
||||
dateAdded: item.dateAdded,
|
||||
uri: item.uri,
|
||||
displayName: item.displayName,
|
||||
dateModified: item.dateModified
|
||||
dateModified: item.dateModified,
|
||||
location: 'longitude ' + item.longitude + ' latitude ' + item.latitude,
|
||||
shootingParams: item.shootingParams
|
||||
};
|
||||
this.dialogController?.open();
|
||||
})
|
||||
|
@ -33,6 +33,8 @@ export class MediaDetails {
|
||||
uri: string = '';
|
||||
displayName: string = '';
|
||||
dateModified: number = 0;
|
||||
location: string = '';
|
||||
shootingParams: string = '';
|
||||
}
|
||||
|
||||
@CustomDialog
|
||||
@ -161,6 +163,42 @@ export struct DetailsDialog {
|
||||
}.margin({
|
||||
bottom: $r('sys.float.ohos_id_text_paragraph_margin_s') })
|
||||
|
||||
Row() {
|
||||
Column() {
|
||||
Text($r('app.string.location'))
|
||||
.fontSize($r('sys.float.ohos_id_text_size_body2'))
|
||||
.fontFamily($r('app.string.id_text_font_family_regular'))
|
||||
.fontColor($r('sys.color.ohos_id_color_text_primary'))
|
||||
}
|
||||
|
||||
Column() {
|
||||
Text(this.mediaDetails.location)
|
||||
.fontSize($r('sys.float.ohos_id_text_size_body2'))
|
||||
.fontFamily($r('app.string.id_text_font_family_regular'))
|
||||
.fontColor($r('sys.color.ohos_id_color_text_secondary'))
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
}
|
||||
}.margin({
|
||||
bottom: $r('sys.float.ohos_id_text_paragraph_margin_s') })
|
||||
|
||||
Row() {
|
||||
Column() {
|
||||
Text($r('app.string.shooting_params'))
|
||||
.fontSize($r('sys.float.ohos_id_text_size_body2'))
|
||||
.fontFamily($r('app.string.id_text_font_family_regular'))
|
||||
.fontColor($r('sys.color.ohos_id_color_text_primary'))
|
||||
}
|
||||
|
||||
Column() {
|
||||
Text(this.mediaDetails.shootingParams)
|
||||
.fontSize($r('sys.float.ohos_id_text_size_body2'))
|
||||
.fontFamily($r('app.string.id_text_font_family_regular'))
|
||||
.fontColor($r('sys.color.ohos_id_color_text_secondary'))
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
}
|
||||
}.margin({
|
||||
bottom: $r('sys.float.ohos_id_text_paragraph_margin_s') })
|
||||
|
||||
if (this.mediaDetails.mediaType === userFileManager.FileType.VIDEO) {
|
||||
Row() {
|
||||
Column() {
|
||||
|
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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 { Log } from '../utils/Log';
|
||||
import { screenManager } from '../common/ScreenManager';
|
||||
import { Constants } from '../constants/Constants';
|
||||
import { userFileModel } from '../base/UserFileModel';
|
||||
|
||||
const TAG: string = 'SelectSensitiveDialog';
|
||||
@CustomDialog
|
||||
export struct SelectSensitiveDialog {
|
||||
@StorageLink('isHorizontal') isHorizontal: boolean = screenManager.isHorizontal();
|
||||
@StorageLink('isSidebar') isSidebar: boolean = screenManager.isSidebar();
|
||||
@StorageLink('leftBlank') leftBlank: number[] = [0, 0, 0, 0];
|
||||
controller?: CustomDialogController ;
|
||||
@Consume uris: string[];
|
||||
|
||||
aboutToAppear(): void {
|
||||
}
|
||||
|
||||
getResolution(height: number, width: number): string {
|
||||
return width + 'x' + height;
|
||||
}
|
||||
hideSensitive(type: number): void {
|
||||
if (this.uris.length === 0) {
|
||||
Log.warn(TAG, 'uris is empty');
|
||||
return;
|
||||
} else {
|
||||
userFileModel.hideSensitives(type, this.uris);
|
||||
}
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Button() {
|
||||
Text($r('app.string.hide_location_and_shootingparam'))
|
||||
.fontSize($r('sys.float.ohos_id_text_size_button1'))
|
||||
.fontColor($r('app.color.color_control_highlight'))
|
||||
.width('100%')
|
||||
.textAlign(TextAlign.Center)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
}
|
||||
.backgroundColor($r('app.color.transparent'))
|
||||
.height($r('app.float.details_dialog_button_height'))
|
||||
.onClick((): void => {
|
||||
this.hideSensitive(0);
|
||||
this.controller?.close();
|
||||
})
|
||||
|
||||
Button() {
|
||||
Text($r('app.string.hide_location_only'))
|
||||
.fontSize($r('sys.float.ohos_id_text_size_button1'))
|
||||
.fontColor($r('app.color.color_control_highlight'))
|
||||
.width('100%')
|
||||
.textAlign(TextAlign.Center)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
}
|
||||
.backgroundColor($r('app.color.transparent'))
|
||||
.height($r('app.float.details_dialog_button_height'))
|
||||
.onClick((): void => {
|
||||
this.hideSensitive(1);
|
||||
this.controller?.close();
|
||||
})
|
||||
|
||||
Button() {
|
||||
Text($r('app.string.hide_shootingparam_only'))
|
||||
.fontSize($r('sys.float.ohos_id_text_size_button1'))
|
||||
.fontColor($r('app.color.color_control_highlight'))
|
||||
.width('100%')
|
||||
.textAlign(TextAlign.Center)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
}
|
||||
.backgroundColor($r('app.color.transparent'))
|
||||
.height($r('app.float.details_dialog_button_height'))
|
||||
.onClick((): void => {
|
||||
this.hideSensitive(2);
|
||||
this.controller?.close();
|
||||
})
|
||||
|
||||
Button() {
|
||||
Text($r('app.string.no_hide_sensitive_type'))
|
||||
.fontSize($r('sys.float.ohos_id_text_size_button1'))
|
||||
.fontColor($r('app.color.color_control_highlight'))
|
||||
.width('100%')
|
||||
.textAlign(TextAlign.Center)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
}
|
||||
.backgroundColor($r('app.color.transparent'))
|
||||
.height($r('app.float.details_dialog_button_height'))
|
||||
.onClick((): void => {
|
||||
this.hideSensitive(3);
|
||||
this.controller?.close();
|
||||
})
|
||||
}
|
||||
.borderRadius($r('app.float.dialog_border_radius'))
|
||||
.width(screenManager.getColumnsWidth(4))
|
||||
.backgroundColor($r('app.color.white'))
|
||||
.margin({
|
||||
right: $r('app.float.dialog_window_margin'),
|
||||
left: $r('app.float.dialog_window_margin'),
|
||||
bottom: this.isHorizontal || this.isSidebar ? 0 : Constants.DIALOG_BOTTOM_OFFSET + px2vp(this.leftBlank[3])
|
||||
})
|
||||
.padding({ left: $r('app.float.dialog_content_margin'), right: $r('app.float.dialog_content_margin') })
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
}
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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 { Log } from '../utils/Log';
|
||||
import { DialogCallback } from '../utils/DialogUtil';
|
||||
import { screenManager } from '../common/ScreenManager';
|
||||
import { Constants } from '../constants/Constants';
|
||||
|
||||
const TAG: string = 'TransCodingDialog';
|
||||
@CustomDialog
|
||||
export struct TransCodingDialog {
|
||||
@StorageLink('isHorizontal') isHorizontal: boolean = screenManager.isHorizontal();
|
||||
@StorageLink('isSidebar') isSidebar: boolean = screenManager.isSidebar();
|
||||
@StorageLink('leftBlank') leftBlank: number[] = [0, 0, 0, 0];
|
||||
controller?: CustomDialogController ;
|
||||
@Consume renameFileName: string;
|
||||
@Consume dialogCallback: DialogCallback;
|
||||
@State isNull: boolean = false;
|
||||
@State dividerColor: Resource = $r('app.color.dialog_divider_h_color_182431');
|
||||
@State dividerWidth: string = '1vp';
|
||||
@State showProgressNum: number = 0;
|
||||
@State transCodingResult: boolean = false;
|
||||
@State fileUri: string = '';
|
||||
|
||||
aboutToAppear(): void {
|
||||
Log.info(TAG, 'aboutToAppear');
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
|
||||
if(this.transCodingResult === true) {
|
||||
Column() {
|
||||
Text($r('app.string.action_transcoding_path')).fontSize(16)
|
||||
Text(`${this.fileUri}`).fontSize(16)
|
||||
Text($r('app.string.action_transcoding_success')).fontSize(30)
|
||||
}.justifyContent(FlexAlign.Center).padding($r('app.float.crop_vertical_padding'))
|
||||
}
|
||||
|
||||
if(this.showProgressNum !== 0 && this.transCodingResult !== true) {
|
||||
Row() {
|
||||
Text($r('app.string.action_transcoding_progress')).fontSize(20)
|
||||
Text(`: ${this.showProgressNum}` + ' %').fontSize(20)
|
||||
}.justifyContent(FlexAlign.Center)
|
||||
.alignItems(VerticalAlign.Center)
|
||||
}
|
||||
|
||||
Stack({ alignContent: Alignment.Top }) {
|
||||
Row() {
|
||||
Button() {
|
||||
Text($r('app.string.no'))
|
||||
.fontSize($r('sys.float.ohos_id_text_size_button1'))
|
||||
.fontColor($r('app.color.color_control_highlight'))
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.width('50%')
|
||||
.textAlign(TextAlign.Center)
|
||||
}
|
||||
.margin({ right: $r('app.float.details_dialog_button_margin_right') })
|
||||
.backgroundColor($r('app.color.transparent'))
|
||||
.height($r('app.float.details_dialog_button_height'))
|
||||
.onClick((): void => {
|
||||
if (this.dialogCallback?.cancelCallback !== undefined) {
|
||||
this.dialogCallback.cancelCallback();
|
||||
};
|
||||
this.controller?.close();
|
||||
})
|
||||
|
||||
Row() {
|
||||
Divider()
|
||||
.vertical(true)
|
||||
.height($r('app.float.dialog_divider_height'))
|
||||
.color($r('app.color.divider_vertical_color'))
|
||||
}.height($r('app.float.details_dialog_button_height'))
|
||||
.alignItems(VerticalAlign.Center)
|
||||
|
||||
Button() {
|
||||
Text($r('app.string.action_transcoding'))
|
||||
.fontSize($r('sys.float.ohos_id_text_size_button1'))
|
||||
.fontColor($r('app.color.color_control_highlight'))
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.width('50%')
|
||||
.textAlign(TextAlign.Center)
|
||||
}
|
||||
.enabled(!this.isNull)
|
||||
.opacity(this.isNull ? $r('app.float.disable_button_opacity') : 1)
|
||||
.margin({ right: $r('app.float.details_dialog_button_margin_left') })
|
||||
.backgroundColor($r('app.color.transparent'))
|
||||
.height($r('app.float.details_dialog_button_height'))
|
||||
.onClick((): void => {
|
||||
if (this.dialogCallback != null && this.dialogCallback.confirmCallback !== null) {
|
||||
const fileUri = (uri: string) => {
|
||||
this.fileUri = uri;
|
||||
Log.info(TAG, 'fileUri uri:' + uri);
|
||||
};
|
||||
const transCodingResult = (result: boolean) => {
|
||||
this.transCodingResult = result;
|
||||
Log.info(TAG, 'Transcoding Result:' + result);
|
||||
};
|
||||
const showProgressNum = (progress: number) => {
|
||||
this.showProgressNum = progress;
|
||||
Log.info(TAG, 'Progress:' + progress);
|
||||
};
|
||||
this.dialogCallback.confirmCallback(fileUri, transCodingResult, showProgressNum);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
.height($r('app.float.details_dialog_button_area_height'))
|
||||
.margin({
|
||||
left: $r('app.float.dialog_content_margin'), right: $r('app.float.dialog_content_margin')
|
||||
})
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.borderRadius($r('app.float.dialog_border_radius'))
|
||||
.width(screenManager.getColumnsWidth(4))
|
||||
.backgroundColor($r('app.color.white'))
|
||||
.margin({
|
||||
right: $r('app.float.dialog_window_margin'),
|
||||
left: $r('app.float.dialog_window_margin'),
|
||||
bottom: this.isHorizontal || this.isSidebar ? 0 : Constants.DIALOG_BOTTOM_OFFSET + px2vp(this.leftBlank[3])
|
||||
})
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ export class BroadcastConstants {
|
||||
static readonly ON_TAB_CHANGED = 'onTabChanged';
|
||||
static readonly RESET_ZERO = 'resetZero';
|
||||
static readonly SHOW_DETAIL_DIALOG = 'showDetailDialog';
|
||||
static readonly SHOW_SENSITIVE_DIALOG = 'showSensitiveDialog';
|
||||
static readonly SHOW_THIRD_DELETE_DIALOG = 'showThirdDeleteDialog';
|
||||
static readonly SHOW_MULTI_SELECT_DIALOG = 'showMultiSelectDialog';
|
||||
static readonly UPDATE_DATA_SOURCE = 'updateDataSource';
|
||||
@ -55,6 +56,7 @@ export class BroadcastConstants {
|
||||
static readonly ON_DATA_RELOADED_WITH_EDIT = 'on_data_reloaded_with_edit';
|
||||
static readonly PHOTO_EDIT_SAVE_COMPLETE: string = 'photo_edit_save_complete';
|
||||
static readonly CHANGE_SWIPER_DURATION = 'change_swiper_duration';
|
||||
static readonly SHOW_TRANS_CODING_DIALOG = 'showTranscodingDialog';
|
||||
// USED for AppStorage
|
||||
static readonly LEFT_BLANK: string = 'leftBlank';
|
||||
static readonly RESET_TAB_SELECTED_STATUE: string = 'reset_tab_selected_statue';
|
||||
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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 { Log } from '../utils/Log';
|
||||
import { BroadcastConstants } from '../constants/BroadcastConstants';
|
||||
import { MenuOperationCallback } from './MenuOperationCallback';
|
||||
import { MenuOperation } from './MenuOperation';
|
||||
import { MenuContext } from './MenuContext';
|
||||
import dataSharePredicates from '@ohos.data.dataSharePredicates';
|
||||
import photoAccessHelper from '@ohos.file.photoAccessHelper';
|
||||
|
||||
const TAG = 'TranscodingMenuOperation';
|
||||
|
||||
export class TranscodingMenuOperation implements MenuOperation, MenuOperationCallback {
|
||||
private menuContext: MenuContext;
|
||||
|
||||
constructor(menuContext: MenuContext) {
|
||||
this.menuContext = menuContext;
|
||||
}
|
||||
|
||||
doAction(): void {
|
||||
if (this.menuContext == null) {
|
||||
Log.warn(TAG, ' menuContext is null, return');
|
||||
return;
|
||||
}
|
||||
let mediaItem = this.menuContext.items[0];
|
||||
if (mediaItem == null) {
|
||||
Log.warn(TAG, ' mediaItem is null, return');
|
||||
return;
|
||||
}
|
||||
|
||||
this.confirmCallback = (fileUri: Function, transCodingResult: Function, showProgressNum: Function): Promise<void> =>
|
||||
this.confirmCallbackBindImpl(fileUri, transCodingResult, showProgressNum);
|
||||
this.cancelCallback = (): void => this.cancelCallbackBindImpl();
|
||||
let fileName = '';
|
||||
if (mediaItem.title != null) {
|
||||
fileName = mediaItem.title;
|
||||
} else if (mediaItem.displayName != null) {
|
||||
let index = mediaItem.displayName.lastIndexOf('.');
|
||||
fileName = mediaItem.displayName.substr(0, index);
|
||||
}
|
||||
|
||||
this.menuContext.broadCast.emit(BroadcastConstants.SHOW_TRANS_CODING_DIALOG,
|
||||
[fileName, this.confirmCallback, this.cancelCallback]);
|
||||
}
|
||||
|
||||
onCompleted(): void {
|
||||
Log.info(TAG, ' TransCoding data succeed!');
|
||||
}
|
||||
|
||||
onError(): void {
|
||||
Log.error(TAG, ' TransCoding data failed!');
|
||||
}
|
||||
|
||||
private async confirmCallback(fileUri: Function, transCodingResult: Function, showProgressNum: Function): Promise<void> {
|
||||
this.confirmCallbackBindImpl(fileUri, transCodingResult, showProgressNum);
|
||||
}
|
||||
|
||||
private async confirmCallbackBindImpl(fileUri: Function, transCodingResult: Function, showProgressNum: Function): Promise<void> {
|
||||
let context = getContext(this);
|
||||
let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
|
||||
let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates();
|
||||
let mediaItem = this.menuContext.items[0];
|
||||
predicates.equalTo(photoAccessHelper.PhotoKeys.URI, mediaItem.uri);
|
||||
let fetchOptions: photoAccessHelper.FetchOptions = {
|
||||
fetchColumns: [],
|
||||
predicates: predicates
|
||||
};
|
||||
|
||||
let testHandler: photoAccessHelper.MediaAssetProgressHandler = {
|
||||
onProgress: (progress: number) => {
|
||||
if (progress > 0) {
|
||||
showProgressNum(progress)
|
||||
}
|
||||
Log.info(TAG, ` Current video conversion progress: ${progress}%`);
|
||||
}
|
||||
};
|
||||
|
||||
let mediaDataHandler: photoAccessHelper.MediaAssetDataHandler<boolean> = {
|
||||
onDataPrepared: (data: boolean) => {
|
||||
transCodingResult(data)
|
||||
Log.info(TAG, ' transCodingSuccess: ' + data);
|
||||
}
|
||||
}
|
||||
|
||||
Log.info(TAG, ' requestOptions before');
|
||||
try {
|
||||
let requestOptions: photoAccessHelper.RequestOptions = {
|
||||
deliveryMode: photoAccessHelper.DeliveryMode.HIGH_QUALITY_MODE,
|
||||
compatibleMode: photoAccessHelper.CompatibleMode.COMPATIBLE_FORMAT_MODE,
|
||||
mediaAssetProgressHandler: testHandler,
|
||||
}
|
||||
let tempDir = context.getApplicationContext().tempDir;
|
||||
let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> = await phAccessHelper.getAssets(fetchOptions);
|
||||
let photoAsset: photoAccessHelper.PhotoAsset = await fetchResult.getFirstObject();
|
||||
let uri = tempDir + photoAsset.displayName;
|
||||
fileUri(uri)
|
||||
Log.info(TAG, ' this.fileUri ' + fileUri);
|
||||
await photoAccessHelper.MediaAssetManager.requestVideoFile(
|
||||
context,
|
||||
photoAsset,
|
||||
requestOptions,
|
||||
uri,
|
||||
mediaDataHandler
|
||||
);
|
||||
} catch (err) {
|
||||
Log.info(TAG, ' operation '+ err);
|
||||
}
|
||||
}
|
||||
|
||||
private cancelCallback(): void {
|
||||
this.cancelCallbackBindImpl();
|
||||
}
|
||||
|
||||
private cancelCallbackBindImpl(): void {
|
||||
Log.info(TAG, ' TransCoding cancel');
|
||||
}
|
||||
}
|
@ -56,7 +56,9 @@ enum ActionID {
|
||||
NAVIGATION_ALBUMS,
|
||||
DOWNLOAD,
|
||||
DOWNLOAD_INVALID,
|
||||
CLEAR_RECYCLE_INVALID
|
||||
CLEAR_RECYCLE_INVALID,
|
||||
HIDE_SENSITIZATION,
|
||||
TRANSCODING
|
||||
}
|
||||
|
||||
class ActionOptions {
|
||||
@ -293,6 +295,14 @@ export class Action {
|
||||
fillColor: $r('app.color.icon_disabled_color'),
|
||||
actionType: $r('app.string.action_deRename')
|
||||
});
|
||||
public static TRANSCODING = new Action({
|
||||
id: ActionID.TRANSCODING,
|
||||
iconRes: $r('app.media.ic_edit_public_redo'),
|
||||
textRes: $r('app.string.action_transcoding'),
|
||||
isAutoTint: null,
|
||||
fillColor: null,
|
||||
actionType: null
|
||||
});
|
||||
public static MOVE = new Action({
|
||||
id: ActionID.MOVE,
|
||||
iconRes: null,
|
||||
@ -309,6 +319,14 @@ export class Action {
|
||||
fillColor: $r('app.color.icon_disabled_color'),
|
||||
actionType: null
|
||||
});
|
||||
public static HIDE_SENSITIZATION = new Action({
|
||||
id: ActionID.HIDE_SENSITIZATION,
|
||||
iconRes: null,
|
||||
textRes: $r('app.string.action_hide_sensitization'),
|
||||
isAutoTint: null,
|
||||
fillColor: null,
|
||||
actionType: null
|
||||
});
|
||||
public static REMOVE = new Action({
|
||||
id: ActionID.REMOVE,
|
||||
iconRes: null,
|
||||
|
@ -55,6 +55,7 @@ import { getAlbumDisplayName } from '../base/UserFileDataHelper';
|
||||
import { startAbility, terminateSelf } from '../utils/AbilityUtils';
|
||||
import { userFileDataItemCache } from '../base/UserFileDataItemCache';
|
||||
import { GlobalContext } from '../common/GlobalContext';
|
||||
import { TranscodingMenuOperation } from '../menus/TranscodingMenuOperation';
|
||||
// page of large photo
|
||||
|
||||
const TAG = 'PhotoBrowser';
|
||||
@ -177,10 +178,25 @@ struct PhotoBrowser {
|
||||
.withBroadCast(this.broadCast)
|
||||
.withAlbumInfo(this.albumInfo);
|
||||
menuOperation = new RenameMenuOperation(menuContext);
|
||||
} else if (action === Action.TRANSCODING) {
|
||||
if (currentPhoto == undefined) {
|
||||
return;
|
||||
}
|
||||
menuContext.withItems([currentPhoto])
|
||||
.withBroadCast(this.broadCast)
|
||||
.withAlbumInfo(this.albumInfo);
|
||||
menuOperation = new TranscodingMenuOperation(menuContext);
|
||||
} else if (action === Action.MOVE) {
|
||||
this.backFromCopy = true;
|
||||
this.routeSelectAlbumPage(MediaOperationType.Move);
|
||||
return;
|
||||
} else if (action == Action.HIDE_SENSITIZATION) {
|
||||
let currentPhoto = this.getCurrentPhoto();
|
||||
let items: UserFileDataItem[] = [];
|
||||
items.push(currentPhoto);
|
||||
Log.info(TAG, 'count is ' + items.length);
|
||||
this.broadCast.emit(BroadcastConstants.SHOW_SENSITIVE_DIALOG, [items]);
|
||||
return;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
@ -340,13 +356,22 @@ struct PhotoBrowser {
|
||||
let list: Action[] = [];
|
||||
if (this.pageFrom === Constants.ENTRY_FROM.RECYCLE) {
|
||||
list.push(Action.RECOVER, Action.DELETE);
|
||||
} else if(await currentPhoto.isVideo()) {
|
||||
let isFavor = await currentPhoto.isFavor();
|
||||
Log.info(TAG,'isFavor' + isFavor)
|
||||
list.push(
|
||||
isFavor ? Action.FAVORITE : Action.NOT_FAVORITE,
|
||||
Action.RENAME,
|
||||
Action.DELETE,
|
||||
Action.TRANSCODING,);
|
||||
} else {
|
||||
let isFavor = await currentPhoto.isFavor();
|
||||
Log.info(TAG,'isFavor' + isFavor)
|
||||
list.push(
|
||||
isFavor ? Action.FAVORITE : Action.NOT_FAVORITE,
|
||||
Action.RENAME,
|
||||
Action.DELETE,);
|
||||
Action.DELETE,
|
||||
Action.HIDE_SENSITIZATION,);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
@ -170,6 +170,8 @@ struct PhotoGridPage {
|
||||
menuOperation.doAction();
|
||||
} else if (action === Action.NEW) {
|
||||
this.routeToAddMediaPage();
|
||||
} else if (action === Action.HIDE_SENSITIZATION) {
|
||||
this.openSelectSensitiveDialog();
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,6 +192,13 @@ struct PhotoGridPage {
|
||||
this.broadCast.emit(BroadcastConstants.SHOW_MULTI_SELECT_DIALOG, [items.length, size]);
|
||||
}
|
||||
}
|
||||
|
||||
async openSelectSensitiveDialog(): Promise<void> {
|
||||
let items: UserFileDataItem[] = this.groupDataSource.getSelectedItems() as UserFileDataItem[];
|
||||
Log.info(TAG, 'lumingfei count is ' + items.length);
|
||||
this.broadCast.emit(BroadcastConstants.SHOW_SENSITIVE_DIALOG, [items]);
|
||||
}
|
||||
|
||||
private routeSelectAlbumPage(pageType: string): void {
|
||||
this.routerStart = true;
|
||||
router.push({
|
||||
@ -467,9 +476,9 @@ struct PhotoGridPage {
|
||||
|
||||
this.initGridRowCount();
|
||||
if (this.albumInfo.albumType==MediaConstants.ALBUM_TYPE_USER){
|
||||
this.moreMenuList = [Action.MOVE, Action.REMOVE, Action.INFO];
|
||||
this.moreMenuList = [Action.MOVE, Action.REMOVE, Action.HIDE_SENSITIZATION, Action.INFO];
|
||||
} else {
|
||||
this.moreMenuList = [Action.MOVE, Action.INFO];
|
||||
this.moreMenuList = [Action.MOVE, Action.HIDE_SENSITIZATION, Action.INFO];
|
||||
}
|
||||
|
||||
this.updateActionBar();
|
||||
@ -537,15 +546,16 @@ struct PhotoGridPage {
|
||||
this.isAllSelected = this.groupDataSource.isSelect();
|
||||
if (this.totalSelectedCount > 0) {
|
||||
if (this.albumInfo.albumType === MediaConstants.ALBUM_TYPE_USER){
|
||||
this.moreMenuList = [Action.MOVE, Action.REMOVE, Action.INFO];
|
||||
this.moreMenuList = [Action.MOVE, Action.REMOVE, Action.HIDE_SENSITIZATION, Action.INFO];
|
||||
} else {
|
||||
this.moreMenuList = [Action.MOVE, Action.INFO];
|
||||
this.moreMenuList = [Action.MOVE, Action.HIDE_SENSITIZATION, Action.INFO];
|
||||
}
|
||||
} else {
|
||||
if (this.albumInfo.albumType === MediaConstants.ALBUM_TYPE_USER){
|
||||
this.moreMenuList = [Action.MOVE_INVALID, Action.REMOVE_INVALID, Action.INFO_INVALID];
|
||||
this.moreMenuList = [Action.MOVE_INVALID, Action.REMOVE_INVALID,
|
||||
Action.HIDE_SENSITIZATION, Action.INFO_INVALID];
|
||||
} else {
|
||||
this.moreMenuList = [Action.MOVE_INVALID, Action.INFO_INVALID];
|
||||
this.moreMenuList = [Action.MOVE_INVALID, Action.HIDE_SENSITIZATION, Action.INFO_INVALID];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,6 +140,22 @@
|
||||
"name": "action_setting",
|
||||
"value": "Settings"
|
||||
},
|
||||
{
|
||||
"name": "action_transcoding",
|
||||
"value": "transCoding"
|
||||
},
|
||||
{
|
||||
"name": "action_transcoding_success",
|
||||
"value": "transCodingSuccess"
|
||||
},
|
||||
{
|
||||
"name": "action_transcoding_progress",
|
||||
"value": "transCodingProgress"
|
||||
},
|
||||
{
|
||||
"name": "action_transcoding_path",
|
||||
"value": "transCodingPath: "
|
||||
},
|
||||
{
|
||||
"name": "action_navigation",
|
||||
"value": "Get directions to this location"
|
||||
@ -903,6 +919,34 @@
|
||||
{
|
||||
"name": "write_image_video_permission",
|
||||
"value": "user write image video permission"
|
||||
},
|
||||
{
|
||||
"name": "location",
|
||||
"value": "Location: "
|
||||
},
|
||||
{
|
||||
"name": "shooting_params",
|
||||
"value": "Shooting params: "
|
||||
},
|
||||
{
|
||||
"name": "action_hide_sensitization",
|
||||
"value": "Hide sensitization"
|
||||
},
|
||||
{
|
||||
"name": "hide_location_and_shootingparam",
|
||||
"value": "Both location and shootingparams"
|
||||
},
|
||||
{
|
||||
"name": "hide_location_only",
|
||||
"value": "Location only"
|
||||
},
|
||||
{
|
||||
"name": "hide_shootingparam_only",
|
||||
"value": "Shootingparams only"
|
||||
},
|
||||
{
|
||||
"name": "no_hide_sensitive_type",
|
||||
"value": "none"
|
||||
}
|
||||
]
|
||||
}
|
@ -144,6 +144,22 @@
|
||||
"name": "action_setting",
|
||||
"value": "设置"
|
||||
},
|
||||
{
|
||||
"name": "action_transcoding",
|
||||
"value": "转码"
|
||||
},
|
||||
{
|
||||
"name": "action_transcoding_success",
|
||||
"value": "转码成功"
|
||||
},
|
||||
{
|
||||
"name": "action_transcoding_progress",
|
||||
"value": "转码进度"
|
||||
},
|
||||
{
|
||||
"name": "action_transcoding_path",
|
||||
"value": "转码视频路径: "
|
||||
},
|
||||
{
|
||||
"name": "action_navigation",
|
||||
"value": "导航"
|
||||
@ -901,12 +917,32 @@
|
||||
"value": "user read file permission"
|
||||
},
|
||||
{
|
||||
"name": "write_permission",
|
||||
"value": "user write file permission"
|
||||
"name": "location",
|
||||
"value": "位置: "
|
||||
},
|
||||
{
|
||||
"name": "write_image_video_permission",
|
||||
"value": "user write image video permission"
|
||||
"name": "shooting_params",
|
||||
"value": "拍摄参数: "
|
||||
},
|
||||
{
|
||||
"name": "action_hide_sensitization",
|
||||
"value": "脱敏"
|
||||
},
|
||||
{
|
||||
"name": "hide_location_and_shootingparam",
|
||||
"value": "位置和拍摄参数"
|
||||
},
|
||||
{
|
||||
"name": "hide_location_only",
|
||||
"value": "位置"
|
||||
},
|
||||
{
|
||||
"name": "hide_shootingparam_only",
|
||||
"value": "拍摄参数"
|
||||
},
|
||||
{
|
||||
"name": "no_hide_sensitive_type",
|
||||
"value": "无"
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user