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 let text = this.context.resourceManager.getStringByNameSync("location_target_statement_content"); 128 let beginIndex = text.indexOf(FLAG_BEGIN); 129 if (beginIndex !== 0 && beginIndex !== -1) { 130 result[0] = text.substr(0, beginIndex); 131 text = text.substr(beginIndex, text.length); 132 } 133 let beginEndIndex = text.indexOf(FLAG_BEGIN_END); 134 let endIndex = text.indexOf(FLAG_END); 135 if (beginEndIndex !== -1 && endIndex !== -1) { 136 result[1] = text.substr(beginEndIndex + 1, endIndex - FLAG_END.length + 1); 137 result[2] = text.substr(endIndex + FLAG_END.length, text.length); 138 } 139 140 return result; 141 } 142 143 /** 144 * get title area padding 145 * 146 * @returns padding 147 */ 148 private getTitleAreaPadding(): Padding { 149 return { 150 top: $r('sys.float.alert_title_padding_top'), 151 right: $r('sys.float.alert_title_padding_right'), 152 left: $r('sys.float.alert_title_padding_left'), 153 bottom: 0, 154 }; 155 } 156 157 /** 158 * get content padding 159 * 160 * @returns padding 161 */ 162 private getContentPadding(): Padding { 163 return { 164 top: $r('sys.float.alert_content_default_padding'), 165 right: $r('sys.float.alert_content_default_padding'), 166 left: $r('sys.float.alert_content_default_padding'), 167 bottom: $r('sys.float.alert_content_default_padding'), 168 }; 169 } 170 171 /** 172 * get button padding 173 * 174 * @returns padding 175 */ 176 private getButtonPadding(): Padding { 177 return { 178 top: 0, 179 right: $r('sys.float.alert_content_default_padding'), 180 left: $r('sys.float.alert_content_default_padding'), 181 bottom: $r('sys.float.alert_content_default_padding'), 182 }; 183 } 184} 185 186@Entry 187@Component 188struct dialogPlusPage { 189 dialogController: CustomDialogController = new CustomDialogController({ 190 builder: LocationCustomDialog({ 191 cancel: this.onCancel, 192 accept: this.onAccept, 193 }), 194 cancel: this.existApp, 195 autoCancel: false, 196 alignment: DialogAlignment.Bottom, 197 customStyle: false 198 }) 199 200 aboutToAppear() { 201 console.info(TAG, 'aboutToAppear execute LocationPrivacyDialog') 202 } 203 204 aboutToDisappear() { 205 let session = AppStorage.get<UIExtensionContentSession>('ConfirmSession'); 206 if (session) { 207 session.terminateSelf(); 208 } 209 } 210 211 onCancel() { 212 console.info(TAG, 'Callback when the first button is clicked') 213 214 const options: commonEventManager.CommonEventPublishData = { 215 code: 0, 216 data: 'message', 217 isSticky: false, 218 parameters: { 'message': 'reject' } 219 } 220 221 commonEventManager.publish(LOCATION_PRIVACY_REJECT_EVENT, options, (err) => { 222 if (err) { 223 console.info(TAG, '[CommonEvent] PublishCallBack err=' + JSON.stringify(err)); 224 } else { 225 console.info(TAG, '[CommonEvent] Publish success') 226 } 227 }) 228 229 let session = AppStorage.get<UIExtensionContentSession>('ConfirmSession'); 230 if (session) { 231 session.terminateSelf(); 232 } 233 } 234 235 onAccept() { 236 console.info(TAG, 'Callback when the second button is clicked') 237 238 const options: commonEventManager.CommonEventPublishData = { 239 code: 0, 240 data: 'message', 241 isSticky: false, 242 parameters: { 'message': 'accept' } 243 } 244 245 commonEventManager.publish(LOCATION_PRIVACY_ACCEPT_EVENT, options, (err) => { 246 if (err) { 247 console.info(TAG, '[CommonEvent] PublishCallBack err=' + JSON.stringify(err)); 248 } else { 249 console.info(TAG, '[CommonEvent] Publish success') 250 } 251 }) 252 253 let session = AppStorage.get<UIExtensionContentSession>('ConfirmSession'); 254 if (session) { 255 session.terminateSelf(); 256 } 257 } 258 259 existApp() { 260 console.info(TAG, 'Click the callback in the blank area') 261 let session = AppStorage.get<UIExtensionContentSession>('ConfirmSession'); 262 if (session) { 263 session.terminateSelf(); 264 } 265 } 266 267 build() { 268 Column(this.dialogController.open()) {} 269 } 270} 271 272/** 273 * get resource size 274 * 275 * @param resourceId resource id 276 * @param defaultValue default value 277 * @returns resource size 278 */ 279function getNumberByResourceId(resourceId: number, defaultValue: number, allowZero?: boolean): number { 280 try { 281 let sourceValue: number = resourceManager.getSystemResourceManager().getNumber(resourceId); 282 if (sourceValue > 0 || allowZero) { 283 return sourceValue; 284 } else { 285 return defaultValue; 286 } 287 } catch (error) { 288 return defaultValue; 289 } 290}