• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import bundleResourceManager from '@ohos.bundle.bundleResourceManager';
17import display from '@ohos.display';
18import window from '@ohos.window';
19import { titleTrim } from '../common/utils';
20import Constants from '../common/constant';
21import fs from '@ohos.file.fs';
22import configPolicy from '@ohos.configPolicy';
23import { EnableNotificationDialog } from '../ServiceExtAbility/NotificationServiceExtAbility';
24import { Callback} from '@ohos.base';
25import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession';
26
27const TAG = 'NotificationDialog_Service ';
28const permission: Record<string, Resource> = {
29  'label': $r('app.string.group_label_notification'),
30  'icon': $r('app.media.ic_public_ring'),
31  'reason': $r('app.string.reason'),
32};
33
34let storage = LocalStorage.getShared();
35
36@Entry(storage)
37@Component
38struct NotificationDialogPage {
39  @StorageLink('isUpdate') isUpdate: number = -1;
40  privacyDialogController: CustomDialogController = new CustomDialogController({
41    builder: PermissionDialog({ isUpdate: $isUpdate }),
42    autoCancel: false,
43    alignment: DialogAlignment.TopStart,
44    customStyle: false,
45    onWillDismiss: (dismissDialogAction: DismissDialogAction) => {
46      console.info(TAG, `dialog onWillDismiss reason= : ${JSON.stringify(dismissDialogAction.reason)}`);
47    },
48    width: '466px',
49    height: '466px'
50  });
51
52  build() {}
53
54  aboutToAppear() {
55    this.privacyDialogController.open();
56  }
57
58  onPageShow() {
59    this.isUpdate++;
60  }
61}
62
63@CustomDialog
64struct PermissionDialog {
65  @State appName: string = '';
66  @State isBottomPopover: boolean = true;
67  @StorageLink('clicked') clicked: boolean = false;
68  @Link @Watch('updateOnPageShow') isUpdate: number;
69  dialog?: EnableNotificationDialog;
70  session?: UIExtensionContentSession;
71  controller?: CustomDialogController;
72
73  build() {
74    Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
75      Column() {
76        Image(permission.icon)
77        .width('92px')
78        .height('92px')
79        .margin({
80            top: '2%'
81        })
82
83        Scroll() {
84          Column() {
85            Row() {
86              Flex({ justifyContent: FlexAlign.Center }) {
87                Text() {
88                  Span(getContext(this).resourceManager.getStringSync(permission.label.id).replace('%s', this.appName))
89                }
90                .fontSize('38px')
91                .fontColor('#FFFFFF')
92                .fontWeight(500)
93                .lineHeight('45px')
94                .margin({
95                  top: '4.1%',
96                  left: '11.2%',
97                  right: '11.2%'
98                })
99                .textAlign(TextAlign.Center)
100              }
101            }
102
103            Row() {
104              Flex({ justifyContent: FlexAlign.Center }) {
105                Button($r('app.string.ALLOW'))
106                .onClick(async (): Promise<void> => {
107                  await this.enableNotification(true);
108                })
109                .backgroundColor('#1F71FF')
110                .width('232px')
111                .height('80px')
112                .fontColor('#FFFFFF')
113                .fontSize('30px')
114                .fontWeight(500)
115              }
116              .margin({top:'4.1%'})
117            }
118
119            Row() {
120              Flex({ justifyContent: FlexAlign.Center }) {
121                Button($r('app.string.BAN'))
122                .onClick(async (): Promise<void> => {
123                  await this.enableNotification(false);
124                })
125                .backgroundColor('#255EA1FF')
126                .width('232px')
127                .height('80px')
128                .fontColor('#5EA1FF')
129                .fontSize('30px')
130                .fontWeight(500)
131              }
132              .margin({top:'4.1%'})
133            }
134          }
135        }
136        .scrollable(ScrollDirection.Vertical)
137        .scrollBar(BarState.Off)
138      }
139    }
140    .margin({
141      top: 0,
142      left: 0,
143      right: 0,
144      bottom: 0
145    })
146    .width('100%')
147    .height('100%')
148    .backgroundColor('#35000000')
149    .backgroundEffect({
150      radius: 20,
151      saturation: 50,
152      adaptiveColor: AdaptiveColor.AVERAGE,
153      blurOptions: {
154        grayscale: [35, 35]
155      }
156    })
157
158  }
159
160  async updateApplicationName(bundleName: string): Promise<void> {
161    console.info(TAG, `updateApplicationName bundleName: ${bundleName}`);
162    try {
163      let bundleFlags = bundleResourceManager.ResourceFlag.GET_RESOURCE_INFO_ALL;
164      let resourceInfo = bundleResourceManager.getBundleResourceInfo(bundleName, bundleFlags);
165      console.info(TAG, `applicationName name : ${JSON.stringify(resourceInfo.label)}`);
166      let appName = resourceInfo.label;
167      this.appName = titleTrim(appName);
168      console.info(TAG, `hap label: ${this.appName}`);
169    } catch (err) {
170      console.error(TAG, `applicationName error : ${err?.code}`);
171    }
172  }
173
174  async updateIsBottomPopover(): Promise<void> {
175    let dis = display.getDefaultDisplaySync();
176    let isVertical = dis.width <= dis.height;
177    try {
178      if (display.isFoldable()) {
179        let foldStatus = display.getFoldStatus();
180        if (foldStatus == display.FoldStatus.FOLD_STATUS_EXPANDED ||
181          foldStatus == display.FoldStatus.FOLD_STATUS_HALF_FOLDED) {
182            this.isBottomPopover = false;
183            return;
184        }
185      }
186    } catch (err) {
187      console.error(TAG, 'Failed to get the device foldable status. Code: ${err?.code}');
188    }
189
190    // read ccm configs
191    let isBottomPopoverTemp = false;
192    try {
193      let filePaths = await configPolicy.getCfgFiles(Constants.CCM_CONFIG_PATH);
194      for (let i = 0; i < filePaths.length; i++) {
195        let res = fs.accessSync(filePaths[i]);
196        if (res) {
197          let fileContent = fs.readTextSync(filePaths[i]);
198          let config: NotificationConfig = JSON.parse(fileContent);
199          if (config.notificationAuthorizationWindow != undefined) {
200            let windowConfig: NotificationAuthorizationWindow = config.notificationAuthorizationWindow;
201            if (windowConfig.isBottomPopover != undefined) {
202              isBottomPopoverTemp = windowConfig.isBottomPopover;
203            }
204          }
205        }
206      }
207    } catch (error) {
208      console.log(TAG, 'Failed get ccm files, Cause: ${err?.code}');
209    }
210    this.isBottomPopover = isBottomPopoverTemp && isVertical;
211  }
212
213  async updateStatus(): Promise<void> {
214    let bundleNameObj = this.dialog?.want.parameters?.bundleName;
215    let bundleName = bundleNameObj ? bundleNameObj.toString() : '';
216    await this.updateApplicationName(bundleName);
217    await this.updateIsBottomPopover();
218  }
219
220  async updateOnPageShow(): Promise<void> {
221    if (this.isUpdate > 0) {
222      await this.updateStatus();
223    }
224  }
225
226  async aboutToAppear(): Promise<void> {
227    this.dialog = storage.get('dialog') as EnableNotificationDialog;
228    this.session = storage.get('session') as UIExtensionContentSession;
229    try {
230      await this.updateStatus();
231    } catch (err) {
232      console.error(TAG, `aboutToAppear error : ${err?.code}`);
233      await this.dialog?.destroyException();
234      await this.session?.terminateSelf();
235    }
236  }
237
238  async aboutToDisappear(): Promise<void> {
239    console.info(TAG, `aboutToDisappear`);
240    this.session?.terminateSelf();
241  }
242
243  async enableNotification(enabled: boolean): Promise<void> {
244    console.info(TAG, `NotificationDialog enableNotification: ${enabled}`);
245    try {
246      await this.dialog?.publishButtonClickedEvent(enabled);
247      this.clicked = true;
248    } catch (err) {
249      console.error(TAG, `NotificationDialog enable error, code is ${err?.code}`);
250      await this.dialog?.destroyException();
251    } finally {
252      await this.dialog?.subWindow?.destroyWindow();
253      this.session?.terminateSelf();
254    }
255  }
256}
257
258interface NotificationConfig {
259  notificationAuthorizationWindow: NotificationAuthorizationWindow;
260}
261
262interface NotificationAuthorizationWindow {
263  isBottomPopover: boolean;
264}
265
266interface NotificationConfigAbc {
267  deviceType: DeviceType;
268}
269
270interface DeviceType {
271  isWatch: boolean;
272}
273