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}