Merge pull request #2832 from 21pages/opt_ui

opt UI
This commit is contained in:
RustDesk 2023-01-16 21:31:03 +08:00 committed by GitHub
commit 5b595ee729
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 482 additions and 71 deletions

View File

@ -613,8 +613,9 @@ class CustomAlertDialog extends StatelessWidget {
Future.delayed(Duration.zero, () {
if (!focusNode.hasFocus) focusNode.requestFocus();
});
return Focus(
focusNode: focusNode,
FocusScopeNode scopeNode = FocusScopeNode();
return FocusScope(
node: scopeNode,
autofocus: true,
onKey: (node, key) {
if (key.logicalKey == LogicalKeyboardKey.escape) {
@ -626,6 +627,11 @@ class CustomAlertDialog extends StatelessWidget {
key.logicalKey == LogicalKeyboardKey.enter) {
if (key is RawKeyDownEvent) onSubmit?.call();
return KeyEventResult.handled;
} else if (key.logicalKey == LogicalKeyboardKey.tab) {
if (key is RawKeyDownEvent) {
scopeNode.nextFocus();
}
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
},
@ -634,8 +640,14 @@ class CustomAlertDialog extends StatelessWidget {
title: title,
contentPadding: EdgeInsets.symmetric(
horizontal: contentPadding ?? 25, vertical: 10),
content:
ConstrainedBox(constraints: contentBoxConstraints, child: content),
content: ConstrainedBox(
constraints: contentBoxConstraints,
child: Theme(
data: ThemeData(
inputDecorationTheme: InputDecorationTheme(
isDense: true, contentPadding: EdgeInsets.all(15)),
),
child: content)),
actions: actions,
),
);

View File

@ -0,0 +1,121 @@
// https://github.com/rodrigobastosv/fancy_password_field
import 'package:flutter/material.dart';
import 'package:flutter_hbb/common.dart';
import 'package:get/get.dart';
import 'package:password_strength/password_strength.dart';
abstract class ValidationRule {
String get name;
bool validate(String value);
}
class UppercaseValidationRule extends ValidationRule {
@override
String get name => translate('uppercase');
@override
bool validate(String value) {
return value.contains(RegExp(r'[A-Z]'));
}
}
class LowercaseValidationRule extends ValidationRule {
@override
String get name => translate('lowercase');
@override
bool validate(String value) {
return value.contains(RegExp(r'[a-z]'));
}
}
class DigitValidationRule extends ValidationRule {
@override
String get name => translate('digit');
@override
bool validate(String value) {
return value.contains(RegExp(r'[0-9]'));
}
}
class SpecialCharacterValidationRule extends ValidationRule {
@override
String get name => translate('special character');
@override
bool validate(String value) {
return value.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]'));
}
}
class MinCharactersValidationRule extends ValidationRule {
final int _numberOfCharacters;
MinCharactersValidationRule(this._numberOfCharacters);
@override
String get name => translate('length>=$_numberOfCharacters');
@override
bool validate(String value) {
return value.length >= _numberOfCharacters;
}
}
class PasswordStrengthIndicator extends StatelessWidget {
final RxString password;
final double weakMedium = 0.33;
final double mediumStrong = 0.67;
const PasswordStrengthIndicator({Key? key, required this.password})
: super(key: key);
@override
Widget build(BuildContext context) {
return Obx(() {
var strength = estimatePasswordStrength(password.value);
return Row(
children: [
Expanded(
child: _indicator(
password.isEmpty ? Colors.grey : _getColor(strength))),
Expanded(
child: _indicator(password.isEmpty || strength < weakMedium
? Colors.grey
: _getColor(strength))),
Expanded(
child: _indicator(password.isEmpty || strength < mediumStrong
? Colors.grey
: _getColor(strength))),
Text(password.isEmpty ? '' : translate(_getLabel(strength)))
.marginOnly(left: password.isEmpty ? 0 : 8),
],
);
});
}
Widget _indicator(Color color) {
return Container(
height: 8,
color: color,
);
}
String _getLabel(double strength) {
if (strength < weakMedium) {
return 'Weak';
} else if (strength < mediumStrong) {
return 'Medium';
} else {
return 'Strong';
}
}
Color _getColor(double strength) {
if (strength < weakMedium) {
return Colors.yellow;
} else if (strength < mediumStrong) {
return Colors.blue;
} else {
return Colors.green;
}
}
}

View File

@ -6,6 +6,7 @@ import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart' hide MenuItem;
import 'package:flutter/services.dart';
import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/common/widgets/custom_password.dart';
import 'package:flutter_hbb/consts.dart';
import 'package:flutter_hbb/desktop/pages/connection_page.dart';
import 'package:flutter_hbb/desktop/pages/desktop_setting_page.dart';
@ -543,6 +544,14 @@ void setPasswordDialog() async {
final p1 = TextEditingController(text: pw);
var errMsg0 = "";
var errMsg1 = "";
final RxString rxPass = p0.text.obs;
final rules = [
DigitValidationRule(),
UppercaseValidationRule(),
LowercaseValidationRule(),
// SpecialCharacterValidationRule(),
MinCharactersValidationRule(8),
];
gFFI.dialogManager.show((setState, close) {
submit() {
@ -551,15 +560,20 @@ void setPasswordDialog() async {
errMsg1 = "";
});
final pass = p0.text.trim();
if (pass.length < 6 && pass.isNotEmpty) {
if (pass.isNotEmpty) {
for (var r in rules) {
if (!r.validate(pass)) {
setState(() {
errMsg0 = translate("Too short, at least 6 characters.");
errMsg0 = '${translate('Prompt')}: ${r.name}';
});
return;
}
}
}
if (p1.text.trim() != pass) {
setState(() {
errMsg1 = translate("The confirmation is not identical.");
errMsg1 =
'${translate('Prompt')}: ${translate("The confirmation is not identical.")}';
});
return;
}
@ -579,23 +593,40 @@ void setPasswordDialog() async {
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text(
"${translate('Password')}:",
textAlign: TextAlign.start,
).marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
Expanded(
child: TextField(
obscureText: true,
decoration: InputDecoration(
labelText: translate('Password'),
border: const OutlineInputBorder(),
errorText: errMsg0.isNotEmpty ? errMsg0 : null),
controller: p0,
focusNode: FocusNode()..requestFocus(),
onChanged: (value) {
rxPass.value = value;
},
),
),
],
),
Row(
children: [
Expanded(child: PasswordStrengthIndicator(password: rxPass)),
],
).marginSymmetric(vertical: 8),
const SizedBox(
height: 8.0,
),
Row(
children: [
Expanded(
child: TextField(
obscureText: true,
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: errMsg0.isNotEmpty ? errMsg0 : null),
controller: p0,
focusNode: FocusNode()..requestFocus(),
labelText: translate('Confirmation'),
errorText: errMsg1.isNotEmpty ? errMsg1 : null),
controller: p1,
),
),
],
@ -603,26 +634,24 @@ void setPasswordDialog() async {
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text("${translate('Confirmation')}:")
.marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
obscureText: true,
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: errMsg1.isNotEmpty ? errMsg1 : null),
controller: p1,
),
),
],
Obx(() => Wrap(
runSpacing: 8,
spacing: 4,
children: rules.map((e) {
var checked = e.validate(rxPass.value.trim());
return Chip(
label: Text(
e.name,
style: TextStyle(
color: checked
? const Color(0xFF0A9471)
: Color.fromARGB(255, 198, 86, 157)),
),
backgroundColor: checked
? const Color(0xFFD0F7ED)
: Color.fromARGB(255, 247, 205, 232));
}).toList(),
))
],
),
),

View File

@ -93,6 +93,7 @@ dependencies:
auto_size_text: ^3.0.0
bot_toast: ^4.0.3
win32: any
password_strength: ^0.2.0
dev_dependencies:

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", "请求提权"),
("wait_accept_uac_tip", "请等待远端用户确认UAC对话框。"),
("Elevate successfully", "提权成功"),
("uppercase", "大写字母"),
("lowercase", "小写字母"),
("digit", "数字"),
("special character", "特殊字符"),
("length>=8", "长度不小于8"),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", "Erhöhte Rechte anfordern"),
("wait_accept_uac_tip", "Bitte warten Sie, bis der entfernte Benutzer den UAC-Dialog akzeptiert hat."),
("Elevate successfully", "Erhöhung der Rechte erfolgreich"),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", "Richiedi elevazione dei diritti"),
("wait_accept_uac_tip", "Attendere che l'utente remoto accetti la finestra di dialogo UAC."),
("Elevate successfully", "Elevazione dei diritti effettuata con successo"),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", "請求提權"),
("wait_accept_uac_tip", "請等待遠端用戶確認UAC對話框。"),
("Elevate successfully", "提權成功"),
("uppercase", "大寫字母"),
("lowercase", "小寫字母"),
("digit", "數字"),
("special character", "特殊字符"),
("length>=8", "長度不小於8"),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}

View File

@ -423,5 +423,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
("uppercase", ""),
("lowercase", ""),
("digit", ""),
("special character", ""),
("length>=8", ""),
("Weak", ""),
("Medium", ""),
("Strong", ""),
].iter().cloned().collect();
}