• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2025 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 { BusinessError } from '@ohos.base';
17import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession';
18import deviceInfo from '@ohos.deviceInfo';
19import display from '@ohos.display';
20import Constant from '../common/constant';
21import i18n from '@ohos.i18n';
22import { KeyCode } from '@ohos.multimodalInput.keyCode';
23
24let dmClass: deviceManager.DeviceManager | null;
25let TAG = '[DeviceManagerUI:PinDialog]==>';
26const ACTION_CANCEL_PINCODE_DISPLAY: number = 3;
27const MSG_CANCEL_PIN_CODE_SHOW: number = 2;
28
29@CustomDialog
30struct PinCustomDialog {
31  @State pinCode: string = '';
32  @State buttonWidth: number = 1;
33  @State buttonHeight: number = 1;
34  @State codeNum: number = 0;
35  @State pinCodeArr: Array<string> = [];
36  @State btnColor: ResourceColor = Color.Transparent;
37  @State isPC: boolean = false;
38  @State mLocalWidth: number = 0;
39  controller?: CustomDialogController
40
41  cancel() {
42    console.log(TAG + 'destruction()');
43    try {
44      console.log(TAG + 'pin dialog terminateSelf');
45      let session = AppStorage.get<UIExtensionContentSession>('pinSession');
46      if (session) {
47        session.terminateSelf();
48      }
49    } catch (err) {
50      console.log(TAG + 'dialog cancel failed: ' + JSON.stringify(err));
51    }
52  }
53
54  aboutToAppear() {
55    console.log(TAG + 'aboutToAppear execute PinCustomDialog');
56    try {
57      this.mLocalWidth = display.getDefaultDisplaySync().width;
58    } catch (err) {
59      console.error('Failed to get display width:', err);
60      this.mLocalWidth = 0;
61    }
62    this.isPC = Constant.isPC();
63    this.pinCode = AppStorage.get('pinCode') as string;
64    this.pinCodeArr = this.pinCode.split('');
65  }
66
67  setUserOperation(operation: number) {
68    console.log(TAG + 'setUserOperation: ' + operation);
69    if (dmClass == null) {
70      console.log(TAG + 'setUserOperation: ' + 'dmClass null');
71      return;
72    }
73    try {
74      dmClass.setUserOperation(operation, 'extra');
75    } catch (error) {
76      console.log(TAG + 'dmClass setUserOperation failed');
77    }
78  }
79
80  private isTibetanLanguages(): boolean {
81    console.info(`${TAG} isTibetanLanguages in`);
82    let locale = new Intl.Locale(i18n.System.getSystemLanguage()).toString();
83    console.info(`${TAG} isTibetanLanguages: ${locale}`);
84    return Constant.TIBETAN_LANGUAGES.includes(locale);
85  }
86
87  build() {
88    GridRow({
89      columns: { xs: 4, sm: 8, md: 24 },
90      gutter: { x: '4vp' },
91      breakpoints: { value: ['600vp', '840vp'] }
92    }) {
93      GridCol({ span: { xs: 4, sm: 4, md: 6 }, offset: { sm: 2, md: 9 } }) {
94        Column() {
95          Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
96            Text($r('app.string.dm_connect_code'))
97              .fontSize('20fp')
98              .fontColor('#E5FFFFFF')
99              .fontWeight(FontWeight.Medium)
100              .lineHeight(this.isTibetanLanguages() ? '32.5vp' : 0)
101              .margin({
102                left: '24vp',
103                right: '24vp'
104              })
105          }
106          .margin({ bottom: '24vp', top: '24vp' })
107
108          Row() {
109            Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
110              ForEach(this.pinCodeArr, (item: string, index: number) => {
111                Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
112                  Text(item)
113                    .fontSize('30fp')
114                    .fontColor('#E5FFFFFF')
115                    .fontWeight(FontWeight.Medium)
116                }.width('24vp')
117                .height('100%')
118                .margin(index === this.pinCodeArr.length - 1 ? {} : { right: '16vp' })
119              })
120            }
121            .height('40vp')
122            .accessibilityText('[n1]' + this.pinCode + '[n0]')
123          }
124          .margin({ bottom: '24vp' })
125
126          Flex({ justifyContent: FlexAlign.Center }) {
127            Button($r('app.string.dm_cancel'))
128              .fontSize('18vp')
129              .fontWeight(FontWeight.Medium)
130              .fontColor('#E5FFFFFF')
131              .width('100%')
132              .height('40vp')
133              .backgroundColor(this.btnColor)
134              .scale({x: this.buttonWidth, y: this.buttonHeight})
135              .border({
136                width: '0.5vp',
137                color: '#26ffffff'
138              })
139              .defaultFocus(true)
140              .onKeyEvent((event?: KeyEvent) => {
141                if (event && event?.keyCode === KeyCode.KEYCODE_HOME && event?.type === KeyType.Down) {
142                  console.log(TAG + 'onKeyEvent eventType: ' + event?.type)
143                  return;
144                }
145                if (event && event?.keyCode === KeyCode.KEYCODE_HOME && event?.type === KeyType.Up) {
146                  console.log(TAG + 'onKeyEvent eventType: ' + event?.type)
147                  if (this.controller) {
148                    this.controller.close();
149                  }
150                  this.cancel();
151                  this.setUserOperation(ACTION_CANCEL_PINCODE_DISPLAY);
152                }
153              })
154              .onClick(() => {
155                if (this.controller) {
156                  this.controller.close();
157                }
158                this.cancel();
159                this.setUserOperation(ACTION_CANCEL_PINCODE_DISPLAY);
160              })
161              .onHover((isHover?: boolean, event?: HoverEvent): void => {
162                if (isHover) {
163                  this.btnColor = '#F1F3F5';
164                  this.buttonWidth = 1.05;
165                  this.buttonHeight = 1.05;
166                } else {
167                  this.btnColor = '#33F1F3F5';
168                  this.buttonWidth = 1;
169                  this.buttonHeight = 1;
170                }
171              })
172              .stateStyles({
173                pressed: {
174                  .backgroundColor('#26FFFFFF')
175                },
176                focused: {
177                  .scale({x: 1.05, y: 1.05})
178                  .backgroundColor('#4DFFFFFF')
179                },
180                normal: {
181                  .backgroundColor('#33F1F3F5')
182                }
183              })
184          }.margin({
185            left: '24vp',
186            right: '24vp',
187            bottom: '24vp' })
188        }
189        .backgroundColor('#3C3C3C')
190        .borderRadius('16vp')
191        .border({
192          width: '0.5vp',
193          color: '#26ffffff',
194          radius: '16vp'
195        })
196        .width(px2vp(this.mLocalWidth) * 0.36)
197        .margin({ left: $r('sys.float.ohos_id_dialog_margin_start'), right: $r('sys.float.ohos_id_dialog_margin_end') })
198      }
199    }
200    .constraintSize({ maxHeight: '80%' })
201  }
202}
203
204@Entry
205@Component
206struct dialogPlusPage {
207  dialogController: CustomDialogController = new CustomDialogController({
208    builder: PinCustomDialog(),
209    cancel: this.onCancel,
210    autoCancel: false,
211    onWillDismiss: ()=>{
212      this.onWillDismiss()
213    },
214    alignment: DialogAlignment.Center,
215    customStyle: true,
216    maskColor: '#CC000000'
217  });
218
219  onCancel() {
220    this.destruction();
221  }
222
223  onWillDismiss() {
224    console.log(TAG + 'onWillDismiss: ' + ACTION_CANCEL_PINCODE_DISPLAY)
225    this.setUserOperation(ACTION_CANCEL_PINCODE_DISPLAY);
226    this.destruction();
227  }
228
229  aboutToAppear() {
230    this.initStatue();
231    console.log(TAG + 'aboutToAppear execute')
232  }
233
234  aboutToDisappear() {
235    console.log(TAG + 'aboutToDisappear executed')
236    if (dmClass != null) {
237      try {
238        dmClass.off('uiStateChange')
239        try {
240          dmClass.release();
241        } catch (err) {
242          let e: BusinessError = err as BusinessError;
243          console.error(TAG + 'release device manager errCode:' + e.code + ',errMessage:' + e.message);
244        }
245      } catch (error) {
246        console.log(TAG + 'dmClass release failed')
247      }
248      dmClass = null
249    }
250  }
251
252  initStatue() {
253    if (dmClass) {
254      console.log(TAG + 'deviceManager exist');
255      return;
256    }
257    deviceManager.createDeviceManager('com.ohos.devicemanagerui.pin',
258      (err: Error, dm: deviceManager.DeviceManager) => {
259        if (err) {
260          console.log('createDeviceManager err:' + JSON.stringify(err) + ' --fail:' + JSON.stringify(dm))
261          return
262        }
263        dmClass = dm
264        dmClass.on('uiStateChange', (data: Record<string, string>) => {
265          console.log('uiStateChange executed, dialog closed' + JSON.stringify(data))
266          let tmpStr: Record<string, number> = JSON.parse(data.param)
267          let msg: number = tmpStr.uiStateMsg as number
268          if (msg === MSG_CANCEL_PIN_CODE_SHOW) {
269            this.destruction()
270          }
271        })
272      });
273  }
274
275  setUserOperation(operation: number) {
276    console.log(TAG + 'setUserOperation: ' + operation)
277    if (dmClass == null) {
278      console.log(TAG + 'setUserOperation: ' + 'dmClass null')
279      return;
280    }
281    try {
282      dmClass.setUserOperation(operation, 'extra');
283    } catch (error) {
284      console.log(TAG + 'dmClass setUserOperation failed')
285    }
286  }
287
288  destruction() {
289    console.log(TAG + 'destruction()');
290    try {
291      console.log(TAG + 'pin dialog terminateSelf');
292      let session = AppStorage.get<UIExtensionContentSession>('pinSession');
293      if (session) {
294        session.terminateSelf();
295      }
296    } catch (err) {
297      console.log(TAG + 'dialog cancel failed: ' + JSON.stringify(err));
298    }
299  }
300
301  build() {
302    Column(this.dialogController.open())
303  }
304}