• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022-2025 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 UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession';
17import commonEventManager from '@ohos.commonEventManager';
18import common from '@ohos.app.ability.common';
19import router from '@ohos.router';
20import resourceManager from '@ohos.resourceManager';
21import { BusinessError } from '@ohos.base';
22
23let TAG = '[Location-Privacy]==>';
24const LOCATION_PRIVACY_ACCEPT_EVENT: string = 'usual.event.LOCATION_PRIVACY_ACCEPT';
25const LOCATION_PRIVACY_REJECT_EVENT: string = 'usual.event.LOCATION_PRIVACY_REJECT';
26const BODY_L = getNumberByResourceId(125830970, 16);
27const TITLE_S = getNumberByResourceId(125830966, 20);
28const BUTTON_HORIZONTAL_SPACE: number = getNumberByResourceId(125831051, 8);
29const BUTTON_LAYOUT_WEIGHT: number = 1;
30const FLAG_BEGIN: string = '<a';
31const FLAG_BEGIN_END: string = '>';
32const FLAG_END: string = '</a>';
33
34@CustomDialog
35struct LocationCustomDialog {
36  controller?: CustomDialogController
37  cancel: () => void = () => {}
38  accept: () => void = () => {}
39  private context = getContext(this) as common.UIAbilityContext;
40
41  build() {
42    Column() {
43      Column() {
44        Row() {
45          Text($r('app.string.location_target_statement_title'))
46            .fontSize(`${TITLE_S}fp`)
47            .fontWeight(FontWeight.Bold)
48            .textAlign(TextAlign.Start)
49            .width("100%")
50            .padding(this.getTitleAreaPadding())
51        }
52      }
53      Column() {
54        Row() {
55          Text() {
56            Span(this.getStatementContent()[0])
57            Span(this.getStatementContent()[1])
58              .fontColor($r('sys.color.ohos_id_color_text_hyperlink'))
59              .fontWeight(FontWeight.Bold)
60              .onClick(() => {
61                console.info(TAG, 'click privacy page');
62                this.routePage();
63              })
64            Span(this.getStatementContent()[2])
65          }
66          .focusable(true)
67          .fontSize(`${BODY_L}fp`)
68          .padding(this.getContentPadding())
69        }
70      }
71      Row() {
72        Button($r('app.string.cancel_button'))
73          .onClick(() => {
74            this.cancel();
75            if (this.controller) {
76              this.controller.close();
77            }
78          })
79          .layoutWeight(BUTTON_LAYOUT_WEIGHT)
80          .buttonStyle(ButtonStyleMode.TEXTUAL)
81          .labelStyle({
82            maxLines: 1,
83            maxFontSize: `${BODY_L}fp`,
84            minFontSize: 9
85          })
86        Row() {
87          Divider()
88            .width($r('sys.float.alert_divider_width'))
89            .height($r('sys.float.alert_divider_height'))
90            .color($r('sys.color.alert_divider_color'))
91            .vertical(true)
92        }
93        .width(BUTTON_HORIZONTAL_SPACE * 2)
94        .justifyContent(FlexAlign.Center)
95        Button($r('app.string.confirm_button'))
96          .onClick(() => {
97            this.accept();
98            if (this.controller) {
99              this.controller.close();
100            }
101          })
102          .layoutWeight(BUTTON_LAYOUT_WEIGHT)
103          .type(ButtonType.ROUNDED_RECTANGLE)
104          .labelStyle({
105            maxLines: 1,
106            maxFontSize: `${BODY_L}fp`,
107            minFontSize: 9
108          })
109      }
110      .padding(this.getButtonPadding())
111    }
112  }
113
114  async routePage() {
115    let options: router.RouterOptions = {
116      url: 'pages/PrivacyLoadPage',
117    }
118    try {
119      await router.pushUrl(options);
120    } catch (err) {
121      console.info(TAG, `fail callback, code: ${(err as BusinessError).code}`);
122    }
123  }
124
125  private getStatementContent(): Array<string> {
126    let result: Array<string> = ['', '', ''];
127    try {
128      let text = this.context.resourceManager.getStringByNameSync("location_target_statement_content");
129      let beginIndex = text.indexOf(FLAG_BEGIN);
130      if (beginIndex !== 0 && beginIndex !== -1) {
131        result[0] = text.substr(0, beginIndex);
132        text = text.substr(beginIndex, text.length);
133      }
134      let beginEndIndex = text.indexOf(FLAG_BEGIN_END);
135      let endIndex = text.indexOf(FLAG_END);
136      if (beginEndIndex !== -1 && endIndex !== -1) {
137        result[1] = text.substr(beginEndIndex + 1, endIndex - FLAG_END.length + 1);
138        result[2] = text.substr(endIndex + FLAG_END.length, text.length);
139      }
140      return result;
141    } catch (error) {
142      let code = (error as BusinessError).code;
143      let message = (error as BusinessError).message;
144      console.error(TAG, `getStatementContent failed, error code is ${code}, message is ${message}`);
145      return result;
146    }
147  }
148
149  /**
150   * get title area padding
151   *
152   * @returns padding
153   */
154  private getTitleAreaPadding(): Padding {
155    return {
156      top: $r('sys.float.alert_title_padding_top'),
157      right: $r('sys.float.alert_title_padding_right'),
158      left: $r('sys.float.alert_title_padding_left'),
159      bottom: 0,
160    };
161  }
162
163  /**
164   * get content padding
165   *
166   * @returns padding
167   */
168  private getContentPadding(): Padding {
169    return {
170      top: $r('sys.float.alert_content_default_padding'),
171      right: $r('sys.float.alert_content_default_padding'),
172      left: $r('sys.float.alert_content_default_padding'),
173      bottom: $r('sys.float.alert_content_default_padding'),
174    };
175  }
176
177  /**
178   * get button padding
179   *
180   * @returns padding
181   */
182  private getButtonPadding(): Padding {
183    return {
184      top: 0,
185      right: $r('sys.float.alert_content_default_padding'),
186      left: $r('sys.float.alert_content_default_padding'),
187      bottom: $r('sys.float.alert_content_default_padding'),
188    };
189  }
190}
191
192@Entry
193@Component
194struct dialogPlusPage {
195  dialogController: CustomDialogController = new CustomDialogController({
196    builder: LocationCustomDialog({
197      cancel: this.onCancel,
198      accept: this.onAccept,
199    }),
200    cancel: this.existApp,
201    autoCancel: false,
202    alignment: DialogAlignment.Bottom,
203    customStyle: false
204  })
205
206  aboutToAppear() {
207    console.info(TAG, 'aboutToAppear execute LocationPrivacyDialog')
208  }
209
210  aboutToDisappear() {
211    let session = AppStorage.get<UIExtensionContentSession>('ConfirmSession');
212    if (session) {
213      session.terminateSelf();
214    }
215  }
216
217  onCancel() {
218    console.info(TAG, 'Callback when the first button is clicked')
219
220    const options: commonEventManager.CommonEventPublishData = {
221      code: 0,
222      data: 'message',
223      isSticky: false,
224      parameters: { 'message': 'reject' }
225    }
226
227    commonEventManager.publish(LOCATION_PRIVACY_REJECT_EVENT, options, (err) => {
228      if (err) {
229        console.info(TAG, '[CommonEvent] PublishCallBack err=' + JSON.stringify(err));
230      } else {
231        console.info(TAG, '[CommonEvent] Publish success')
232      }
233    })
234
235    let session = AppStorage.get<UIExtensionContentSession>('ConfirmSession');
236    if (session) {
237      session.terminateSelf();
238    }
239  }
240
241  onAccept() {
242    console.info(TAG, 'Callback when the second button is clicked')
243
244    const options: commonEventManager.CommonEventPublishData = {
245      code: 0,
246      data: 'message',
247      isSticky: false,
248      parameters: { 'message': 'accept' }
249    }
250
251    commonEventManager.publish(LOCATION_PRIVACY_ACCEPT_EVENT, options, (err) => {
252      if (err) {
253        console.info(TAG, '[CommonEvent] PublishCallBack err=' + JSON.stringify(err));
254      } else {
255        console.info(TAG, '[CommonEvent] Publish success')
256      }
257    })
258
259    let session = AppStorage.get<UIExtensionContentSession>('ConfirmSession');
260    if (session) {
261      session.terminateSelf();
262    }
263  }
264
265  existApp() {
266    console.info(TAG, 'Click the callback in the blank area')
267    let session = AppStorage.get<UIExtensionContentSession>('ConfirmSession');
268    if (session) {
269      session.terminateSelf();
270    }
271  }
272
273  build() {
274    Column(this.dialogController.open()) {}
275  }
276}
277
278/**
279  * get resource size
280  *
281  * @param resourceId resource id
282  * @param defaultValue default value
283  * @returns resource size
284  */
285function getNumberByResourceId(resourceId: number, defaultValue: number, allowZero?: boolean): number {
286  try {
287    let sourceValue: number = resourceManager.getSystemResourceManager().getNumber(resourceId);
288    if (sourceValue > 0 || allowZero) {
289      return sourceValue;
290    } else {
291      return defaultValue;
292    }
293  } catch (error) {
294    return defaultValue;
295  }
296}