From 77de0d05f95d45d3f84e28df8b43fb2fd1328f1f Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 14 Oct 2022 11:19:49 +0800 Subject: [PATCH] msgbox & translations Signed-off-by: fufesou --- flutter/lib/common.dart | 14 ++++- .../lib/desktop/pages/desktop_home_page.dart | 2 +- flutter/lib/mobile/widgets/dialog.dart | 2 +- flutter/lib/models/model.dart | 17 +++--- libs/hbb_common/protos/message.proto | 14 +++++ libs/hbb_common/src/config.rs | 10 +++- src/client.rs | 19 ++++-- src/client/io_loop.rs | 59 ++++++++++++------- src/common.rs | 6 +- src/flutter.rs | 3 +- src/lang/cn.rs | 4 ++ src/lang/cs.rs | 4 ++ src/lang/da.rs | 4 ++ src/lang/de.rs | 4 ++ src/lang/en.rs | 1 + src/lang/eo.rs | 4 ++ src/lang/es.rs | 4 ++ src/lang/fr.rs | 4 ++ src/lang/hu.rs | 4 ++ src/lang/id.rs | 4 ++ src/lang/it.rs | 4 ++ src/lang/ja.rs | 4 ++ src/lang/ko.rs | 4 ++ src/lang/kz.rs | 4 ++ src/lang/pl.rs | 4 ++ src/lang/pt_PT.rs | 4 ++ src/lang/ptbr.rs | 4 ++ src/lang/ru.rs | 4 ++ src/lang/sk.rs | 4 ++ src/lang/template.rs | 4 ++ src/lang/tr.rs | 4 ++ src/lang/tw.rs | 4 ++ src/lang/ua.rs | 4 ++ src/lang/vn.rs | 4 ++ src/port_forward.rs | 4 +- src/server/connection.rs | 4 ++ src/server/video_service.rs | 16 ++++- src/server/wayland.rs | 34 +++++++++-- src/ui/common.tis | 12 ++-- src/ui/msgbox.tis | 12 ++++ src/ui/remote.rs | 4 +- src/ui_session_interface.rs | 10 ++-- 42 files changed, 271 insertions(+), 64 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 686ef3144..caa143632 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -18,6 +18,7 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:window_manager/window_manager.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:window_size/window_size.dart' as window_size; +import 'package:url_launcher/url_launcher.dart'; import 'common/widgets/overlay.dart'; import 'mobile/pages/file_manager_page.dart'; @@ -618,8 +619,8 @@ class CustomAlertDialog extends StatelessWidget { } } -void msgBox( - String type, String title, String text, OverlayDialogManager dialogManager, +void msgBox(String type, String title, String text, String link, + OverlayDialogManager dialogManager, {bool? hasCancel}) { dialogManager.dismissAll(); List buttons = []; @@ -636,6 +637,12 @@ void msgBox( dialogManager.dismissAll(); } + jumplink() { + if (link.startsWith('http')) { + launchUrl(Uri.parse(link)); + } + } + if (type != "connecting" && type != "success" && !type.contains("nook")) { hasOk = true; buttons.insert(0, msgBoxButton(translate('OK'), submit)); @@ -654,6 +661,9 @@ void msgBox( dialogManager.dismissAll(); })); } + if (link.isNotEmpty) { + buttons.insert(0, msgBoxButton(translate('JumpLink'), jumplink)); + } dialogManager.show((setState, close) => CustomAlertDialog( title: _msgBoxTitle(title), content: SelectableText(translate(text), diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index 4bdbbbaac..a31a71802 100644 --- a/flutter/lib/desktop/pages/desktop_home_page.dart +++ b/flutter/lib/desktop/pages/desktop_home_page.dart @@ -414,7 +414,7 @@ class _DesktopHomePageState extends State final root = await bind.mainIsRoot(); final release = await bind.mainIsRelease(); if (Platform.isWindows && release && !installed && !root) { - msgBox('custom-elevation-nocancel', 'Prompt', 'elevation_prompt', + msgBox('custom-elevation-nocancel', 'Prompt', 'elevation_prompt', '', gFFI.dialogManager); } }); diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index 455922e34..ca82cbed9 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -6,7 +6,7 @@ import '../../models/model.dart'; import '../../models/platform_model.dart'; void clientClose(OverlayDialogManager dialogManager) { - msgBox('', 'Close', 'Are you sure to close the connection?', dialogManager); + msgBox('', 'Close', 'Are you sure to close the connection?', '', dialogManager); } void showSuccess() { diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 1fd33bc77..79cd7ad54 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -222,26 +222,27 @@ class FfiModel with ChangeNotifier { handleMsgBox(Map evt, String id) { if (parent.target == null) return; final dialogManager = parent.target!.dialogManager; - var type = evt['type']; - var title = evt['title']; - var text = evt['text']; + final type = evt['type']; + final title = evt['title']; + final text = evt['text']; + final link = evt['link']; if (type == 're-input-password') { wrongPasswordDialog(id, dialogManager); } else if (type == 'input-password') { enterPasswordDialog(id, dialogManager); } else if (type == 'restarting') { - showMsgBox(id, type, title, text, false, dialogManager, hasCancel: false); + showMsgBox(id, type, title, text, link, false, dialogManager, hasCancel: false); } else { var hasRetry = evt['hasRetry'] == 'true'; - showMsgBox(id, type, title, text, hasRetry, dialogManager); + showMsgBox(id, type, title, text, link, hasRetry, dialogManager); } } /// Show a message box with [type], [title] and [text]. - showMsgBox(String id, String type, String title, String text, bool hasRetry, - OverlayDialogManager dialogManager, + showMsgBox(String id, String type, String title, String text, String link, + bool hasRetry, OverlayDialogManager dialogManager, {bool? hasCancel}) { - msgBox(type, title, text, dialogManager, hasCancel: hasCancel); + msgBox(type, title, text, link, dialogManager, hasCancel: hasCancel); _timer?.cancel(); if (hasRetry) { _timer = Timer(Duration(seconds: _reconnects), () { diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 1f3d24157..a48ec9d14 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -506,6 +506,19 @@ message AudioFrame { int64 timestamp = 2; } +// Notify peer to show message box. +message MessageBox { + // Message type. Refer to flutter/lib/commom.dart/msgBox(). + string msgtype = 1; + string title = 2; + // English + string text = 3; + // If not empty, msgbox provides a button to following the link. + // The link here can't be directly http url. + // It must be the key of http url configed in peer side or "rustdesk://*" (jump in app). + string link = 4; +} + message BackNotification { // no need to consider block input by someone else enum BlockInputState { @@ -581,5 +594,6 @@ message Message { FileResponse file_response = 18; Misc misc = 19; Cliprdr cliprdr = 20; + MessageBox message_box = 21; } } diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 0ef507a13..ad0585549 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -53,11 +53,19 @@ lazy_static::lazy_static! { static ref HW_CODEC_CONFIG: Arc> = Arc::new(RwLock::new(HwCodecConfig::load())); } -// #[cfg(any(target_os = "android", target_os = "ios"))] lazy_static::lazy_static! { pub static ref APP_DIR: Arc> = Default::default(); pub static ref APP_HOME_DIR: Arc> = Default::default(); } + +// #[cfg(any(target_os = "android", target_os = "ios"))] +lazy_static::lazy_static! { + pub static ref HELPER_URL: HashMap<&'static str, &'static str> = HashMap::from([ + ("rustdesk docs home", "https://rustdesk.com/docs/en/"), + ("rustdesk docs x11-required", "https://rustdesk.com/docs/en/manual/linux/#x11-required"), + ]); +} + const CHARS: &'static [char] = &[ '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', diff --git a/src/client.rs b/src/client.rs index 8723480f3..6b3917790 100644 --- a/src/client.rs +++ b/src/client.rs @@ -48,7 +48,10 @@ pub use super::lang::*; pub mod file_trait; pub mod helper; pub mod io_loop; -use crate::ui_session_interface::global_save_keyboard_mode; +use crate::{ + server::video_service::{SCRAP_X11_REF_URL, SCRAP_X11_REQUIRED}, + ui_session_interface::global_save_keyboard_mode, +}; pub static SERVER_KEYBOARD_ENABLED: AtomicBool = AtomicBool::new(true); pub static SERVER_FILE_TRANSFER_ENABLED: AtomicBool = AtomicBool::new(true); pub static SERVER_CLIPBOARD_ENABLED: AtomicBool = AtomicBool::new(true); @@ -1263,10 +1266,14 @@ impl LoginConfigHandler { pub fn handle_login_error(&mut self, err: &str, interface: &impl Interface) -> bool { if err == "Wrong Password" { self.password = Default::default(); - interface.msgbox("re-input-password", err, "Do you want to enter again?"); + interface.msgbox("re-input-password", err, "Do you want to enter again?", ""); true } else { - interface.msgbox("error", "Login Error", err); + if err.contains(SCRAP_X11_REQUIRED) { + interface.msgbox("error", "Login Error", err, SCRAP_X11_REF_URL); + } else { + interface.msgbox("error", "Login Error", err, ""); + } false } } @@ -1636,7 +1643,7 @@ pub async fn handle_hash( if password.is_empty() { // login without password, the remote side can click accept send_login(lc.clone(), Vec::new(), peer).await; - interface.msgbox("input-password", "Password Required", ""); + interface.msgbox("input-password", "Password Required", "", ""); } else { let mut hasher = Sha256::new(); hasher.update(&password); @@ -1689,7 +1696,7 @@ pub async fn handle_login_from_ui( pub trait Interface: Send + Clone + 'static + Sized { /// Send message data to remote peer. fn send(&self, data: Data); - fn msgbox(&self, msgtype: &str, title: &str, text: &str); + fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str); fn handle_login_error(&mut self, err: &str) -> bool; fn handle_peer_info(&mut self, pi: PeerInfo); fn set_force_relay(&mut self, direct: bool, received: bool); @@ -1697,7 +1704,7 @@ pub trait Interface: Send + Clone + 'static + Sized { fn is_port_forward(&self) -> bool; fn is_rdp(&self) -> bool; fn on_error(&self, err: &str) { - self.msgbox("error", "Error", err); + self.msgbox("error", "Error", err, ""); } fn is_force_relay(&self) -> bool; async fn handle_hash(&mut self, pass: &str, hash: Hash, peer: &mut Stream); diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index 7e3bbb3dc..a415576c8 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -119,7 +119,7 @@ impl Remote { Err(err) => { log::error!("Connection closed: {}", err); self.handler.set_force_relay(direct, received); - self.handler.msgbox("error", "Connection Error", &err.to_string()); + self.handler.msgbox("error", "Connection Error", &err.to_string(), ""); break; } Ok(ref bytes) => { @@ -134,10 +134,10 @@ impl Remote { } else { if self.handler.is_restarting_remote_device() { log::info!("Restart remote device"); - self.handler.msgbox("restarting", "Restarting Remote Device", "remote_restarting_tip"); + self.handler.msgbox("restarting", "Restarting Remote Device", "remote_restarting_tip", ""); } else { log::info!("Reset by the peer"); - self.handler.msgbox("error", "Connection Error", "Reset by the peer"); + self.handler.msgbox("error", "Connection Error", "Reset by the peer", ""); } break; } @@ -162,12 +162,12 @@ impl Remote { } _ = self.timer.tick() => { if last_recv_time.elapsed() >= SEC30 { - self.handler.msgbox("error", "Connection Error", "Timeout"); + self.handler.msgbox("error", "Connection Error", "Timeout", ""); break; } if !self.read_jobs.is_empty() { if let Err(err) = fs::handle_read_jobs(&mut self.read_jobs, &mut peer).await { - self.handler.msgbox("error", "Connection Error", &err.to_string()); + self.handler.msgbox("error", "Connection Error", &err.to_string(), ""); break; } self.update_jobs_status(); @@ -191,7 +191,7 @@ impl Remote { } Err(err) => { self.handler - .msgbox("error", "Connection Error", &err.to_string()); + .msgbox("error", "Connection Error", &err.to_string(), ""); } } if let Some(stop) = stop_clipboard { @@ -971,7 +971,7 @@ impl Remote { } } Some(misc::Union::CloseReason(c)) => { - self.handler.msgbox("error", "Connection Error", &c); + self.handler.msgbox("error", "Connection Error", &c, ""); return false; } Some(misc::Union::BackNotification(notification)) => { @@ -981,8 +981,12 @@ impl Remote { } Some(misc::Union::Uac(uac)) => { if uac { - self.handler - .msgbox("custom-uac-nocancel", "Warning", "uac_warning"); + self.handler.msgbox( + "custom-uac-nocancel", + "Warning", + "uac_warning", + "", + ); } } Some(misc::Union::ForegroundWindowElevated(elevated)) => { @@ -991,6 +995,7 @@ impl Remote { "custom-elevated-foreground-nocancel", "Warning", "elevated_foreground_window_warning", + "", ); } } @@ -1012,6 +1017,19 @@ impl Remote { } _ => {} }, + Some(message::Union::MessageBox(msgbox)) => { + let mut link = msgbox.link; + if !link.starts_with("rustdesk://") { + if let Some(v) = hbb_common::config::HELPER_URL.get(&link as &str) { + link = v.to_string(); + } else { + log::warn!("Message box ignore link {} for security", &link); + link = "".to_string(); + } + } + self.handler + .msgbox(&msgbox.msgtype, &msgbox.title, &msgbox.text, &link); + } _ => {} } } @@ -1053,7 +1071,7 @@ impl Remote { } back_notification::BlockInputState::BlkOnFailed => { self.handler - .msgbox("custom-error", "Block user input", "Failed"); + .msgbox("custom-error", "Block user input", "Failed", ""); self.update_block_input_state(false); } back_notification::BlockInputState::BlkOffSucceeded => { @@ -1061,7 +1079,7 @@ impl Remote { } back_notification::BlockInputState::BlkOffFailed => { self.handler - .msgbox("custom-error", "Unblock user input", "Failed"); + .msgbox("custom-error", "Unblock user input", "Failed", ""); } _ => {} } @@ -1086,51 +1104,52 @@ impl Remote { "error", "Connecting...", "Someone turns on privacy mode, exit", + "", ); return false; } back_notification::PrivacyModeState::PrvNotSupported => { self.handler - .msgbox("custom-error", "Privacy mode", "Unsupported"); + .msgbox("custom-error", "Privacy mode", "Unsupported", ""); self.update_privacy_mode(false); } back_notification::PrivacyModeState::PrvOnSucceeded => { self.handler - .msgbox("custom-nocancel", "Privacy mode", "In privacy mode"); + .msgbox("custom-nocancel", "Privacy mode", "In privacy mode", ""); self.update_privacy_mode(true); } back_notification::PrivacyModeState::PrvOnFailedDenied => { self.handler - .msgbox("custom-error", "Privacy mode", "Peer denied"); + .msgbox("custom-error", "Privacy mode", "Peer denied", ""); self.update_privacy_mode(false); } back_notification::PrivacyModeState::PrvOnFailedPlugin => { self.handler - .msgbox("custom-error", "Privacy mode", "Please install plugins"); + .msgbox("custom-error", "Privacy mode", "Please install plugins", ""); self.update_privacy_mode(false); } back_notification::PrivacyModeState::PrvOnFailed => { self.handler - .msgbox("custom-error", "Privacy mode", "Failed"); + .msgbox("custom-error", "Privacy mode", "Failed", ""); self.update_privacy_mode(false); } back_notification::PrivacyModeState::PrvOffSucceeded => { self.handler - .msgbox("custom-nocancel", "Privacy mode", "Out privacy mode"); + .msgbox("custom-nocancel", "Privacy mode", "Out privacy mode", ""); self.update_privacy_mode(false); } back_notification::PrivacyModeState::PrvOffByPeer => { self.handler - .msgbox("custom-error", "Privacy mode", "Peer exit"); + .msgbox("custom-error", "Privacy mode", "Peer exit", ""); self.update_privacy_mode(false); } back_notification::PrivacyModeState::PrvOffFailed => { self.handler - .msgbox("custom-error", "Privacy mode", "Failed to turn off"); + .msgbox("custom-error", "Privacy mode", "Failed to turn off", ""); } back_notification::PrivacyModeState::PrvOffUnknown => { self.handler - .msgbox("custom-error", "Privacy mode", "Turned off"); + .msgbox("custom-error", "Privacy mode", "Turned off", ""); // log::error!("Privacy mode is turned off with unknown reason"); self.update_privacy_mode(false); } diff --git a/src/common.rs b/src/common.rs index 26903eacf..3022e5b56 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,5 +1,6 @@ use std::{ collections::HashMap, + future::Future, sync::{Arc, Mutex}, }; @@ -21,6 +22,8 @@ use hbb_common::{ // #[cfg(any(target_os = "android", target_os = "ios", feature = "cli"))] use hbb_common::{config::RENDEZVOUS_PORT, futures::future::join_all}; +pub type NotifyMessageBox = fn(String, String, String, String) -> dyn Future; + pub const CLIPBOARD_NAME: &'static str = "clipboard"; pub const CLIPBOARD_INTERVAL: u64 = 333; @@ -44,8 +47,7 @@ pub fn global_init() -> bool { true } -pub fn global_clean() { -} +pub fn global_clean() {} #[inline] pub fn valid_for_numlock(evt: &KeyEvent) -> bool { diff --git a/src/flutter.rs b/src/flutter.rs index b65ce4412..2b95f9cfb 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -310,7 +310,7 @@ impl InvokeUiSession for FlutterHandler { ); } - fn msgbox(&self, msgtype: &str, title: &str, text: &str, retry: bool) { + fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str, retry: bool) { let has_retry = if retry { "true" } else { "" }; self.push_event( "msgbox", @@ -318,6 +318,7 @@ impl InvokeUiSession for FlutterHandler { ("type", msgtype), ("title", title), ("text", text), + ("link", link), ("hasRetry", has_retry), ], ); diff --git a/src/lang/cn.rs b/src/lang/cn.rs index c88b0182c..cf2575a7f 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", "自定义"), ("Full Access", "完全访问"), ("Screen Share", "仅共享屏幕"), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland 需要 Ubuntu 21.04 或更高版本。"), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland 需要更高版本的 linux 发行版。 请尝试 X11 桌面或更改您的操作系统。"), + ("JumpLink", "查看"), + ("Please Select the screen to be shared(Operate on the peer side).", "请选择要分享的画面(对端操作)。"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index f616d518b..162fdc1ed 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland vyžaduje Ubuntu 21.04 nebo vyšší verzi."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland vyžaduje vyšší verzi linuxové distribuce. Zkuste prosím X11 desktop nebo změňte OS."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Vyberte prosím obrazovku, kterou chcete sdílet (Ovládejte na straně protějšku)."), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 3fe49d051..df9929d1f 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland kræver Ubuntu 21.04 eller nyere version."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland kræver en højere version af linux distro. Prøv venligst X11 desktop eller skift dit OS."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Vælg venligst den skærm, der skal deles (Betjen på peer-siden)."), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 4942b3171..b0f6d0ba3 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland erfordert Ubuntu 21.04 oder eine höhere Version."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland erfordert eine höhere Version der Linux-Distribution. Bitte versuchen Sie den X11-Desktop oder ändern Sie Ihr Betriebssystem."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Bitte wählen Sie den Bildschirm aus, der freigegeben werden soll (auf der Peer-Seite arbeiten)."), ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index 279f26cd1..7c95f8abb 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -33,5 +33,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevation_prompt", "Running software without privilege elevation may cause problems when remote users operate certain windows."), ("uac_warning", "Temporarily denied access due to elevation request, please wait for the remote user to accept the UAC dialog. To avoid this problem, it is recommended to install the software on the remote device or run it with administrator privileges."), ("elevated_foreground_window_warning", "Temporarily unable to use the mouse and keyboard, because the current window of the remote desktop requires higher privilege to operate, you can request the remote user to minimize the current window. To avoid this problem, it is recommended to install the software on the remote device or run it with administrator privileges."), + ("JumpLink", "View"), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 9bfea5440..ca0f12bcd 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland postulas Ubuntu 21.04 aŭ pli altan version."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland postulas pli altan version de linuksa distro. Bonvolu provi X11-labortablon aŭ ŝanĝi vian OS."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Bonvolu Elekti la ekranon por esti dividita (Funkciu ĉe la sama flanko)."), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 3b6419572..3be5f920e 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland requiere Ubuntu 21.04 o una versión superior."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland requiere una versión superior de la distribución de Linux. Pruebe el escritorio X11 o cambie su sistema operativo."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Seleccione la pantalla que se compartirá (Operar en el lado del compañero)."), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index b7dbd5636..484c415fc 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland nécessite Ubuntu 21.04 ou une version supérieure."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland nécessite une version supérieure de la distribution Linux. Veuillez essayer le bureau X11 ou changer votre système d'exploitation."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Veuillez sélectionner l'écran à partager (opérer du côté pair)."), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index aa5e34d09..c2d5903e1 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "A Waylandhoz Ubuntu 21.04 vagy újabb verzió szükséges."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "A Wayland a Linux disztró magasabb verzióját igényli. Próbálja ki az X11 desktopot, vagy változtassa meg az operációs rendszert."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Kérjük, válassza ki a megosztani kívánt képernyőt (a társoldalon működjön)."), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 1ab7fd134..33aae1579 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland membutuhkan Ubuntu 21.04 atau versi yang lebih tinggi."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland membutuhkan versi distro linux yang lebih tinggi. Silakan coba desktop X11 atau ubah OS Anda."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Silakan Pilih layar yang akan dibagikan (Operasi di sisi rekan)."), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 65c16567c..5b37e9291 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland richiede Ubuntu 21.04 o versione successiva."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland richiede una versione superiore della distribuzione Linux. Prova X11 desktop o cambia il tuo sistema operativo."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Seleziona lo schermo da condividere (opera sul lato peer)."), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 75a9c0c9b..593ef0186 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland には、Ubuntu 21.04 以降のバージョンが必要です。"), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland には、より高いバージョンの Linux ディストリビューションが必要です。 X11 デスクトップを試すか、OS を変更してください。"), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "共有する画面を選択してください(ピア側で操作)。"), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index eccb4d836..1b668462e 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland는 Ubuntu 21.04 이상 버전이 필요합니다."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland에는 더 높은 버전의 Linux 배포판이 필요합니다. X11 데스크탑을 시도하거나 OS를 변경하십시오."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "공유할 화면을 선택하십시오(피어 측에서 작동)."), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 9a1e23c23..e55b0a3e3 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland Ubuntu 21.04 немесе одан жоғары нұсқасын қажет етеді."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland linux дистрибутивінің жоғарырақ нұсқасын қажет етеді. X11 жұмыс үстелін қолданып көріңіз немесе операциялық жүйеңізді өзгертіңіз."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Бөлісетін экранды таңдаңыз (бірдей жағынан жұмыс жасаңыз)."), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index e96061729..16f1a5ff3 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland wymaga Ubuntu 21.04 lub nowszego."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland wymaga wyższej wersji dystrybucji Linuksa. Wypróbuj pulpit X11 lub zmień system operacyjny."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Wybierz ekran do udostępnienia (działaj po stronie równorzędnej)."), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index e17967998..ea90329a5 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland requer Ubuntu 21.04 ou versão superior."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland requer uma versão superior da distribuição linux. Por favor, tente o desktop X11 ou mude seu sistema operacional."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Por favor, selecione a tela a ser compartilhada (operar no lado do peer)."), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index c2965405d..8a6280aed 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", ""), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", ""), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 95c59dede..5fe9c89ec 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland требует Ubuntu 21.04 или более позднюю версию."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Для Wayland требуется более поздняя версия дистрибутива Linux. Пожалуйста, попробуйте рабочий стол X11 или смените ОС."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Пожалуйста, выберите экран для совместного использования (работайте на одноранговой стороне)."), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 5064e1069..23c8b7220 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland vyžaduje Ubuntu 21.04 alebo vyššiu verziu."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland vyžaduje vyššiu verziu linuxovej distribúcie. Skúste X11 desktop alebo zmeňte OS."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Vyberte obrazovku, ktorú chcete zdieľať (Ovládajte na strane partnera)."), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index e08a2ba76..6d549b02a 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", ""), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", ""), + ("JumpLink", ""), + ("Please Select the screen to be shared(Operate on the peer side).", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 117a5683b..1cf50b2ca 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland, Ubuntu 21.04 veya daha yüksek bir sürüm gerektirir."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland, linux dağıtımının daha yüksek bir sürümünü gerektirir. Lütfen X11 masaüstünü deneyin veya işletim sisteminizi değiştirin."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Lütfen paylaşılacak ekranı seçiniz (Ekran tarafında çalıştırın)."), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index d0bce5d77..91d0ab169 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", "自定義"), ("Full Access", "完全訪問"), ("Screen Share", "僅共享屏幕"), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland 需要 Ubuntu 21.04 或更高版本。"), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland 需要更高版本的 linux 發行版。 請嘗試 X11 桌面或更改您的操作系統。"), + ("JumpLink", "查看"), + ("Please Select the screen to be shared(Operate on the peer side).", "請選擇要分享的畫面(在對端操作)。"), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index f17e17a93..528b919b8 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland потребує Ubuntu 21.04 або новішої версії."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Для Wayland потрібна новіша версія дистрибутива Linux. Будь ласка, спробуйте робочий стіл X11 або змініть свою ОС."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Будь ласка, виберіть екран, до якого потрібно надати доступ (працюйте на стороні однорангового пристрою)."), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 30e32a82c..7f368126f 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -377,5 +377,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Custom", ""), ("Full Access", ""), ("Screen Share", ""), + ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland yêu cầu phiên bản Ubuntu 21.04 trở lên."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland yêu cầu phiên bản distro linux cao hơn. Vui lòng thử máy tính để bàn X11 hoặc thay đổi hệ điều hành của bạn."), + ("JumpLink", "View"), + ("Please Select the screen to be shared(Operate on the peer side).", "Vui lòng Chọn màn hình để chia sẻ (Hoạt động ở phía ngang hàng)."), ].iter().cloned().collect(); } diff --git a/src/port_forward.rs b/src/port_forward.rs index 934743edc..f50f40db8 100644 --- a/src/port_forward.rs +++ b/src/port_forward.rs @@ -75,13 +75,13 @@ pub async fn listen( let interface = interface.clone(); tokio::spawn(async move { if let Err(err) = run_forward(forward, stream).await { - interface.msgbox("error", "Error", &err.to_string()); + interface.msgbox("error", "Error", &err.to_string(), ""); } log::info!("connection from {:?} closed", addr); }); } Err(err) => { - interface.msgbox("error", "Error", &err.to_string()); + interface.msgbox("error", "Error", &err.to_string(), ""); } _ => {} } diff --git a/src/server/connection.rs b/src/server/connection.rs index c451d5a1c..dca05e088 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -742,6 +742,10 @@ impl Connection { res.set_peer_info(pi); } else { try_activate_screen(); + if let Some(msg_out) = super::video_service::is_inited_msg() { + self.send(msg_out).await; + } + match super::video_service::get_displays().await { Err(err) => { res.set_error(format!("Error: {}", err)); diff --git a/src/server/video_service.rs b/src/server/video_service.rs index 2b94077be..d43996559 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -39,6 +39,12 @@ use std::{ #[cfg(windows)] use virtual_display; +pub const SCRAP_UBUNTU_HIGHER_REQUIRED: &str = "Wayland requires Ubuntu 21.04 or higher version."; +pub const SCRAP_OTHER_VERSION_OR_X11_REQUIRED: &str = + "Wayland requires higher version of linux distro. Please try X11 desktop or change your OS."; +pub const SCRAP_X11_REQUIRED: &str = "x11 expected"; +pub const SCRAP_X11_REF_URL: &str = "https://rustdesk.com/docs/en/manual/linux/#x11-required"; + pub const NAME: &'static str = "video"; lazy_static::lazy_static! { @@ -569,7 +575,7 @@ fn run(sp: GenericService) -> ResultType<()> { { if !scrap::is_x11() { if would_block_count >= 100 { - // For now, the user should choose and agree screen sharing agiain. + // For now, the user should choose and agree screen sharing agiain. // to-do: Remember choice, attendless... super::wayland::release_resouce(); bail!("Wayland capturer none 100 times, try restart captuere"); @@ -747,6 +753,14 @@ pub(super) fn get_displays_2(all: &Vec) -> (usize, Vec) { (*lock, displays) } +pub fn is_inited_msg() -> Option { + #[cfg(target_os = "linux")] + if !scrap::is_x11() { + return super::wayland::is_inited(); + } + None +} + pub async fn get_displays() -> ResultType<(usize, Vec)> { #[cfg(target_os = "linux")] { diff --git a/src/server/wayland.rs b/src/server/wayland.rs index 6d4a85399..8cf1623c5 100644 --- a/src/server/wayland.rs +++ b/src/server/wayland.rs @@ -3,11 +3,9 @@ use hbb_common::{allow_err, platform::linux::DISTRO}; use scrap::{set_map_err, Capturer, Display, Frame, TraitCapturer}; use std::io; -pub const SCRAP_UBUNTU_HIGHER_REQUIRED: &str = "Wayland requires Ubuntu 21.04 or higher version."; -pub const SCRAP_OTHER_VERSION_OR_X11_REQUIRED: &str = - "Wayland requires higher version of linux distro. Please try X11 desktop or change your OS."; -pub const SCRAP_X11_REQUIRED: &str = "X11 is required"; -pub const SCRAP_X11_REF_URL: &str = "https://rustdesk.com/docs/en/manual/linux/#x11-required"; +use super::video_service::{ + SCRAP_OTHER_VERSION_OR_X11_REQUIRED, SCRAP_UBUNTU_HIGHER_REQUIRED, SCRAP_X11_REQUIRED, +}; lazy_static::lazy_static! { static ref CAP_DISPLAY_INFO: RwLock = RwLock::new(0); @@ -26,7 +24,10 @@ fn map_err_scrap(err: String) -> io::Error { // std::process::exit(-1); // } - log::error!("REMOVE ME ===================================== wayland scrap error {}", &err); + log::error!( + "REMOVE ME ===================================== wayland scrap error {}", + &err + ); if DISTRO.name.to_uppercase() == "Ubuntu".to_uppercase() { if DISTRO.version_id < "21".to_owned() { @@ -93,6 +94,27 @@ pub(super) async fn ensure_inited() -> ResultType<()> { check_init().await } +pub(super) fn is_inited() -> Option { + if scrap::is_x11() { + None + } else { + if *CAP_DISPLAY_INFO.read().unwrap() == 0 { + let mut msg_out = Message::new(); + let res = MessageBox { + msgtype: "nook-nocancel-hasclose".to_owned(), + title: "Wayland".to_owned(), + text: "Please Select the screen to be shared(Operate on the peer side).".to_owned(), + link: "".to_owned(), + ..Default::default() + }; + msg_out.set_message_box(res); + Some(msg_out) + } else { + None + } + } +} + async fn check_init() -> ResultType<()> { if !scrap::is_x11() { let mut minx = 0; diff --git a/src/ui/common.tis b/src/ui/common.tis index 69e5565f0..e591f45a3 100644 --- a/src/ui/common.tis +++ b/src/ui/common.tis @@ -232,7 +232,7 @@ class ChatBox: Reactor.Component { /******************** start of msgbox ****************************************/ var remember_password = false; -function msgbox(type, title, content, callback=null, height=180, width=500, hasRetry=false, contentStyle="") { +function msgbox(type, title, content, link, callback=null, height=180, width=500, hasRetry=false, contentStyle="") { $(body).scrollTo(0, 0); if (!type) { closeMsgbox(); @@ -264,21 +264,21 @@ function msgbox(type, title, content, callback=null, height=180, width=500, hasR } else if (type.indexOf("custom") < 0 && !is_port_forward && !callback) { callback = function() { view.close(); } } - $(#msgbox).content(); + $(#msgbox).content(); } function connecting() { handler.msgbox("connecting", "Connecting...", "Connection in progress. Please wait."); } -handler.msgbox = function(type, title, text, hasRetry=false) { +handler.msgbox = function(type, title, text, link = "", hasRetry=false) { // crash somehow (when input wrong password), even with small time, for example, 1ms - self.timer(60ms, function() { msgbox(type, title, text, null, 180, 500, hasRetry); }); + self.timer(60ms, function() { msgbox(type, title, text, link, null, 180, 500, hasRetry); }); } var reconnectTimeout = 1000; -handler.msgbox_retry = function(type, title, text, hasRetry) { - handler.msgbox(type, title, text, hasRetry); +handler.msgbox_retry = function(type, title, text, link, hasRetry) { + handler.msgbox(type, title, text, link, hasRetry); if (hasRetry) { self.timer(0, retryConnect); self.timer(reconnectTimeout, retryConnect); diff --git a/src/ui/msgbox.tis b/src/ui/msgbox.tis index 7d1430cb0..3f40c367d 100644 --- a/src/ui/msgbox.tis +++ b/src/ui/msgbox.tis @@ -1,3 +1,5 @@ +import * as env from "@env"; + function translate_text(text) { if (text.indexOf('Failed') == 0 && text.indexOf(': ') > 0) { var fds = text.split(': '); @@ -22,6 +24,7 @@ class MsgboxComponent: Reactor.Component { this.type = params.type; this.title = params.title; this.content = params.content; + this.link = params.link; this.remember = params.remember; this.callback = params.callback; this.hasRetry = params.hasRetry; @@ -93,6 +96,7 @@ class MsgboxComponent: Reactor.Component { var content = this.getContent(); var hasCancel = this.type.indexOf("error") < 0 && this.type.indexOf("nocancel") < 0 && this.type != "restarting"; var hasOk = this.type != "connecting" && this.type != "success" && this.type.indexOf("nook") < 0; + var hasLink = this.link != ""; var hasClose = this.type.indexOf("hasclose") >= 0; var show_progress = this.type == "connecting"; var me = this; @@ -121,6 +125,7 @@ class MsgboxComponent: Reactor.Component { {hasCancel || this.hasRetry ? : ""} {this.hasSkip() ? : ""} {hasOk || this.hasRetry ? : ""} + {hasLink ? : ""} {hasClose ? : ""} @@ -155,6 +160,13 @@ class MsgboxComponent: Reactor.Component { if (this.callback) this.callback(values); if (this.close) this.close(); } + + event click $(button#jumplink) { + stdout.println("REMOVE ME ================================= jump link" + this.link); + if (this.link.indexOf("http") == 0) { + env.launch(this.link); + } + } event click $(button#submit) { if (this.type == "error") { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index b3f443dda..dfd6394a5 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -238,8 +238,8 @@ impl InvokeUiSession for SciterHandler { self.call("updatePi", &make_args!(pi_sciter)); } - fn msgbox(&self, msgtype: &str, title: &str, text: &str, retry: bool) { - self.call2("msgbox_retry", &make_args!(msgtype, title, text, retry)); + fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str, retry: bool) { + self.call2("msgbox_retry", &make_args!(msgtype, title, text, link, retry)); } fn new_message(&self, msg: String) { diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index f5cc0499d..cf550ed63 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -1088,7 +1088,7 @@ pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default { fn job_progress(&self, id: i32, file_num: i32, speed: f64, finished_size: f64); fn adapt_size(&self); fn on_rgba(&self, data: &[u8]); - fn msgbox(&self, msgtype: &str, title: &str, text: &str, retry: bool); + fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str, retry: bool); #[cfg(any(target_os = "android", target_os = "ios"))] fn clipboard(&self, content: String); } @@ -1137,9 +1137,9 @@ impl Interface for Session { self.lc.read().unwrap().conn_type.eq(&ConnType::RDP) } - fn msgbox(&self, msgtype: &str, title: &str, text: &str) { + fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str) { let retry = check_if_retry(msgtype, title, text); - self.ui_handler.msgbox(msgtype, title, text, retry); + self.ui_handler.msgbox(msgtype, title, text, link, retry); } fn handle_login_error(&mut self, err: &str) -> bool { @@ -1164,7 +1164,7 @@ impl Interface for Session { if pi.displays.is_empty() { self.lc.write().unwrap().handle_peer_info(&pi); self.update_privacy_mode(); - self.msgbox("error", "Remote Error", "No Display"); + self.msgbox("error", "Remote Error", "No Display", ""); return; } let p = self.lc.read().unwrap().should_auto_login(); @@ -1181,7 +1181,7 @@ impl Interface for Session { if self.is_file_transfer() { self.close_success(); } else if !self.is_port_forward() { - self.msgbox("success", "Successful", "Connected, waiting for image..."); + self.msgbox("success", "Successful", "Connected, waiting for image...", ""); } #[cfg(windows)] {