1/**
2 * Copyright (c) 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 */
15
16import screen from '@ohos.screen';
17import userAuth from '@ohos.userIAM.userAuth';
18import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession';
19import { DialogType } from '../common/module/DialogType';
20import FuncUtils from '../common/utils/FuncUtils';
21import LogUtils from '../common/utils/LogUtils';
22import Constants, { CmdData, CmdType, FingerPosition, WantParams, WidgetCommand } from '../common/vm/Constants';
23import CustomPassword from './components/CustomPassword';
24import FaceAuth from './components/FaceAuth';
25import FingerprintAuth from './components/FingerprintAuth';
26import PasswordAuth from './components/PasswordAuth';
27import common from '@ohos.app.ability.common';
28
29const DEFAULT_SIZE = 72;
30const FIVE_SECOND = 5000;
31const LANDSCAPE = 2;
32const TAG = 'Index';
33let userAuthWidgetMgr: userAuth.UserAuthWidgetMgr;
34
35@Entry
36@Component
37struct Index {
38  @State authType: Array<userAuth.UserAuthType> = [userAuth.UserAuthType.PIN];
39  @State type: string[] = [];
40  @State topHeight: number = DEFAULT_SIZE;
41  @State bottomHeight: number = DEFAULT_SIZE;
42  @State pinSubType: string = Constants.pinNumber;
43  @State dialogType: DialogType = DialogType.ALL;
44  @State windowModeType: string = 'DIALOG_BOX';
45  @State cmdData: Array<CmdType> = [];
46  @State isLandscape: boolean = false;
47  @Provide underFingerPrint: boolean = false;
48  @State loadFlag: boolean = false;
49
50  onScreenChange(): void {
51    try {
52      screen.getAllScreens((err, data) => {
53        if (err.code) {
54          LogUtils.error(TAG, 'Failed to get all screens. err: ' + err.code);
55          (AppStorage.get("session") as UIExtensionContentSession)?.terminateSelf();
56          return;
57        }
58        LogUtils.debug(TAG, ' get all screens. result:-- ' + JSON.stringify(data));
59        this.isLandscape = data[0]?.orientation === LANDSCAPE
60          || data[0]?.supportedModeInfo[0]?.width > data[0]?.supportedModeInfo[0]?.height;
61        AppStorage.SetOrCreate('titleLength', (data[0]?.supportedModeInfo[0]?.width * 0.8 / fp2px(16)))
62        LogUtils.debug(TAG, 'titleLength: ' + (data[0]?.supportedModeInfo[0]?.width * 0.8 / fp2px(16)));
63        LogUtils.debug(TAG, 'title: ' + (AppStorage.get("wantParams") as WantParams)?.title.length);
64        AppStorage.SetOrCreate('IS_LANDSCAPE', this.isLandscape);
65        LogUtils.debug(TAG, 'WantParams: ' + JSON.stringify(AppStorage.get("wantParams") as WantParams));
66        if ((AppStorage.get("wantParams") as WantParams)) {
67          this.getParams((AppStorage.get("wantParams") as WantParams));
68          this.handleAuthStart();
69          this.cmdData = (AppStorage.get("wantParams") as WantParams)?.cmd as CmdType[];
70        } else {
71          LogUtils.error(TAG, 'aboutToAppear wantParams null');
72          (AppStorage.get("session") as UIExtensionContentSession)?.terminateSelf();
73        }
74        if (this.isLandscape && this.underFingerPrint) {
75          setTimeout(() => {
76            (AppStorage.get("session") as UIExtensionContentSession)?.terminateSelf();
77          }, FIVE_SECOND)
78        } else {
79          this.loadFlag = true;
80        }
81      });
82    } catch (error) {
83      LogUtils.error(TAG, 'getAllScreens catch error: ' + error?.code);
84      (AppStorage.get("session") as UIExtensionContentSession)?.terminateSelf();
85    }
86  }
87
88  handleAuthStart(): void {
89    LogUtils.info(TAG, 'handleAuthStart');
90    try {
91      userAuthWidgetMgr = userAuth.getUserAuthWidgetMgr(Constants.userAuthWidgetMgrVersion);
92      LogUtils.info(TAG, 'getUserAuthWidgetMgr success');
93      let that = this;
94      userAuthWidgetMgr.on('command', {
95        sendCommand(result) {
96          LogUtils.info(TAG, 'sendCommand result: ' + result);
97          const cmdDataObj: WidgetCommand = JSON.parse(result || '{}');
98          that.cmdData = cmdDataObj?.cmd || [];
99          that.pinSubType = cmdDataObj?.pinSubType;
100          that.handleIsUnder(cmdDataObj?.cmd || []);
101        }
102      });
103    } catch (error) {
104      LogUtils.error(TAG, 'getUserAuthWidgetMgr catch error: ' + error?.code);
105      (AppStorage.get("session") as UIExtensionContentSession)?.terminateSelf();
106    }
107  }
108
109  handleIsUnder(cmd: Array<CmdType>): void {
110    try {
111      LogUtils.info(TAG, 'handleIsUnder');
112      cmd?.length > 0 && cmd.map((item) => {
113        const payload: CmdData = item?.payload;
114        if (payload.type === Constants.noticeTypeFinger) {
115          if (payload.sensorInfo && JSON.stringify(payload.sensorInfo) !== '{}') {
116            const fingerPosition: FingerPosition = JSON.parse(payload.sensorInfo);
117            if (fingerPosition?.sensorType === 'UNDER_SCREEN_SENSOR' ||
118              fingerPosition?.sensorType === 'BOTH_SENSOR' ||
119              fingerPosition?.sensorType === 'SensorType1') {
120              this.underFingerPrint = true;
121            }
122          }
123        }
124      });
125    } catch (error) {
126      LogUtils.error(TAG, 'handleIsUnder catch error: ' + error?.code);
127    }
128  }
129
130  aboutToAppear(): void {
131    LogUtils.debug(TAG, 'aboutToAppear');
132    FuncUtils.getWindowHeight();
133    this.onScreenChange();
134  }
135
136  aboutToDisappear(): void {
137    LogUtils.info(TAG, 'aboutToDisappear');
138    if (userAuthWidgetMgr) {
139      userAuthWidgetMgr.off('command', {
140        sendCommand(result) {
141          LogUtils.info(TAG, 'aboutToDisappear userAuthWidgetMgr offCommand result: ' + JSON.stringify(result));
142        }
143      });
144    }
145  }
146
147  getParams(result: WantParams): void {
148    LogUtils.info(TAG, 'getParams');
149    const resultInfo: WantParams = result;
150    this.pinSubType = resultInfo?.pinSubType;
151    const newType = resultInfo?.type && resultInfo?.type.map(item => {
152      if (item === Constants.noticeTypePin) {
153        return userAuth.UserAuthType.PIN;
154      } else if (item === Constants.noticeTypeFinger) {
155        return userAuth.UserAuthType.FINGERPRINT;
156      } else if (item === Constants.noticeTypeFace) {
157        return userAuth.UserAuthType.FACE;
158      } else {
159        return userAuth.UserAuthType.PIN;
160      }
161    })
162    AppStorage.setOrCreate("widgetContextId", resultInfo?.widgetContextId);
163    this.authType = newType;
164    this.type = resultInfo?.type;
165    this.windowModeType = resultInfo?.windowModeType;
166    this.dialogType = FuncUtils.getDialogType(newType);
167    this.cmdData = resultInfo?.cmd || [];
168    this.handleIsUnder(resultInfo?.cmd || []);
169  }
170
171  build() {
172    Column() {
173      if (this.isLandscape && this.underFingerPrint) {
174        Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Center, alignItems: ItemAlign.End }) {
175          Column() {
176            Text((AppStorage.get("context") as common.ExtensionContext)?.resourceManager
177              .getStringSync($r('app.string.unified_authwidget_tip_verify_in_portrait_mode').id))
178              .draggable(false)
179              .fontColor($r('sys.color.ohos_id_color_text_primary_contrary'))
180              .fontSize($r('sys.float.ohos_id_text_size_body2'))
181              .fontWeight(FontWeight.Regular)
182          }
183          .backgroundColor($r('sys.color.ohos_id_color_instant_tip_bg'))
184          .borderRadius($r('sys.float.ohos_id_corner_radius_default_l'))
185          .padding({
186            left: $r('app.float.padding_16'),
187            top: $r('app.float.padding_8'),
188            right: $r('app.float.padding_16'),
189            bottom: $r('app.float.padding_8')
190          })
191          .margin({ bottom: $r('app.float.margin_64') })
192        }
193        .width(Constants.fullContainerWidth)
194        .height(Constants.fullContainerHeight)
195      } else if (this.loadFlag) {
196        Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceAround, alignItems: ItemAlign.Center }) {
197          if ('DIALOG_BOX' === this.windowModeType) {
198            if (this.authType.includes(userAuth.UserAuthType.FACE)) {
199              FaceAuth({
200                type: $windowModeType,
201                pinSubType: $pinSubType,
202                dialogType: $dialogType,
203                cmdData: $cmdData,
204              })
205            } else if (this.authType.includes(userAuth.UserAuthType.FINGERPRINT)) {
206              FingerprintAuth({
207                type: $windowModeType,
208                pinSubType: $pinSubType,
209                dialogType: $dialogType,
210                cmdData: $cmdData,
211              })
212            } else {
213              PasswordAuth({
214                pinSubType: $pinSubType,
215                cmdData: $cmdData
216              })
217            }
218          } else {
219            // full screen PIN
220            CustomPassword({
221              authType: $authType,
222              pinSubType: $pinSubType,
223              cmdData: $cmdData,
224            })
225          }
226        }
227      }
228    }
229  }
230}