1/**
2 * Copyright (c) 2022-2024 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 { WidthPercent } from '../common/util/ConfigData';
17import HeadComponent from '../common/component/headComponent';
18import { SubEntryComponent } from '../common/component/subEntryComponent';
19import CmFaPresenter from '../presenter/CmFaPresenter';
20import { GlobalContext } from '../common/GlobalContext';
21import router from '@ohos.router';
22import promptAction from '@ohos.promptAction';
23import { CustomContentDialog } from '@ohos.arkui.advanced.Dialog';
24import { NavEntryKey } from '../common/NavEntryKey';
25import { SheetParam } from './picker/SheetParam';
26
27const DISPLAY_DURATION: number = 2000;
28const COPIES_NUM: number = 12;
29
30class CertListItem {
31  public targetPage: string = '';
32  public title: Resource = $r('app.string.CA_cert');
33};
34
35@Entry
36@Component
37export struct CertificateComponent {
38  @State columnMargin: string = '12vp';
39  @State mFaPresenter: CmFaPresenter = CmFaPresenter.getInstance();
40  private listItems: Array<CertListItem> = [
41    { targetPage: 'pages/trustedCa', title: $r('app.string.CA_cert') },
42    { targetPage: 'pages/cerEvidenceFa', title: $r('app.string.userEvidence') }
43  ];
44  @Styles normalStyle() {
45    .backgroundColor($r('sys.color.ohos_id_color_card_bg'))
46  };
47  @Styles pressedStyle() {
48    .backgroundColor($r('sys.color.ohos_id_color_click_effect'))
49  };
50
51  isStartBySheet: boolean = false;
52  selected?: (path: string) => void;
53  @State private headRectHeight: number = 64;
54  @State private headRectHeightReal: number = 0;
55  @Prop sheetParam: SheetParam;
56  private scroller: Scroller = new Scroller();
57  @State private scrollerHeight: number = 0;
58
59  build() {
60    Column() {
61      GridRow({
62        columns: COPIES_NUM,
63        gutter: vp2px(1) === 2 ? $r('app.float.wh_value_12') : $r('app.float.wh_value_0')
64      }) {
65        GridCol({ span: COPIES_NUM }) {
66          Stack({ alignContent: Alignment.Top }) {
67            Column() {
68              HeadComponent({ headName: $r('app.string.certificateTab'), icBackIsVisibility: !this.isStartBySheet })
69                .margin({
70                  top: this.isStartBySheet ? 8 : 0,
71                  left: 12,
72                  right: 12
73                })
74            }.onAreaChange((oldArea, newArea) => {
75              this.headRectHeight = newArea.height as number;
76              this.headRectHeightReal = newArea.height as number;
77            }).zIndex(1)
78
79            Stack({ alignContent: Alignment.TopEnd }) {
80              Scroll(this.scroller) {
81                Column({ space: this.columnMargin }) {
82                  List() {
83                    ForEach(this.listItems, (item: CertListItem) => {
84                      ListItem() {
85                        SubEntryComponent({ targetPage: item.targetPage, title: item.title,
86                          onItemClicked: targetRouter => {
87                            if (this.isStartBySheet) {
88                              if (targetRouter === 'pages/trustedCa') {
89                                this.selected?.(NavEntryKey.CA_CERTIFICATE_ENTRY);
90                              } else {
91                                this.selected?.(NavEntryKey.CREDENTIAL_LIST_ENTRY);
92                              }
93                            } else {
94                              router.pushUrl({
95                                url: targetRouter
96                              });
97                            }
98                          } })
99                      }
100                      .stateStyles({
101                        normal: this.normalStyle,
102                        pressed: this.pressedStyle
103                      });
104                    }, (item: CertListItem) => JSON.stringify(item))
105                  }
106                  .padding($r('app.float.wh_value_4'))
107                  .divider({
108                    strokeWidth: $r('app.float.sys_list_divider_strokeWidth_value'),
109                    color: $r('sys.color.ohos_id_color_list_separator'),
110                    startMargin: $r('app.float.wh_value_8'),
111                    endMargin: $r('app.float.wh_value_8')
112                  })
113                  .borderRadius($r('app.float.user_list_divider_borderRadius_value'))
114                  .backgroundColor($r('sys.color.ohos_id_color_list_card_bg'))
115
116                  CertInstallComponent({ mFaPresenter: $mFaPresenter, onItemClicked: () => {
117                    if (this.isStartBySheet) {
118                      this.selected?.(NavEntryKey.INSTALL_ENTRY);
119                    } else {
120                      router.pushUrl({
121                        url: 'pages/certInstallFromStorage'
122                      }, router.RouterMode.Standard)
123                    }
124                  } })
125
126                  DeleteAll({ mFaPresenter: $mFaPresenter })
127                }
128                .width(WidthPercent.WH_100_100)
129              }
130              .align(Alignment.Top)
131              .scrollable(ScrollDirection.Vertical)
132              .scrollBar(BarState.Off)
133              .width(WidthPercent.WH_100_100)
134              .height(this.isStartBySheet ? WidthPercent.WH_AUTO : WidthPercent.WH_100_100)
135              .edgeEffect(EdgeEffect.Spring)
136              .padding({
137                left: 16,
138                right: 16,
139                bottom: $r('app.float.wh_value_24')
140              })
141              .constraintSize({
142                minHeight: this.getScrollMinHeight()
143              }).onAreaChange((oldArea, newArea) => {
144                this.scrollerHeight = newArea.height as number;
145              })
146
147              Column() {
148                ScrollBar({
149                  scroller: this.scroller,
150                  direction: ScrollBarDirection.Vertical,
151                  state: BarState.Auto
152                }).margin({
153                  bottom: $r('app.float.wh_value_24')
154                })
155              }.height(this.scrollerHeight)
156            }
157            .padding({
158              top: this.headRectHeight
159            })
160            .width(WidthPercent.WH_100_100)
161            .height(this.isStartBySheet ? WidthPercent.WH_AUTO : WidthPercent.WH_100_100)
162          }
163          .width(WidthPercent.WH_100_100)
164          .height(this.isStartBySheet ? WidthPercent.WH_AUTO : WidthPercent.WH_100_100)
165        }
166      }
167      .margin(vp2px(1) === 2 ? $r('app.float.item_common_horizontal_margin') : $r('app.float.wh_value_0'))
168      .width(WidthPercent.WH_100_100)
169      .height(this.isStartBySheet ? WidthPercent.WH_AUTO : WidthPercent.WH_100_100);
170    }
171    .backgroundColor($r('sys.color.ohos_id_color_sub_background'))
172    .width(WidthPercent.WH_100_100)
173    .height(this.isStartBySheet ? WidthPercent.WH_AUTO : WidthPercent.WH_100_100)
174  }
175
176  getScrollMinHeight() {
177    if (this.sheetParam === undefined || this.headRectHeightReal === 0 ||
178      this.sheetParam.sheetMinHeight < this.headRectHeightReal) {
179      return 0;
180    }
181    return this.sheetParam.sheetMinHeight - this.headRectHeightReal;
182  }
183
184  onPageShow() {
185    let uri = GlobalContext.getContext().getAbilityWant().uri;
186    GlobalContext.getContext().clearAbilityWantUri();
187
188    if (uri === 'certInstall') {
189      router.pushUrl({
190        url: 'pages/certInstallFromStorage'
191      })
192    } else if (uri === 'requestAuthorize') {
193      this.mFaPresenter.startRequestAuth(GlobalContext.getContext().getAbilityWant().parameters?.appUid as string);
194    } else {
195      console.error('The want type is not supported');
196    }
197  }
198}
199
200@Component
201struct DeleteAll {
202  @Link mFaPresenter: CmFaPresenter;
203  @Styles normalStyle() {
204    .backgroundColor($r('sys.color.ohos_id_color_card_bg'))
205    .borderRadius($r('app.float.user_list_divider_borderRadius_value'))
206  };
207  @Styles pressedStyle() {
208    .backgroundColor($r('sys.color.ohos_id_color_click_effect'))
209    .borderRadius($r('app.float.user_list_divider_borderRadius_value'))
210  };
211
212  deleteWarnDialog: CustomDialogController = new CustomDialogController({
213    builder: CustomContentDialog({
214      contentBuilder: () => {
215        this.deleteWarnContent();
216      },
217      contentAreaPadding: {right: $r('app.float.wh_value_0')},
218      buttons: [
219        {
220          value: $r('app.string.deleteAllCredCancel'),
221          buttonStyle: ButtonStyleMode.TEXTUAL,
222          action: () => {
223            this.deleteWarnDialog?.close();
224          }
225        },
226        {
227          value: $r('app.string.deleteAllCredDelete'),
228          buttonStyle: ButtonStyleMode.TEXTUAL,
229          action: () => {
230            this.mFaPresenter.uninstallAllCert();
231            this.deleteWarnDialog?.close();
232            promptAction.showToast({
233              message: $r('app.string.delete_success'),
234              duration: DISPLAY_DURATION,
235            })
236          },
237          role: ButtonRole.ERROR
238        }
239      ]
240    }),
241  })
242
243  @Builder
244  deleteWarnContent(): void {
245    Column() {
246      Text($r('app.string.deleteAllCredDialogTitle'))
247        .height($r('app.float.wh_value_56'))
248        .fontSize($r('sys.float.ohos_id_text_size_dialog_tittle'))
249        .fontColor($r('sys.color.ohos_id_color_text_primary'))
250        .fontWeight(FontWeight.Medium)
251        .margin({
252          left: $r('app.float.wh_value_24'),
253          right: $r('app.float.wh_value_24')
254        })
255        .alignSelf(ItemAlign.Start)
256
257      Text($r('app.string.deleteAllCredDialogMessage'))
258        .fontSize($r('sys.float.ohos_id_text_size_body1'))
259        .fontWeight(FontWeight.Regular)
260        .fontColor($r('sys.color.ohos_id_color_text_primary'))
261        .margin({
262          top: $r('app.float.wh_value_16'),
263          left: $r('app.float.wh_value_24'),
264          right: $r('app.float.wh_value_24')
265        })
266        .alignSelf(ItemAlign.Start)
267    }
268    .width(WidthPercent.WH_100_100)
269    .borderRadius($r('app.float.user_list_divider_borderRadius_value'))
270  }
271
272  build() {
273    Row() {
274      Text($r('app.string.deleteAllCred'))
275        .fontSize($r('app.float.font_16'))
276        .lineHeight($r('app.float.wh_value_22'))
277        .fontWeight(FontWeight.Medium)
278        .fontColor($r('sys.color.ohos_id_color_text_hyperlink'))
279        .padding({ left: $r('app.float.distance_8') })
280        .stateStyles({
281          normal: this.normalStyle,
282          pressed: this.pressedStyle
283        })
284        .height(WidthPercent.WH_100_100)
285        .borderRadius($r('app.float.radius_20'))
286        .width(WidthPercent.WH_100_100)
287        .textAlign(TextAlign.Start);
288    }
289    .padding($r('app.float.distance_4'))
290    .height($r('app.float.wh_value_56'))
291    .width(WidthPercent.WH_100_100)
292    .borderRadius($r('app.float.radius_24'))
293    .backgroundColor($r('sys.color.ohos_id_color_foreground_contrary'))
294    .onClick(() => {
295      this.deleteWarnDialog.open();
296    })
297  }
298}
299
300@Component
301export struct CertInstallComponent {
302  @Link mFaPresenter: CmFaPresenter;
303  @Styles normalStyle() {
304    .backgroundColor($r('sys.color.ohos_id_color_card_bg'))
305    .borderRadius($r('app.float.user_list_divider_borderRadius_value'))
306  };
307  @Styles pressedStyle() {
308    .backgroundColor($r('sys.color.ohos_id_color_click_effect'))
309    .borderRadius($r('app.float.user_list_divider_borderRadius_value'))
310  };
311
312  onItemClicked?: () => void;
313
314  build() {
315    Column() {
316      Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
317        Row() {
318          Text($r('app.string.installInStorageDevice'))
319            .fontSize($r('app.float.font_16'))
320            .lineHeight($r('app.float.wh_value_22'))
321            .fontColor($r('sys.color.ohos_id_color_text_primary'))
322            .fontWeight(FontWeight.Medium)
323            .margin({ left: $r('app.float.wh_value_8') });
324        }
325
326        Image($r('app.media.ic_settings_arrow'))
327          .width($r('app.float.wh_value_12'))
328          .height($r('app.float.wh_value_24'))
329          .fillColor($r('sys.color.ohos_id_color_primary'))
330          .opacity($r('app.float.opacity_0_2'))
331          .margin({ right: $r('app.float.wh_value_8') });
332      }
333      .borderRadius($r('app.float.radius_20'))
334      .height(WidthPercent.WH_100_100)
335      .width(WidthPercent.WH_100_100)
336      .stateStyles({
337        normal: this.normalStyle,
338        pressed: this.pressedStyle
339      })
340    }
341    .backgroundColor($r('sys.color.ohos_id_color_foreground_contrary'))
342    .padding($r('app.float.distance_4'))
343    .height($r('app.float.wh_value_56'))
344    .borderRadius($r('app.float.radius_24'))
345    .onClick(() => {
346      this.onItemClicked?.();
347    });
348  }
349}
350