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}