1/**
2 * Copyright (c) 2024-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 HeadComponent from '../../common/component/headComponent';
17import { ConfigValue, WidthPercent } from '../../common/util/ConfigData';
18import { BusinessError } from '@ohos.base';
19import { CMModelErrorCode } from '../../model/CertMangerModel';
20import { RouterFileVo } from '../../model/CertManagerVo/RouterInfoVo';
21import { GlobalContext } from '../../common/GlobalContext';
22import CmInstallPresenter from '../../presenter/CmInstallPresenter';
23import { SheetParam } from './SheetParam';
24import { NavEntryKey } from '../../common/NavEntryKey';
25
26const TAG: string = 'CredPwdInputPage: ';
27
28export class CredPwdInputParam {
29  public credFile: RouterFileVo;
30
31  constructor(file: RouterFileVo) {
32    this.credFile = file;
33  }
34}
35
36@Component
37export struct CredPwdInputPage {
38  private stack?: NavPathStack;
39
40  private credFile?: RouterFileVo;
41
42  @State private bottomRectHeight: number = 80;
43  @State private headRectHeight: number = 64;
44  @State private headRectHeightReal: number = 0;
45
46  @State certPwd: string = '';
47  @State isPasswordError: boolean = false;
48  @State passWordWarn: number = 0;
49  @Prop sheetParam: SheetParam;
50
51  build() {
52    NavDestination() {
53      Stack({ alignContent: Alignment.Bottom }) {
54        Stack({ alignContent: Alignment.Top }) {
55          Column() {
56            HeadComponent({ headName: $r('app.string.certificatePwdTab'), isStartBySheet: true, onBackClicked: () => {
57              this.stack?.pop();
58            } })
59              .margin({
60                left: $r('app.float.wh_value_12'),
61                top: 8
62              })
63          }.zIndex(1)
64          .onAreaChange((oldArea, newArea) => {
65            this.headRectHeight = newArea.height as number;
66            this.headRectHeightReal = newArea.height as number;
67          })
68
69          Stack({ alignContent: Alignment.TopEnd }) {
70            Scroll() {
71              this.buildContent()
72            }
73            .align(Alignment.Top)
74            .scrollable(ScrollDirection.Vertical)
75            .scrollBar(BarState.Off)
76            .edgeEffect(EdgeEffect.Spring)
77            .width(WidthPercent.WH_100_100)
78            .height(WidthPercent.WH_AUTO)
79            .constraintSize({
80              minHeight: this.getScrollMinHeight()
81            })
82          }.padding({
83            top: this.headRectHeight
84          })
85        }
86        .width(WidthPercent.WH_100_100)
87        .height(WidthPercent.WH_AUTO)
88        .padding({
89          bottom: this.bottomRectHeight
90        })
91
92        Column() {
93          Button() {
94            Text($r('app.string.installPwdInputConfirm'))
95              .fontSize($r('sys.float.ohos_id_text_size_body1'))
96              .fontWeight(FontWeight.Medium)
97              .fontColor($r('app.color.install_confirm_bt_font_color'))
98          }
99          .type(ButtonType.Capsule)
100          .backgroundColor($r('app.color.install_confirm_bt_bg_color'))
101          .width(WidthPercent.WH_100_100)
102          .height($r('app.float.wh_value_40'))
103          .margin({
104            top: $r('app.float.distance_16'),
105            bottom: $r('app.float.distance_24')
106          })
107          .enabled(this.certPwd !== undefined && this.certPwd.length > 0)
108          .onClick(() => {
109            if (this.credFile === undefined || this.credFile === null) {
110              console.error(TAG + 'Cred file is undefined');
111              return;
112            }
113            this.isPasswordError = false;
114            GlobalContext.getContext().getPwdStore().setCertPwd(this.certPwd);
115            CmInstallPresenter.getInstance().installCert(this.credFile.uri, '', this.credFile.suffix, false).then((resultCode) => {
116              this.passWordWarn = resultCode;
117              console.log(TAG + 'install cred result code = ' + resultCode);
118              if (resultCode === CMModelErrorCode.CM_MODEL_ERROR_PASSWORD_ERR) {
119                this.isPasswordError = true;
120              } else {
121                this.stack?.pop();
122              }
123            });
124          })
125        }.onAreaChange((oldArea: Area, newArea: Area) => {
126          this.bottomRectHeight = newArea.height as number;
127        })
128        .padding({
129          left: 16, right: 16
130        })
131      }
132      .width(WidthPercent.WH_100_100)
133      .height(WidthPercent.WH_AUTO)
134    }
135    .expandSafeArea([SafeAreaType.KEYBOARD])
136    .hideTitleBar(true)
137    .width(WidthPercent.WH_100_100)
138    .height(this.sheetParam?.lastSheetPage === NavEntryKey.CRED_PWD_INPUT_ENTRY ?
139      WidthPercent.WH_AUTO : this.sheetParam?.sheetMinHeight)
140    .backgroundColor($r('sys.color.background_secondary'))
141    .onReady((ctx: NavDestinationContext) => {
142      this.stack = ctx.pathStack;
143      try {
144        this.credFile = (ctx.pathInfo.param as CredPwdInputParam).credFile;
145      } catch (err) {
146        let error = err as BusinessError;
147        console.error(TAG + 'Get cred file failed: ' + error?.code + ', message: ' + error?.message);
148      }
149    })
150  }
151
152  @Builder
153  private buildContent() {
154    Column() {
155      Text($r('app.string.certificatePwdInfo'))
156        .fontColor($r('sys.color.ohos_id_color_text_primary'))
157        .fontSize($r('sys.float.ohos_id_text_size_body1'))
158        .fontWeight(FontWeight.Medium)
159        .margin({
160          top: $r('app.float.distance_24'),
161          left: $r('app.float.distance_24')
162        })
163        .alignSelf(ItemAlign.Start);
164
165      TextInput({ text: this.certPwd })
166        .type(InputType.Password)
167        .focusable(true)
168        .border(this.isPasswordError ? {
169          width: $r('app.float.wh_value_1'),
170          color: $r('sys.color.ohos_id_color_warning')
171        } : { width: $r('app.float.wh_value_0') })
172        .maxLength(ConfigValue.PWD_MAX_LENGTH)
173        .margin({
174          top: $r('app.float.distance_16'),
175          left: $r('app.float.distance_24'),
176          right: $r('app.float.distance_24')
177        })
178        .height($r('app.float.wh_value_40'))
179        .onChange((value: string) => {
180          this.certPwd = value;
181        })
182
183      Row() {
184        Text($r('app.string.Password_Message'))
185          .fontFamily('HarmonyHeiTi')
186          .fontSize($r('app.float.distance_14'))
187          .fontWeight(FontWeight.Regular)
188          .lineHeight($r('app.float.distance_19'))
189          .width(WidthPercent.WH_100_100)
190          .textAlign(TextAlign.Center)
191          .fontColor($r('sys.color.ohos_id_color_warning'))
192          .visibility(this.passWordWarn === CMModelErrorCode.CM_MODEL_ERROR_PASSWORD_ERR
193            ? Visibility.Visible : Visibility.None)
194      }
195    }
196    .width(WidthPercent.WH_100_100)
197    .alignItems(HorizontalAlign.Start)
198  }
199
200  getScrollMinHeight() {
201    if (this.sheetParam === undefined || this.headRectHeightReal === 0 ||
202      this.sheetParam.sheetMinHeight < (this.headRectHeightReal + this.bottomRectHeight)) {
203      return 0;
204    }
205    return this.sheetParam.sheetMinHeight - this.headRectHeightReal - this.bottomRectHeight;
206  }
207}