forked from mirrors/rustdesk
Add Android device deployment flow (#15146)
* Add Android device deployment flow Notify the Android Flutter UI when the server requires deployment, add a deploy dialog with API token/custom ID inputs, and reuse shared deploy logic for CLI and FFI Signed-off-by: 21pages <sunboeasy@gmail.com> * Hide Android deploy API token input Signed-off-by: 21pages <sunboeasy@gmail.com> * add more translations Signed-off-by: 21pages <sunboeasy@gmail.com> * optimize transations Signed-off-by: 21pages <sunboeasy@gmail.com> * Hide deploy action for outgoing-only clients Signed-off-by: 21pages <sunboeasy@gmail.com> * Fix deployment register throttle state reset Signed-off-by: 21pages <sunboeasy@gmail.com> * Move Android deploy dialog out of settings page Signed-off-by: 21pages <sunboeasy@gmail.com> * Use async mutex for deploy register throttle Signed-off-by: 21pages <sunboeasy@gmail.com> --------- Signed-off-by: 21pages <sunboeasy@gmail.com>
This commit is contained in:
parent
32c6e32e04
commit
d99ddf6816
59 changed files with 604 additions and 66 deletions
|
|
@ -27,6 +27,7 @@ import 'common.dart';
|
||||||
import 'consts.dart';
|
import 'consts.dart';
|
||||||
import 'mobile/pages/home_page.dart';
|
import 'mobile/pages/home_page.dart';
|
||||||
import 'mobile/pages/server_page.dart';
|
import 'mobile/pages/server_page.dart';
|
||||||
|
import 'mobile/widgets/deploy_dialog.dart';
|
||||||
import 'models/platform_model.dart';
|
import 'models/platform_model.dart';
|
||||||
|
|
||||||
import 'package:flutter_hbb/plugin/handlers.dart'
|
import 'package:flutter_hbb/plugin/handlers.dart'
|
||||||
|
|
@ -575,6 +576,14 @@ _registerEventHandler() {
|
||||||
NativeUiHandler.instance.onEvent(evt);
|
NativeUiHandler.instance.onEvent(evt);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (isAndroid) {
|
||||||
|
platformFFI.registerEventHandler(
|
||||||
|
'android_needs_deploy', 'android_needs_deploy', (_) async {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
showDeployPromptDialog();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget keyListenerBuilder(BuildContext context, Widget? child) {
|
Widget keyListenerBuilder(BuildContext context, Widget? child) {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import '../../common/widgets/login.dart';
|
||||||
import '../../consts.dart';
|
import '../../consts.dart';
|
||||||
import '../../models/model.dart';
|
import '../../models/model.dart';
|
||||||
import '../../models/platform_model.dart';
|
import '../../models/platform_model.dart';
|
||||||
|
import '../widgets/deploy_dialog.dart';
|
||||||
import '../widgets/dialog.dart';
|
import '../widgets/dialog.dart';
|
||||||
import 'home_page.dart';
|
import 'home_page.dart';
|
||||||
import 'scan_page.dart';
|
import 'scan_page.dart';
|
||||||
|
|
@ -728,6 +729,13 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
|
||||||
onPressed: (context) {
|
onPressed: (context) {
|
||||||
changeSocks5Proxy();
|
changeSocks5Proxy();
|
||||||
}),
|
}),
|
||||||
|
if (isAndroid && !bind.isOutgoingOnly())
|
||||||
|
SettingsTile(
|
||||||
|
title: Text(translate('Deploy')),
|
||||||
|
leading: Icon(Icons.cloud_upload),
|
||||||
|
onPressed: (context) {
|
||||||
|
showDeployDialog();
|
||||||
|
}),
|
||||||
if (!disabledSettings && !_hideNetwork && !_hideWebSocket)
|
if (!disabledSettings && !_hideNetwork && !_hideWebSocket)
|
||||||
SettingsTile.switchTile(
|
SettingsTile.switchTile(
|
||||||
title: Text(translate('Use WebSocket')),
|
title: Text(translate('Use WebSocket')),
|
||||||
|
|
|
||||||
114
flutter/lib/mobile/widgets/deploy_dialog.dart
Normal file
114
flutter/lib/mobile/widgets/deploy_dialog.dart
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
import '../../common.dart';
|
||||||
|
import '../../models/platform_model.dart';
|
||||||
|
|
||||||
|
const _deployDialogTag = 'android-deploy-device';
|
||||||
|
|
||||||
|
void showDeployPromptDialog() {
|
||||||
|
gFFI.dialogManager.dismissByTag(_deployDialogTag);
|
||||||
|
gFFI.dialogManager.show<bool>((setState, close, context) {
|
||||||
|
submit() => close(true);
|
||||||
|
return CustomAlertDialog(
|
||||||
|
title: Text(translate("Deploy")),
|
||||||
|
content: Text(translate("server_requires_deployment_tip")),
|
||||||
|
actions: [
|
||||||
|
dialogButton("Cancel", onPressed: close, isOutline: true),
|
||||||
|
dialogButton("OK", onPressed: submit),
|
||||||
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: close,
|
||||||
|
);
|
||||||
|
}, tag: _deployDialogTag).then((deploy) {
|
||||||
|
if (deploy == true) {
|
||||||
|
showDeployDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void showDeployDialog() {
|
||||||
|
gFFI.dialogManager.dismissByTag(_deployDialogTag);
|
||||||
|
final tokenController = TextEditingController();
|
||||||
|
final idController = TextEditingController();
|
||||||
|
var errorText = "";
|
||||||
|
var isInProgress = false;
|
||||||
|
gFFI.dialogManager.show((setState, close, context) {
|
||||||
|
submit() async {
|
||||||
|
if (isInProgress) return;
|
||||||
|
final token = tokenController.text.trim();
|
||||||
|
if (token.isEmpty) {
|
||||||
|
setState(() {
|
||||||
|
errorText = translate("token is required!");
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
errorText = "";
|
||||||
|
isInProgress = true;
|
||||||
|
});
|
||||||
|
String res;
|
||||||
|
try {
|
||||||
|
res = await bind.mainDeployDevice(
|
||||||
|
token: token, id: idController.text.trim());
|
||||||
|
} catch (e) {
|
||||||
|
setState(() {
|
||||||
|
errorText = translate(e.toString());
|
||||||
|
isInProgress = false;
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (res.isEmpty) {
|
||||||
|
close();
|
||||||
|
await gFFI.serverModel.fetchID();
|
||||||
|
showToast(translate("Successful"));
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
errorText = translate(res.toString());
|
||||||
|
isInProgress = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CustomAlertDialog(
|
||||||
|
title: Text(translate("Deploy")),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
TextField(
|
||||||
|
controller: tokenController,
|
||||||
|
decoration: InputDecoration(labelText: translate("API Token")),
|
||||||
|
obscureText: true,
|
||||||
|
enableSuggestions: false,
|
||||||
|
autocorrect: false,
|
||||||
|
autofocus: true,
|
||||||
|
).workaroundFreezeLinuxMint(),
|
||||||
|
TextField(
|
||||||
|
controller: idController,
|
||||||
|
decoration:
|
||||||
|
InputDecoration(labelText: translate("Custom ID (optional)")),
|
||||||
|
).workaroundFreezeLinuxMint(),
|
||||||
|
if (errorText.isNotEmpty)
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: SelectableText(
|
||||||
|
errorText,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.error,
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
).paddingOnly(top: 8),
|
||||||
|
),
|
||||||
|
if (isInProgress) const LinearProgressIndicator().paddingOnly(top: 8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
dialogButton("Cancel",
|
||||||
|
onPressed: isInProgress ? null : close, isOutline: true),
|
||||||
|
dialogButton("OK", onPressed: isInProgress ? null : submit),
|
||||||
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: isInProgress ? null : close,
|
||||||
|
);
|
||||||
|
}, tag: _deployDialogTag);
|
||||||
|
}
|
||||||
|
|
@ -2034,7 +2034,14 @@ class RustdeskImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
String mainResolveAvatarUrl({required String avatar, dynamic hint}) {
|
String mainResolveAvatarUrl({required String avatar, dynamic hint}) {
|
||||||
return js.context.callMethod('getByName', ['resolve_avatar_url', avatar])?.toString() ?? avatar;
|
return js.context.callMethod(
|
||||||
|
'getByName', ['resolve_avatar_url', avatar])?.toString() ??
|
||||||
|
avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> mainDeployDevice(
|
||||||
|
{required String token, required String id, dynamic hint}) {
|
||||||
|
throw UnimplementedError("mainDeployDevice");
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {}
|
void dispose() {}
|
||||||
|
|
|
||||||
|
|
@ -644,6 +644,8 @@ pub fn core_main() -> Option<Vec<String>> {
|
||||||
} else if args[0] == "--deploy" {
|
} else if args[0] == "--deploy" {
|
||||||
if config::Config::no_register_device() {
|
if config::Config::no_register_device() {
|
||||||
println!("Cannot deploy an unregistrable device!");
|
println!("Cannot deploy an unregistrable device!");
|
||||||
|
} else if config::is_outgoing_only() {
|
||||||
|
println!("Cannot deploy Outgoing-only clients.");
|
||||||
} else if crate::platform::is_installed() && is_root() {
|
} else if crate::platform::is_installed() && is_root() {
|
||||||
let max = args.len() - 1;
|
let max = args.len() - 1;
|
||||||
let pos = args.iter().position(|x| x == "--token").unwrap_or(max);
|
let pos = args.iter().position(|x| x == "--token").unwrap_or(max);
|
||||||
|
|
@ -661,72 +663,28 @@ pub fn core_main() -> Option<Vec<String>> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let new_id = get_value("--id");
|
let new_id = get_value("--id");
|
||||||
let local_id = crate::ipc::get_id();
|
match crate::ui_interface::deploy_device(token, new_id) {
|
||||||
let id_to_deploy = new_id.clone().unwrap_or_else(|| local_id.clone());
|
crate::ui_interface::DeployResult::Ok => {
|
||||||
let uuid = crate::encode64(hbb_common::get_uuid());
|
println!("Device deployed.");
|
||||||
let pk = crate::encode64(
|
|
||||||
hbb_common::config::Config::get_key_pair().1,
|
|
||||||
);
|
|
||||||
let body = serde_json::json!({
|
|
||||||
"id": id_to_deploy,
|
|
||||||
"uuid": uuid,
|
|
||||||
"pk": pk,
|
|
||||||
});
|
|
||||||
let header = "Authorization: Bearer ".to_owned() + &token;
|
|
||||||
let url = crate::ui_interface::get_api_server() + "/api/devices/deploy";
|
|
||||||
match crate::post_request_sync(url, body.to_string(), &header) {
|
|
||||||
Err(err) => {
|
|
||||||
println!("Request failed: {}", err);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
}
|
||||||
Ok(text) => {
|
crate::ui_interface::DeployResult::NotEnabled => {
|
||||||
let parsed: serde_json::Value =
|
println!("Server does not require deployment.");
|
||||||
serde_json::from_str(&text).unwrap_or(serde_json::Value::Null);
|
std::process::exit(3);
|
||||||
let result = parsed["result"].as_str().unwrap_or("");
|
}
|
||||||
match result {
|
crate::ui_interface::DeployResult::InvalidInput => {
|
||||||
"OK" => {
|
println!("Invalid input.");
|
||||||
if let Some(ref new_id) = new_id {
|
std::process::exit(5);
|
||||||
if *new_id != local_id {
|
}
|
||||||
if let Err(err) =
|
crate::ui_interface::DeployResult::IdTaken(id) => {
|
||||||
crate::ipc::set_config("id", new_id.clone())
|
println!(
|
||||||
{
|
"Id `{}` is already used by another machine on the server.",
|
||||||
println!(
|
id
|
||||||
"Failed to persist deployed id locally: {}",
|
);
|
||||||
err
|
std::process::exit(6);
|
||||||
);
|
}
|
||||||
std::process::exit(1);
|
crate::ui_interface::DeployResult::Error(err) => {
|
||||||
}
|
println!("{}", err);
|
||||||
}
|
std::process::exit(1);
|
||||||
}
|
|
||||||
if let Err(err) = crate::ipc::notify_deployed() {
|
|
||||||
log::warn!("Failed to notify deployed state: {}", err);
|
|
||||||
}
|
|
||||||
println!("Device deployed.");
|
|
||||||
}
|
|
||||||
"NOT_ENABLED" => {
|
|
||||||
println!("Server does not require deployment.");
|
|
||||||
std::process::exit(3);
|
|
||||||
}
|
|
||||||
"INVALID_INPUT" => {
|
|
||||||
println!("Invalid input.");
|
|
||||||
std::process::exit(5);
|
|
||||||
}
|
|
||||||
"ID_TAKEN" => {
|
|
||||||
println!(
|
|
||||||
"Id `{}` is already used by another machine on the server.",
|
|
||||||
id_to_deploy
|
|
||||||
);
|
|
||||||
std::process::exit(6);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
if text.is_empty() {
|
|
||||||
println!("Unknown response.");
|
|
||||||
} else {
|
|
||||||
println!("{}", text);
|
|
||||||
}
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1153,6 +1153,22 @@ pub fn main_get_api_server() -> String {
|
||||||
get_api_server()
|
get_api_server()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn main_deploy_device(token: String, id: String) -> String {
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
{
|
||||||
|
let new_id = match id.trim() {
|
||||||
|
"" => None,
|
||||||
|
id => Some(id.to_owned()),
|
||||||
|
};
|
||||||
|
ui_interface::deploy_device(token, new_id).message()
|
||||||
|
}
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
|
{
|
||||||
|
let _ = (token, id);
|
||||||
|
"Deployment is not supported on this platform.".to_owned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main_resolve_avatar_url(avatar: String) -> SyncReturn<String> {
|
pub fn main_resolve_avatar_url(avatar: String) -> SyncReturn<String> {
|
||||||
SyncReturn(resolve_avatar_url(avatar))
|
SyncReturn(resolve_avatar_url(avatar))
|
||||||
}
|
}
|
||||||
|
|
@ -2116,6 +2132,7 @@ pub fn main_start_service() {
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
{
|
{
|
||||||
config::Config::set_option("stop-service".into(), "".into());
|
config::Config::set_option("stop-service".into(), "".into());
|
||||||
|
crate::rendezvous_mediator::reset_needs_deploy_notification();
|
||||||
crate::rendezvous_mediator::RendezvousMediator::restart();
|
crate::rendezvous_mediator::RendezvousMediator::restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3055,6 +3072,7 @@ pub mod server_side {
|
||||||
pub unsafe extern "system" fn Java_ffi_FFI_startService(_env: JNIEnv, _class: JClass) {
|
pub unsafe extern "system" fn Java_ffi_FFI_startService(_env: JNIEnv, _class: JClass) {
|
||||||
log::debug!("startService from jvm");
|
log::debug!("startService from jvm");
|
||||||
config::Config::set_option("stop-service".into(), "".into());
|
config::Config::set_option("stop-service".into(), "".into());
|
||||||
|
crate::rendezvous_mediator::reset_needs_deploy_notification();
|
||||||
crate::rendezvous_mediator::RendezvousMediator::restart();
|
crate::rendezvous_mediator::RendezvousMediator::restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "كلمة المرور المحددة مسبقًا قيد الاستخدام"),
|
("preset-password-in-use-tip", "كلمة المرور المحددة مسبقًا قيد الاستخدام"),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "Пададзены пароль цяпер выкарыстоўваецца"),
|
("preset-password-in-use-tip", "Пададзены пароль цяпер выкарыстоўваецца"),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "当前使用预设密码"),
|
("preset-password-in-use-tip", "当前使用预设密码"),
|
||||||
("Enable privacy mode", "允许隐私模式"),
|
("Enable privacy mode", "允许隐私模式"),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", "API 令牌"),
|
||||||
|
("Deploy", "部署"),
|
||||||
|
("Custom ID (optional)", "自定义 ID(可选)"),
|
||||||
|
("server_requires_deployment_tip", "服务器要求显式部署此设备。是否立即部署?"),
|
||||||
|
("The server does not require explicit deployment.", "服务器不需要显式部署。"),
|
||||||
|
("Unknown response.", "未知响应。"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "Das voreingestellte Passwort wird derzeit verwendet."),
|
("preset-password-in-use-tip", "Das voreingestellte Passwort wird derzeit verwendet."),
|
||||||
("Enable privacy mode", "Datenschutzmodus aktivieren"),
|
("Enable privacy mode", "Datenschutzmodus aktivieren"),
|
||||||
("allow-remote-toolbar-docking-any-edge", "Andocken der Remote-Symbolleiste an jeden Fensterrand zulassen"),
|
("allow-remote-toolbar-docking-any-edge", "Andocken der Remote-Symbolleiste an jeden Fensterrand zulassen"),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -275,5 +275,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("password-hidden-tip", "Permanent password is set (hidden)."),
|
("password-hidden-tip", "Permanent password is set (hidden)."),
|
||||||
("preset-password-in-use-tip", "Preset password is currently in use."),
|
("preset-password-in-use-tip", "Preset password is currently in use."),
|
||||||
("allow-remote-toolbar-docking-any-edge", "Allow docking remote toolbar to any window edge"),
|
("allow-remote-toolbar-docking-any-edge", "Allow docking remote toolbar to any window edge"),
|
||||||
|
("server_requires_deployment_tip", "The server requires this device to be deployed explicitly. Deploy now?"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "Se está usando la contraseña predeterminada."),
|
("preset-password-in-use-tip", "Se está usando la contraseña predeterminada."),
|
||||||
("Enable privacy mode", "Habilitar modo privado"),
|
("Enable privacy mode", "Habilitar modo privado"),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "Le mot de passe prédéfini est actuellement utilisé."),
|
("preset-password-in-use-tip", "Le mot de passe prédéfini est actuellement utilisé."),
|
||||||
("Enable privacy mode", "Activer le mode de confidentialité"),
|
("Enable privacy mode", "Activer le mode de confidentialité"),
|
||||||
("allow-remote-toolbar-docking-any-edge", "Autoriser l’ancrage de la barre d’outils à distance sur n’importe quel bord de la fenêtre"),
|
("allow-remote-toolbar-docking-any-edge", "Autoriser l’ancrage de la barre d’outils à distance sur n’importe quel bord de la fenêtre"),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "પ્રીસેટ પાસવર્ડ વપરાશમાં છે."),
|
("preset-password-in-use-tip", "પ્રીસેટ પાસવર્ડ વપરાશમાં છે."),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "पूर्व-निर्धारित पासवर्ड उपयोग में है।"),
|
("preset-password-in-use-tip", "पूर्व-निर्धारित पासवर्ड उपयोग में है।"),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "Jelenleg az alapértelmezett jelszót használja."),
|
("preset-password-in-use-tip", "Jelenleg az alapértelmezett jelszót használja."),
|
||||||
("Enable privacy mode", "Adatvédelmi mód aktiválása"),
|
("Enable privacy mode", "Adatvédelmi mód aktiválása"),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "È attualmente in uso la password preimpostata."),
|
("preset-password-in-use-tip", "È attualmente in uso la password preimpostata."),
|
||||||
("Enable privacy mode", "Abilita modalità privacy"),
|
("Enable privacy mode", "Abilita modalità privacy"),
|
||||||
("allow-remote-toolbar-docking-any-edge", "Consenti ancoraggio barra strumenti remota a qualsiasi bordo della finestra"),
|
("allow-remote-toolbar-docking-any-edge", "Consenti ancoraggio barra strumenti remota a qualsiasi bordo della finestra"),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "プリセットパスワードが現在使用されています"),
|
("preset-password-in-use-tip", "プリセットパスワードが現在使用されています"),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "현재 사전 설정된 비밀번호가 사용 중입니다."),
|
("preset-password-in-use-tip", "현재 사전 설정된 비밀번호가 사용 중입니다."),
|
||||||
("Enable privacy mode", "개인정보 보호 모드 사용함"),
|
("Enable privacy mode", "개인정보 보호 모드 사용함"),
|
||||||
("allow-remote-toolbar-docking-any-edge", "원격 도구 모음을 창 가장자리에 도킹 허용"),
|
("allow-remote-toolbar-docking-any-edge", "원격 도구 모음을 창 가장자리에 도킹 허용"),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "Iepriekš iestatītā parole pašlaik tiek izmantota."),
|
("preset-password-in-use-tip", "Iepriekš iestatītā parole pašlaik tiek izmantota."),
|
||||||
("Enable privacy mode", "Iespējot privātuma režīmu"),
|
("Enable privacy mode", "Iespējot privātuma režīmu"),
|
||||||
("allow-remote-toolbar-docking-any-edge", "Atļaut attālās rīkjoslas piestiprināšanu pie jebkuras loga malas"),
|
("allow-remote-toolbar-docking-any-edge", "Atļaut attālās rīkjoslas piestiprināšanu pie jebkuras loga malas"),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "പ്രീസെറ്റ് പാസ്വേഡ് ഉപയോഗത്തിലാണ്."),
|
("preset-password-in-use-tip", "പ്രീസെറ്റ് പാസ്വേഡ് ഉപയോഗത്തിലാണ്."),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "Het basis wachtwoord is momenteel in gebruik."),
|
("preset-password-in-use-tip", "Het basis wachtwoord is momenteel in gebruik."),
|
||||||
("Enable privacy mode", "Privacymodus inschakelen"),
|
("Enable privacy mode", "Privacymodus inschakelen"),
|
||||||
("allow-remote-toolbar-docking-any-edge", "Sta toe om de werkbalk-op-afstand aan de rand van het venster te plaatsen"),
|
("allow-remote-toolbar-docking-any-edge", "Sta toe om de werkbalk-op-afstand aan de rand van het venster te plaatsen"),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "Obecnie używane jest hasło domyślne."),
|
("preset-password-in-use-tip", "Obecnie używane jest hasło domyślne."),
|
||||||
("Enable privacy mode", "Włącz tryb prywatny"),
|
("Enable privacy mode", "Włącz tryb prywatny"),
|
||||||
("allow-remote-toolbar-docking-any-edge", "Zezwalaj na dokowanie zdalnego paska narzędzi do dowolnej krawędzi"),
|
("allow-remote-toolbar-docking-any-edge", "Zezwalaj na dokowanie zdalnego paska narzędzi do dowolnej krawędzi"),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "A senha predefinida está sendo usada."),
|
("preset-password-in-use-tip", "A senha predefinida está sendo usada."),
|
||||||
("Enable privacy mode", "Habilitar modo de privacidade"),
|
("Enable privacy mode", "Habilitar modo de privacidade"),
|
||||||
("allow-remote-toolbar-docking-any-edge", "Permitir fixar a barra de ferramentas remota em qualquer borda da janela"),
|
("allow-remote-toolbar-docking-any-edge", "Permitir fixar a barra de ferramentas remota em qualquer borda da janela"),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "Se folosește o parolă prestabilită. Se recomandă setarea unei parole personalizate pentru securitate sporită."),
|
("preset-password-in-use-tip", "Se folosește o parolă prestabilită. Se recomandă setarea unei parole personalizate pentru securitate sporită."),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "Установленный пароль сейчас используется."),
|
("preset-password-in-use-tip", "Установленный пароль сейчас используется."),
|
||||||
("Enable privacy mode", "Использовать режим конфиденциальности"),
|
("Enable privacy mode", "Использовать режим конфиденциальности"),
|
||||||
("allow-remote-toolbar-docking-any-edge", "Разрешать прикрепление удалённой панели инструментов к любому краю окна"),
|
("allow-remote-toolbar-docking-any-edge", "Разрешать прикрепление удалённой панели инструментов к любому краю окна"),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "Önceden ayarlanmış parola kullanılıyor"),
|
("preset-password-in-use-tip", "Önceden ayarlanmış parola kullanılıyor"),
|
||||||
("Enable privacy mode", "Gizlilik modunu etkinleştir"),
|
("Enable privacy mode", "Gizlilik modunu etkinleştir"),
|
||||||
("allow-remote-toolbar-docking-any-edge", "Uzak araç çubuğunun pencerenin herhangi bir kenarına sabitlenmesine izin ver"),
|
("allow-remote-toolbar-docking-any-edge", "Uzak araç çubuğunun pencerenin herhangi bir kenarına sabitlenmesine izin ver"),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", "目前正在使用預設密碼"),
|
("preset-password-in-use-tip", "目前正在使用預設密碼"),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,5 +745,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||||
("preset-password-in-use-tip", ""),
|
("preset-password-in-use-tip", ""),
|
||||||
("Enable privacy mode", ""),
|
("Enable privacy mode", ""),
|
||||||
("allow-remote-toolbar-docking-any-edge", ""),
|
("allow-remote-toolbar-docking-any-edge", ""),
|
||||||
|
("API Token", ""),
|
||||||
|
("Deploy", ""),
|
||||||
|
("Custom ID (optional)", ""),
|
||||||
|
("server_requires_deployment_tip", ""),
|
||||||
|
("The server does not require explicit deployment.", ""),
|
||||||
|
("Unknown response.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ static SHOULD_EXIT: AtomicBool = AtomicBool::new(false);
|
||||||
static MANUAL_RESTARTED: AtomicBool = AtomicBool::new(false);
|
static MANUAL_RESTARTED: AtomicBool = AtomicBool::new(false);
|
||||||
static SENT_REGISTER_PK: AtomicBool = AtomicBool::new(false);
|
static SENT_REGISTER_PK: AtomicBool = AtomicBool::new(false);
|
||||||
pub(crate) static NEEDS_DEPLOY: AtomicBool = AtomicBool::new(false);
|
pub(crate) static NEEDS_DEPLOY: AtomicBool = AtomicBool::new(false);
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
static NOTIFIED_NEEDS_DEPLOY: AtomicBool = AtomicBool::new(false);
|
||||||
// register_pk retry interval (ms) when device is awaiting deployment
|
// register_pk retry interval (ms) when device is awaiting deployment
|
||||||
const DEPLOY_RETRY_INTERVAL: i64 = 30_000;
|
const DEPLOY_RETRY_INTERVAL: i64 = 30_000;
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
|
|
@ -66,6 +68,26 @@ async fn deploy_register_throttled() -> bool {
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
fn notify_android_needs_deploy() {
|
||||||
|
if NOTIFIED_NEEDS_DEPLOY.load(Ordering::SeqCst) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let event = serde_json::json!({ "name": "android_needs_deploy" }).to_string();
|
||||||
|
if matches!(
|
||||||
|
crate::flutter::push_global_event(crate::flutter::APP_TYPE_MAIN, event),
|
||||||
|
Some(true)
|
||||||
|
) {
|
||||||
|
NOTIFIED_NEEDS_DEPLOY.store(true, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
pub(crate) fn reset_needs_deploy_notification() {
|
||||||
|
NEEDS_DEPLOY.store(false, Ordering::SeqCst);
|
||||||
|
NOTIFIED_NEEDS_DEPLOY.store(false, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RendezvousMediator {
|
pub struct RendezvousMediator {
|
||||||
addr: TargetAddr<'static>,
|
addr: TargetAddr<'static>,
|
||||||
|
|
@ -117,6 +139,7 @@ impl RendezvousMediator {
|
||||||
crate::platform::linux_desktop_manager::start_xdesktop();
|
crate::platform::linux_desktop_manager::start_xdesktop();
|
||||||
}
|
}
|
||||||
scrap::codec::test_av1();
|
scrap::codec::test_av1();
|
||||||
|
*LAST_NOT_DEPLOYED_REGISTER.lock().await = None;
|
||||||
loop {
|
loop {
|
||||||
let timeout = Arc::new(RwLock::new(CONNECT_TIMEOUT));
|
let timeout = Arc::new(RwLock::new(CONNECT_TIMEOUT));
|
||||||
let conn_start_time = Instant::now();
|
let conn_start_time = Instant::now();
|
||||||
|
|
@ -322,6 +345,8 @@ impl RendezvousMediator {
|
||||||
Config::set_host_key_confirmed(&self.host_prefix, true);
|
Config::set_host_key_confirmed(&self.host_prefix, true);
|
||||||
*SOLVING_PK_MISMATCH.lock().await = "".to_owned();
|
*SOLVING_PK_MISMATCH.lock().await = "".to_owned();
|
||||||
NEEDS_DEPLOY.store(false, Ordering::SeqCst);
|
NEEDS_DEPLOY.store(false, Ordering::SeqCst);
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
reset_needs_deploy_notification();
|
||||||
}
|
}
|
||||||
Ok(register_pk_response::Result::UUID_MISMATCH) => {
|
Ok(register_pk_response::Result::UUID_MISMATCH) => {
|
||||||
self.handle_uuid_mismatch(sink).await?;
|
self.handle_uuid_mismatch(sink).await?;
|
||||||
|
|
@ -336,6 +361,8 @@ impl RendezvousMediator {
|
||||||
// was deleted by an admin while running.
|
// was deleted by an admin while running.
|
||||||
Config::set_key_confirmed(false);
|
Config::set_key_confirmed(false);
|
||||||
Config::set_host_key_confirmed(&self.host_prefix, false);
|
Config::set_host_key_confirmed(&self.host_prefix, false);
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
notify_android_needs_deploy();
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
log::error!("unknown RegisterPkResponse");
|
log::error!("unknown RegisterPkResponse");
|
||||||
|
|
|
||||||
|
|
@ -1020,6 +1020,102 @@ pub fn get_api_server() -> String {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum DeployResult {
|
||||||
|
Ok,
|
||||||
|
NotEnabled,
|
||||||
|
InvalidInput,
|
||||||
|
IdTaken(String),
|
||||||
|
Error(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeployResult {
|
||||||
|
pub fn message(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Self::Ok => "".to_owned(),
|
||||||
|
Self::NotEnabled => "The server does not require explicit deployment.".to_owned(),
|
||||||
|
Self::InvalidInput => "Invalid input.".to_owned(),
|
||||||
|
Self::IdTaken(id) => {
|
||||||
|
format!(
|
||||||
|
"Id `{}` is already used by another machine on the server.",
|
||||||
|
id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Self::Error(err) => err.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deploy_device(token: String, new_id: Option<String>) -> DeployResult {
|
||||||
|
if Config::no_register_device() {
|
||||||
|
return DeployResult::Error("Cannot deploy an unregistrable device!".to_owned());
|
||||||
|
}
|
||||||
|
let token = token.trim();
|
||||||
|
if token.is_empty() {
|
||||||
|
return DeployResult::Error("token is required!".to_owned());
|
||||||
|
}
|
||||||
|
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||||
|
let local_id = Config::get_id();
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
let local_id = ipc::get_id();
|
||||||
|
let id_to_deploy = new_id.clone().unwrap_or_else(|| local_id.clone());
|
||||||
|
let uuid = crate::encode64(hbb_common::get_uuid());
|
||||||
|
let pk = crate::encode64(Config::get_key_pair().1);
|
||||||
|
let body = serde_json::json!({
|
||||||
|
"id": id_to_deploy,
|
||||||
|
"uuid": uuid,
|
||||||
|
"pk": pk,
|
||||||
|
});
|
||||||
|
let header = "Authorization: Bearer ".to_owned() + token;
|
||||||
|
let url = get_api_server() + "/api/devices/deploy";
|
||||||
|
let text = match crate::post_request_sync(url, body.to_string(), &header) {
|
||||||
|
Ok(text) => text,
|
||||||
|
Err(err) => return DeployResult::Error(format!("Request failed: {}", err)),
|
||||||
|
};
|
||||||
|
let parsed: serde_json::Value = serde_json::from_str(&text).unwrap_or(serde_json::Value::Null);
|
||||||
|
match parsed["result"].as_str().unwrap_or("") {
|
||||||
|
"OK" => {
|
||||||
|
if let Some(new_id) = new_id {
|
||||||
|
if new_id != local_id {
|
||||||
|
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||||
|
{
|
||||||
|
Config::set_key_confirmed(false);
|
||||||
|
Config::set_id(&new_id);
|
||||||
|
}
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
if let Err(err) = ipc::set_config("id", new_id) {
|
||||||
|
return DeployResult::Error(format!(
|
||||||
|
"Failed to persist deployed id locally: {}",
|
||||||
|
err
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
if let Err(err) = ipc::notify_deployed() {
|
||||||
|
log::warn!("Failed to notify deployed state: {}", err);
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
{
|
||||||
|
crate::rendezvous_mediator::NEEDS_DEPLOY
|
||||||
|
.store(false, std::sync::atomic::Ordering::SeqCst);
|
||||||
|
crate::rendezvous_mediator::reset_needs_deploy_notification();
|
||||||
|
crate::rendezvous_mediator::RendezvousMediator::restart();
|
||||||
|
}
|
||||||
|
DeployResult::Ok
|
||||||
|
}
|
||||||
|
"NOT_ENABLED" => DeployResult::NotEnabled,
|
||||||
|
"INVALID_INPUT" => DeployResult::InvalidInput,
|
||||||
|
"ID_TAKEN" => DeployResult::IdTaken(id_to_deploy),
|
||||||
|
_ => {
|
||||||
|
if text.is_empty() {
|
||||||
|
DeployResult::Error("Unknown response.".to_owned())
|
||||||
|
} else {
|
||||||
|
DeployResult::Error(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn has_hwcodec() -> bool {
|
pub fn has_hwcodec() -> bool {
|
||||||
// Has real hardware codec using gpu
|
// Has real hardware codec using gpu
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue