| 
									
										
										
										
											2022-04-26 21:21:08 +08:00
										 |  |  | import 'dart:async'; | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  | import 'dart:convert'; | 
					
						
							| 
									
										
										
										
											2022-03-07 22:54:34 +08:00
										 |  |  | import 'package:flutter/material.dart'; | 
					
						
							| 
									
										
										
										
											2023-01-12 21:03:05 +08:00
										 |  |  | import 'package:get/get.dart'; | 
					
						
							| 
									
										
										
										
											2022-06-13 21:07:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-24 23:33:00 +08:00
										 |  |  | import '../../common.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-15 19:31:58 +08:00
										 |  |  | import '../../models/model.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-08 22:27:27 +08:00
										 |  |  | import '../../models/platform_model.dart'; | 
					
						
							| 
									
										
										
										
											2022-03-07 22:54:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-15 16:49:55 +08:00
										 |  |  | void clientClose(String id, OverlayDialogManager dialogManager) { | 
					
						
							| 
									
										
										
										
											2023-01-30 17:56:35 +08:00
										 |  |  |   msgBox(id, 'info', 'Close', 'Are you sure to close the connection?', '', | 
					
						
							| 
									
										
										
										
											2022-11-15 16:49:55 +08:00
										 |  |  |       dialogManager); | 
					
						
							| 
									
										
										
										
											2022-03-07 22:54:34 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-15 14:39:31 +08:00
										 |  |  | void showSuccess() { | 
					
						
							|  |  |  |   showToast(translate("Successful")); | 
					
						
							| 
									
										
										
										
											2022-03-30 23:09:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-15 14:39:31 +08:00
										 |  |  | void showError() { | 
					
						
							|  |  |  |   showToast(translate("Error")); | 
					
						
							| 
									
										
										
										
											2022-03-30 23:09:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-15 19:31:58 +08:00
										 |  |  | void showRestartRemoteDevice( | 
					
						
							|  |  |  |     PeerInfo pi, String id, OverlayDialogManager dialogManager) async { | 
					
						
							|  |  |  |   final res = | 
					
						
							|  |  |  |       await dialogManager.show<bool>((setState, close) => CustomAlertDialog( | 
					
						
							|  |  |  |             title: Row(children: [ | 
					
						
							| 
									
										
										
										
											2023-02-28 15:57:25 +01:00
										 |  |  |               Icon(Icons.warning_rounded, color: Colors.redAccent, size: 28), | 
					
						
							|  |  |  |               Text(translate("Restart Remote Device")).paddingOnly(left: 10), | 
					
						
							| 
									
										
										
										
											2022-08-15 19:31:58 +08:00
										 |  |  |             ]), | 
					
						
							| 
									
										
										
										
											2023-03-01 14:50:50 +01:00
										 |  |  |             content: Text( | 
					
						
							|  |  |  |                 "${translate('Are you sure you want to restart')} \n${pi.username}@${pi.hostname}($id) ?"), | 
					
						
							|  |  |  |             actions: [ | 
					
						
							|  |  |  |               dialogButton( | 
					
						
							|  |  |  |                 "Cancel", | 
					
						
							|  |  |  |                 icon: Icon(Icons.close_rounded), | 
					
						
							|  |  |  |                 onPressed: close, | 
					
						
							|  |  |  |                 isOutline: true, | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |               dialogButton( | 
					
						
							|  |  |  |                 "OK", | 
					
						
							|  |  |  |                 icon: Icon(Icons.done_rounded), | 
					
						
							|  |  |  |                 onPressed: () => close(true), | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |             ], | 
					
						
							| 
									
										
										
										
											2023-01-30 17:56:35 +08:00
										 |  |  |             onCancel: close, | 
					
						
							|  |  |  |             onSubmit: () => close(true), | 
					
						
							| 
									
										
										
										
											2022-08-15 19:31:58 +08:00
										 |  |  |           )); | 
					
						
							|  |  |  |   if (res == true) bind.sessionRestartRemoteDevice(id: id); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  | void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async { | 
					
						
							| 
									
										
										
										
											2022-08-08 22:27:27 +08:00
										 |  |  |   final pw = await bind.mainGetPermanentPassword(); | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  |   final p0 = TextEditingController(text: pw); | 
					
						
							|  |  |  |   final p1 = TextEditingController(text: pw); | 
					
						
							| 
									
										
										
										
											2022-03-30 23:09:19 +08:00
										 |  |  |   var validateLength = false; | 
					
						
							|  |  |  |   var validateSame = false; | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  |   dialogManager.show((setState, close) { | 
					
						
							| 
									
										
										
										
											2023-01-30 17:56:35 +08:00
										 |  |  |     submit() async { | 
					
						
							|  |  |  |       close(); | 
					
						
							|  |  |  |       dialogManager.showLoading(translate("Waiting")); | 
					
						
							|  |  |  |       if (await gFFI.serverModel.setPermanentPassword(p0.text)) { | 
					
						
							|  |  |  |         dialogManager.dismissAll(); | 
					
						
							|  |  |  |         showSuccess(); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         dialogManager.dismissAll(); | 
					
						
							|  |  |  |         showError(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 23:09:19 +08:00
										 |  |  |     return CustomAlertDialog( | 
					
						
							| 
									
										
										
										
											2023-02-28 16:36:44 +01:00
										 |  |  |       title: Column( | 
					
						
							|  |  |  |         mainAxisAlignment: MainAxisAlignment.center, | 
					
						
							|  |  |  |         children: [ | 
					
						
							|  |  |  |           Icon(Icons.password_rounded, color: MyTheme.accent), | 
					
						
							|  |  |  |           Text(translate('Set your own password')).paddingOnly(left: 10), | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       ), | 
					
						
							| 
									
										
										
										
											2023-03-01 14:50:50 +01:00
										 |  |  |       content: Form( | 
					
						
							|  |  |  |           autovalidateMode: AutovalidateMode.onUserInteraction, | 
					
						
							|  |  |  |           child: Column(mainAxisSize: MainAxisSize.min, children: [ | 
					
						
							|  |  |  |             TextFormField( | 
					
						
							|  |  |  |               autofocus: true, | 
					
						
							|  |  |  |               obscureText: true, | 
					
						
							|  |  |  |               keyboardType: TextInputType.visiblePassword, | 
					
						
							|  |  |  |               decoration: InputDecoration( | 
					
						
							|  |  |  |                 labelText: translate('Password'), | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |               controller: p0, | 
					
						
							|  |  |  |               validator: (v) { | 
					
						
							|  |  |  |                 if (v == null) return null; | 
					
						
							|  |  |  |                 final val = v.trim().length > 5; | 
					
						
							|  |  |  |                 if (validateLength != val) { | 
					
						
							|  |  |  |                   // use delay to make setState success
 | 
					
						
							|  |  |  |                   Future.delayed(Duration(microseconds: 1), | 
					
						
							|  |  |  |                       () => setState(() => validateLength = val)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return val | 
					
						
							|  |  |  |                     ? null | 
					
						
							|  |  |  |                     : translate('Too short, at least 6 characters.'); | 
					
						
							|  |  |  |               }, | 
					
						
							| 
									
										
										
										
											2022-03-30 23:09:19 +08:00
										 |  |  |             ), | 
					
						
							| 
									
										
										
										
											2023-03-01 14:50:50 +01:00
										 |  |  |             TextFormField( | 
					
						
							|  |  |  |               obscureText: true, | 
					
						
							|  |  |  |               keyboardType: TextInputType.visiblePassword, | 
					
						
							|  |  |  |               decoration: InputDecoration( | 
					
						
							|  |  |  |                 labelText: translate('Confirmation'), | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |               controller: p1, | 
					
						
							|  |  |  |               validator: (v) { | 
					
						
							|  |  |  |                 if (v == null) return null; | 
					
						
							|  |  |  |                 final val = p0.text == v; | 
					
						
							|  |  |  |                 if (validateSame != val) { | 
					
						
							|  |  |  |                   Future.delayed(Duration(microseconds: 1), | 
					
						
							|  |  |  |                       () => setState(() => validateSame = val)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return val | 
					
						
							|  |  |  |                     ? null | 
					
						
							|  |  |  |                     : translate('The confirmation is not identical.'); | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |           ])), | 
					
						
							| 
									
										
										
										
											2023-01-30 17:56:35 +08:00
										 |  |  |       onCancel: close, | 
					
						
							|  |  |  |       onSubmit: (validateLength && validateSame) ? submit : null, | 
					
						
							| 
									
										
										
										
											2023-03-01 14:50:50 +01:00
										 |  |  |       actions: [ | 
					
						
							|  |  |  |         dialogButton( | 
					
						
							|  |  |  |           'Cancel', | 
					
						
							|  |  |  |           icon: Icon(Icons.close_rounded), | 
					
						
							|  |  |  |           onPressed: close, | 
					
						
							|  |  |  |           isOutline: true, | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         dialogButton( | 
					
						
							|  |  |  |           'OK', | 
					
						
							|  |  |  |           icon: Icon(Icons.done_rounded), | 
					
						
							|  |  |  |           onPressed: (validateLength && validateSame) ? submit : null, | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |       ], | 
					
						
							| 
									
										
										
										
											2022-03-30 23:09:19 +08:00
										 |  |  |     ); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  | void setTemporaryPasswordLengthDialog( | 
					
						
							|  |  |  |     OverlayDialogManager dialogManager) async { | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  |   List<String> lengths = ['6', '8', '10']; | 
					
						
							| 
									
										
										
										
											2022-08-08 22:27:27 +08:00
										 |  |  |   String length = await bind.mainGetOption(key: "temporary-password-length"); | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  |   var index = lengths.indexOf(length); | 
					
						
							|  |  |  |   if (index < 0) index = 0; | 
					
						
							|  |  |  |   length = lengths[index]; | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  |   dialogManager.show((setState, close) { | 
					
						
							| 
									
										
										
										
											2022-09-22 17:38:18 +08:00
										 |  |  |     setLength(newValue) { | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  |       final oldValue = length; | 
					
						
							|  |  |  |       if (oldValue == newValue) return; | 
					
						
							|  |  |  |       setState(() { | 
					
						
							|  |  |  |         length = newValue; | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2022-08-08 22:27:27 +08:00
										 |  |  |       bind.mainSetOption(key: "temporary-password-length", value: newValue); | 
					
						
							|  |  |  |       bind.mainUpdateTemporaryPassword(); | 
					
						
							| 
									
										
										
										
											2022-07-29 22:07:45 +08:00
										 |  |  |       Future.delayed(Duration(milliseconds: 200), () { | 
					
						
							|  |  |  |         close(); | 
					
						
							|  |  |  |         showSuccess(); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2022-09-22 17:38:18 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  |     return CustomAlertDialog( | 
					
						
							|  |  |  |       title: Text(translate("Set temporary password length")), | 
					
						
							|  |  |  |       content: Column( | 
					
						
							|  |  |  |           mainAxisSize: MainAxisSize.min, | 
					
						
							|  |  |  |           children: | 
					
						
							|  |  |  |               lengths.map((e) => getRadio(e, e, length, setLength)).toList()), | 
					
						
							|  |  |  |       actions: [], | 
					
						
							|  |  |  |       contentPadding: 14, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   }, backDismiss: true, clickMaskDismiss: true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  | void enterPasswordDialog(String id, OverlayDialogManager dialogManager) async { | 
					
						
							| 
									
										
										
										
											2022-03-07 22:54:34 +08:00
										 |  |  |   final controller = TextEditingController(); | 
					
						
							| 
									
										
										
										
											2022-08-16 15:22:57 +08:00
										 |  |  |   var remember = await bind.sessionGetRemember(id: id) ?? false; | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  |   dialogManager.dismissAll(); | 
					
						
							|  |  |  |   dialogManager.show((setState, close) { | 
					
						
							| 
									
										
										
										
											2022-09-29 10:48:27 +08:00
										 |  |  |     cancel() { | 
					
						
							|  |  |  |       close(); | 
					
						
							|  |  |  |       closeConnection(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     submit() { | 
					
						
							|  |  |  |       var text = controller.text.trim(); | 
					
						
							|  |  |  |       if (text == '') return; | 
					
						
							|  |  |  |       gFFI.login(id, text, remember); | 
					
						
							|  |  |  |       close(); | 
					
						
							|  |  |  |       dialogManager.showLoading(translate('Logging in...'), | 
					
						
							|  |  |  |           onCancel: closeConnection); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |     return CustomAlertDialog( | 
					
						
							| 
									
										
										
										
											2023-02-28 16:36:44 +01:00
										 |  |  |       title: Row( | 
					
						
							|  |  |  |         mainAxisAlignment: MainAxisAlignment.center, | 
					
						
							|  |  |  |         children: [ | 
					
						
							|  |  |  |           Icon(Icons.password_rounded, color: MyTheme.accent), | 
					
						
							|  |  |  |           Text(translate('Password Required')).paddingOnly(left: 10), | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       ), | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |       content: Column(mainAxisSize: MainAxisSize.min, children: [ | 
					
						
							|  |  |  |         PasswordWidget(controller: controller), | 
					
						
							|  |  |  |         CheckboxListTile( | 
					
						
							|  |  |  |           contentPadding: const EdgeInsets.all(0), | 
					
						
							|  |  |  |           dense: true, | 
					
						
							|  |  |  |           controlAffinity: ListTileControlAffinity.leading, | 
					
						
							|  |  |  |           title: Text( | 
					
						
							|  |  |  |             translate('Remember password'), | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |           value: remember, | 
					
						
							|  |  |  |           onChanged: (v) { | 
					
						
							|  |  |  |             if (v != null) { | 
					
						
							|  |  |  |               setState(() => remember = v); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, | 
					
						
							| 
									
										
										
										
											2022-03-07 22:54:34 +08:00
										 |  |  |         ), | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |       ]), | 
					
						
							| 
									
										
										
										
											2023-03-01 14:50:50 +01:00
										 |  |  |       actions: [ | 
					
						
							|  |  |  |         dialogButton( | 
					
						
							|  |  |  |           'Cancel', | 
					
						
							|  |  |  |           icon: Icon(Icons.close_rounded), | 
					
						
							|  |  |  |           onPressed: cancel, | 
					
						
							|  |  |  |           isOutline: true, | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         dialogButton( | 
					
						
							|  |  |  |           'OK', | 
					
						
							|  |  |  |           icon: Icon(Icons.done_rounded), | 
					
						
							|  |  |  |           onPressed: submit, | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |       ], | 
					
						
							| 
									
										
										
										
											2022-09-29 10:48:27 +08:00
										 |  |  |       onSubmit: submit, | 
					
						
							|  |  |  |       onCancel: cancel, | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |     ); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-30 17:56:35 +08:00
										 |  |  | void wrongPasswordDialog( | 
					
						
							|  |  |  |     String id, OverlayDialogManager dialogManager, type, title, text) { | 
					
						
							|  |  |  |   dialogManager.dismissAll(); | 
					
						
							|  |  |  |   dialogManager.show((setState, close) { | 
					
						
							|  |  |  |     cancel() { | 
					
						
							|  |  |  |       close(); | 
					
						
							|  |  |  |       closeConnection(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     submit() { | 
					
						
							|  |  |  |       enterPasswordDialog(id, dialogManager); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return CustomAlertDialog( | 
					
						
							|  |  |  |         title: null, | 
					
						
							|  |  |  |         content: msgboxContent(type, title, text), | 
					
						
							|  |  |  |         onSubmit: submit, | 
					
						
							|  |  |  |         onCancel: cancel, | 
					
						
							|  |  |  |         actions: [ | 
					
						
							|  |  |  |           dialogButton( | 
					
						
							|  |  |  |             'Cancel', | 
					
						
							|  |  |  |             onPressed: cancel, | 
					
						
							|  |  |  |             isOutline: true, | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |           dialogButton( | 
					
						
							|  |  |  |             'Retry', | 
					
						
							|  |  |  |             onPressed: submit, | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |         ]); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  | void showServerSettingsWithValue( | 
					
						
							|  |  |  |     ServerConfig serverConfig, OverlayDialogManager dialogManager) async { | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |   Map<String, dynamic> oldOptions = jsonDecode(await bind.mainGetOptions()); | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |   final oldCfg = ServerConfig.fromOptions(oldOptions); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |   var isInProgress = false; | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |   final idCtrl = TextEditingController(text: serverConfig.idServer); | 
					
						
							|  |  |  |   final relayCtrl = TextEditingController(text: serverConfig.relayServer); | 
					
						
							|  |  |  |   final apiCtrl = TextEditingController(text: serverConfig.apiServer); | 
					
						
							|  |  |  |   final keyCtrl = TextEditingController(text: serverConfig.key); | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |   String? idServerMsg; | 
					
						
							|  |  |  |   String? relayServerMsg; | 
					
						
							|  |  |  |   String? apiServerMsg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dialogManager.show((setState, close) { | 
					
						
							|  |  |  |     Future<bool> validate() async { | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |       if (idCtrl.text != oldCfg.idServer) { | 
					
						
							|  |  |  |         final res = await validateAsync(idCtrl.text); | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |         setState(() => idServerMsg = res); | 
					
						
							|  |  |  |         if (idServerMsg != null) return false; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |       if (relayCtrl.text != oldCfg.relayServer) { | 
					
						
							|  |  |  |         relayServerMsg = await validateAsync(relayCtrl.text); | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |         if (relayServerMsg != null) return false; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |       if (apiCtrl.text != oldCfg.apiServer) { | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |         if (apiServerMsg != null) return false; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return CustomAlertDialog( | 
					
						
							|  |  |  |       title: Text(translate('ID/Relay Server')), | 
					
						
							|  |  |  |       content: Form( | 
					
						
							|  |  |  |           child: Column( | 
					
						
							|  |  |  |               mainAxisSize: MainAxisSize.min, | 
					
						
							|  |  |  |               children: <Widget>[ | 
					
						
							|  |  |  |                     TextFormField( | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |                       controller: idCtrl, | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |                       decoration: InputDecoration( | 
					
						
							|  |  |  |                           labelText: translate('ID Server'), | 
					
						
							|  |  |  |                           errorText: idServerMsg), | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  |                   ] + | 
					
						
							|  |  |  |                   (isAndroid | 
					
						
							|  |  |  |                       ? [ | 
					
						
							|  |  |  |                           TextFormField( | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |                             controller: relayCtrl, | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |                             decoration: InputDecoration( | 
					
						
							|  |  |  |                                 labelText: translate('Relay Server'), | 
					
						
							|  |  |  |                                 errorText: relayServerMsg), | 
					
						
							|  |  |  |                           ) | 
					
						
							|  |  |  |                         ] | 
					
						
							|  |  |  |                       : []) + | 
					
						
							|  |  |  |                   [ | 
					
						
							|  |  |  |                     TextFormField( | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |                       controller: apiCtrl, | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |                       decoration: InputDecoration( | 
					
						
							|  |  |  |                         labelText: translate('API Server'), | 
					
						
							|  |  |  |                       ), | 
					
						
							|  |  |  |                       autovalidateMode: AutovalidateMode.onUserInteraction, | 
					
						
							|  |  |  |                       validator: (v) { | 
					
						
							|  |  |  |                         if (v != null && v.isNotEmpty) { | 
					
						
							|  |  |  |                           if (!(v.startsWith('http://') || | 
					
						
							|  |  |  |                               v.startsWith("https://"))) { | 
					
						
							|  |  |  |                             return translate("invalid_http"); | 
					
						
							|  |  |  |                           } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         return apiServerMsg; | 
					
						
							|  |  |  |                       }, | 
					
						
							|  |  |  |                     ), | 
					
						
							|  |  |  |                     TextFormField( | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |                       controller: keyCtrl, | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |                       decoration: InputDecoration( | 
					
						
							|  |  |  |                         labelText: 'Key', | 
					
						
							|  |  |  |                       ), | 
					
						
							|  |  |  |                     ), | 
					
						
							|  |  |  |                     Offstage( | 
					
						
							|  |  |  |                         offstage: !isInProgress, | 
					
						
							|  |  |  |                         child: LinearProgressIndicator()) | 
					
						
							|  |  |  |                   ])), | 
					
						
							|  |  |  |       actions: [ | 
					
						
							| 
									
										
										
										
											2023-01-15 19:46:16 +08:00
										 |  |  |         dialogButton('Cancel', onPressed: () { | 
					
						
							|  |  |  |           close(); | 
					
						
							|  |  |  |         }, isOutline: true), | 
					
						
							|  |  |  |         dialogButton( | 
					
						
							|  |  |  |           'OK', | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |           onPressed: () async { | 
					
						
							|  |  |  |             setState(() { | 
					
						
							|  |  |  |               idServerMsg = null; | 
					
						
							|  |  |  |               relayServerMsg = null; | 
					
						
							|  |  |  |               apiServerMsg = null; | 
					
						
							|  |  |  |               isInProgress = true; | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |             if (await validate()) { | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |               if (idCtrl.text != oldCfg.idServer) { | 
					
						
							|  |  |  |                 if (oldCfg.idServer.isNotEmpty) { | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |                   await gFFI.userModel.logOut(); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |                 bind.mainSetOption( | 
					
						
							|  |  |  |                     key: "custom-rendezvous-server", value: idCtrl.text); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               if (relayCtrl.text != oldCfg.relayServer) { | 
					
						
							|  |  |  |                 bind.mainSetOption(key: "relay-server", value: relayCtrl.text); | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |               } | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |               if (keyCtrl.text != oldCfg.key) { | 
					
						
							|  |  |  |                 bind.mainSetOption(key: "key", value: keyCtrl.text); | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |               } | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |               if (apiCtrl.text != oldCfg.apiServer) { | 
					
						
							|  |  |  |                 bind.mainSetOption(key: "api-server", value: apiCtrl.text); | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |               } | 
					
						
							|  |  |  |               close(); | 
					
						
							| 
									
										
										
										
											2022-12-26 10:12:01 +09:00
										 |  |  |               showToast(translate('Successful')); | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |             } | 
					
						
							|  |  |  |             setState(() { | 
					
						
							|  |  |  |               isInProgress = false; | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |       ], | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-30 17:56:35 +08:00
										 |  |  | void showWaitUacDialog( | 
					
						
							|  |  |  |     String id, OverlayDialogManager dialogManager, String type) { | 
					
						
							| 
									
										
										
										
											2023-01-12 21:03:05 +08:00
										 |  |  |   dialogManager.dismissAll(); | 
					
						
							|  |  |  |   dialogManager.show( | 
					
						
							|  |  |  |       tag: '$id-wait-uac', | 
					
						
							|  |  |  |       (setState, close) => CustomAlertDialog( | 
					
						
							| 
									
										
										
										
											2023-01-30 17:56:35 +08:00
										 |  |  |             title: null, | 
					
						
							| 
									
										
										
										
											2023-02-05 16:56:13 +08:00
										 |  |  |             content: msgboxContent(type, 'Wait', 'wait_accept_uac_tip'), | 
					
						
							| 
									
										
										
										
											2023-01-12 21:03:05 +08:00
										 |  |  |           )); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-24 15:51:13 +08:00
										 |  |  | void showRequestElevationDialog(String id, OverlayDialogManager dialogManager) { | 
					
						
							| 
									
										
										
										
											2023-01-12 21:03:05 +08:00
										 |  |  |   RxString groupValue = ''.obs; | 
					
						
							|  |  |  |   RxString errUser = ''.obs; | 
					
						
							|  |  |  |   RxString errPwd = ''.obs; | 
					
						
							|  |  |  |   TextEditingController userController = TextEditingController(); | 
					
						
							|  |  |  |   TextEditingController pwdController = TextEditingController(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void onRadioChanged(String? value) { | 
					
						
							|  |  |  |     if (value != null) { | 
					
						
							|  |  |  |       groupValue.value = value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const minTextStyle = TextStyle(fontSize: 14); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var content = Obx(() => Column(children: [ | 
					
						
							|  |  |  |         Row( | 
					
						
							|  |  |  |           children: [ | 
					
						
							|  |  |  |             Radio( | 
					
						
							|  |  |  |                 value: '', | 
					
						
							|  |  |  |                 groupValue: groupValue.value, | 
					
						
							|  |  |  |                 onChanged: onRadioChanged), | 
					
						
							|  |  |  |             Expanded( | 
					
						
							|  |  |  |                 child: | 
					
						
							|  |  |  |                     Text(translate('Ask the remote user for authentication'))), | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         Align( | 
					
						
							|  |  |  |           alignment: Alignment.centerLeft, | 
					
						
							|  |  |  |           child: Text( | 
					
						
							|  |  |  |                   translate( | 
					
						
							|  |  |  |                       'Choose this if the remote account is administrator'), | 
					
						
							|  |  |  |                   style: TextStyle(fontSize: 13)) | 
					
						
							|  |  |  |               .marginOnly(left: 40), | 
					
						
							|  |  |  |         ).marginOnly(bottom: 15), | 
					
						
							|  |  |  |         Row( | 
					
						
							|  |  |  |           children: [ | 
					
						
							|  |  |  |             Radio( | 
					
						
							|  |  |  |                 value: 'logon', | 
					
						
							|  |  |  |                 groupValue: groupValue.value, | 
					
						
							|  |  |  |                 onChanged: onRadioChanged), | 
					
						
							|  |  |  |             Expanded( | 
					
						
							|  |  |  |               child: Text(translate( | 
					
						
							|  |  |  |                   'Transmit the username and password of administrator')), | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         Row( | 
					
						
							|  |  |  |           children: [ | 
					
						
							|  |  |  |             Expanded( | 
					
						
							|  |  |  |                 flex: 1, | 
					
						
							|  |  |  |                 child: Text( | 
					
						
							|  |  |  |                   '${translate('Username')}:', | 
					
						
							|  |  |  |                   style: minTextStyle, | 
					
						
							|  |  |  |                 ).marginOnly(right: 10)), | 
					
						
							|  |  |  |             Expanded( | 
					
						
							|  |  |  |               flex: 3, | 
					
						
							|  |  |  |               child: TextField( | 
					
						
							|  |  |  |                 controller: userController, | 
					
						
							|  |  |  |                 style: minTextStyle, | 
					
						
							|  |  |  |                 decoration: InputDecoration( | 
					
						
							|  |  |  |                     isDense: true, | 
					
						
							|  |  |  |                     contentPadding: EdgeInsets.symmetric(vertical: 15), | 
					
						
							|  |  |  |                     hintText: 'eg: admin', | 
					
						
							|  |  |  |                     errorText: errUser.isEmpty ? null : errUser.value), | 
					
						
							|  |  |  |                 onChanged: (s) { | 
					
						
							|  |  |  |                   if (s.isNotEmpty) { | 
					
						
							|  |  |  |                     errUser.value = ''; | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |         ).marginOnly(left: 40), | 
					
						
							|  |  |  |         Row( | 
					
						
							|  |  |  |           children: [ | 
					
						
							|  |  |  |             Expanded( | 
					
						
							|  |  |  |                 flex: 1, | 
					
						
							|  |  |  |                 child: Text( | 
					
						
							|  |  |  |                   '${translate('Password')}:', | 
					
						
							|  |  |  |                   style: minTextStyle, | 
					
						
							|  |  |  |                 ).marginOnly(right: 10)), | 
					
						
							|  |  |  |             Expanded( | 
					
						
							|  |  |  |               flex: 3, | 
					
						
							|  |  |  |               child: TextField( | 
					
						
							|  |  |  |                 controller: pwdController, | 
					
						
							|  |  |  |                 obscureText: true, | 
					
						
							|  |  |  |                 style: minTextStyle, | 
					
						
							|  |  |  |                 decoration: InputDecoration( | 
					
						
							|  |  |  |                     isDense: true, | 
					
						
							|  |  |  |                     contentPadding: EdgeInsets.symmetric(vertical: 15), | 
					
						
							|  |  |  |                     errorText: errPwd.isEmpty ? null : errPwd.value), | 
					
						
							|  |  |  |                 onChanged: (s) { | 
					
						
							|  |  |  |                   if (s.isNotEmpty) { | 
					
						
							|  |  |  |                     errPwd.value = ''; | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |         ).marginOnly(left: 40), | 
					
						
							|  |  |  |         Align( | 
					
						
							|  |  |  |             alignment: Alignment.centerLeft, | 
					
						
							|  |  |  |             child: Text(translate('still_click_uac_tip'), | 
					
						
							|  |  |  |                     style: TextStyle(fontSize: 13, fontWeight: FontWeight.bold)) | 
					
						
							|  |  |  |                 .marginOnly(top: 20)), | 
					
						
							|  |  |  |       ])); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dialogManager.dismissAll(); | 
					
						
							|  |  |  |   dialogManager.show(tag: '$id-request-elevation', (setState, close) { | 
					
						
							|  |  |  |     void submit() { | 
					
						
							|  |  |  |       if (groupValue.value == 'logon') { | 
					
						
							|  |  |  |         if (userController.text.isEmpty) { | 
					
						
							|  |  |  |           errUser.value = translate('Empty Username'); | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (pwdController.text.isEmpty) { | 
					
						
							|  |  |  |           errPwd.value = translate('Empty Password'); | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         bind.sessionElevateWithLogon( | 
					
						
							|  |  |  |             id: id, | 
					
						
							|  |  |  |             username: userController.text, | 
					
						
							|  |  |  |             password: pwdController.text); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         bind.sessionElevateDirect(id: id); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return CustomAlertDialog( | 
					
						
							|  |  |  |       title: Text(translate('Request Elevation')), | 
					
						
							|  |  |  |       content: content, | 
					
						
							|  |  |  |       actions: [ | 
					
						
							| 
									
										
										
										
											2023-01-15 19:46:16 +08:00
										 |  |  |         dialogButton('Cancel', onPressed: close, isOutline: true), | 
					
						
							|  |  |  |         dialogButton('OK', onPressed: submit), | 
					
						
							| 
									
										
										
										
											2023-01-12 21:03:05 +08:00
										 |  |  |       ], | 
					
						
							|  |  |  |       onSubmit: submit, | 
					
						
							|  |  |  |       onCancel: close, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void showOnBlockDialog( | 
					
						
							|  |  |  |   String id, | 
					
						
							|  |  |  |   String type, | 
					
						
							|  |  |  |   String title, | 
					
						
							|  |  |  |   String text, | 
					
						
							|  |  |  |   OverlayDialogManager dialogManager, | 
					
						
							|  |  |  | ) { | 
					
						
							|  |  |  |   if (dialogManager.existing('$id-wait-uac') || | 
					
						
							|  |  |  |       dialogManager.existing('$id-request-elevation')) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   dialogManager.show(tag: '$id-$type', (setState, close) { | 
					
						
							|  |  |  |     void submit() { | 
					
						
							|  |  |  |       close(); | 
					
						
							| 
									
										
										
										
											2023-02-24 15:51:13 +08:00
										 |  |  |       showRequestElevationDialog(id, dialogManager); | 
					
						
							| 
									
										
										
										
											2023-01-12 21:03:05 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return CustomAlertDialog( | 
					
						
							| 
									
										
										
										
											2023-01-30 17:56:35 +08:00
										 |  |  |       title: null, | 
					
						
							|  |  |  |       content: msgboxContent(type, title, | 
					
						
							|  |  |  |           "${translate(text)}${type.contains('uac') ? '\n' : '\n\n'}${translate('request_elevation_tip')}"), | 
					
						
							| 
									
										
										
										
											2023-01-12 21:03:05 +08:00
										 |  |  |       actions: [ | 
					
						
							| 
									
										
										
										
											2023-01-30 17:56:35 +08:00
										 |  |  |         dialogButton('Wait', onPressed: close, isOutline: true), | 
					
						
							| 
									
										
										
										
											2023-01-15 19:46:16 +08:00
										 |  |  |         dialogButton('Request Elevation', onPressed: submit), | 
					
						
							| 
									
										
										
										
											2023-01-12 21:03:05 +08:00
										 |  |  |       ], | 
					
						
							|  |  |  |       onSubmit: submit, | 
					
						
							|  |  |  |       onCancel: close, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void showElevationError(String id, String type, String title, String text, | 
					
						
							|  |  |  |     OverlayDialogManager dialogManager) { | 
					
						
							|  |  |  |   dialogManager.show(tag: '$id-$type', (setState, close) { | 
					
						
							|  |  |  |     void submit() { | 
					
						
							|  |  |  |       close(); | 
					
						
							| 
									
										
										
										
											2023-02-24 15:51:13 +08:00
										 |  |  |       showRequestElevationDialog(id, dialogManager); | 
					
						
							| 
									
										
										
										
											2023-01-12 21:03:05 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return CustomAlertDialog( | 
					
						
							| 
									
										
										
										
											2023-01-30 17:56:35 +08:00
										 |  |  |       title: null, | 
					
						
							|  |  |  |       content: msgboxContent(type, title, text), | 
					
						
							| 
									
										
										
										
											2023-01-12 21:03:05 +08:00
										 |  |  |       actions: [ | 
					
						
							| 
									
										
										
										
											2023-01-15 19:46:16 +08:00
										 |  |  |         dialogButton('Cancel', onPressed: () { | 
					
						
							|  |  |  |           close(); | 
					
						
							|  |  |  |         }, isOutline: true), | 
					
						
							|  |  |  |         dialogButton('Retry', onPressed: submit), | 
					
						
							| 
									
										
										
										
											2023-01-12 21:03:05 +08:00
										 |  |  |       ], | 
					
						
							|  |  |  |       onSubmit: submit, | 
					
						
							|  |  |  |       onCancel: close, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-30 17:56:35 +08:00
										 |  |  | void showWaitAcceptDialog(String id, String type, String title, String text, | 
					
						
							|  |  |  |     OverlayDialogManager dialogManager) { | 
					
						
							|  |  |  |   dialogManager.dismissAll(); | 
					
						
							|  |  |  |   dialogManager.show((setState, close) { | 
					
						
							|  |  |  |     onCancel() { | 
					
						
							|  |  |  |       closeConnection(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return CustomAlertDialog( | 
					
						
							|  |  |  |       title: null, | 
					
						
							|  |  |  |       content: msgboxContent(type, title, text), | 
					
						
							|  |  |  |       actions: [ | 
					
						
							|  |  |  |         dialogButton('Cancel', onPressed: onCancel, isOutline: true), | 
					
						
							|  |  |  |       ], | 
					
						
							|  |  |  |       onCancel: onCancel, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  | Future<String?> validateAsync(String value) async { | 
					
						
							|  |  |  |   value = value.trim(); | 
					
						
							|  |  |  |   if (value.isEmpty) { | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   final res = await bind.mainTestIfValidServer(server: value); | 
					
						
							|  |  |  |   return res.isEmpty ? null : res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  | class PasswordWidget extends StatefulWidget { | 
					
						
							| 
									
										
										
										
											2022-09-22 17:38:18 +08:00
										 |  |  |   PasswordWidget({Key? key, required this.controller, this.autoFocus = true}) | 
					
						
							|  |  |  |       : super(key: key); | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   final TextEditingController controller; | 
					
						
							| 
									
										
										
										
											2022-09-22 17:38:18 +08:00
										 |  |  |   final bool autoFocus; | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							| 
									
										
										
										
											2022-09-22 17:38:18 +08:00
										 |  |  |   State<PasswordWidget> createState() => _PasswordWidgetState(); | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _PasswordWidgetState extends State<PasswordWidget> { | 
					
						
							|  |  |  |   bool _passwordVisible = false; | 
					
						
							| 
									
										
										
										
											2022-04-26 21:21:08 +08:00
										 |  |  |   final _focusNode = FocusNode(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void initState() { | 
					
						
							|  |  |  |     super.initState(); | 
					
						
							| 
									
										
										
										
											2022-09-22 17:38:18 +08:00
										 |  |  |     if (widget.autoFocus) { | 
					
						
							|  |  |  |       Timer(Duration(milliseconds: 50), () => _focusNode.requestFocus()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-26 21:21:08 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void dispose() { | 
					
						
							|  |  |  |     _focusNode.unfocus(); | 
					
						
							|  |  |  |     _focusNode.dispose(); | 
					
						
							|  |  |  |     super.dispose(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     return TextField( | 
					
						
							| 
									
										
										
										
											2022-04-26 21:21:08 +08:00
										 |  |  |       focusNode: _focusNode, | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |       controller: widget.controller, | 
					
						
							|  |  |  |       obscureText: !_passwordVisible, | 
					
						
							|  |  |  |       //This will obscure text dynamically
 | 
					
						
							|  |  |  |       keyboardType: TextInputType.visiblePassword, | 
					
						
							|  |  |  |       decoration: InputDecoration( | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  |         labelText: translate('Password'), | 
					
						
							|  |  |  |         hintText: translate('Enter your password'), | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |         // Here is key idea
 | 
					
						
							|  |  |  |         suffixIcon: IconButton( | 
					
						
							|  |  |  |           icon: Icon( | 
					
						
							| 
									
										
										
										
											2023-02-03 15:07:45 +08:00
										 |  |  |               // Based on passwordVisible state choose the icon
 | 
					
						
							|  |  |  |               _passwordVisible ? Icons.visibility : Icons.visibility_off, | 
					
						
							|  |  |  |               color: MyTheme.lightTheme.primaryColor), | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |           onPressed: () { | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |             // Update the state i.e. toggle the state of passwordVisible variable
 | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |             setState(() { | 
					
						
							|  |  |  |               _passwordVisible = !_passwordVisible; | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |