unlock with PIN (#8977)

* add custom password to unlock settings

* If not set, use admin password; if set, use custom settings password.
* At least 4 characters.
* Set with gui or command line.

Signed-off-by: 21pages <sunboeasy@gmail.com>

* Update cn.rs

---------

Signed-off-by: 21pages <sunboeasy@gmail.com>
Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
This commit is contained in:
21pages 2024-08-07 16:21:38 +08:00 committed by GitHub
parent bc6ce6c7ee
commit 76d5a8b205
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
51 changed files with 425 additions and 9 deletions

View File

@ -679,6 +679,7 @@ class PasswordWidget extends StatefulWidget {
this.reRequestFocus = false, this.reRequestFocus = false,
this.hintText, this.hintText,
this.errorText, this.errorText,
this.title,
}) : super(key: key); }) : super(key: key);
final TextEditingController controller; final TextEditingController controller;
@ -686,6 +687,7 @@ class PasswordWidget extends StatefulWidget {
final bool reRequestFocus; final bool reRequestFocus;
final String? hintText; final String? hintText;
final String? errorText; final String? errorText;
final String? title;
@override @override
State<PasswordWidget> createState() => _PasswordWidgetState(); State<PasswordWidget> createState() => _PasswordWidgetState();
@ -729,7 +731,7 @@ class _PasswordWidgetState extends State<PasswordWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DialogTextField( return DialogTextField(
title: translate(DialogTextField.kPasswordTitle), title: translate(widget.title ?? DialogTextField.kPasswordTitle),
hintText: translate(widget.hintText ?? 'Enter your password'), hintText: translate(widget.hintText ?? 'Enter your password'),
controller: widget.controller, controller: widget.controller,
prefixIcon: DialogTextField.kPasswordIcon, prefixIcon: DialogTextField.kPasswordIcon,
@ -2216,3 +2218,98 @@ void CommonConfirmDialog(OverlayDialogManager dialogManager, String content,
); );
}); });
} }
void changeUnlockPinDialog(String oldPin, Function() callback) {
final pinController = TextEditingController(text: oldPin);
final confirmController = TextEditingController(text: oldPin);
String? pinErrorText;
String? confirmationErrorText;
gFFI.dialogManager.show((setState, close, context) {
submit() async {
pinErrorText = null;
confirmationErrorText = null;
final pin = pinController.text.trim();
final confirm = confirmController.text.trim();
if (pin != confirm) {
setState(() {
confirmationErrorText =
translate('The confirmation is not identical.');
});
return;
}
final errorMsg = bind.mainSetUnlockPin(pin: pin);
if (errorMsg != '') {
setState(() {
pinErrorText = translate(errorMsg);
});
return;
}
callback.call();
close();
}
return CustomAlertDialog(
title: Text(translate("Set PIN")),
content: Column(
children: [
DialogTextField(
title: 'PIN',
controller: pinController,
obscureText: true,
errorText: pinErrorText,
),
DialogTextField(
title: translate('Confirmation'),
controller: confirmController,
obscureText: true,
errorText: confirmationErrorText,
)
],
).marginOnly(bottom: 12),
actions: [
dialogButton(translate("Cancel"), onPressed: close, isOutline: true),
dialogButton(translate("OK"), onPressed: submit),
],
onSubmit: submit,
onCancel: close,
);
});
}
void checkUnlockPinDialog(String correctPin, Function() passCallback) {
final controller = TextEditingController();
String? errorText;
gFFI.dialogManager.show((setState, close, context) {
submit() async {
final pin = controller.text.trim();
if (correctPin != pin) {
setState(() {
errorText = translate('Wrong PIN');
});
return;
}
passCallback.call();
close();
}
return CustomAlertDialog(
content: Row(
children: [
Expanded(
child: PasswordWidget(
title: 'PIN',
controller: controller,
errorText: errorText,
hintText: '',
))
],
).marginOnly(bottom: 12),
actions: [
dialogButton(translate("Cancel"), onPressed: close, isOutline: true),
dialogButton(translate("OK"), onPressed: submit),
],
onSubmit: submit,
onCancel: close,
);
});
}

View File

@ -1018,6 +1018,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
_OptionCheckBox(context, 'allow-only-conn-window-open-tip', _OptionCheckBox(context, 'allow-only-conn-window-open-tip',
'allow-only-conn-window-open', 'allow-only-conn-window-open',
reverse: false, enabled: enabled), reverse: false, enabled: enabled),
if (bind.mainIsInstalled()) unlockPin()
]); ]);
} }
@ -1265,6 +1266,40 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
}(), }(),
]; ];
} }
Widget unlockPin() {
bool enabled = !locked;
RxString unlockPin = bind.mainGetUnlockPin().obs;
update() async {
unlockPin.value = bind.mainGetUnlockPin();
}
onChanged(bool? checked) async {
changeUnlockPinDialog(unlockPin.value, update);
}
final isOptFixed = isOptionFixed(kOptionWhitelist);
return GestureDetector(
child: Obx(() => Row(
children: [
Checkbox(
value: unlockPin.isNotEmpty,
onChanged: enabled && !isOptFixed ? onChanged : null)
.marginOnly(right: 5),
Expanded(
child: Text(
translate('Unlock with PIN'),
style: TextStyle(color: disabledTextColor(context, enabled)),
))
],
)),
onTap: enabled
? () {
onChanged(!unlockPin.isNotEmpty);
}
: null,
).marginOnly(left: _kCheckBoxLeftMargin);
}
} }
class _Network extends StatefulWidget { class _Network extends StatefulWidget {
@ -2160,10 +2195,15 @@ Widget _lock(
Text(translate(label)).marginOnly(left: 5), Text(translate(label)).marginOnly(left: 5),
]).marginSymmetric(vertical: 2)), ]).marginSymmetric(vertical: 2)),
onPressed: () async { onPressed: () async {
final unlockPin = bind.mainGetUnlockPin();
if (unlockPin.isEmpty) {
bool checked = await callMainCheckSuperUserPermission(); bool checked = await callMainCheckSuperUserPermission();
if (checked) { if (checked) {
onUnlock(); onUnlock();
} }
} else {
checkUnlockPinDialog(unlockPin, onUnlock);
}
}, },
).marginSymmetric(horizontal: 2, vertical: 4), ).marginSymmetric(horizontal: 2, vertical: 4),
).marginOnly(left: _kCardLeftMargin), ).marginOnly(left: _kCardLeftMargin),

View File

@ -1622,5 +1622,13 @@ class RustdeskImpl {
throw UnimplementedError(); throw UnimplementedError();
} }
String mainGetUnlockPin({dynamic hint}) {
throw UnimplementedError();
}
String mainSetUnlockPin({required String pin, dynamic hint}) {
throw UnimplementedError();
}
void dispose() {} void dispose() {}
} }

View File

@ -208,6 +208,8 @@ pub struct Config2 {
nat_type: i32, nat_type: i32,
#[serde(default, deserialize_with = "deserialize_i32")] #[serde(default, deserialize_with = "deserialize_i32")]
serial: i32, serial: i32,
#[serde(default, deserialize_with = "deserialize_string")]
unlock_pin: String,
#[serde(default)] #[serde(default)]
socks: Option<Socks5Server>, socks: Option<Socks5Server>,
@ -427,15 +429,21 @@ fn patch(path: PathBuf) -> PathBuf {
impl Config2 { impl Config2 {
fn load() -> Config2 { fn load() -> Config2 {
let mut config = Config::load_::<Config2>("2"); let mut config = Config::load_::<Config2>("2");
let mut store = false;
if let Some(mut socks) = config.socks { if let Some(mut socks) = config.socks {
let (password, _, store) = let (password, _, store2) =
decrypt_str_or_original(&socks.password, PASSWORD_ENC_VERSION); decrypt_str_or_original(&socks.password, PASSWORD_ENC_VERSION);
socks.password = password; socks.password = password;
config.socks = Some(socks); config.socks = Some(socks);
store |= store2;
}
let (unlock_pin, _, store2) =
decrypt_str_or_original(&config.unlock_pin, PASSWORD_ENC_VERSION);
config.unlock_pin = unlock_pin;
store |= store2;
if store { if store {
config.store(); config.store();
} }
}
config config
} }
@ -450,6 +458,8 @@ impl Config2 {
encrypt_str_or_original(&socks.password, PASSWORD_ENC_VERSION, ENCRYPT_MAX_LEN); encrypt_str_or_original(&socks.password, PASSWORD_ENC_VERSION, ENCRYPT_MAX_LEN);
config.socks = Some(socks); config.socks = Some(socks);
} }
config.unlock_pin =
encrypt_str_or_original(&config.unlock_pin, PASSWORD_ENC_VERSION, ENCRYPT_MAX_LEN);
Config::store_(&config, "2"); Config::store_(&config, "2");
} }
@ -1081,6 +1091,19 @@ impl Config {
NetworkType::Direct NetworkType::Direct
} }
pub fn get_unlock_pin() -> String {
CONFIG2.read().unwrap().unlock_pin.clone()
}
pub fn set_unlock_pin(pin: &str) {
let mut config = CONFIG2.write().unwrap();
if pin == config.unlock_pin {
return;
}
config.unlock_pin = pin.to_string();
config.store();
}
pub fn get() -> Config { pub fn get() -> Config {
return CONFIG.read().unwrap().clone(); return CONFIG.read().unwrap().clone();
} }

View File

@ -316,6 +316,20 @@ pub fn core_main() -> Option<Vec<String>> {
} }
} }
return None; return None;
} else if args[0] == "--set-unlock-pin" {
#[cfg(feature = "flutter")]
if args.len() == 2 {
if crate::platform::is_installed() && is_root() {
if let Err(err) = crate::ipc::set_unlock_pin(args[1].to_owned(), false) {
println!("{err}");
} else {
println!("Done!");
}
} else {
println!("Installation and administrative privileges required!");
}
}
return None;
} else if args[0] == "--get-id" { } else if args[0] == "--get-id" {
println!("{}", crate::ipc::get_id()); println!("{}", crate::ipc::get_id());
return None; return None;

View File

@ -1617,6 +1617,14 @@ pub fn main_check_super_user_permission() -> bool {
check_super_user_permission() check_super_user_permission()
} }
pub fn main_get_unlock_pin() -> SyncReturn<String> {
SyncReturn(get_unlock_pin())
}
pub fn main_set_unlock_pin(pin: String) -> SyncReturn<String> {
SyncReturn(set_unlock_pin(pin))
}
pub fn main_check_mouse_time() { pub fn main_check_mouse_time() {
check_mouse_time(); check_mouse_time();
} }

View File

@ -484,6 +484,8 @@ async fn handle(data: Data, stream: &mut Connection) {
}; };
} else if name == "voice-call-input" { } else if name == "voice-call-input" {
value = crate::audio_service::get_voice_call_input_device(); value = crate::audio_service::get_voice_call_input_device();
} else if name == "unlock-pin" {
value = Some(Config::get_unlock_pin());
} else { } else {
value = None; value = None;
} }
@ -501,6 +503,8 @@ async fn handle(data: Data, stream: &mut Connection) {
Config::set_salt(&value); Config::set_salt(&value);
} else if name == "voice-call-input" { } else if name == "voice-call-input" {
crate::audio_service::set_voice_call_input_device(Some(value), true); crate::audio_service::set_voice_call_input_device(Some(value), true);
} else if name == "unlock-pin" {
Config::set_unlock_pin(&value);
} else { } else {
return; return;
} }
@ -891,6 +895,37 @@ pub fn set_permanent_password(v: String) -> ResultType<()> {
set_config("permanent-password", v) set_config("permanent-password", v)
} }
#[cfg(feature = "flutter")]
#[cfg(not(any(target_os = "android", target_os = "ios")))]
pub fn set_unlock_pin(v: String, translate: bool) -> ResultType<()> {
let v = v.trim().to_owned();
let min_len = 4;
if !v.is_empty() && v.len() < min_len {
let err = if translate {
crate::lang::translate(
"Requires at least {".to_string() + &format!("{min_len}") + "} characters",
)
} else {
// Sometimes, translated can't show normally in command line
format!("Requires at least {} characters", min_len)
};
bail!(err);
}
Config::set_unlock_pin(&v);
set_config("unlock-pin", v)
}
#[cfg(feature = "flutter")]
#[cfg(not(any(target_os = "android", target_os = "ios")))]
pub fn get_unlock_pin() -> String {
if let Ok(Some(v)) = get_config("unlock-pin") {
Config::set_unlock_pin(&v);
v
} else {
Config::get_unlock_pin()
}
}
pub fn get_id() -> String { pub fn get_id() -> String {
if let Ok(Some(v)) = get_config("id") { if let Ok(Some(v)) = get_config("id") {
// update salt also, so that next time reinstallation not causing first-time auto-login failure // update salt also, so that next time reinstallation not causing first-time auto-login failure

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", "关于 RustDesk"), ("About RustDesk", "关于 RustDesk"),
("Send clipboard keystrokes", "发送剪贴板按键"), ("Send clipboard keystrokes", "发送剪贴板按键"),
("network_error_tip", "请检查网络连接,然后点击再试"), ("network_error_tip", "请检查网络连接,然后点击再试"),
("Unlock with PIN", "使用 PIN 码解锁设置"),
("Requires at least {} characters", "不少于{}个字符"),
("Wrong PIN", "PIN 码错误"),
("Set PIN", "设置 PIN 码"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", "O RustDesk"), ("About RustDesk", "O RustDesk"),
("Send clipboard keystrokes", "Odesílat stisky kláves schránky"), ("Send clipboard keystrokes", "Odesílat stisky kláves schránky"),
("network_error_tip", "Zkontrolujte prosím připojení k síti a klikněte na tlačítko Opakovat."), ("network_error_tip", "Zkontrolujte prosím připojení k síti a klikněte na tlačítko Opakovat."),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", "Über RustDesk"), ("About RustDesk", "Über RustDesk"),
("Send clipboard keystrokes", "Tastenanschläge aus der Zwischenablage senden"), ("Send clipboard keystrokes", "Tastenanschläge aus der Zwischenablage senden"),
("network_error_tip", "Bitte überprüfen Sie Ihre Netzwerkverbindung und versuchen Sie es dann erneut."), ("network_error_tip", "Bitte überprüfen Sie Ihre Netzwerkverbindung und versuchen Sie es dann erneut."),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -631,6 +631,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("cancel-bot-confirm-tip", "Sei sicuro di voler annullare Telegram?"), ("cancel-bot-confirm-tip", "Sei sicuro di voler annullare Telegram?"),
("About RustDesk", "Info su RustDesk"), ("About RustDesk", "Info su RustDesk"),
("Send clipboard keystrokes", "Invia sequenze tasti appunti"), ("Send clipboard keystrokes", "Invia sequenze tasti appunti"),
("network_error_tip", "Controlla la connessione di rete, quindi seleziona 'Riprova'.") ("network_error_tip", "Controlla la connessione di rete, quindi seleziona 'Riprova'."),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", "RustDeskについて"), ("About RustDesk", "RustDeskについて"),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", "RustDesk 대하여"), ("About RustDesk", "RustDesk 대하여"),
("Send clipboard keystrokes", "클립보드 키 입력 전송"), ("Send clipboard keystrokes", "클립보드 키 입력 전송"),
("network_error_tip", "네트워크 연결을 확인한 후 다시 시도하세요."), ("network_error_tip", "네트워크 연결을 확인한 후 다시 시도하세요."),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", "Over RustDesk"), ("About RustDesk", "Over RustDesk"),
("Send clipboard keystrokes", "Klembord toetsaanslagen verzenden"), ("Send clipboard keystrokes", "Klembord toetsaanslagen verzenden"),
("network_error_tip", "Controleer de netwerkverbinding en selecteer 'Opnieuw proberen'."), ("network_error_tip", "Controleer de netwerkverbinding en selecteer 'Opnieuw proberen'."),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", "О RustDesk"), ("About RustDesk", "О RustDesk"),
("Send clipboard keystrokes", "Отправлять нажатия клавиш из буфера обмена"), ("Send clipboard keystrokes", "Отправлять нажатия клавиш из буфера обмена"),
("network_error_tip", "Проверьте подключение к сети, затем нажмите \"Повтор\"."), ("network_error_tip", "Проверьте подключение к сети, затем нажмите \"Повтор\"."),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", "O RustDesk"), ("About RustDesk", "O RustDesk"),
("Send clipboard keystrokes", "Odoslať stlačenia klávesov zo schránky"), ("Send clipboard keystrokes", "Odoslať stlačenia klávesov zo schránky"),
("network_error_tip", "Skontrolujte svoje sieťové pripojenie a potom kliknite na tlačidlo Opakovať."), ("network_error_tip", "Skontrolujte svoje sieťové pripojenie a potom kliknite na tlačidlo Opakovať."),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", "關於 RustDesk"), ("About RustDesk", "關於 RustDesk"),
("Send clipboard keystrokes", "發送剪貼簿按鍵"), ("Send clipboard keystrokes", "發送剪貼簿按鍵"),
("network_error_tip", "請檢查網路連結,然後點擊重試"), ("network_error_tip", "請檢查網路連結,然後點擊重試"),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", "Про Rustdesk"), ("About RustDesk", "Про Rustdesk"),
("Send clipboard keystrokes", "Надіслати вміст буфера обміну"), ("Send clipboard keystrokes", "Надіслати вміст буфера обміну"),
("network_error_tip", "Будь ласка, перевірте ваше підключення до мережі та натисність \"Повторити\""), ("network_error_tip", "Будь ласка, перевірте ваше підключення до мережі та натисність \"Повторити\""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -632,5 +632,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("About RustDesk", ""), ("About RustDesk", ""),
("Send clipboard keystrokes", ""), ("Send clipboard keystrokes", ""),
("network_error_tip", ""), ("network_error_tip", ""),
("Unlock with PIN", ""),
("Requires at least {} characters", ""),
("Wrong PIN", ""),
("Set PIN", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -1444,3 +1444,22 @@ pub fn check_hwcodec() {
}) })
} }
} }
#[cfg(feature = "flutter")]
pub fn get_unlock_pin() -> String {
#[cfg(any(target_os = "android", target_os = "ios"))]
return String::default();
#[cfg(not(any(target_os = "android", target_os = "ios")))]
return ipc::get_unlock_pin();
}
#[cfg(feature = "flutter")]
pub fn set_unlock_pin(pin: String) -> String {
#[cfg(any(target_os = "android", target_os = "ios"))]
return String::default();
#[cfg(not(any(target_os = "android", target_os = "ios")))]
match ipc::set_unlock_pin(pin, true) {
Ok(_) => String::default(),
Err(err) => err.to_string(),
}
}