diff --git a/build-profile.json5 b/build-profile.json5 index d68ada5..1007dbf 100644 --- a/build-profile.json5 +++ b/build-profile.json5 @@ -4,9 +4,9 @@ { "name": "default", "signingConfig": "release", - "compileSdkVersion": 11, - "compatibleSdkVersion": 11, - "targetSdkVersion": 11, + "compileSdkVersion": 12, + "compatibleSdkVersion": 12, + "targetSdkVersion": 12, "runtimeOS": "OpenHarmony", } ], diff --git a/product/phone/src/main/ets/PrivacyDialog/DialogAbility.ets b/product/phone/src/main/ets/PrivacyDialog/DialogAbility.ets new file mode 100644 index 0000000..614fbb2 --- /dev/null +++ b/product/phone/src/main/ets/PrivacyDialog/DialogAbility.ets @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 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 UIExtensionAbility from '@ohos.app.ability.UIExtensionAbility'; +import media from '@ohos.multimedia.media'; +import Log from '../../../../../../common/src/main/ets/default/Log'; +import Want from '@ohos.app.ability.Want'; +import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; +import { BusinessError } from '@ohos.base'; + +const TAG = 'AVScreenCapture-DiaLogUIExtensionAbility'; + +export default class DialogAbility extends UIExtensionAbility { + onCreate(): void { + Log.showInfo(TAG, 'DialogAbility onCreate'); + globalThis.sessionId = -1; + globalThis.userChoice = 'false'; + } + + onForeground(): void { + Log.showInfo(TAG, 'DialogAbility onForeground'); + } + + onBackground(): void { + Log.showInfo(TAG, 'DialogAbility onBackground'); + } + + onDestroy(): void { + Log.showInfo(TAG, `Report user choice sessionId(${globalThis.sessionId}), userChoice(${globalThis.userChoice})`); + media.reportAVScreenCaptureUserChoice(Number(globalThis.sessionId), globalThis.userChoice); + } + + onSessionCreate(want: Want, session: UIExtensionContentSession): void { + Log.showInfo(TAG, 'onSessionCreate'); + globalThis.dialogContext = this.context; + globalThis.dialogWant = want; + globalThis.dialogSession = session; + globalThis.sessionId = want.parameters?.sessionId as number; + let param: Record = { + 'session': session + } + let storage: LocalStorage = new LocalStorage(param); + try { + session.loadContent('PrivacyDialog/DialogPage', storage); + } catch (err) { + Log.showError(TAG, 'session loadContent error: ' + (err as BusinessError).message); + } + session.setWindowBackgroundColor('#00ffffff'); + } + + onSessionDestroy(session: UIExtensionContentSession): void { + Log.showInfo(TAG, 'UIExtAbility onSessionDestroy'); + } +} \ No newline at end of file diff --git a/product/phone/src/main/ets/PrivacyDialog/DialogPage.ets b/product/phone/src/main/ets/PrivacyDialog/DialogPage.ets new file mode 100644 index 0000000..fe65765 --- /dev/null +++ b/product/phone/src/main/ets/PrivacyDialog/DialogPage.ets @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2024 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 Log from '../../../../../../common/src/main/ets/default/Log'; +import Want from '@ohos.app.ability.Want'; +import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; +import measure from '@ohos.measure'; +import display from '@ohos.display' + +const TAG = 'AVScreenCapture-DiaLogPage'; + +@CustomDialog +struct PrivacyWindowDialog { + cancel?: () => void; + confirm?: () => void; + controller: CustomDialogController; + appLabel: string = ''; + overflow: boolean = false; + + build() { + Column() { + if (this.overflow) { + Row() { + Text($r('app.string.avscreencapture_privacy_window_title')) + .fontWeight(FontWeight.Bold) + .textAlign(TextAlign.Start) + .width('100%') + .textOverflow({ overflow: TextOverflow.Ellipsis}) + .maxLines(2) + .fontSize(16) + } + .alignItems(VerticalAlign.Center) + .padding({ top: 16, bottom: 16 }) + .margin({ left: 24, right: 24}) + } else { + Row() { + Text($r('app.string.avscreencapture_privacy_window_title')) + .fontWeight(FontWeight.Bold) + .textAlign(TextAlign.Start) + .width('100%') + .fontSize($r('sys.float.ohos_id_text_size_headline8')) + } + .alignItems(VerticalAlign.Center) + .margin({ left: 24, right: 24 }) + .height(56) + } + + Column() { + Text($r('app.string.avscreencapture_privacy_window_content', this.appLabel)) + .fontSize($r('sys.float.ohos_id_text_size_body1')) + .fontColor($r('sys.color.ohos_id_color_text_primary')) + .width('100%') + } + .margin({ left: 24, right: 24 }) + + Flex({ justifyContent: FlexAlign.SpaceAround}) { + Column() { + Button($r('app.string.avscreencapture_privacy_window_cancel'), { type: ButtonType.Capsule }) + .onClick(() => { + this.controller.close(); + if (this.cancel) { + this.cancel(); + } + }) + .backgroundColor(Color.Transparent) + .fontColor($r('sys.color.ohos_id_color_text_primary_activated')) + .fontSize($r('sys.float.ohos_id_text_size_button1')) + .width('100%') + .height('100%') + } + .width('100%') + + Column() { + Column() + .backgroundColor($r('sys.color.ohos_id_color_list_separator')) + .height(24) + .width(1) + } + .margin({ left: 2, right: 2, top: 8 }) + .justifyContent(FlexAlign.Center) + + Column() { + Button($r('app.string.avscreencapture_privacy_window_agree'), { type: ButtonType.Capsule }) + .onClick(() => { + this.controller.close(); + if (this.confirm) { + this.confirm(); + } + }) + .backgroundColor(Color.Transparent) + .fontColor($r('sys.color.ohos_id_color_text_primary_activated')) + .fontSize($r('sys.float.ohos_id_text_size_button1')) + .width('100%') + .height('100%') + } + .width('100%') + } + .height(40) + .margin({ top: 8, bottom: 16, left: 16, right: 16 }) + } + } +} + +const MARGIN_DISTANCE = 24; +const BORDER_DISTANCE = 16; + +@Entry +@Component +export struct DialogPage { + private want = globalThis.dialogWant as Want; + private session = globalThis.dialogSession as UIExtensionContentSession; + private appLabel: string = ''; + private overflow: boolean = false; + + dialogController: CustomDialogController = new CustomDialogController({ + builder: PrivacyWindowDialog({ + cancel: () => { this.onCancel() }, + confirm: () => { this.onConfirm() }, + appLabel: this.appLabel, + overflow: this.overflow + }), + alignment: DialogAlignment.Center, + autoCancel: false, + backgroundColor: Color.White + }) + + getTextLength(text: Resource, fontSize: Resource): void { + let textLength: number = measure.measureText({ + textContent: text, + fontSize: fontSize + }); + let windowWidth = display.getDefaultDisplaySync().width; + let textMaxLength = px2vp(windowWidth) - BORDER_DISTANCE - MARGIN_DISTANCE; + if (px2vp(textLength) > textMaxLength) { + Log.showInfo(TAG, 'title overflow, need change line'); + this.overflow = true; + } else { + this.overflow = false; + } + } + + async onCancel(): Promise { + Log.showInfo(TAG, 'Cancel is clicked'); + globalThis.userChoice = 'false'; + await this.session.terminateSelf(); + } + + async onConfirm(): Promise { + Log.showInfo(TAG, 'Agree is clicked'); + globalThis.userChoice = 'true'; + await this.session.terminateSelf(); + } + + async onPageShow(): Promise { + this.getTextLength($r('app.string.avscreencapture_privacy_window_title'), + $r('sys.float.ohos_id_text_size_headline8')); + this.getAppName(); + Log.showInfo(TAG, 'onPageShow'); + this.dialogController.open(); + } + + onPageHide(): void { + Log.showInfo(TAG, 'onPageHide') + } + + getAppName(): void { + if (this.want.parameters?.callingLabel) { + this.appLabel = (this.want.parameters?.appLabel).toString(); + Log.showInfo(TAG, `appLabel: ${this.appLabel}`); + } + } + + build() {} +} \ No newline at end of file diff --git a/product/phone/src/main/module.json5 b/product/phone/src/main/module.json5 index f21eb6f..e6aed8e 100644 --- a/product/phone/src/main/module.json5 +++ b/product/phone/src/main/module.json5 @@ -39,6 +39,12 @@ "resource": "$profile:main_pages" } ] + }, + { + "name": "com.ohos.screenshot.DialogAbility", + "srcEntry": "./ets/PrivacyDialog/DialogAbility.ets", + "visible": true, + "type": "sys/commonUI" } ], "requestPermissions": [ diff --git a/product/phone/src/main/resources/base/element/string.json b/product/phone/src/main/resources/base/element/string.json index 32baeb3..47ab569 100644 --- a/product/phone/src/main/resources/base/element/string.json +++ b/product/phone/src/main/resources/base/element/string.json @@ -23,6 +23,22 @@ { "name": "write_media_reason", "value": "Screenshot apps need to write media files" + }, + { + "name": "avscreencapture_privacy_window_title", + "value": "Privacy notice" + }, + { + "name": "avscreencapture_privacy_window_content", + "value": "%s will be able to record or project everything that's shown on your screen, as well as system sounds. Be sure to safeguard sensitive personal information such as passwords, payment information, photos, videos, and conversations." + }, + { + "name": "avscreencapture_privacy_window_cancel", + "value": "Deny" + }, + { + "name": "avscreencapture_privacy_window_agree", + "value": "Allow" } ] } \ No newline at end of file diff --git a/product/phone/src/main/resources/base/profile/main_pages.json b/product/phone/src/main/resources/base/profile/main_pages.json index feec276..2be6ca3 100644 --- a/product/phone/src/main/resources/base/profile/main_pages.json +++ b/product/phone/src/main/resources/base/profile/main_pages.json @@ -1,5 +1,6 @@ { "src": [ - "pages/index" + "pages/index", + "PrivacyDialog/DialogPage" ] } diff --git a/product/phone/src/main/resources/en_US/element/string.json b/product/phone/src/main/resources/en_US/element/string.json index bf90189..e339904 100644 --- a/product/phone/src/main/resources/en_US/element/string.json +++ b/product/phone/src/main/resources/en_US/element/string.json @@ -27,6 +27,22 @@ { "name": "write_media_reason", "value": "Screenshot apps need to write media files" + }, + { + "name": "avscreencapture_privacy_window_title", + "value": "Privacy notice" + }, + { + "name": "avscreencapture_privacy_window_content", + "value": "%s will be able to record or project everything that's shown on your screen, as well as system sounds. Be sure to safeguard sensitive personal information such as passwords, payment information, photos, videos, and conversations." + }, + { + "name": "avscreencapture_privacy_window_cancel", + "value": "Deny" + }, + { + "name": "avscreencapture_privacy_window_agree", + "value": "Allow" } ] } \ No newline at end of file diff --git a/product/phone/src/main/resources/zh_CN/element/string.json b/product/phone/src/main/resources/zh_CN/element/string.json index cd669a4..315f5b6 100644 --- a/product/phone/src/main/resources/zh_CN/element/string.json +++ b/product/phone/src/main/resources/zh_CN/element/string.json @@ -27,6 +27,22 @@ { "name": "write_media_reason", "value": "Screenshot apps need to write media files" + }, + { + "name": "avscreencapture_privacy_window_title", + "value": "录屏投屏管理" + }, + { + "name": "avscreencapture_privacy_window_content", + "value": "\"%s\"将录制/投射您屏幕上显示的内容和系统声音。请注意保护个人敏感信息,如密码、付款信息、照片、录像、聊天记录等。" + }, + { + "name": "avscreencapture_privacy_window_cancel", + "value": "不允许" + }, + { + "name": "avscreencapture_privacy_window_agree", + "value": "允许" } ] } \ No newline at end of file