• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 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 */
15import deviceManager from '@ohos.distributedHardware.deviceManager';
16import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'
17
18let dmClass: deviceManager.DeviceManager | null;
19let TAG = '[DeviceManagerUI:InputPinDialog]==>';
20const ACTION_CANCEL_PINCODE_INPUT: number = 4;
21const ACTION_DONE_PINCODE_INPUT: number = 5;
22const MSG_PIN_CODE_ERROR: number = 0;
23const MSG_CANCEL_PIN_CODE_INPUT: number = 3;
24const MSG_DOING_AUTH: number = 4;
25const BUTTON_BG_COLOR = 'rgba(255, 255, 255, 0.15)';
26const TOAST_DURATION_TIME_MS = 1500;
27const MAX_PINCODE_LENGTH = 6;
28
29@Entry
30@Component
31struct Index {
32  @State isTimes: number = 3;
33  @State passwordCircle: string[] = ['', '', '', '', '', ''];
34  @State errorTips: Resource = $r('app.plural.dm_incorrect_code', this.isTimes, this.isTimes);
35  @State @Watch('onChangeInput') input: string = '';
36  private keyboards: string[][] = [
37    ['1', '2', '3'],
38    ['4', '5', '6'],
39    ['7', '8', '9'],
40    ['', '0', 'x'],
41  ];
42  @State isUserInput: boolean = false;
43  @State isUserOperate: boolean = false;
44
45  dialogController: CustomDialogController = new CustomDialogController({
46    builder: errTips({attemptTimes: this.isTimes, errTips: this.errorTips}),
47    autoCancel: false,
48    alignment: DialogAlignment.Center,
49    customStyle: true,
50    maskColor: $r('sys.color.ohos_id_color_mask_thin'),
51  });
52
53  aboutToAppear() {
54    if (dmClass) {
55      console.log(TAG + 'deviceManager exist');
56      return;
57    }
58    deviceManager.createDeviceManager('com.ohos.devicemanagerui.input',
59      (err: Error, dm: deviceManager.DeviceManager) => {
60      if (err) {
61        console.log('createDeviceManager err:' + JSON.stringify(err) + '  --fail:' + '${dm}');
62        return;
63      }
64      dmClass = dm;
65      dmClass.on('uiStateChange', (data: Record<string, string>) => {
66        console.log('uiStateChange executed, dialog closed' + JSON.stringify(data));
67        let tmpStr: Record<string, number> = JSON.parse(data.param);
68        let msg: number = tmpStr.uiStateMsg as number;
69        if (msg === MSG_DOING_AUTH) {
70          this.errorTips = $r('app.string.dm_authenticating');
71          return;
72        }
73        if (msg === MSG_CANCEL_PIN_CODE_INPUT) {
74          this.destruction();
75          return;
76        }
77        if (msg === MSG_PIN_CODE_ERROR) {
78          this.isTimes--;
79          this.errorTips = $r('app.plural.dm_incorrect_code', this.isTimes, this.isTimes);
80          this.input = '';
81          this.passwordCircle = ['', '', '', '', '', ''];
82          this.showToast();
83        }
84      });
85    });
86  }
87
88  aboutToDisappear() {
89    console.log(TAG + 'aboutToDisappear begin');
90    if (dmClass != null) {
91      try {
92        dmClass.off('uiStateChange');
93        dmClass.release();
94      } catch (error) {
95        console.log('dmClass release failed');
96      }
97      dmClass = null;
98    }
99  }
100
101  showToast() {
102    if (this.dialogController) {
103      this.dialogController.open();
104      setTimeout(() => {
105        this.dialogController.close();
106      }, TOAST_DURATION_TIME_MS);
107    }
108  }
109
110  onPageHide() {
111    console.log('onPageHide');
112    if (this.isUserOperate) {
113      console.log('user operate');
114      return;
115    }
116    this.cancel();
117  }
118
119  destruction() {
120    console.log(TAG + 'destruction begin');
121    let session = AppStorage.get<UIExtensionContentSession>('inputSession');
122    if (session) {
123      session.terminateSelf();
124    }
125  }
126
127  setUserOperation(operation: number, extra: string) {
128    console.log('setUserOperation: ' + operation);
129    if (dmClass === null) {
130      console.log('setUserOperation: ' + 'dmClass null');
131      return;
132    }
133    try {
134      this.isUserOperate = true;
135      dmClass.setUserOperation(operation, extra);
136    } catch (error) {
137      console.log('dmClass setUserOperation failed');
138    }
139  }
140
141  cancel() {
142    console.log('cancle');
143    if (dmClass) {
144      console.log('deviceManager exist');
145    } else {
146      console.log('createDeviceManager is null');
147      return;
148    }
149    console.log('cancle' + ACTION_CANCEL_PINCODE_INPUT);
150    this.setUserOperation(ACTION_CANCEL_PINCODE_INPUT, 'extra');
151    this.destruction();
152  }
153
154  confirm() {
155    console.log('confirm');
156    if (this.input === null || this.input === '') {
157      return;
158    }
159    if (dmClass) {
160      console.log('deviceManager exist');
161    } else {
162      console.log('createDeviceManager is null');
163      return;
164    }
165    console.log('confirm' + JSON.stringify(ACTION_DONE_PINCODE_INPUT));
166    this.setUserOperation(ACTION_DONE_PINCODE_INPUT, this.input);
167  }
168
169  build() {
170    Column() {
171      this.titleBuilder();
172      this.keyboardMocker();
173    }
174    .backgroundColor(Color.Black)
175    .height('100%')
176    .width('100%')
177  }
178
179  @Builder
180  keyBuilder(key: string) {
181    GridItem() {
182      Button(key)
183        .backgroundColor(BUTTON_BG_COLOR)
184        .fontColor('#FFFFFF')
185        .fontSize($r('sys.float.ohos_id_text_size_headline6'))
186        .onClick(() => {
187          if (this.input.length >= MAX_PINCODE_LENGTH) {
188            return;
189          }
190          this.input += key.toString();
191        })
192        .size({ width: 60, height: 48 })
193        .margin({ left: 3, top: 2 })
194        .visibility(key === '' ? Visibility.None : Visibility.Visible)
195    }
196  }
197
198  @Builder
199  processKey(key: string) {
200    if (key === 'x') {
201      this.SymbolDelete();
202    } else {
203      this.keyBuilder(key);
204    }
205  }
206
207  @Builder
208  keyboardMocker() {
209    Grid() {
210      ForEach(this.keyboards, (keysArr: string[]) => {
211        ForEach(keysArr, (key: string) => {
212          this.processKey(key);
213        })
214      })
215    }
216    .width(189)
217    .height(200)
218    .margin({ top: 2 })
219  }
220
221  @Builder
222  SymbolDelete() {
223    SymbolGlyph($r('sys.symbol.delete_left_fill'))
224      .fontSize('28vp')
225      .renderingStrategy(SymbolRenderingStrategy.MULTIPLE_OPACITY)
226      .fontColor(['#FFFFFF'])
227      .margin({ left: 10, top: 5 })
228      .onClick(() => {
229        this.input = this.input.slice(0, -1);
230      })
231      .visibility(this.isUserInput ? Visibility.Visible : Visibility.None)
232  }
233
234  @Builder
235  PinCode() {
236    Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
237      ForEach(this.passwordCircle, (item:string) => {
238        Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
239          Text(item)
240            .fontSize($r('sys.float.ohos_id_text_size_sub_title2'))
241            .fontColor('#FFFFFF')
242            .fontWeight(FontWeight.Medium)
243        }.width('7%')
244        .visibility(item === '' ? Visibility.None : Visibility.Visible)
245      })
246      ForEach(this.passwordCircle, (item: string) => {
247        Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
248          Column()
249            .width(9)
250            .height(9)
251            .border({ width: 1, color: '#FFFFFF', radius: 9})
252            .alignItems(HorizontalAlign.Center)
253        }.width('7%')
254        .visibility(item === '' ? Visibility.Visible : Visibility.None)
255      })
256    }
257  }
258
259  @Builder
260  titleBuilder() {
261    Text($r('app.string.dm_enter_peer_connect_code'))
262      .fontColor('#FFFFFF')
263      .fontSize($r('sys.float.ohos_id_text_size_body2'))
264      .margin({ top: 10 })
265      .textOverflow({ overflow: TextOverflow.MARQUEE })
266      .visibility(this.isUserInput ? Visibility.None : Visibility.Visible)
267      .height(19)
268    Stack() {
269      List() {
270        ListItem() {
271          this.PinCode();
272        }
273      }
274    }
275    .visibility(this.isUserInput ? Visibility.Visible : Visibility.None)
276    .margin({ top: 9 })
277    .height(20)
278  }
279
280  onChangeInput(changedPropertyName: string) {
281    let length = this.input.length;
282    for (let i = 0; i < MAX_PINCODE_LENGTH; ++i) {
283      if (i < length) {
284        this.passwordCircle[i] = this.input[i];
285      } else {
286        this.passwordCircle[i] = '';
287      }
288    }
289    if (length === MAX_PINCODE_LENGTH) {
290      setTimeout(() => {
291        this.setUserOperation(ACTION_DONE_PINCODE_INPUT, this.input);
292      }, 50);
293    }
294    this.isUserInput = true;
295  }
296}
297
298@CustomDialog
299struct errTips {
300  controller?: CustomDialogController;
301  @Link attemptTimes: number;
302  @Link errTips: Resource;
303  build() {
304    Column() {
305      Text(this.errTips)
306        .fontSize(15)
307        .fontColor('#FFFFFF')
308        .textAlign(TextAlign.Center)
309        .backgroundColor('#F2404040')
310    }
311    .justifyContent(FlexAlign.Center)
312    .width(205)
313    .padding({left: 12, right: 12, top: 10, bottom: 10 })
314    .backgroundColor('#F2404040')
315    .borderRadius(19)
316  }
317}