From d3dfde5560f90dcf8101f64c7fc6dc50e0049def Mon Sep 17 00:00:00 2001 From: chehang Date: Fri, 22 Sep 2023 19:21:29 +0800 Subject: [PATCH] enable_notification_dialog support create multiple dialogs Signed-off-by: chehang Change-Id: I78d359ecdae9f64a38a3a642a9d2956ed08eee51 --- .../enable_notification_dialog/BUILD.gn | 1 - .../src/main/ets/Application/AbilityStage.ts | 4 +- .../NotificationServiceExtAbility.ts | 208 +++++++++----- .../entry/src/main/ets/common/constant.ets | 140 ++++++++++ .../entry/src/main/ets/common/utils.ets | 31 +++ .../src/main/ets/pages/notificationDialog.ets | 253 +++++++++++++++--- .../entry/src/main/ets/pages/notifybody.ets | 99 ------- .../entry/src/main/module.json | 5 +- .../main/resources/base/element/string.json | 30 ++- .../resources/base/media/ic_public_ring.svg | 13 + .../src/main/resources/zh/element/string.json | 30 ++- 11 files changed, 606 insertions(+), 208 deletions(-) create mode 100644 services/dialog_ui/enable_notification_dialog/entry/src/main/ets/common/constant.ets create mode 100644 services/dialog_ui/enable_notification_dialog/entry/src/main/ets/common/utils.ets delete mode 100644 services/dialog_ui/enable_notification_dialog/entry/src/main/ets/pages/notifybody.ets create mode 100644 services/dialog_ui/enable_notification_dialog/entry/src/main/resources/base/media/ic_public_ring.svg diff --git a/services/dialog_ui/enable_notification_dialog/BUILD.gn b/services/dialog_ui/enable_notification_dialog/BUILD.gn index 90f6f2a56..c6dcbe265 100644 --- a/services/dialog_ui/enable_notification_dialog/BUILD.gn +++ b/services/dialog_ui/enable_notification_dialog/BUILD.gn @@ -29,7 +29,6 @@ ohos_hap("enable_notification_dialog_hap") { } ohos_js_assets("enable_notification_dialog_js_assets") { - hap_profile = "entry/src/main/module.json" ets2abc = true source_dir = "entry/src/main/ets" } diff --git a/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/Application/AbilityStage.ts b/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/Application/AbilityStage.ts index 243b7d032..84592de28 100644 --- a/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/Application/AbilityStage.ts +++ b/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/Application/AbilityStage.ts @@ -13,10 +13,10 @@ * limitations under the License. */ -import AbilityStage from "@ohos.app.ability.AbilityStage" +import AbilityStage from "@ohos.app.ability.AbilityStage"; export default class DialogAbilityStage extends AbilityStage { onCreate() { console.log('DialogAbilityStage onCreate'); } -} \ No newline at end of file +} diff --git a/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/ServiceExtAbility/NotificationServiceExtAbility.ts b/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/ServiceExtAbility/NotificationServiceExtAbility.ts index e6a557b25..566259a0a 100644 --- a/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/ServiceExtAbility/NotificationServiceExtAbility.ts +++ b/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/ServiceExtAbility/NotificationServiceExtAbility.ts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 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 @@ -13,84 +13,168 @@ * limitations under the License. */ +import display from '@ohos.display'; +import emitter from '@ohos.events.emitter'; import extension from '@ohos.app.ability.ServiceExtensionAbility'; +import notification from '@ohos.notification'; import window from '@ohos.window'; -import display from '@ohos.display'; -import deviceInfo from '@ohos.deviceInfo'; -const TAG = 'NotificationDialog_Service'; - -let winNum = 1; -let win; -export default class NotificationDialogServiceExtensionAbility extends extension { - onCreate(want): void { - console.debug(TAG, 'onCreate, want: ' + JSON.stringify(want)); - globalThis.notificationExtensionContext = this.context; - globalThis.closeDialog = (): void => { - console.info(TAG, 'click waiting for a response'); - if (win !== undefined) { - win.destroyWindow(); +import type Want from '@ohos.app.ability.Want'; + +const TAG = 'NotificationDialog_Service '; + +const enableNotificationDialogDestroyedEvent = { + eventId: 1, + priority: emitter.EventPriority.LOW +}; + +async function handleDialogQuitException(want: Want): Promise { + await notification.enableNotification({ + 'bundle': want.parameters.from.toString() + }, false); +} + + +export class EnableNotificationDialog { + static ENABLE_NOTIFICATION_DIALOG_NAME = 'EnableNotificationDialog'; + static DIALOG_PATH = 'pages/notificationDialog'; + static TRANSPARANT_COLOR = '#00000000'; + + id: number; + want: Want; + window: window.Window; + storage: LocalStorage; + + constructor(id: number, want: Want) { + this.id = id; + this.want = want; + this.window = undefined; + } + + async createWindow(windowType: window.WindowType, context, displayRect): Promise { + try { + let winArgs = { + 'name': `${EnableNotificationDialog.ENABLE_NOTIFICATION_DIALOG_NAME}${this.id}`, + 'windowType': windowType, + 'ctx': context + }; + let win = await window.createWindow(winArgs); + this.window = win; + + if (windowType === window.WindowType.TYPE_DIALOG) { + await win.bindDialogTarget(this.want.parameters.callerToken['value'], + async (): Promise => { + console.info(TAG, `window ${this.id} died`); + await this.destroyException(); + } + ); } - globalThis.notificationExtensionContext.terminateSelf(); - }; - }; - onRequest(want, startId): void { - globalThis.abilityWant = want; + this.storage = new LocalStorage({ + 'dialog': this + }); + await win.moveWindowTo(displayRect.left, displayRect.top); + await win.resize(displayRect.width, displayRect.height); + await win.loadContent(EnableNotificationDialog.DIALOG_PATH, this.storage); + await win.setWindowBackgroundColor(EnableNotificationDialog.TRANSPARANT_COLOR); + await win.showWindow(); + await win.setWindowLayoutFullScreen(true); + } catch (err) { + if (this.window !== undefined) { + await this.destroyWindow(); + } + console.error(TAG, 'window create failed!'); + throw new Error('Failed to create window'); + } + } - if (want['parameters']['callerToken'] !== undefined && want['parameters']['callerToken'] != null) { - globalThis.callerToken = want['parameters']['callerToken']; + async destroyException(): Promise { + if (this.window !== undefined) { + emitter.emit(enableNotificationDialogDestroyedEvent, { + data: { + 'id': this.id + } + }); + await handleDialogQuitException(this.want); + await this.destroyWindow(); } - display.getDefaultDisplay().then(() => { + } - if (globalThis.callerToken != null) { - if (winNum > 1) { - win.destroy(); - winNum--; + async destroy(): Promise { + if (this.window !== undefined) { + emitter.emit(enableNotificationDialogDestroyedEvent, { + data: { + 'id': this.id } - this.createWindow('EnableNotificationDialog' + startId, window.WindowType.TYPE_DIALOG); - winNum++; - } else { - this.createWindow('EnableNotificationDialog' + startId, window.WindowType.TYPE_SYSTEM_ALERT); - } + }); + await this.destroyWindow(); + } + } + + async destroyWindow(): Promise { + await this.window.destroyWindow(); + this.window = undefined; + } +}; + + +class NotificationDialogServiceExtensionAbility extends extension { + static MAX_DIALOG_NUM = 10; + dialogs: Array = []; + + onCreate(want: Want): void { + console.info(TAG, `onCreate, want: ${JSON.stringify(want)}`); + AppStorage.SetOrCreate('context', this.context); + emitter.on(enableNotificationDialogDestroyedEvent, (data) => { + let did = data.data.id; + this.dialogs = this.dialogs.filter((dialog: EnableNotificationDialog) => { + return dialog.id !== did; + }); + console.info(TAG, `Dialog ${did} destroyed.`); + if (this.dialogs.length === 0) { + this.context.terminateSelf(); + console.info(TAG, 'terminated'); + } }); } + async onRequest(want: Want, startId: number): Promise { + console.log(TAG, `onRequest ${startId}`); + try { + await this.removeExceededDialog(); + let dialog = new EnableNotificationDialog(startId, want); + let winType = want.parameters.callerToken !== undefined ? + window.WindowType.TYPE_DIALOG : window.WindowType.TYPE_SYSTEM_ALERT; + let dis = display.getDefaultDisplaySync(); + let navigationBarRect = { + left: 0, + top: 0, + width: dis.width, + height: dis.height + }; + await dialog.createWindow(winType, this.context, navigationBarRect); + this.dialogs.push(dialog); + } catch (err) { + console.error(TAG, `Failed to handle request ${startId}.`); + await handleDialogQuitException(want); + } + } + onDestroy(): void { console.info(TAG, 'onDestroy.'); } - private async createWindow(name: string, windowType: number) { - console.info(TAG, 'create window'); - try { - win = await window.create(globalThis.notificationExtensionContext, name, windowType); - - if (globalThis.callerToken != null) { - await win.bindDialogTarget(globalThis.callerToken.value, () => { - win.destroyWindow(); - winNum--; - if (winNum === 0) { - globalThis.notificationExtensionContext.terminateSelf(); - } - }); - } - - if (deviceInfo.deviceType === 'default' || deviceInfo.deviceType === 'phone') { - let def = display.getDefaultDisplaySync(); - win.moveTo(0, 0); - win.resetSize(def.width, def.height); - } else { - let def = display.getDefaultDisplaySync(); - let topMargin = 60; - let bottomMargin = 96; - win.moveTo(0, def.densityPixels * topMargin); - win.resetSize(def.width, def.height - def.densityPixels * bottomMargin - def.densityPixels * topMargin); + private async removeExceededDialog(): Promise { + if (this.dialogs.length >= NotificationDialogServiceExtensionAbility.MAX_DIALOG_NUM) { + // remove dialogs by creating time + let removed = this.dialogs.splice(0, + this.dialogs.length - NotificationDialogServiceExtensionAbility.MAX_DIALOG_NUM + 1); + for (let dialog of removed) { + await handleDialogQuitException(dialog.want); + await dialog.destroyWindow(); } - await win.loadContent('pages/notificationDialog'); - await win.show(); - await win.setBackgroundColor('#00000000'); - } catch { - console.error(TAG, 'window create failed!'); } } }; + +export default NotificationDialogServiceExtensionAbility; diff --git a/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/common/constant.ets b/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/common/constant.ets new file mode 100644 index 000000000..c091a003b --- /dev/null +++ b/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/common/constant.ets @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2023 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 default class Constants { + // grid useSizeType + static GUTTER = 0; + static XS_COLUMNS = 2; + static XS_SPAN = 2; + static XS_OFFSET = 0; + static SM_COLUMNS = 4; + static SM_SPAN = 4; + static SM_OFFSET = 0; + static MD_COLUMNS = 8; + static MD_SPAN = 8; + static MD_OFFSET = 0; + static LG_COLUMNS = 12; + static LG_SPAN = 8; + static LG_OFFSET = 2; + + static DIALOG_GUTTER = 16; + static DIALOG_MARGIN = 16; + static DIALOG_MARGIN_VERTICAL = 12; + static DIALOG_MD_SPAN = 4; + static DIALOG_MD_OFFSET = 2; + static DIALOG_LG_SPAN = 4; + static DIALOG_LG_OFFSET = 4; + + // 100% width,height + static FULL_WIDTH = '100%'; + static FULL_HEIGHT = '100%'; + + // public property style + static PERMISSION = 1; + static APPLICATION = 0; + static LAYOUT_WEIGHT = 1; + static FLEX_GROW = 1; + static TEXT_BIG_FONT_SIZE = 20; + static TEXT_MIDDLE_FONT_SIZE = 16; + static TEXT_SMALL_FONT_SIZE = 14; + static TEXT_SMALLER_FONT_SIZE = 12; + static TEXT_LINE_HEIGHT = 22; + static TEXT_BIG_LINE_HEIGHT = 28; + static TEXT_SMALL_LINE_HEIGHT = 19; + static CONSTRAINTSIZE_MINHEIGHT = 48; + static LISTITEM_ROW_HEIGHT = 48; + static LISTITEM_PADDING_LEFT = 24; + static LIST_PADDING_LEFT = 12 + static LISTITEM_PADDING_RIGHT = 24; + static LISTITEM_PADDING_LEFT_RECORD = 32; + static LISTITEM_PADDING_RIGHT_RECORD = 50; + static LISTITEM_MARGIN_BOTTOM = 12; + static LISTITEM_HEIGHT_PERMISSION = 64; + static LISTITEM_HEIGHT_APPLICATION = 72; + static IMAGE_HEIGHT = 24; + static IMAGE_WIDTH = 12; + static IMAGE_HEIGHT_RECORD = 12; + static IMAGE_WIDTH_RECORD = 24; + static IMAGE_HEIGHT_RECORD_APPLICATION = 16; + static IMAGE_WIDTH_RECORD_APPLICATION = 16; + static TITLE_MARGIN_BOTTOM = 16; + static SUBTITLE_MIN_HEIGHT = 48; + static SUBTITLE_LINE_HEIGHT = 24; + static SUBTITLE_PADDING_TOP = 16; + static SUBTITLE_PADDING_BOTTOM = 8; + static TAB_HEIGHT = 56; + static TAB_LINE_HEIGHT = 100; + static TAB_INNER_PADDING = 8; + static TAB_DECORATION_HEIGHT = 2; + static TAB_DECORATION_POSITION_Y = 6; + static DEFAULT_PADDING_START = 12; + static DEFAULT_PADDING_END = 12; + static DEFAULT_PADDING_TOP = 12; + static DEFAULT_PADDING_BOTTOM = 12; + static DEFAULT_MARGIN_START = 12; + static DEFAULT_MARGIN_END = 12; + static DEFAULT_MARGIN_TOP = 12; + static DEFAULT_MARGIN_BOTTOM = 12; + static DEFAULT_SLIDER_WIDTH = 60; + static DEFAULT_SLIDER_HEIGHT = 40; + static OFFSET = 100; + static CLICK_SHADOW_LENGTH = 48; + static DIVIDER = '1px'; + static DIVIDER_HEIGHT = 24; + static DIVIDER_MARGIN_RIGHT_PERMISSION = 52; + static DIVIDER_MARGIN_RIGHT_APPLICATION = 68; + + static START_SUBSCRIPT = 0; + static END_SUBSCRIPT = 500; + static MAXIMUM_HEADER_LINES = 1; + static MAXIMUM_HEADER_WIDTH = 200; + static MAXIMUM_HEADER_HEIGHT = 500; + static MAXIMUM_HEADER_LENGTH = 1000; + + static RECORD_PADDING_BOTTOM = '20%'; + + // icon of dialog + static DIALOG_ICON_WIDTH = 24; + static DIALOG_ICON_HEIGHT = 24; + static DIALOG_ICON_MARGIN_TOP = 23; + + // label text of dialog + static DIALOG_LABEL_FONT_SIZE = 10; + static DIALOG_LABEL_MARGIN_TOP = 2; + static DIALOG_LABEL_LINE_HEIGHT = 14; + + // request text of dialog + static DIALOG_REQ_FONT_SIZE = 16; + static DIALOG_REQ_MARGIN_TOP = 16; + static DIALOG_REQ_MARGIN_LEFT = 24; + static DIALOG_REQ_MARGIN_RIGHT = 24; + static DIALOG_REQ_LINE_HEIGHT = 22; + + // description text of dialog + static DIALOG_DESP_FONT_SIZE = 14; + static DIALOG_DESP_MARGIN_TOP = 2; + static DIALOG_DESP_MARGIN_LEFT = 24; + static DIALOG_DESP_MARGIN_RIGHT = 24; + static DIALOG_DESP_MARGIN_BOTTOM = 8; + static DIALOG_DESP_LINE_HEIGHT = 19; + + static BUTTON_MARGIN_TOP = 8; + static BUTTON_MARGIN_LEFT = 16; + static BUTTON_MARGIN_RIGHT = 16; + static BUTTON_HEIGHT = 40; + + static DIALOG_PRIVACY_BORDER_RADIUS = 32; + static DIALOG_PADDING_BOTTOM = 16; +} diff --git a/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/common/utils.ets b/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/common/utils.ets new file mode 100644 index 000000000..766156628 --- /dev/null +++ b/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/common/utils.ets @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 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 Constants from './constant'; + +/** + * Omit display when application name is too long + * @param {String} Application name + */ +export function titleTrim(title: string): string { + let length = title.length; + if (length > Constants.MAXIMUM_HEADER_LENGTH) { + let str = ''; + str = title.substring(0, Constants.MAXIMUM_HEADER_LENGTH) + '...'; + return str; + } else { + return title; + } +} diff --git a/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/pages/notificationDialog.ets b/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/pages/notificationDialog.ets index 019cf0034..ef03d29d4 100644 --- a/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/pages/notificationDialog.ets +++ b/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/pages/notificationDialog.ets @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Copyright (c) 2023 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 @@ -13,42 +13,233 @@ * limitations under the License. */ -import rpc from '@ohos.rpc'; -import mediaquery from '@ohos.mediaquery' +import bundleManager from '@ohos.bundle.bundleManager'; import deviceInfo from '@ohos.deviceInfo'; -import { NotificationDialogBody } from '../pages/notifybody' +import display from '@ohos.display'; +import notification from '@ohos.notification'; +import window from '@ohos.window'; +import { titleTrim } from '../common/utils'; +import Constants from '../common/constant'; +import { EnableNotificationDialog } from '../ServiceExtAbility/NotificationServiceExtAbility'; -@Entry +const TAG = 'NotificationDialog_Service '; +const permission: Record = { + 'label': $r('app.string.group_label_notification'), + 'icon': $r('app.media.ic_public_ring'), + 'reason': $r('app.string.reason'), +}; +const bottomPopoverTypes = ['default', 'phone']; + +let storage = LocalStorage.getShared(); + +@Extend(Button) function customizeButton() { + .backgroundColor($r('sys.color.ohos_id_color_dialog_bg')) + .fontColor($r('sys.color.ohos_id_color_text_primary_activated')) + .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE) + .fontWeight(FontWeight.Medium) + .height(Constants.BUTTON_HEIGHT) + .flexGrow(Constants.FLEX_GROW) +} + +@Entry(storage) @Component -struct NotificationDialog { - controller: CustomDialogController - private TAG = "[NotificationDialog_Service]" - listener = mediaquery.matchMediaSync('(orientation: landscape)') - @State isLand: boolean = false - onLand = (mediaQueryResult) => { - if (mediaQueryResult.matches) { - this.isLand = true - } else { - this.isLand = false - } +struct NotificationDialogPage { + @State isUpdate: number = -1; + + privacyDialogController: CustomDialogController = new CustomDialogController({ + builder: PermissionDialog({ isUpdate: $isUpdate }), + autoCancel: false, + alignment: DialogAlignment.Center, + customStyle: true + }); + + build() {} + + aboutToAppear() { + this.privacyDialogController.open(); } + onPageShow() { + this.isUpdate++; + } +} + +@CustomDialog +struct PermissionDialog { + @State appName: string = ''; + @State naviHeight: number = 0; + @State isBottomPopover: boolean = true; + @Link @Watch('updateOnPageShow') isUpdate: number; + dialog?: EnableNotificationDialog; + controller?: CustomDialogController; + build() { - if (this.isLand || !(deviceInfo.deviceType == 'default' || deviceInfo.deviceType == 'phone')) { - //horizontal - Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { - NotificationDialogBody() + GridRow({ columns: { xs: Constants.XS_COLUMNS, sm: Constants.SM_COLUMNS, md: Constants.MD_COLUMNS, lg: Constants.LG_COLUMNS }, gutter: Constants.DIALOG_GUTTER }) { + GridCol({ span: { xs: Constants.XS_SPAN, sm: Constants.SM_SPAN, md: Constants.DIALOG_MD_SPAN, lg: Constants.DIALOG_LG_SPAN }, + offset: {xs: Constants.XS_OFFSET, sm: Constants.SM_OFFSET, md: Constants.DIALOG_MD_OFFSET, lg: Constants.DIALOG_LG_OFFSET} }) { + Flex({ justifyContent: FlexAlign.Center, alignItems: this.isBottomPopover ? ItemAlign.End : ItemAlign.Center }) { + Column() { + Image(permission.icon) + .width(Constants.DIALOG_ICON_WIDTH) + .height(Constants.DIALOG_ICON_HEIGHT) + .fillColor($r('sys.color.ohos_id_color_text_primary')) + .margin({ + top: Constants.DIALOG_ICON_MARGIN_TOP + }) + Scroll() { + Column() { + Row() { + Flex({ justifyContent: FlexAlign.Start }) { + Text() { + Span($r('app.string.whether_to_allow')) + Span(this.appName) + Span($r('app.string.quotes')) + Span(permission.label) + } + .fontSize(Constants.DIALOG_REQ_FONT_SIZE) + .fontColor($r('sys.color.ohos_id_color_text_primary')) + .fontWeight(FontWeight.Medium) + .lineHeight(Constants.DIALOG_REQ_LINE_HEIGHT) + .margin({ + top: Constants.DIALOG_REQ_MARGIN_TOP, + left: Constants.DIALOG_REQ_MARGIN_LEFT, + right: Constants.DIALOG_REQ_MARGIN_RIGHT + }) + } + } + Row() { + Flex({ justifyContent: FlexAlign.Start }) { + Text() { + Span(permission.reason) + } + .fontSize(Constants.DIALOG_DESP_FONT_SIZE) + .fontColor($r('sys.color.ohos_id_color_text_secondary')) + .lineHeight(Constants.DIALOG_DESP_LINE_HEIGHT) + .margin({ + top: Constants.DIALOG_DESP_MARGIN_TOP, + left: Constants.DIALOG_DESP_MARGIN_LEFT, + right: Constants.DIALOG_DESP_MARGIN_RIGHT, + bottom: Constants.DIALOG_DESP_MARGIN_BOTTOM + }) + } + } + } + } + .constraintSize({ maxHeight: Constants.MAXIMUM_HEADER_HEIGHT }) + Row() { + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Button($r('app.string.BAN')) + .onClick(async (): Promise => { + await this.enableNotification(false); + }) + .customizeButton() + Divider() + .color($r('sys.color.ohos_id_color_list_separator')) + .vertical(true) + .height(Constants.DIVIDER_HEIGHT) + .opacity(.2) + Button($r('app.string.ALLOW')) + .onClick(async (): Promise => { + await this.enableNotification(true); + }) + .customizeButton() + } + .margin({ left: Constants.BUTTON_MARGIN_LEFT, right: Constants.BUTTON_MARGIN_RIGHT }) + } + } + .backgroundColor($r('sys.color.ohos_id_color_dialog_bg')) + .borderRadius(Constants.DIALOG_PRIVACY_BORDER_RADIUS) + .width(Constants.FULL_WIDTH) + .padding({ bottom: Constants.DIALOG_PADDING_BOTTOM }) + .margin({ bottom: $r('sys.float.ohos_id_dialog_margin_bottom') }) + .clip(true) + } + .width(Constants.FULL_WIDTH) + .height(Constants.FULL_HEIGHT) } - .width("100%") - .height("100%") - } else { - //vertical - Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Center, alignItems: ItemAlign.End }) { - NotificationDialogBody() - } - .width("100%") - .height("100%") - .padding({bottom: 48}) + } + .margin({ + left: this.isBottomPopover ? Constants.DIALOG_MARGIN_VERTICAL : Constants.DIALOG_MARGIN, + right: this.isBottomPopover ? Constants.DIALOG_MARGIN_VERTICAL : Constants.DIALOG_MARGIN, + bottom: this.isBottomPopover ? this.naviHeight : 0 + }) + } + + async updateApplicationName(bundleName: string): Promise { + console.info(TAG, `updateApplicationName bundleName: ${bundleName}`); + try { + let applicationInfo = await bundleManager.getApplicationInfo(bundleName, + bundleManager.ApplicationFlag.GET_APPLICATION_INFO_DEFAULT); + let extensionContext = AppStorage.Get('context') as Context; + let context = extensionContext.createBundleContext(bundleName); + let appName = context.resourceManager.getStringSync(applicationInfo.labelId); + this.appName = titleTrim(appName); + console.info(TAG, `hap label: ${applicationInfo.label}, value ${this.appName}`); + } catch (err) { + console.error(TAG, `applicationName error : ${JSON.stringify(err)}`); + } + } + + updateAvoidWindow(): void { + let type = window.AvoidAreaType.TYPE_SYSTEM; + try { + this.dialog.window.on('avoidAreaChange', (data): void => { + if (data.type == window.AvoidAreaType.TYPE_SYSTEM) { + console.info(TAG, `avoidAreaChange: ${JSON.stringify(data)}`); + this.naviHeight = data.area.bottomRect.height; + } + }); + let avoidArea = this.dialog.window.getWindowAvoidArea(type); + console.info(TAG, `avoidArea: ${JSON.stringify(avoidArea)}`); + this.naviHeight = avoidArea.bottomRect.height; + } catch (err) { + console.error(TAG, `Failed to obtain the area. Cause: ${JSON.stringify(err)}`); + } + } + + updateIsBottomPopover(): void { + let dis = display.getDefaultDisplaySync(); + let isVertical = dis.width <= dis.height; + this.isBottomPopover = bottomPopoverTypes.includes(deviceInfo.deviceType) && isVertical; + } + + async updateStatus(): Promise { + let bundleNameObj = this.dialog.want.parameters.from; + let bundleName = bundleNameObj ? bundleNameObj.toString() : ''; + await this.updateApplicationName(bundleName); + this.updateIsBottomPopover(); + } + + async updateOnPageShow(): Promise { + if (this.isUpdate > 0) { + await this.updateStatus(); + } + } + + async aboutToAppear(): Promise { + this.dialog = storage.get('dialog') as EnableNotificationDialog; + this.updateAvoidWindow(); + try { + await this.updateStatus(); + } catch (err) { + console.error(TAG, `aboutToAppear error : + ${JSON.stringify(err)}`); + await this.dialog.destroyException(); + } + } + + async enableNotification(enabled: boolean): Promise { + console.info(TAG, `NotificationDialog enableNotification: ${enabled}`); + let fromObj = this.dialog.want.parameters.from; + let bundleOption = { + bundle: fromObj ? fromObj.toString() : '' + } as notification.BundleOption; + console.info(TAG, 'NotificationDialog before enableNotification', JSON.stringify(bundleOption)); + try { + await notification.enableNotification(bundleOption, enabled); + } catch (err) { + console.error(TAG, `NotificationDialog enable error, code is ${err.code}`); + } finally { + await this.dialog.destroy(); } } -} \ No newline at end of file +} diff --git a/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/pages/notifybody.ets b/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/pages/notifybody.ets deleted file mode 100644 index b456db655..000000000 --- a/services/dialog_ui/enable_notification_dialog/entry/src/main/ets/pages/notifybody.ets +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2023 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 notification from '@ohos.notification' - -@Component -export struct NotificationDialogBody { - build() { - Column() { - Text($r('app.string.if_allow_to_publish_notification')) - .width("350vp") - .fontSize(18) - .fontColor("#182431") - .fontWeight(400) - .opacity(1) - .maxLines(2) - .textAlign(TextAlign.Center) - .margin({ bottom: 8 }) - - Row() { - Button() { - Row() { - Text($r('app.string.ban')) - .textAlign(TextAlign.Center) - .fontSize("19fp") - .fontWeight(500) - .fontColor("#0D81F2") - } - } - .onClick(() => { - this.privacyChose(false) - console.info("after privacyChose") - }) - .width("116vp") - .height("40vp") - .margin({ top: "9vp", bottom: "9vp", left: "8vp" }) - .backgroundColor("#FFFFFF") - - Text() - .backgroundColor('#e1e1e1') - .height('22fp') - .width('1px') - - Button() { - Row() { - Text($r('app.string.allow')) - .textAlign(TextAlign.Center) - .fontSize("19fp") - .fontWeight(500) - .fontColor("#0D81F2") - } - } - .onClick(() => { - this.privacyChose(true) - console.info("after privacyChose") - }) - .width("116vp") - .height("40vp") - .margin({ top: "9vp", right: "8vp", bottom: "9vp" }) - .backgroundColor("#FFFFFF") - } - .height(56) - } - .width('360vp') - .borderRadius(24) - .alignItems(HorizontalAlign.Center) - .backgroundColor("#FFFFFF") - .borderColor('#e1e1e1') - .borderWidth('1px') - .padding({left:24, top:24, right:24}) - } - - async privacyChose(flag) { - console.info("NotificationDialog privacyChose: " + flag) - let enable = flag; - let bundleOption = { - bundle: globalThis.abilityWant.parameters['from'] - } - console.info("NotificationDialog before enableNotification") - await notification.enableNotification(bundleOption, enable, (err) => { - if (err.code) { - console.error('Start enableNotification failed. ErrCode: ' + JSON.stringify(err.code)); - } - }) - globalThis.closeDialog() - } -} \ No newline at end of file diff --git a/services/dialog_ui/enable_notification_dialog/entry/src/main/module.json b/services/dialog_ui/enable_notification_dialog/entry/src/main/module.json index 8f5104850..18153b2f8 100644 --- a/services/dialog_ui/enable_notification_dialog/entry/src/main/module.json +++ b/services/dialog_ui/enable_notification_dialog/entry/src/main/module.json @@ -1,7 +1,7 @@ { "module": { "name": "entry", - "type": "entry", + "type": "feature", "srcEntrance": "./ets/Application/AbilityStage.ts", "description": "$string:entry_desc", "mainElement": "MainAbility", @@ -13,7 +13,6 @@ "deliveryWithInstall": true, "installationFree": false, "pages": "$profile:main_pages", - "uiSyntax": "ets", "abilities": [], "extensionAbilities": [ { @@ -38,4 +37,4 @@ } ] } -} \ No newline at end of file +} diff --git a/services/dialog_ui/enable_notification_dialog/entry/src/main/resources/base/element/string.json b/services/dialog_ui/enable_notification_dialog/entry/src/main/resources/base/element/string.json index aa5f19dd3..ff42825db 100644 --- a/services/dialog_ui/enable_notification_dialog/entry/src/main/resources/base/element/string.json +++ b/services/dialog_ui/enable_notification_dialog/entry/src/main/resources/base/element/string.json @@ -13,16 +13,36 @@ "value": "NotificationDialog" }, { - "name": "if_allow_to_publish_notification", - "value": "Do you allow the app to publish notification?" + "name": "period", + "value": "." }, { - "name": "allow", + "name": "comma", + "value": ", " + }, + { + "name": "whether_to_allow", + "value": "Allow \"" + }, + { + "name": "quotes", + "value": "\"" + }, + { + "name": "reason", + "value": "These may include banner notifications, lock screen notifications, notification sounds, and more. You can change this in Settings." + }, + { + "name": "ALLOW", "value": "ALLOW" }, { - "name": "ban", + "name": "BAN", "value": "BAN" + }, + { + "name": "group_label_notification", + "value": " to send notifications?" } ] -} \ No newline at end of file +} diff --git a/services/dialog_ui/enable_notification_dialog/entry/src/main/resources/base/media/ic_public_ring.svg b/services/dialog_ui/enable_notification_dialog/entry/src/main/resources/base/media/ic_public_ring.svg new file mode 100644 index 000000000..beec8f08c --- /dev/null +++ b/services/dialog_ui/enable_notification_dialog/entry/src/main/resources/base/media/ic_public_ring.svg @@ -0,0 +1,13 @@ + + + Public/ic_public_ring + + + + + + + + + + \ No newline at end of file diff --git a/services/dialog_ui/enable_notification_dialog/entry/src/main/resources/zh/element/string.json b/services/dialog_ui/enable_notification_dialog/entry/src/main/resources/zh/element/string.json index d2d2f2e91..5ab3cb3ac 100644 --- a/services/dialog_ui/enable_notification_dialog/entry/src/main/resources/zh/element/string.json +++ b/services/dialog_ui/enable_notification_dialog/entry/src/main/resources/zh/element/string.json @@ -13,16 +13,36 @@ "value": "NotificationDialog" }, { - "name": "allow", + "name": "period", + "value": "。" + }, + { + "name": "comma", + "value": "," + }, + { + "name": "whether_to_allow", + "value": "是否允许“" + }, + { + "name": "quotes", + "value": "”" + }, + { + "name": "reason", + "value": "包括横幅、锁屏、铃声等。可前往“设置”>“通知和状态栏”更改。" + }, + { + "name": "ALLOW", "value": "允许" }, { - "name": "ban", + "name": "BAN", "value": "禁止" }, { - "name": "if_allow_to_publish_notification", - "value": "是否允许发送通知?" + "name": "group_label_notification", + "value": "发送通知?" } ] -} \ No newline at end of file +} -- Gitee