| 
									
										
										
										
											2022-04-26 21:21:08 +08:00
										 |  |  | import 'dart:async'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-07 22:54:34 +08:00
										 |  |  | import 'package:flutter/material.dart'; | 
					
						
							| 
									
										
										
										
											2022-04-19 13:07:45 +08:00
										 |  |  | import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; | 
					
						
							| 
									
										
										
										
											2022-03-07 22:54:34 +08:00
										 |  |  | import '../common.dart'; | 
					
						
							|  |  |  | import '../models/model.dart'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void clientClose() { | 
					
						
							|  |  |  |   msgBox('', 'Close', 'Are you sure to close the connection?'); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 23:09:19 +08:00
										 |  |  | const SEC1 = Duration(seconds: 1); | 
					
						
							| 
									
										
										
										
											2022-04-19 13:07:45 +08:00
										 |  |  | void showSuccess({Duration duration = SEC1}) { | 
					
						
							|  |  |  |   SmartDialog.dismiss(); | 
					
						
							| 
									
										
										
										
											2022-04-26 21:21:08 +08:00
										 |  |  |   showToast(translate("Successful"), duration: SEC1); | 
					
						
							| 
									
										
										
										
											2022-03-30 23:09:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-26 21:21:08 +08:00
										 |  |  | void showError({Duration duration = SEC1}) { | 
					
						
							| 
									
										
										
										
											2022-04-19 13:07:45 +08:00
										 |  |  |   SmartDialog.dismiss(); | 
					
						
							| 
									
										
										
										
											2022-04-26 21:21:08 +08:00
										 |  |  |   showToast(translate("Error"), duration: SEC1); | 
					
						
							| 
									
										
										
										
											2022-03-30 23:09:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-26 21:21:08 +08:00
										 |  |  | void updatePasswordDialog() { | 
					
						
							| 
									
										
										
										
											2022-03-30 23:09:19 +08:00
										 |  |  |   final p0 = TextEditingController(); | 
					
						
							|  |  |  |   final p1 = TextEditingController(); | 
					
						
							|  |  |  |   var validateLength = false; | 
					
						
							|  |  |  |   var validateSame = false; | 
					
						
							|  |  |  |   DialogManager.show((setState, close) { | 
					
						
							|  |  |  |     return CustomAlertDialog( | 
					
						
							|  |  |  |       title: Text(translate('Set your own password')), | 
					
						
							|  |  |  |       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), | 
					
						
							| 
									
										
										
										
											2022-04-26 21:21:08 +08:00
										 |  |  |                       () => setState(() => validateLength = val)); | 
					
						
							| 
									
										
										
										
											2022-03-30 23:09:19 +08:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 return val | 
					
						
							|  |  |  |                     ? null | 
					
						
							|  |  |  |                     : translate('Too short, at least 6 characters.'); | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             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), | 
					
						
							| 
									
										
										
										
											2022-04-26 21:21:08 +08:00
										 |  |  |                       () => setState(() => validateSame = val)); | 
					
						
							| 
									
										
										
										
											2022-03-30 23:09:19 +08:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 return val | 
					
						
							|  |  |  |                     ? null | 
					
						
							|  |  |  |                     : translate('The confirmation is not identical.'); | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |           ])), | 
					
						
							|  |  |  |       actions: [ | 
					
						
							|  |  |  |         TextButton( | 
					
						
							|  |  |  |           style: flatButtonStyle, | 
					
						
							|  |  |  |           onPressed: () { | 
					
						
							|  |  |  |             close(); | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           child: Text(translate('Cancel')), | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         TextButton( | 
					
						
							|  |  |  |           style: flatButtonStyle, | 
					
						
							|  |  |  |           onPressed: (validateLength && validateSame) | 
					
						
							|  |  |  |               ? () async { | 
					
						
							| 
									
										
										
										
											2022-04-26 21:21:08 +08:00
										 |  |  |                   close(); | 
					
						
							|  |  |  |                   showLoading(translate("Waiting")); | 
					
						
							|  |  |  |                   if (await FFI.serverModel.updatePassword(p0.text)) { | 
					
						
							|  |  |  |                     showSuccess(); | 
					
						
							|  |  |  |                   } else { | 
					
						
							|  |  |  |                     showError(); | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-03-30 23:09:19 +08:00
										 |  |  |               : null, | 
					
						
							|  |  |  |           child: Text(translate('OK')), | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |       ], | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-07 22:54:34 +08:00
										 |  |  | void enterPasswordDialog(String id) { | 
					
						
							|  |  |  |   final controller = TextEditingController(); | 
					
						
							|  |  |  |   var remember = FFI.getByName('remember', id) == 'true'; | 
					
						
							| 
									
										
										
										
											2022-03-13 23:07:52 +08:00
										 |  |  |   DialogManager.show((setState, close) { | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |     return CustomAlertDialog( | 
					
						
							|  |  |  |       title: Text(translate('Password Required')), | 
					
						
							|  |  |  |       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
										 |  |  |       ]), | 
					
						
							|  |  |  |       actions: [ | 
					
						
							| 
									
										
										
										
											2022-03-07 22:54:34 +08:00
										 |  |  |         TextButton( | 
					
						
							|  |  |  |           style: flatButtonStyle, | 
					
						
							|  |  |  |           onPressed: () { | 
					
						
							| 
									
										
										
										
											2022-03-13 23:07:52 +08:00
										 |  |  |             close(); | 
					
						
							|  |  |  |             backToHome(); | 
					
						
							| 
									
										
										
										
											2022-03-07 22:54:34 +08:00
										 |  |  |           }, | 
					
						
							|  |  |  |           child: Text(translate('Cancel')), | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         TextButton( | 
					
						
							|  |  |  |           style: flatButtonStyle, | 
					
						
							|  |  |  |           onPressed: () { | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |             var text = controller.text.trim(); | 
					
						
							|  |  |  |             if (text == '') return; | 
					
						
							|  |  |  |             FFI.login(text, remember); | 
					
						
							| 
									
										
										
										
											2022-03-13 23:07:52 +08:00
										 |  |  |             close(); | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |             showLoading(translate('Logging in...')); | 
					
						
							| 
									
										
										
										
											2022-03-07 22:54:34 +08:00
										 |  |  |           }, | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |           child: Text(translate('OK')), | 
					
						
							| 
									
										
										
										
											2022-03-07 22:54:34 +08:00
										 |  |  |         ), | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |       ], | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void wrongPasswordDialog(String id) { | 
					
						
							| 
									
										
										
										
											2022-03-13 23:07:52 +08:00
										 |  |  |   DialogManager.show((setState, close) => CustomAlertDialog( | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |           title: Text(translate('Wrong Password')), | 
					
						
							|  |  |  |           content: Text(translate('Do you want to enter again?')), | 
					
						
							|  |  |  |           actions: [ | 
					
						
							|  |  |  |             TextButton( | 
					
						
							|  |  |  |               style: flatButtonStyle, | 
					
						
							|  |  |  |               onPressed: () { | 
					
						
							| 
									
										
										
										
											2022-03-13 23:07:52 +08:00
										 |  |  |                 close(); | 
					
						
							|  |  |  |                 backToHome(); | 
					
						
							| 
									
										
										
										
											2022-03-13 00:32:44 +08:00
										 |  |  |               }, | 
					
						
							|  |  |  |               child: Text(translate('Cancel')), | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             TextButton( | 
					
						
							|  |  |  |               style: flatButtonStyle, | 
					
						
							|  |  |  |               onPressed: () { | 
					
						
							|  |  |  |                 enterPasswordDialog(id); | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               child: Text(translate('Retry')), | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |           ])); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class PasswordWidget extends StatefulWidget { | 
					
						
							|  |  |  |   PasswordWidget({Key? key, required this.controller}) : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   final TextEditingController controller; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   _PasswordWidgetState createState() => _PasswordWidgetState(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _PasswordWidgetState extends State<PasswordWidget> { | 
					
						
							|  |  |  |   bool _passwordVisible = false; | 
					
						
							| 
									
										
										
										
											2022-04-26 21:21:08 +08:00
										 |  |  |   final _focusNode = FocusNode(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void initState() { | 
					
						
							|  |  |  |     super.initState(); | 
					
						
							|  |  |  |     Timer(Duration(milliseconds: 50), () => _focusNode.requestFocus()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @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( | 
					
						
							|  |  |  |         labelText: Translator.call('Password'), | 
					
						
							|  |  |  |         hintText: Translator.call('Enter your password'), | 
					
						
							|  |  |  |         // Here is key idea
 | 
					
						
							|  |  |  |         suffixIcon: IconButton( | 
					
						
							|  |  |  |           icon: Icon( | 
					
						
							|  |  |  |             // Based on passwordVisible state choose the icon
 | 
					
						
							|  |  |  |             _passwordVisible ? Icons.visibility : Icons.visibility_off, | 
					
						
							|  |  |  |             color: Theme.of(context).primaryColorDark, | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |           onPressed: () { | 
					
						
							|  |  |  |             // Update the state i.e. toogle the state of passwordVisible variable
 | 
					
						
							|  |  |  |             setState(() { | 
					
						
							|  |  |  |               _passwordVisible = !_passwordVisible; | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |