1/*
2 * Copyright (c) 2023-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 */
15import curves from '@ohos.curves';
16import { common } from '@kit.AbilityKit';
17import { BusinessError } from '@kit.BasicServicesKit';
18import { hilog } from '@kit.PerformanceAnalysisKit';
19
20const START_TIME = 250;
21const END_TIME = 200;
22const BORDER_RADIUS = 12;
23const ZINDEX_NUM = 9;
24
25
26export enum MarginType {
27  DEFAULT_MARGIN = 0,
28  FIT_MARGIN = 1,
29}
30
31export interface PromptOptions {
32  icon?: ResourceStr,
33  tip?: ResourceStr,
34  marginType: MarginType,
35  actionText?: ResourceStr,
36  marginTop: Dimension,
37  isShown?: boolean
38}
39
40@Component
41export struct ExceptionPrompt {
42  @Prop options: PromptOptions
43  touchBackgroundColor: Resource = $r('sys.color.ohos_id_color_sub_background_transparent')
44  maxAppFontScale: number = 1;
45  isFollowingSystemFontScale: boolean = false;
46  onTipClick: () => void = () => {
47    // Click the text on the left to change into the connecting state
48  }
49  onActionTextClick: () => void = () => {
50    // Click Set Network to open the Set network pop-up interface
51  }
52
53  @Builder
54  TextBuilder() {
55    Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign
56      .Center }) {
57      Row() {
58        Image(this.options.icon ?? $r('sys.media.ohos_ic_public_fail'))
59          .width("24vp")
60          .height('24vp')
61          .fillColor($r('sys.color.ohos_id_color_warning'))
62        Text(this.options.tip)
63          .fontSize($r('sys.float.ohos_id_text_size_body1'))
64          .minFontScale(1)
65          .maxFontScale(Math.min(this.updateFontScale(), 2))
66          .fontColor($r('sys.color.ohos_id_color_warning'))
67          .textOverflow({ overflow: TextOverflow.Ellipsis })
68          .maxLines(2)
69          .margin({
70            left: $r('sys.float.ohos_id_dialog_margin_end'),
71            right: $r('sys.float.ohos_id_dialog_margin_end')
72          })
73      }
74      .padding({ right: $r('sys.float.ohos_id_default_padding_end') })
75      .width('100%')
76      .onClick(() => {
77        this.onTipClick() //Click the callback of the prompt text
78      })
79
80      if (this.options.actionText) {
81        Button({ stateEffect: true, type: ButtonType.Normal }) {
82          Row() {
83            Text(this.options.actionText)
84              .fontSize($r('sys.float.ohos_id_text_size_body2'))
85              .minFontScale(1)
86              .maxFontScale(Math.min(this.updateFontScale(), 2))
87              .fontColor($r('sys.color.ohos_id_color_text_secondary'))
88              .maxLines(2)
89              .padding(0)
90              .margin({ right: $r('sys.float.ohos_id_text_paragraph_margin_s') })
91              .textOverflow({ overflow: TextOverflow.Ellipsis })
92            Image($r('sys.media.ohos_ic_public_arrow_right'))
93              .width('12vp')
94              .height('24vp')
95              .fillColor($r('sys.color.ohos_id_color_tertiary'))
96          }
97        }
98        .backgroundColor(this.touchBackgroundColor)
99        .width(this.options.actionText ? 144 : 0)
100        .borderRadius($r('sys.float.ohos_id_corner_radius_subtab'))
101        .padding({
102          right: $r('sys.float.ohos_id_elements_margin_vertical_l'),
103          left: $r('sys.float.ohos_id_elements_margin_vertical_l')
104        })
105        .onTouch((event) => {
106
107          if (event.type === TouchType.Down) {
108            this.touchBackgroundColor = $r('sys.color.ohos_id_color_click_effect')
109            this.onActionTextClick() //Click the icon button on the right for the callback
110          } else if (event.type === TouchType.Up) {
111            this.touchBackgroundColor = $r('sys.color.ohos_id_color_sub_background_transparent')
112          }
113        })
114
115      }
116    }
117    .padding({
118      left: $r('sys.float.ohos_id_notification_margin_start'),
119      right: $r('sys.float.ohos_id_text_paragraph_margin_s'),
120      top: $r('sys.float.ohos_id_default_padding_start'),
121      bottom: $r('sys.float.ohos_id_default_padding_end')
122    })
123  }
124
125  build() {
126    Row() {
127      Column() {
128        Column() {
129          this.TextBuilder()
130        }
131        .width('100%')
132        .borderRadius(BORDER_RADIUS)
133        .backgroundColor($r('sys.color.comp_background_warning_secondary'))
134        .zIndex(ZINDEX_NUM)
135      }
136      .padding(this.options.marginType === MarginType.DEFAULT_MARGIN ? {
137        left: $r('sys.float.ohos_id_card_margin_start'),
138        right: $r('sys.float.ohos_id_card_margin_end')
139      } : {
140        left: $r('sys.float.ohos_id_max_padding_start'),
141        right: $r('sys.float.ohos_id_max_padding_end')
142      })
143      .transition(
144        TransitionEffect.OPACITY.animation({
145          curve: curves.cubicBezierCurve(0.33, 0, 0.67, 1),
146          duration: this.options.isShown ? START_TIME : END_TIME
147        })
148      )
149      .visibility(this.options.isShown ? Visibility.Visible : Visibility.None)
150    }
151    .width('100%')
152    .position({ y: this.options.marginTop })
153    .zIndex(ZINDEX_NUM)
154  }
155
156  aboutToAppear() {
157    try {
158      let uiContent: UIContext = this.getUIContext();
159      this.isFollowingSystemFontScale = uiContent.isFollowingSystemFontScale();
160      this.maxAppFontScale = uiContent.getMaxFontScale();
161    } catch (err) {
162      let code: number = (err as BusinessError).code;
163      let message: string = (err as BusinessError).message;
164      hilog.error(0x3900, 'Ace', `Failed to init fontsizescale info, cause, code: ${code}, message: ${message}`);
165    }
166  }
167
168  updateFontScale(): number {
169    let uiContent: UIContext = this.getUIContext();
170    let systemFontScale = (uiContent.getHostContext() as common.UIAbilityContext)?.config?.fontSizeScale ?? 1;
171    if (!this.isFollowingSystemFontScale) {
172      return 1;
173    }
174    return Math.min(systemFontScale, this.maxAppFontScale);
175  }
176}