1/* 2 * Copyright (c) 2023-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 16if (!('finalizeConstruction' in ViewPU.prototype)) { 17 Reflect.set(ViewPU.prototype, 'finalizeConstruction', () => { 18 }); 19} 20if (PUV2ViewBase.contextStack === undefined) { 21 Reflect.set(PUV2ViewBase, 'contextStack', []); 22} 23const curves = requireNativeModule('ohos.curves'); 24const hilog = requireNapi('hilog'); 25const START_TIME = 250; 26const END_TIME = 200; 27const BORDER_RADIUS = 12; 28const ZINDEX_NUM = 9; 29const SYMBOL_SIZE = 24; 30const MAX_SYMBOL_FONT_SCALE = 2; 31const MIN_SYMBOL_FONT_SCALE = 1; 32const DEFAULT_SYMBOL_FONT_SCALE = 1; 33 34export var MarginType; 35(function (MarginType) { 36 MarginType[MarginType['DEFAULT_MARGIN'] = 0] = 'DEFAULT_MARGIN'; 37 MarginType[MarginType['FIT_MARGIN'] = 1] = 'FIT_MARGIN'; 38})(MarginType || (MarginType = {})); 39 40export class ExceptionPrompt extends ViewPU { 41 constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) { 42 super(parent, __localStorage, elmtId, extraInfo); 43 if (typeof paramsLambda === 'function') { 44 this.paramsGenerator_ = paramsLambda; 45 } 46 this.__options = new SynchedPropertyObjectOneWayPU(params.options, this, 'options'); 47 this.__fontSizeScale = new ObservedPropertyObjectPU(undefined, this, 'fontSizeScale'); 48 this.touchBackgroundColor = { 49 'id': -1, 50 'type': 10001, 51 params: ['sys.color.ohos_id_color_sub_background_transparent'], 52 'bundleName': '__harDefaultBundleName__', 53 'moduleName': '__harDefaultModuleName__' 54 }; 55 this.maxAppFontScale = 1; 56 this.isFollowingSystemFontScale = false; 57 this.onTipClick = undefined; 58 this.onActionTextClick = undefined; 59 this.callbackId = undefined; 60 this.callbacks = { 61 onConfigurationUpdated: (config) => { 62 this.fontSizeScale = Math.min(this.updateFontScale(), MAX_SYMBOL_FONT_SCALE); 63 this.fontSizeScale = Math.max(this.fontSizeScale, MIN_SYMBOL_FONT_SCALE); 64 }, onMemoryLevel() { 65 } 66 }; 67 this.setInitiallyProvidedValue(params); 68 this.finalizeConstruction(); 69 } 70 71 setInitiallyProvidedValue(params) { 72 if (params.fontSizeScale !== undefined) { 73 this.fontSizeScale = params.fontSizeScale; 74 } 75 if (params.touchBackgroundColor !== undefined) { 76 this.touchBackgroundColor = params.touchBackgroundColor; 77 } 78 if (params.maxAppFontScale !== undefined) { 79 this.maxAppFontScale = params.maxAppFontScale; 80 } 81 if (params.isFollowingSystemFontScale !== undefined) { 82 this.isFollowingSystemFontScale = params.isFollowingSystemFontScale; 83 } 84 if (params.onTipClick !== undefined) { 85 this.onTipClick = params.onTipClick; 86 } 87 if (params.onActionTextClick !== undefined) { 88 this.onActionTextClick = params.onActionTextClick; 89 } 90 if (params.callbackId !== undefined) { 91 this.callbackId = params.callbackId; 92 } 93 if (params.callbacks !== undefined) { 94 this.callbacks = params.callbacks; 95 } 96 } 97 98 updateStateVars(params) { 99 this.__options.reset(params.options); 100 } 101 102 purgeVariableDependenciesOnElmtId(rmElmtId) { 103 this.__options.purgeDependencyOnElmtId(rmElmtId); 104 this.__fontSizeScale.purgeDependencyOnElmtId(rmElmtId); 105 } 106 107 aboutToBeDeleted() { 108 this.__options.aboutToBeDeleted(); 109 this.__fontSizeScale.aboutToBeDeleted(); 110 SubscriberManager.Get().delete(this.id__()); 111 this.aboutToBeDeletedInternal(); 112 } 113 114 get options() { 115 return this.__options.get(); 116 } 117 118 set options(newValue) { 119 this.__options.set(newValue); 120 } 121 122 get fontSizeScale() { 123 return this.__fontSizeScale.get(); 124 } 125 126 set fontSizeScale(newValue) { 127 this.__fontSizeScale.set(newValue); 128 } 129 130 TextBuilder(parent = null) { 131 this.observeComponentCreation2((elmtId, isInitialRender) => { 132 Flex.create({ 133 justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign 134 .Center 135 }); 136 Flex.padding({ 137 left: { 138 'id': -1, 139 'type': 10002, 140 params: ['sys.float.ohos_id_notification_margin_start'], 141 'bundleName': '__harDefaultBundleName__', 142 'moduleName': '__harDefaultModuleName__' 143 }, 144 right: { 145 'id': -1, 146 'type': 10002, 147 params: ['sys.float.ohos_id_text_paragraph_margin_s'], 148 'bundleName': '__harDefaultBundleName__', 149 'moduleName': '__harDefaultModuleName__' 150 }, 151 top: { 152 'id': -1, 153 'type': 10002, 154 params: ['sys.float.ohos_id_default_padding_start'], 155 'bundleName': '__harDefaultBundleName__', 156 'moduleName': '__harDefaultModuleName__' 157 }, 158 bottom: { 159 'id': -1, 160 'type': 10002, 161 params: ['sys.float.ohos_id_default_padding_end'], 162 'bundleName': '__harDefaultBundleName__', 163 'moduleName': '__harDefaultModuleName__' 164 } 165 }); 166 }, Flex); 167 this.observeComponentCreation2((elmtId, isInitialRender) => { 168 Row.create(); 169 Row.padding({ 170 right: { 171 'id': -1, 172 'type': 10002, 173 params: ['sys.float.ohos_id_default_padding_end'], 174 'bundleName': '__harDefaultBundleName__', 175 'moduleName': '__harDefaultModuleName__' 176 } 177 }); 178 Row.width('100%'); 179 Row.accessibilityDescription(this.onTipClick ? '' : ' '); 180 Row.onClick(() => { 181 this.onTipClick && this.onTipClick(); 182 }); 183 }, Row); 184 this.observeComponentCreation2((elmtId, isInitialRender) => { 185 If.create(); 186 if (this.options?.symbolStyle !== undefined) { 187 this.ifElseBranchUpdateFunction(0, () => { 188 this.observeComponentCreation2((elmtId, isInitialRender) => { 189 SymbolGlyph.create(); 190 SymbolGlyph.fontColor([{ 191 'id': -1, 192 'type': 10001, 193 params: ['sys.color.ohos_id_color_warning'], 194 'bundleName': '__harDefaultBundleName__', 195 'moduleName': '__harDefaultModuleName__' 196 }]); 197 SymbolGlyph.attributeModifier.bind(this)(this.options?.symbolStyle); 198 SymbolGlyph.effectStrategy(SymbolEffectStrategy.NONE); 199 SymbolGlyph.symbolEffect(new SymbolEffect(), false); 200 SymbolGlyph.fontSize(`${(this.fontSizeScale ?? DEFAULT_SYMBOL_FONT_SCALE) * SYMBOL_SIZE}vp`); 201 }, SymbolGlyph); 202 }); 203 } else { 204 this.ifElseBranchUpdateFunction(1, () => { 205 this.observeComponentCreation2((elmtId, isInitialRender) => { 206 If.create(); 207 if (Util.isSymbolResource(this.options?.icon)) { 208 this.ifElseBranchUpdateFunction(0, () => { 209 this.observeComponentCreation2((elmtId, isInitialRender) => { 210 SymbolGlyph.create(this.options?.icon ?? { 211 'id': -1, 212 'type': 40000, 213 params: ['sys.symbol.exclamationmark_circle'], 214 'bundleName': '__harDefaultBundleName__', 215 'moduleName': '__harDefaultModuleName__' 216 }); 217 SymbolGlyph.fontColor([{ 218 'id': -1, 219 'type': 10001, 220 params: ['sys.color.ohos_id_color_warning'], 221 'bundleName': '__harDefaultBundleName__', 222 'moduleName': '__harDefaultModuleName__' 223 }]); 224 SymbolGlyph.fontSize(`${(this.fontSizeScale ?? DEFAULT_SYMBOL_FONT_SCALE) * 225 SYMBOL_SIZE}vp`); 226 }, SymbolGlyph); 227 }); 228 } else { 229 this.ifElseBranchUpdateFunction(1, () => { 230 this.observeComponentCreation2((elmtId, isInitialRender) => { 231 Image.create(this.options?.icon); 232 Image.width('24vp'); 233 Image.height('24vp'); 234 Image.fillColor({ 235 'id': -1, 236 'type': 10001, 237 params: ['sys.color.ohos_id_color_warning'], 238 'bundleName': '__harDefaultBundleName__', 239 'moduleName': '__harDefaultModuleName__' 240 }); 241 }, Image); 242 }); 243 } 244 }, If); 245 If.pop(); 246 }); 247 } 248 }, If); 249 If.pop(); 250 this.observeComponentCreation2((elmtId, isInitialRender) => { 251 Text.create(this.options.tip); 252 Text.fontSize({ 253 'id': -1, 254 'type': 10002, 255 params: ['sys.float.ohos_id_text_size_body1'], 256 'bundleName': '__harDefaultBundleName__', 257 'moduleName': '__harDefaultModuleName__' 258 }); 259 Text.minFontScale(1); 260 Text.maxFontScale(Math.min(this.updateFontScale(), 2)); 261 Text.fontColor({ 262 'id': -1, 263 'type': 10001, 264 params: ['sys.color.ohos_id_color_warning'], 265 'bundleName': '__harDefaultBundleName__', 266 'moduleName': '__harDefaultModuleName__' 267 }); 268 Text.textOverflow({ overflow: TextOverflow.Ellipsis }); 269 Text.maxLines(2); 270 Text.margin({ 271 left: { 272 'id': -1, 273 'type': 10002, 274 params: ['sys.float.ohos_id_dialog_margin_end'], 275 'bundleName': '__harDefaultBundleName__', 276 'moduleName': '__harDefaultModuleName__' 277 }, 278 }); 279 Text.flexShrink(1); 280 }, Text); 281 Text.pop(); 282 Row.pop(); 283 this.observeComponentCreation2((elmtId, isInitialRender) => { 284 If.create(); 285 if (this.options.actionText) { 286 this.ifElseBranchUpdateFunction(0, () => { 287 this.observeComponentCreation2((elmtId, isInitialRender) => { 288 Button.createWithChild({ stateEffect: false, type: ButtonType.Normal }); 289 Button.backgroundColor(this.touchBackgroundColor); 290 Button.width(this.options.actionText ? 144 : 0); 291 Button.borderRadius({ 292 'id': -1, 293 'type': 10002, 294 params: ['sys.float.ohos_id_corner_radius_subtab'], 295 'bundleName': '__harDefaultBundleName__', 296 'moduleName': '__harDefaultModuleName__' 297 }); 298 Button.padding({ 299 right: { 300 'id': -1, 301 'type': 10002, 302 params: ['sys.float.padding_level2'], 303 'bundleName': '__harDefaultBundleName__', 304 'moduleName': '__harDefaultModuleName__' 305 }, 306 }); 307 Button.accessibilityDescription(this.onActionTextClick ? '' : ' '); 308 Button.accessibilityRole(this.onActionTextClick ? AccessibilityRoleType.BUTTON : 309 AccessibilityRoleType.ROLE_NONE); 310 Button.onClick(() => { 311 this.onActionTextClick && this.onActionTextClick(); 312 }); 313 }, Button); 314 this.observeComponentCreation2((elmtId, isInitialRender) => { 315 Row.create(); 316 Row.width('100%'); 317 Row.justifyContent(FlexAlign.End); 318 }, Row); 319 this.observeComponentCreation2((elmtId, isInitialRender) => { 320 Text.create(this.options.actionText); 321 Text.fontSize({ 322 'id': -1, 323 'type': 10002, 324 params: ['sys.float.ohos_id_text_size_body2'], 325 'bundleName': '__harDefaultBundleName__', 326 'moduleName': '__harDefaultModuleName__' 327 }); 328 Text.minFontScale(1); 329 Text.maxFontScale(Math.min(this.updateFontScale(), 2)); 330 Text.fontColor({ 331 'id': -1, 332 'type': 10001, 333 params: ['sys.color.ohos_id_color_text_secondary'], 334 'bundleName': '__harDefaultBundleName__', 335 'moduleName': '__harDefaultModuleName__' 336 }); 337 Text.maxLines(2); 338 Text.padding(0); 339 Text.margin({ 340 right: { 341 'id': -1, 342 'type': 10002, 343 params: ['sys.float.ohos_id_text_paragraph_margin_s'], 344 'bundleName': '__harDefaultBundleName__', 345 'moduleName': '__harDefaultModuleName__' 346 } 347 }); 348 Text.textOverflow({ overflow: TextOverflow.Ellipsis }); 349 Text.flexShrink(1); 350 Text.textAlign(TextAlign.End); 351 }, Text); 352 Text.pop(); 353 this.observeComponentCreation2((elmtId, isInitialRender) => { 354 SymbolGlyph.create({ 355 'id': -1, 356 'type': 40000, 357 params: ['sys.symbol.chevron_right'], 358 'bundleName': '__harDefaultBundleName__', 359 'moduleName': '__harDefaultModuleName__' 360 }); 361 SymbolGlyph.fontSize(`${(this.fontSizeScale ?? DEFAULT_SYMBOL_FONT_SCALE) * SYMBOL_SIZE}vp`); 362 SymbolGlyph.fontColor([{ 363 'id': -1, 364 'type': 10001, 365 params: ['sys.color.ohos_id_color_tertiary'], 366 'bundleName': '__harDefaultBundleName__', 367 'moduleName': '__harDefaultModuleName__' 368 }]); 369 }, SymbolGlyph); 370 Row.pop(); 371 Button.pop(); 372 }); 373 } else { 374 this.ifElseBranchUpdateFunction(1, () => { 375 }); 376 } 377 }, If); 378 If.pop(); 379 Flex.pop(); 380 } 381 382 initialRender() { 383 this.observeComponentCreation2((elmtId, isInitialRender) => { 384 Row.create(); 385 Row.width('100%'); 386 Row.position({ y: this.options.marginTop }); 387 Row.zIndex(ZINDEX_NUM); 388 }, Row); 389 this.observeComponentCreation2((elmtId, isInitialRender) => { 390 Column.create(); 391 Column.padding(this.options.marginType === MarginType.DEFAULT_MARGIN ? { 392 left: { 393 'id': -1, 394 'type': 10002, 395 params: ['sys.float.ohos_id_card_margin_start'], 396 'bundleName': '__harDefaultBundleName__', 397 'moduleName': '__harDefaultModuleName__' 398 }, 399 right: { 400 'id': -1, 401 'type': 10002, 402 params: ['sys.float.ohos_id_card_margin_end'], 403 'bundleName': '__harDefaultBundleName__', 404 'moduleName': '__harDefaultModuleName__' 405 } 406 } : { 407 left: { 408 'id': -1, 409 'type': 10002, 410 params: ['sys.float.ohos_id_max_padding_start'], 411 'bundleName': '__harDefaultBundleName__', 412 'moduleName': '__harDefaultModuleName__' 413 }, 414 right: { 415 'id': -1, 416 'type': 10002, 417 params: ['sys.float.ohos_id_max_padding_end'], 418 'bundleName': '__harDefaultBundleName__', 419 'moduleName': '__harDefaultModuleName__' 420 } 421 }); 422 Column.transition(TransitionEffect.OPACITY.animation({ 423 curve: curves.cubicBezierCurve(0.33, 0, 0.67, 1), 424 duration: this.options.isShown ? START_TIME : END_TIME 425 })); 426 Column.visibility(this.options.isShown ? Visibility.Visible : Visibility.None); 427 }, Column); 428 this.observeComponentCreation2((elmtId, isInitialRender) => { 429 Column.create(); 430 Column.width('100%'); 431 Column.borderRadius(BORDER_RADIUS); 432 Column.backgroundColor({ 433 'id': -1, 434 'type': 10001, 435 params: ['sys.color.comp_background_warning_secondary'], 436 'bundleName': '__harDefaultBundleName__', 437 'moduleName': '__harDefaultModuleName__' 438 }); 439 Column.zIndex(ZINDEX_NUM); 440 }, Column); 441 this.TextBuilder.bind(this)(); 442 Column.pop(); 443 Column.pop(); 444 Row.pop(); 445 } 446 447 aboutToAppear() { 448 try { 449 let uiContent = this.getUIContext(); 450 this.isFollowingSystemFontScale = uiContent.isFollowingSystemFontScale(); 451 this.maxAppFontScale = uiContent.getMaxFontScale(); 452 this.fontSizeScale = Math.min(this.updateFontScale(), MAX_SYMBOL_FONT_SCALE); 453 this.fontSizeScale = Math.max(this.fontSizeScale, MIN_SYMBOL_FONT_SCALE); 454 this.callbackId = uiContent.getHostContext()?.getApplicationContext()?.on('environment', this.callbacks); 455 } catch (err) { 456 let code = err.code; 457 let message = err.message; 458 hilog.error(0x3900, 'Ace', `Failed to init fontsizescale info, cause, code: ${code}, message: ${message}`); 459 } 460 } 461 462 aboutToDisappear() { 463 if (this.callbackId) { 464 this.getUIContext().getHostContext()?.getApplicationContext()?.off('environment', this.callbackId); 465 this.callbackId = void (0); 466 } 467 } 468 469 updateFontScale() { 470 let uiContent = this.getUIContext(); 471 let systemFontScale = uiContent.getHostContext()?.config?.fontSizeScale ?? 1; 472 if (!this.isFollowingSystemFontScale) { 473 return 1; 474 } 475 return Math.min(systemFontScale, this.maxAppFontScale); 476 } 477 478 rerender() { 479 this.updateDirtyElements(); 480 } 481} 482 483class Util { 484 static isSymbolResource(resourceStr) { 485 if (resourceStr === undefined) { 486 return true; 487 } 488 if (!Util.isResourceType(resourceStr)) { 489 return false; 490 } 491 let resource = resourceStr; 492 return resource.type === Util.RESOURCE_TYPE_SYMBOL; 493 } 494 495 static isResourceType(resource) { 496 if (!resource) { 497 return false; 498 } 499 return typeof resource !== 'string'; 500 } 501} 502 503Util.RESOURCE_TYPE_SYMBOL = 40000; 504 505export default { 506 MarginType, 507 ExceptionPrompt 508}