From 8ebfd3f62890aa1fa1192af9c554d97860227cf9 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 24 Mar 2023 15:21:14 +0800 Subject: [PATCH] refactor dialog Signed-off-by: fufesou --- flutter/lib/common/widgets/dialog.dart | 546 ++++++++++++++++++ flutter/lib/common/widgets/login.dart | 59 +- .../lib/desktop/pages/connection_page.dart | 2 + flutter/lib/desktop/pages/remote_page.dart | 2 +- .../lib/desktop/widgets/remote_toolbar.dart | 2 +- .../lib/mobile/pages/file_manager_page.dart | 2 +- flutter/lib/mobile/pages/remote_page.dart | 1 + flutter/lib/mobile/widgets/dialog.dart | 425 +------------- flutter/lib/models/model.dart | 7 +- src/lang/ca.rs | 3 + src/lang/cn.rs | 3 + src/lang/cs.rs | 3 + src/lang/da.rs | 3 + src/lang/de.rs | 3 + src/lang/el.rs | 3 + src/lang/eo.rs | 3 + src/lang/es.rs | 3 + src/lang/fa.rs | 3 + src/lang/fr.rs | 3 + src/lang/hu.rs | 3 + src/lang/id.rs | 3 + src/lang/it.rs | 3 + src/lang/ja.rs | 3 + src/lang/ko.rs | 3 + src/lang/kz.rs | 3 + src/lang/nl.rs | 3 + src/lang/pl.rs | 3 + src/lang/pt_PT.rs | 3 + src/lang/ptbr.rs | 3 + src/lang/ro.rs | 3 + src/lang/ru.rs | 3 + src/lang/sk.rs | 3 + src/lang/sl.rs | 3 + src/lang/sq.rs | 3 + src/lang/sr.rs | 3 + src/lang/sv.rs | 3 + src/lang/template.rs | 3 + src/lang/th.rs | 3 + src/lang/tr.rs | 3 + src/lang/tw.rs | 5 +- src/lang/ua.rs | 3 + src/lang/vn.rs | 3 + 42 files changed, 671 insertions(+), 476 deletions(-) diff --git a/flutter/lib/common/widgets/dialog.dart b/flutter/lib/common/widgets/dialog.dart index ff1a372d0..97662d822 100644 --- a/flutter/lib/common/widgets/dialog.dart +++ b/flutter/lib/common/widgets/dialog.dart @@ -1,10 +1,18 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import '../../common.dart'; +import '../../models/model.dart'; import '../../models/platform_model.dart'; +void clientClose(String id, OverlayDialogManager dialogManager) { + msgBox(id, 'info', 'Close', 'Are you sure to close the connection?', '', + dialogManager); +} + abstract class ValidationRule { String get name; bool validate(String value); @@ -290,3 +298,541 @@ Future changeDirectAccessPort( }); return controller.text; } + +class DialogTextField extends StatelessWidget { + final String title; + final String? hintText; + final bool obscureText; + final String? errorText; + final String? helperText; + final Widget? prefixIcon; + final Widget? suffixIcon; + final TextEditingController controller; + final FocusNode? focusNode; + + static const kUsernameTitle = 'Username'; + static const kUsernameIcon = Icon(Icons.account_circle_outlined); + static const kPasswordTitle = 'Password'; + static const kPasswordIcon = Icon(Icons.lock_outline); + + DialogTextField( + {Key? key, + this.focusNode, + this.obscureText = false, + this.errorText, + this.helperText, + this.prefixIcon, + this.suffixIcon, + this.hintText, + required this.title, + required this.controller}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + child: TextField( + decoration: InputDecoration( + labelText: title, + hintText: hintText, + prefixIcon: prefixIcon, + suffixIcon: suffixIcon, + helperText: helperText, + helperMaxLines: 8, + errorText: errorText, + ), + controller: controller, + focusNode: focusNode, + autofocus: true, + obscureText: obscureText, + ), + ), + ], + ).paddingSymmetric(vertical: 4.0); + } +} + +class PasswordWidget extends StatefulWidget { + PasswordWidget({ + Key? key, + required this.controller, + this.autoFocus = true, + this.hintText, + this.errorText, + }) : super(key: key); + + final TextEditingController controller; + final bool autoFocus; + final String? hintText; + final String? errorText; + + @override + State createState() => _PasswordWidgetState(); +} + +class _PasswordWidgetState extends State { + bool _passwordVisible = false; + final _focusNode = FocusNode(); + Timer? _timer; + + @override + void initState() { + super.initState(); + if (widget.autoFocus) { + _timer = + Timer(Duration(milliseconds: 50), () => _focusNode.requestFocus()); + } + } + + @override + void dispose() { + _timer?.cancel(); + _focusNode.unfocus(); + _focusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return DialogTextField( + title: translate(DialogTextField.kPasswordTitle), + hintText: translate(widget.hintText ?? 'Enter your password'), + controller: widget.controller, + prefixIcon: DialogTextField.kPasswordIcon, + suffixIcon: IconButton( + icon: Icon( + // Based on passwordVisible state choose the icon + _passwordVisible ? Icons.visibility : Icons.visibility_off, + color: MyTheme.lightTheme.primaryColor), + onPressed: () { + // Update the state i.e. toggle the state of passwordVisible variable + setState(() { + _passwordVisible = !_passwordVisible; + }); + }, + ), + obscureText: !_passwordVisible, + errorText: widget.errorText, + focusNode: _focusNode, + ); + } +} + +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, + ), + ]); + }); +} + +void enterPasswordDialog(String id, OverlayDialogManager dialogManager) async { + await _connectDialog( + id, + dialogManager, + peerPasswordController: TextEditingController(), + ); +} + +void enterUserLoginDialog(String id, OverlayDialogManager dialogManager) async { + await _connectDialog( + id, + dialogManager, + usernameController: TextEditingController(), + passwordController: TextEditingController(), + ); +} + +void enterUserLoginAndPasswordDialog( + String id, OverlayDialogManager dialogManager) async { + await _connectDialog( + id, + dialogManager, + usernameController: TextEditingController(), + passwordController: TextEditingController(), + peerPasswordController: TextEditingController(), + ); +} + +_connectDialog( + String id, + OverlayDialogManager dialogManager, { + TextEditingController? usernameController, + TextEditingController? passwordController, + TextEditingController? peerPasswordController, +}) async { + var remember = await bind.sessionGetRemember(id: id) ?? false; + dialogManager.dismissAll(); + dialogManager.show((setState, close) { + cancel() { + close(); + closeConnection(); + } + + submit() { + final username = usernameController?.text.trim() ?? ''; + final password = passwordController?.text.trim() ?? ''; + final peerPassword = peerPasswordController?.text.trim() ?? ''; + if (peerPasswordController != null && peerPassword.isEmpty) return; + gFFI.login( + // username, + // password, + id, + peerPassword, + remember, + ); + close(); + dialogManager.showLoading(translate('Logging in...'), + onCancel: closeConnection); + } + + return CustomAlertDialog( + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.password_rounded, color: MyTheme.accent), + Text(translate(usernameController == null + ? 'Password Required' + : 'Login Required')) + .paddingOnly(left: 10), + ], + ), + content: Column(mainAxisSize: MainAxisSize.min, children: [ + usernameController == null + ? Offstage() + : DialogTextField( + title: translate(DialogTextField.kUsernameTitle), + controller: usernameController, + prefixIcon: DialogTextField.kUsernameIcon, + errorText: null, + ), + passwordController == null + ? Offstage() + : PasswordWidget( + controller: passwordController, + autoFocus: false, + ), + peerPasswordController == null + ? Offstage() + : PasswordWidget( + controller: peerPasswordController, + autoFocus: usernameController == null, + hintText: 'Enter RustDesk password', + ), + peerPasswordController == null + ? Offstage() + : CheckboxListTile( + contentPadding: const EdgeInsets.all(0), + dense: true, + controlAffinity: ListTileControlAffinity.leading, + title: Text( + translate('Remember RustDesk password'), + ), + value: remember, + onChanged: (v) { + if (v != null) { + setState(() => remember = v); + } + }, + ), + ]), + actions: [ + dialogButton( + 'Cancel', + icon: Icon(Icons.close_rounded), + onPressed: cancel, + isOutline: true, + ), + dialogButton( + 'OK', + icon: Icon(Icons.done_rounded), + onPressed: submit, + ), + ], + onSubmit: submit, + onCancel: cancel, + ); + }); +} + +void showWaitUacDialog( + String id, OverlayDialogManager dialogManager, String type) { + dialogManager.dismissAll(); + dialogManager.show( + tag: '$id-wait-uac', + (setState, close) => CustomAlertDialog( + title: null, + content: msgboxContent(type, 'Wait', 'wait_accept_uac_tip'), + )); +} + +// Another username && password dialog? +void showRequestElevationDialog(String id, OverlayDialogManager dialogManager) { + 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: translate('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: [ + dialogButton('Cancel', onPressed: close, isOutline: true), + dialogButton('OK', onPressed: submit), + ], + 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(); + showRequestElevationDialog(id, dialogManager); + } + + return CustomAlertDialog( + title: null, + content: msgboxContent(type, title, + "${translate(text)}${type.contains('uac') ? '\n' : '\n\n'}${translate('request_elevation_tip')}"), + actions: [ + dialogButton('Wait', onPressed: close, isOutline: true), + dialogButton('Request Elevation', onPressed: submit), + ], + 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(); + showRequestElevationDialog(id, dialogManager); + } + + return CustomAlertDialog( + title: null, + content: msgboxContent(type, title, text), + actions: [ + dialogButton('Cancel', onPressed: () { + close(); + }, isOutline: true), + dialogButton('Retry', onPressed: submit), + ], + onSubmit: submit, + onCancel: close, + ); + }); +} + +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, + ); + }); +} + +void showRestartRemoteDevice( + PeerInfo pi, String id, OverlayDialogManager dialogManager) async { + final res = + await dialogManager.show((setState, close) => CustomAlertDialog( + title: Row(children: [ + Icon(Icons.warning_rounded, color: Colors.redAccent, size: 28), + Text(translate("Restart Remote Device")).paddingOnly(left: 10), + ]), + 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), + ), + ], + onCancel: close, + onSubmit: () => close(true), + )); + if (res == true) bind.sessionRestartRemoteDevice(id: id); +} diff --git a/flutter/lib/common/widgets/login.dart b/flutter/lib/common/widgets/login.dart index 7b37c590d..3959c301c 100644 --- a/flutter/lib/common/widgets/login.dart +++ b/flutter/lib/common/widgets/login.dart @@ -9,6 +9,7 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../common.dart'; +import './dialog.dart'; class _IconOP extends StatelessWidget { final String icon; @@ -324,17 +325,16 @@ class LoginWidgetUserPass extends StatelessWidget { children: [ const SizedBox(height: 8.0), DialogTextField( - title: translate("Username"), + title: translate(DialogTextField.kUsernameTitle), controller: username, focusNode: userFocusNode, - prefixIcon: Icon(Icons.account_circle_outlined), + prefixIcon: DialogTextField.kUsernameIcon, errorText: usernameMsg), - DialogTextField( - title: translate("Password"), - obscureText: true, - controller: pass, - prefixIcon: Icon(Icons.lock_outline), - errorText: passMsg), + PasswordWidget( + controller: pass, + autoFocus: false, + errorText: passMsg, + ), Obx(() => CheckboxListTile( contentPadding: const EdgeInsets.all(0), dense: true, @@ -377,49 +377,6 @@ class LoginWidgetUserPass extends StatelessWidget { } } -class DialogTextField extends StatelessWidget { - final String title; - final bool obscureText; - final String? errorText; - final String? helperText; - final Widget? prefixIcon; - final TextEditingController controller; - final FocusNode? focusNode; - - DialogTextField( - {Key? key, - this.focusNode, - this.obscureText = false, - this.errorText, - this.helperText, - this.prefixIcon, - required this.title, - required this.controller}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - child: TextField( - decoration: InputDecoration( - labelText: title, - prefixIcon: prefixIcon, - helperText: helperText, - helperMaxLines: 8, - errorText: errorText), - controller: controller, - focusNode: focusNode, - autofocus: true, - obscureText: obscureText, - ), - ), - ], - ).paddingSymmetric(vertical: 4.0); - } -} - /// common login dialog for desktop /// call this directly Future loginDialog() async { diff --git a/flutter/lib/desktop/pages/connection_page.dart b/flutter/lib/desktop/pages/connection_page.dart index b6debbd8d..a593810fd 100644 --- a/flutter/lib/desktop/pages/connection_page.dart +++ b/flutter/lib/desktop/pages/connection_page.dart @@ -19,6 +19,8 @@ import '../../common/widgets/peer_tab_page.dart'; import '../../models/platform_model.dart'; import '../widgets/button.dart'; +import 'package:flutter_hbb/common/widgets/dialog.dart'; + /// Connection page for connecting to a remote peer. class ConnectionPage extends StatefulWidget { const ConnectionPage({Key? key}) : super(key: key); diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index aea073ace..1bc09f137 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -17,7 +17,7 @@ import '../../consts.dart'; import '../../common/widgets/overlay.dart'; import '../../common/widgets/remote_input.dart'; import '../../common.dart'; -import '../../mobile/widgets/dialog.dart'; +import '../../common/widgets/dialog.dart'; import '../../models/model.dart'; import '../../models/platform_model.dart'; import '../../common/shared_state.dart'; diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart index c89bfa766..45a1a55bc 100644 --- a/flutter/lib/desktop/widgets/remote_toolbar.dart +++ b/flutter/lib/desktop/widgets/remote_toolbar.dart @@ -16,7 +16,7 @@ import 'package:desktop_multi_window/desktop_multi_window.dart'; import 'package:window_size/window_size.dart' as window_size; import '../../common.dart'; -import '../../mobile/widgets/dialog.dart'; +import '../../common/widgets/dialog.dart'; import '../../models/model.dart'; import '../../models/platform_model.dart'; import '../../common/shared_state.dart'; diff --git a/flutter/lib/mobile/pages/file_manager_page.dart b/flutter/lib/mobile/pages/file_manager_page.dart index c6ba42d31..30e0661f6 100644 --- a/flutter/lib/mobile/pages/file_manager_page.dart +++ b/flutter/lib/mobile/pages/file_manager_page.dart @@ -8,7 +8,7 @@ import 'package:toggle_switch/toggle_switch.dart'; import 'package:wakelock/wakelock.dart'; import '../../common.dart'; -import '../widgets/dialog.dart'; +import '../../common/widgets/dialog.dart'; class FileManagerPage extends StatefulWidget { FileManagerPage({Key? key, required this.id}) : super(key: key); diff --git a/flutter/lib/mobile/pages/remote_page.dart b/flutter/lib/mobile/pages/remote_page.dart index 4d94dc669..8f4efaece 100644 --- a/flutter/lib/mobile/pages/remote_page.dart +++ b/flutter/lib/mobile/pages/remote_page.dart @@ -14,6 +14,7 @@ import 'package:wakelock/wakelock.dart'; import '../../common.dart'; import '../../common/widgets/overlay.dart'; +import '../../common/widgets/dialog.dart'; import '../../common/widgets/remote_input.dart'; import '../../models/input_model.dart'; import '../../models/model.dart'; diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index b14401795..b281895ff 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -4,51 +4,16 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../common.dart'; -import '../../models/model.dart'; import '../../models/platform_model.dart'; -void clientClose(String id, OverlayDialogManager dialogManager) { - msgBox(id, 'info', 'Close', 'Are you sure to close the connection?', '', - dialogManager); -} - -void showSuccess() { +void _showSuccess() { showToast(translate("Successful")); } -void showError() { +void _showError() { showToast(translate("Error")); } -void showRestartRemoteDevice( - PeerInfo pi, String id, OverlayDialogManager dialogManager) async { - final res = - await dialogManager.show((setState, close) => CustomAlertDialog( - title: Row(children: [ - Icon(Icons.warning_rounded, color: Colors.redAccent, size: 28), - Text(translate("Restart Remote Device")).paddingOnly(left: 10), - ]), - 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), - ), - ], - onCancel: close, - onSubmit: () => close(true), - )); - if (res == true) bind.sessionRestartRemoteDevice(id: id); -} - void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async { final pw = await bind.mainGetPermanentPassword(); final p0 = TextEditingController(text: pw); @@ -61,10 +26,10 @@ void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async { dialogManager.showLoading(translate("Waiting")); if (await gFFI.serverModel.setPermanentPassword(p0.text)) { dialogManager.dismissAll(); - showSuccess(); + _showSuccess(); } else { dialogManager.dismissAll(); - showError(); + _showError(); } } @@ -157,7 +122,7 @@ void setTemporaryPasswordLengthDialog( bind.mainUpdateTemporaryPassword(); Future.delayed(Duration(milliseconds: 200), () { close(); - showSuccess(); + _showSuccess(); }); } @@ -173,101 +138,6 @@ void setTemporaryPasswordLengthDialog( }, backDismiss: true, clickMaskDismiss: true); } -void enterPasswordDialog(String id, OverlayDialogManager dialogManager) async { - final controller = TextEditingController(); - var remember = await bind.sessionGetRemember(id: id) ?? false; - dialogManager.dismissAll(); - dialogManager.show((setState, close) { - 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); - } - - return CustomAlertDialog( - title: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(Icons.password_rounded, color: MyTheme.accent), - Text(translate('Password Required')).paddingOnly(left: 10), - ], - ), - 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); - } - }, - ), - ]), - actions: [ - dialogButton( - 'Cancel', - icon: Icon(Icons.close_rounded), - onPressed: cancel, - isOutline: true, - ), - dialogButton( - 'OK', - icon: Icon(Icons.done_rounded), - onPressed: submit, - ), - ], - onSubmit: submit, - onCancel: cancel, - ); - }); -} - -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, - ), - ]); - }); -} - void showServerSettingsWithValue( ServerConfig serverConfig, OverlayDialogManager dialogManager) async { Map oldOptions = jsonDecode(await bind.mainGetOptions()); @@ -393,232 +263,6 @@ void showServerSettingsWithValue( }); } -void showWaitUacDialog( - String id, OverlayDialogManager dialogManager, String type) { - dialogManager.dismissAll(); - dialogManager.show( - tag: '$id-wait-uac', - (setState, close) => CustomAlertDialog( - title: null, - content: msgboxContent(type, 'Wait', 'wait_accept_uac_tip'), - )); -} - -void showRequestElevationDialog(String id, OverlayDialogManager dialogManager) { - 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: translate('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: [ - dialogButton('Cancel', onPressed: close, isOutline: true), - dialogButton('OK', onPressed: submit), - ], - 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(); - showRequestElevationDialog(id, dialogManager); - } - - return CustomAlertDialog( - title: null, - content: msgboxContent(type, title, - "${translate(text)}${type.contains('uac') ? '\n' : '\n\n'}${translate('request_elevation_tip')}"), - actions: [ - dialogButton('Wait', onPressed: close, isOutline: true), - dialogButton('Request Elevation', onPressed: submit), - ], - 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(); - showRequestElevationDialog(id, dialogManager); - } - - return CustomAlertDialog( - title: null, - content: msgboxContent(type, title, text), - actions: [ - dialogButton('Cancel', onPressed: () { - close(); - }, isOutline: true), - dialogButton('Retry', onPressed: submit), - ], - onSubmit: submit, - onCancel: close, - ); - }); -} - -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, - ); - }); -} - Future validateAsync(String value) async { value = value.trim(); if (value.isEmpty) { @@ -627,62 +271,3 @@ Future validateAsync(String value) async { final res = await bind.mainTestIfValidServer(server: value); return res.isEmpty ? null : res; } - -class PasswordWidget extends StatefulWidget { - PasswordWidget({Key? key, required this.controller, this.autoFocus = true}) - : super(key: key); - - final TextEditingController controller; - final bool autoFocus; - - @override - State createState() => _PasswordWidgetState(); -} - -class _PasswordWidgetState extends State { - bool _passwordVisible = false; - final _focusNode = FocusNode(); - - @override - void initState() { - super.initState(); - if (widget.autoFocus) { - Timer(Duration(milliseconds: 50), () => _focusNode.requestFocus()); - } - } - - @override - void dispose() { - _focusNode.unfocus(); - _focusNode.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return TextField( - focusNode: _focusNode, - controller: widget.controller, - obscureText: !_passwordVisible, - //This will obscure text dynamically - keyboardType: TextInputType.visiblePassword, - decoration: InputDecoration( - labelText: translate('Password'), - hintText: translate('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: MyTheme.lightTheme.primaryColor), - onPressed: () { - // Update the state i.e. toggle the state of passwordVisible variable - setState(() { - _passwordVisible = !_passwordVisible; - }); - }, - ), - ), - ); - } -} diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index c5c3999ee..701fae48c 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -25,7 +25,7 @@ import 'package:get/get.dart'; import '../common.dart'; import '../utils/image.dart' as img; -import '../mobile/widgets/dialog.dart'; +import '../common/widgets/dialog.dart'; import 'input_model.dart'; import 'platform_model.dart'; @@ -293,6 +293,11 @@ class FfiModel with ChangeNotifier { wrongPasswordDialog(id, dialogManager, type, title, text); } else if (type == 'input-password') { enterPasswordDialog(id, dialogManager); + } else if (type == 'xsession-login' || type == 'xsession-re-login') { + // to-do + } else if (type == 'xsession-login-password' || + type == 'xsession-login-password') { + // to-do } else if (type == 'restarting') { showMsgBox(id, type, title, text, link, false, dialogManager, hasCancel: false); diff --git a/src/lang/ca.rs b/src/lang/ca.rs index c77d73944..5a9e7b914 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 14dc440ae..ee3433282 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "此文件与对方的一致"), ("show_monitors_tip", ""), ("View Mode", "浏览模式"), + ("Enter RustDesk password", "请输入RustDesk密码"), + ("Remember RustDesk password", "记住RustDesk密码"), + ("Login Required", "需要登陆"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 5e8bdba5f..cfb23eca6 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 542543155..0c5615902 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 876c6dd46..46c6d5ded 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Diese Datei ist identisch mit der Datei der Gegenstelle."), ("show_monitors_tip", "Monitore in der Symbolleiste anzeigen"), ("View Mode", "Ansichtsmodus"), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index 6d8a77d20..46a482a1b 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Το αρχείο είναι πανομοιότυπο με αυτό του άλλου υπολογιστή."), ("show_monitors_tip", "Εμφάνιση οθονών στη γραμμή εργαλείων"), ("View Mode", "Λειτουργία προβολής"), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 6d697528d..f3d9923a5 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index ed53d22bd..5885a3647 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Este archivo es idéntico al del par."), ("show_monitors_tip", "Mostrar monitores en la barra de herramientas"), ("View Mode", "Modo Vista"), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index ffdf22a50..b41713f5c 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "این فایل با فایل همتا یکسان است."), ("show_monitors_tip", "نمایش مانیتورها در نوار ابزار"), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 6aa7f12f6..7e42b53b6 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 474b3a70d..03ea22b5b 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 3bdef56bb..d6717ae93 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 5b3e4d92f..56229059b 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Questo file è identico a quello del peer."), ("show_monitors_tip", "Mostra schermi nella barra degli strumenti"), ("View Mode", "Modalità di visualizzazione"), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 925ccebde..dbf69b76b 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 89c65a332..95138b2b1 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 0ec4d099b..cb7ccace4 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 46ae3799a..b20895b71 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index aabf14fc7..28c870f2c 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 25561d43a..15eff4cbd 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 6a6df5078..b036637fa 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 886f27bd4..cc7ecdf5d 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 0dd1c6fe9..95ddba4b9 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Файл идентичен файлу на удалённом узле."), ("show_monitors_tip", "Показывать мониторы на панели инструментов"), ("View Mode", "Режим просмотра"), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index ceed59b43..00233f8a7 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 14e50fc1d..d6c276ae6 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 142074539..1da1c45dd 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 7ea384def..adea7f7cf 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 31db07b30..ca93ba385 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 343d6c1ea..538f9454a 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index a05f8ff88..c740eb6f4 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index e00877118..4d2370c94 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index d80aea781..f85d72034 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "此檔案與對方的檔案一致"), ("show_monitors_tip", "在工具列中顯示顯示器"), ("View Mode", "瀏覽模式"), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); -} \ No newline at end of file +} diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 7abfd4188..70abb42db 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 918106363..d73882558 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -480,5 +480,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), + ("Enter RustDesk password", ""), + ("Remember RustDesk password", ""), + ("Login Required", ""), ].iter().cloned().collect(); }