From b556b5d7f6935c4a027d9127dafc8a07fa61d1cc Mon Sep 17 00:00:00 2001 From: Jimmy GALLAND Date: Sat, 21 Jan 2023 23:07:48 +0100 Subject: [PATCH 01/83] add templates/translations for Tab Home label, and two other label translations in About tab --- src/lang/ca.rs | 3 +++ src/lang/cn.rs | 3 +++ src/lang/cs.rs | 3 +++ src/lang/da.rs | 3 +++ src/lang/de.rs | 3 +++ src/lang/eo.rs | 3 +++ src/lang/es.rs | 3 +++ src/lang/fa.rs | 3 +++ src/lang/fr.rs | 3 +++ src/lang/gr.rs | 3 +++ src/lang/hu.rs | 3 +++ src/lang/id.rs | 3 +++ src/lang/it.rs | 3 +++ src/lang/ja.rs | 3 +++ src/lang/ko.rs | 3 +++ src/lang/kz.rs | 3 +++ src/lang/pl.rs | 3 +++ src/lang/pt_PT.rs | 3 +++ src/lang/ptbr.rs | 3 +++ src/lang/ru.rs | 3 +++ src/lang/sk.rs | 3 +++ src/lang/sl.rs | 3 +++ src/lang/sq.rs | 3 +++ src/lang/sr.rs | 3 +++ src/lang/sv.rs | 3 +++ src/lang/template.rs | 3 +++ src/lang/th.rs | 3 +++ src/lang/tr.rs | 3 +++ src/lang/tw.rs | 3 +++ src/lang/ua.rs | 3 +++ src/lang/vn.rs | 3 +++ 31 files changed, 93 insertions(+) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 72f55b44b..64b9bb35f 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Sobre"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Silenciar"), ("Audio Input", "Entrada d'àudio"), ("Enhancements", "Millores"), diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 14e8a463d..b95f79972 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -42,6 +42,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Slogan_tip", ""), ("Privacy Statement", ""), ("Mute", "静音"), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Audio Input", "音频输入"), ("Enhancements", "增强功能"), ("Hardware Codec", "硬件编解码"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index e2935770c..b40f79405 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -42,6 +42,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Slogan_tip", ""), ("Privacy Statement", ""), ("Mute", "Ztlumit"), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Audio Input", "Vstup zvuku"), ("Enhancements", ""), ("Hardware Codec", ""), diff --git a/src/lang/da.rs b/src/lang/da.rs index 937990ea8..8bd3e9a7b 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -42,6 +42,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Slogan_tip", ""), ("Privacy Statement", ""), ("Mute", "Sluk for mikrofonen"), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Audio Input", "Lydindgang"), ("Enhancements", ""), ("Hardware Codec", ""), diff --git a/src/lang/de.rs b/src/lang/de.rs index 7394a4628..e1adc224b 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -42,6 +42,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Slogan_tip", "Mit Herzblut programmiert - in einer Welt, die im Chaos versinkt!"), ("Privacy Statement", "Datenschutz"), ("Mute", "Stummschalten"), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Audio Input", "Audioeingang"), ("Enhancements", "Verbesserungen"), ("Hardware Codec", "Hardware-Codec"), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 839c69bbb..cbaa013d5 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Pri"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Muta"), ("Audio Input", "Aŭdia enigo"), ("Enhancements", ""), diff --git a/src/lang/es.rs b/src/lang/es.rs index 5161f9846..613497476 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Acerca de"), ("Slogan_tip", "Hecho con corazón en este mundo caótico!"), ("Privacy Statement", "Declaración de privacidad"), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Silenciar"), ("Audio Input", "Entrada de audio"), ("Enhancements", "Mejoras"), diff --git a/src/lang/fa.rs b/src/lang/fa.rs index dfd76405e..a7a4df073 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "درباره"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "بستن صدا"), ("Audio Input", "ورودی صدا"), ("Enhancements", "بهبودها"), diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 9c9860fb2..273760aac 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "À propos de"), ("Slogan_tip", "Fait avec cœur dans ce monde chaotique!"), ("Privacy Statement", "Déclaration de confidentialité"), + ("Build Date", "Date de compilation"), + ("Version", "Version"), + ("Home", "Accueil"), ("Mute", "Muet"), ("Audio Input", "Entrée audio"), ("Enhancements", "Améliorations"), diff --git a/src/lang/gr.rs b/src/lang/gr.rs index 6ec1152cd..b50f9fbf5 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Πληροφορίες"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Σίγαση"), ("Audio Input", "Είσοδος ήχου"), ("Enhancements", "Βελτιώσεις"), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 295104a67..c4e791da8 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -42,6 +42,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Slogan_tip", ""), ("Privacy Statement", ""), ("Mute", "Némítás"), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Audio Input", "Hangátvitel"), ("Enhancements", "Fejlesztések"), ("Hardware Codec", "Hardware kodek"), diff --git a/src/lang/id.rs b/src/lang/id.rs index 5604a0c52..9b8fb9f33 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Tentang"), ("Slogan_tip", ""), ("Privacy Statement", "Pernyataan Privasi"), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Bisukan"), ("Audio Input", "Masukkan Audio"), ("Enhancements", "Peningkatan"), diff --git a/src/lang/it.rs b/src/lang/it.rs index 7b979aff0..e56893249 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Informazioni"), ("Slogan_tip", "Fatta con il cuore in questo mondo caotico!"), ("Privacy Statement", "Informativa sulla privacy"), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Silenzia"), ("Audio Input", "Input audio"), ("Enhancements", "Miglioramenti"), diff --git a/src/lang/ja.rs b/src/lang/ja.rs index a280940c7..04b199950 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "情報"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "ミュート"), ("Audio Input", "音声入力デバイス"), ("Enhancements", "追加機能"), diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 1cdf529ce..a2d55bd1c 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "정보"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "음소거"), ("Audio Input", "오디오 입력"), ("Enhancements", ""), diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 59d26135f..328f4c29b 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Туралы"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Дыбыссыздандыру"), ("Audio Input", "Аудио Еңгізу"), ("Enhancements", "Жақсартулар"), diff --git a/src/lang/pl.rs b/src/lang/pl.rs index ee4b45334..061b97f99 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "O"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Wycisz"), ("Audio Input", "Wejście audio"), ("Enhancements", "Ulepszenia"), diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 66373a5e9..8ae67062c 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Sobre"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Silenciar"), ("Audio Input", "Entrada de Áudio"), ("Enhancements", "Melhorias"), diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 5a137f391..fbe2c1cf8 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Sobre"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Desativar som"), ("Audio Input", "Entrada de Áudio"), ("Enhancements", "Melhorias"), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index a7e42e0e4..4f222291e 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "О программе"), ("Slogan_tip", "Сделано с душой в этом безумном мире!"), ("Privacy Statement", "Заявление о конфиденциальности"), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Отключить звук"), ("Audio Input", "Аудиовход"), ("Enhancements", "Улучшения"), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index c735cb28c..609523f05 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "O RustDesk"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Stíšiť"), ("Audio Input", "Zvukový vstup"), ("Enhancements", ""), diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 6a17cc906..c779ca33c 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "O programu"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Izklopi zvok"), ("Audio Input", "Avdio vhod"), ("Enhancements", "Izboljšave"), diff --git a/src/lang/sq.rs b/src/lang/sq.rs index ebb43f6b7..1939f6275 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Rreth"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Pa zë"), ("Audio Input", "Inputi zërit"), ("Enhancements", "Përmirësimet"), diff --git a/src/lang/sr.rs b/src/lang/sr.rs index d9463318d..91c8f31b3 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "O programu"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Utišaj"), ("Audio Input", "Audio ulaz"), ("Enhancements", "Proširenja"), diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 146e60f9a..65bfc5122 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Om"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Tyst"), ("Audio Input", "Ljud input"), ("Enhancements", "Förbättringar"), diff --git a/src/lang/template.rs b/src/lang/template.rs index 729932973..bd2d44d80 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", ""), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", ""), ("Audio Input", ""), ("Enhancements", ""), diff --git a/src/lang/th.rs b/src/lang/th.rs index a78509e59..7e1d8c45a 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "เกี่ยวกับ"), ("Slogan_tip", "ทำด้วยใจ ในโลกใบนี้ที่ยุ่งเหยิง!"), ("Privacy Statement", "คำแถลงเกี่ยวกับความเป็นส่วนตัว"), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "ปิดเสียง"), ("Audio Input", "ออดิโออินพุท"), ("Enhancements", "การปรับปรุง"), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 483ee67e3..47e59e551 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Hakkında"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Sustur"), ("Audio Input", "Ses Girişi"), ("Enhancements", "Geliştirmeler"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 459c517ff..9404c1192 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "關於"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "靜音"), ("Audio Input", "音訊輸入"), ("Enhancements", "增強功能"), diff --git a/src/lang/ua.rs b/src/lang/ua.rs index ca99be12e..eadd7ed84 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Про RustDesk"), ("Slogan_tip", "Створено з душею в цьому хаотичному світі!"), ("Privacy Statement", "Декларація про конфіденційність"), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Вимкнути звук"), ("Audio Input", "Аудіовхід"), ("Enhancements", "Покращення"), diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 53de4e67c..c5d44ebc7 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -41,6 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "About"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Mute", "Tắt tiếng"), ("Audio Input", "Đầu vào âm thanh"), ("Enhancements", "Các tiện itchs"), From 7c2d7df62e02d881f7ad32e34c3a94eb8e0bd132 Mon Sep 17 00:00:00 2001 From: 21pages Date: Sat, 28 Jan 2023 16:39:24 +0800 Subject: [PATCH 02/83] quick support if right click && run as admin on win Signed-off-by: 21pages --- src/core_main.rs | 13 ++++++++----- src/server/portable_service.rs | 17 ++++++----------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/core_main.rs b/src/core_main.rs index 8b99f6131..4a2f6164c 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -54,11 +54,6 @@ pub fn core_main() -> Option> { return core_main_invoke_new_connection(std::env::args()); } let click_setup = cfg!(windows) && args.is_empty() && crate::common::is_setup(&arg_exe); - #[cfg(not(feature = "flutter"))] - { - _is_quick_support = - cfg!(windows) && args.is_empty() && arg_exe.to_lowercase().ends_with("qs.exe"); - } if click_setup { args.push("--install".to_owned()); flutter_args.push("--install".to_string()); @@ -70,6 +65,14 @@ pub fn core_main() -> Option> { println!("{}", crate::VERSION); return None; } + #[cfg(windows)] + { + _is_quick_support |= !crate::platform::is_installed() + && args.is_empty() + && (arg_exe.to_lowercase().ends_with("qs.exe") + || (!click_setup && crate::platform::is_elevated(None).unwrap_or(false))); + crate::portable_service::client::set_quick_support(_is_quick_support); + } #[cfg(debug_assertions)] { use hbb_common::env_logger::*; diff --git a/src/server/portable_service.rs b/src/server/portable_service.rs index 0651fd4ce..748cb39e4 100644 --- a/src/server/portable_service.rs +++ b/src/server/portable_service.rs @@ -459,6 +459,7 @@ pub mod client { static ref RUNNING: Arc> = Default::default(); static ref SHMEM: Arc>> = Default::default(); static ref SENDER : Mutex> = Mutex::new(client::start_ipc_server()); + static ref QUICK_SUPPORT: Arc> = Default::default(); } pub enum StartPara { @@ -561,6 +562,10 @@ pub mod client { *SHMEM.lock().unwrap() = None; } + pub fn set_quick_support(v: bool) { + *QUICK_SUPPORT.lock().unwrap() = v; + } + fn set_dir_permission(dir: &PathBuf) -> bool { // // give Everyone RX permission std::process::Command::new("icacls") @@ -685,17 +690,7 @@ pub mod client { use DataPortableService::*; let rx = Arc::new(tokio::sync::Mutex::new(rx)); let postfix = IPC_SUFFIX; - #[cfg(feature = "flutter")] - let quick_support = { - let args: Vec<_> = std::env::args().collect(); - args.contains(&"--quick_support".to_string()) - }; - #[cfg(not(feature = "flutter"))] - let quick_support = std::env::current_exe() - .unwrap_or("".into()) - .to_string_lossy() - .to_lowercase() - .ends_with("qs.exe"); + let quick_support = QUICK_SUPPORT.lock().unwrap().clone(); match new_listener(postfix).await { Ok(mut incoming) => loop { From 3e4a8671152cdae2f33e926a3045b72e3edaf59e Mon Sep 17 00:00:00 2001 From: 21pages Date: Sat, 28 Jan 2023 16:41:47 +0800 Subject: [PATCH 03/83] opt elevation code Signed-off-by: 21pages --- flutter/lib/models/server_model.dart | 2 +- src/server/connection.rs | 165 +++++++++++++++------------ src/server/video_service.rs | 8 +- src/ui_cm_interface.rs | 4 +- 4 files changed, 102 insertions(+), 77 deletions(-) diff --git a/flutter/lib/models/server_model.dart b/flutter/lib/models/server_model.dart index 7703182cd..56dca4cdf 100644 --- a/flutter/lib/models/server_model.dart +++ b/flutter/lib/models/server_model.dart @@ -28,7 +28,7 @@ class ServerModel with ChangeNotifier { bool _inputOk = false; bool _audioOk = false; bool _fileOk = false; - bool _showElevation = true; + bool _showElevation = false; bool _hideCm = false; int _connectStatus = 0; // Rendezvous Server status String _verificationMethod = ""; diff --git a/src/server/connection.rs b/src/server/connection.rs index c259d54cf..c7aa7fe0c 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -3,6 +3,8 @@ use super::{input_service::*, *}; use crate::clipboard_file::*; #[cfg(not(any(target_os = "android", target_os = "ios")))] use crate::common::update_clipboard; +#[cfg(windows)] +use crate::portable_service::client as portable_client; use crate::video_service; #[cfg(any(target_os = "android", target_os = "ios"))] use crate::{common::DEVICE_NAME, flutter::connection_manager::start_channel}; @@ -101,8 +103,8 @@ pub struct Connection { lr: LoginRequest, last_recv_time: Arc>, chat_unanswered: bool, - #[allow(unused)] - elevation_requested: bool, + #[cfg(windows)] + portable: PortableState, from_switch: bool, } @@ -199,7 +201,8 @@ impl Connection { lr: Default::default(), last_recv_time: Arc::new(Mutex::new(Instant::now())), chat_unanswered: false, - elevation_requested: false, + #[cfg(windows)] + portable: Default::default(), from_switch: false, }; #[cfg(not(any(target_os = "android", target_os = "ios")))] @@ -247,14 +250,6 @@ impl Connection { #[cfg(not(any(target_os = "android", target_os = "ios")))] std::thread::spawn(move || Self::handle_input(rx_input, tx_cloned)); let mut second_timer = time::interval(Duration::from_secs(1)); - #[cfg(windows)] - let mut last_uac = false; - #[cfg(windows)] - let mut last_foreground_window_elevated = false; - #[cfg(windows)] - let mut last_portable_service_running = false; - #[cfg(windows)] - let is_installed = crate::platform::is_installed(); loop { tokio::select! { @@ -362,8 +357,7 @@ impl Connection { } #[cfg(windows)] ipc::Data::DataPortableService(ipc::DataPortableService::RequestStart) => { - use crate::portable_service::client; - if let Err(e) = client::start_portable_service(client::StartPara::Direct) { + if let Err(e) = portable_client::start_portable_service(portable_client::StartPara::Direct) { log::error!("Failed to start portable service from cm:{:?}", e); } } @@ -458,46 +452,7 @@ impl Connection { }, _ = second_timer.tick() => { #[cfg(windows)] - { - if !is_installed && conn.file_transfer.is_none() && conn.port_forward_socket.is_none(){ - let portable_service_running = crate::portable_service::client::running(); - if portable_service_running != last_portable_service_running { - last_portable_service_running = portable_service_running; - if portable_service_running && conn.elevation_requested { - let mut misc = Misc::new(); - misc.set_portable_service_running(portable_service_running); - let mut msg = Message::new(); - msg.set_misc(misc); - conn.inner.send(msg.into()); - } - } - let uac = crate::video_service::IS_UAC_RUNNING.lock().unwrap().clone(); - if last_uac != uac { - last_uac = uac; - if !uac || !portable_service_running{ - let mut misc = Misc::new(); - misc.set_uac(uac); - let mut msg = Message::new(); - msg.set_misc(misc); - conn.inner.send(msg.into()); - } - } - let foreground_window_elevated = crate::video_service::IS_FOREGROUND_WINDOW_ELEVATED.lock().unwrap().clone(); - if last_foreground_window_elevated != foreground_window_elevated { - last_foreground_window_elevated = foreground_window_elevated; - if !foreground_window_elevated || !portable_service_running { - let mut misc = Misc::new(); - misc.set_foreground_window_elevated(foreground_window_elevated); - let mut msg = Message::new(); - msg.set_misc(misc); - conn.inner.send(msg.into()); - } - } - let show_elevation = !portable_service_running; - conn.send_to_cm(ipc::Data::DataPortableService(ipc::DataPortableService::CmShowElevation(show_elevation))); - - } - } + conn.portable_check(); } _ = test_delay_timer.tick() => { if last_recv_time.elapsed() >= SEC30 { @@ -1537,15 +1492,14 @@ impl Connection { #[cfg(windows)] { let mut err = "No need to elevate".to_string(); - if !crate::platform::is_installed() - && !crate::portable_service::client::running() - { - use crate::portable_service::client; - err = client::start_portable_service(client::StartPara::Direct) - .err() - .map_or("".to_string(), |e| e.to_string()); + if !crate::platform::is_installed() && !portable_client::running() { + err = portable_client::start_portable_service( + portable_client::StartPara::Direct, + ) + .err() + .map_or("".to_string(), |e| e.to_string()); } - self.elevation_requested = err.is_empty(); + self.portable.elevation_requested = err.is_empty(); let mut misc = Misc::new(); misc.set_elevation_response(err); let mut msg = Message::new(); @@ -1557,18 +1511,14 @@ impl Connection { #[cfg(windows)] { let mut err = "No need to elevate".to_string(); - if !crate::platform::is_installed() - && !crate::portable_service::client::running() - { - use crate::portable_service::client; - err = client::start_portable_service(client::StartPara::Logon( - _r.username, - _r.password, - )) + if !crate::platform::is_installed() && !portable_client::running() { + err = portable_client::start_portable_service( + portable_client::StartPara::Logon(_r.username, _r.password), + ) .err() .map_or("".to_string(), |e| e.to_string()); } - self.elevation_requested = err.is_empty(); + self.portable.elevation_requested = err.is_empty(); let mut misc = Misc::new(); misc.set_elevation_response(err); let mut msg = Message::new(); @@ -1810,6 +1760,59 @@ impl Connection { pub fn alive_conns() -> Vec { ALIVE_CONNS.lock().unwrap().clone() } + + #[cfg(windows)] + fn portable_check(&mut self) { + if self.portable.is_installed + || self.file_transfer.is_some() + || self.port_forward_socket.is_some() + { + return; + } + let running = portable_client::running(); + let show_elevation = !running; + self.send_to_cm(ipc::Data::DataPortableService( + ipc::DataPortableService::CmShowElevation(show_elevation), + )); + if self.authorized { + let p = &mut self.portable; + if running != p.last_running { + p.last_running = running; + if running && p.elevation_requested { + let mut misc = Misc::new(); + misc.set_portable_service_running(running); + let mut msg = Message::new(); + msg.set_misc(misc); + self.inner.send(msg.into()); + } + } + let uac = crate::video_service::IS_UAC_RUNNING.lock().unwrap().clone(); + if p.last_uac != uac { + p.last_uac = uac; + if !uac || !running { + let mut misc = Misc::new(); + misc.set_uac(uac); + let mut msg = Message::new(); + msg.set_misc(misc); + self.inner.send(msg.into()); + } + } + let foreground_window_elevated = crate::video_service::IS_FOREGROUND_WINDOW_ELEVATED + .lock() + .unwrap() + .clone(); + if p.last_foreground_window_elevated != foreground_window_elevated { + p.last_foreground_window_elevated = foreground_window_elevated; + if !foreground_window_elevated || !running { + let mut misc = Misc::new(); + misc.set_foreground_window_elevated(foreground_window_elevated); + let mut msg = Message::new(); + msg.set_misc(misc); + self.inner.send(msg.into()); + } + } + } + } } pub fn insert_switch_sides_uuid(id: String, uuid: uuid::Uuid) { @@ -1984,3 +1987,25 @@ pub enum FileAuditType { RemoteSend = 0, RemoteReceive = 1, } + +#[cfg(windows)] +pub struct PortableState { + pub last_uac: bool, + pub last_foreground_window_elevated: bool, + pub last_running: bool, + pub is_installed: bool, + pub elevation_requested: bool, +} + +#[cfg(windows)] +impl Default for PortableState { + fn default() -> Self { + Self { + is_installed: crate::platform::is_installed(), + last_uac: Default::default(), + last_foreground_window_elevated: Default::default(), + last_running: Default::default(), + elevation_requested: Default::default(), + } + } +} diff --git a/src/server/video_service.rs b/src/server/video_service.rs index 599dfbd54..d041a433c 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -956,15 +956,17 @@ fn start_uac_elevation_check() { START.call_once(|| { if !crate::platform::is_installed() && !crate::platform::is_root() - && !crate::platform::is_elevated(None).map_or(false, |b| b) + && !crate::portable_service::client::running() { std::thread::spawn(|| loop { std::thread::sleep(std::time::Duration::from_secs(1)); if let Ok(uac) = crate::ui::win_privacy::is_process_consent_running() { *IS_UAC_RUNNING.lock().unwrap() = uac; } - if let Ok(elevated) = crate::platform::is_foreground_window_elevated() { - *IS_FOREGROUND_WINDOW_ELEVATED.lock().unwrap() = elevated; + if !crate::platform::is_elevated(None).unwrap_or(false) { + if let Ok(elevated) = crate::platform::is_foreground_window_elevated() { + *IS_FOREGROUND_WINDOW_ELEVATED.lock().unwrap() = elevated; + } } }); } diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index d620bcbc9..5d451e4d4 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -789,9 +789,7 @@ fn cm_inner_send(id: i32, data: Data) { pub fn can_elevate() -> bool { #[cfg(windows)] - { - return !crate::platform::is_installed() && !crate::portable_service::client::running(); - } + return !crate::platform::is_installed(); #[cfg(not(windows))] return false; } From 19f04f29c0c70d450237d26365fe178b97758d37 Mon Sep 17 00:00:00 2001 From: 21pages Date: Sat, 28 Jan 2023 17:10:40 +0800 Subject: [PATCH 04/83] fix desktop dialog request focus Signed-off-by: 21pages --- flutter/lib/common.dart | 9 ++++----- flutter/lib/common/widgets/login.dart | 2 ++ flutter/lib/desktop/widgets/remote_menubar.dart | 1 + 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index f4e0c2d75..6ee57ef50 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -608,12 +608,11 @@ class CustomAlertDialog extends StatelessWidget { @override Widget build(BuildContext context) { - FocusNode focusNode = FocusNode(); - // request focus if there is no focused FocusNode in the dialog - Future.delayed(Duration.zero, () { - if (!focusNode.hasFocus) focusNode.requestFocus(); - }); + // request focus FocusScopeNode scopeNode = FocusScopeNode(); + Future.delayed(Duration.zero, () { + if (!scopeNode.hasFocus) scopeNode.requestFocus(); + }); return FocusScope( node: scopeNode, autofocus: true, diff --git a/flutter/lib/common/widgets/login.dart b/flutter/lib/common/widgets/login.dart index 2f10ac005..05fc1fc5c 100644 --- a/flutter/lib/common/widgets/login.dart +++ b/flutter/lib/common/widgets/login.dart @@ -666,6 +666,8 @@ Future verificationCodeDialog(UserPayload? user) async { child: const LinearProgressIndicator()), ], ), + onCancel: close, + onSubmit: onVerify, actions: [ dialogButton("Cancel", onPressed: close, isOutline: true), dialogButton("Verify", onPressed: onVerify), diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 62289d5f0..b9d793744 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -653,6 +653,7 @@ class _RemoteMenubarState extends State { )); } if (pi.platform != kPeerPlatformAndroid && + pi.platform != kPeerPlatformMacOS && // unsupport yet version_cmp(peer_version, '1.2.0') >= 0) { displayMenu.add(MenuEntryButton( childBuilder: (TextStyle? style) => Text( From 8a88640b18f13dcb608ba0708a1cf599584f7221 Mon Sep 17 00:00:00 2001 From: NicKoehler <53040044+NicKoehler@users.noreply.github.com> Date: Sat, 28 Jan 2023 11:49:09 +0100 Subject: [PATCH 05/83] Update it.rs --- src/lang/it.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lang/it.rs b/src/lang/it.rs index d7340b27f..322c324ce 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -41,9 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Informazioni"), ("Slogan_tip", "Fatta con il cuore in questo mondo caotico!"), ("Privacy Statement", "Informativa sulla privacy"), - ("Build Date", ""), - ("Version", ""), - ("Home", ""), + ("Build Date", "Data della build"), + ("Version", "Versione"), + ("Home", "Home"), ("Mute", "Silenzia"), ("Audio Input", "Input audio"), ("Enhancements", "Miglioramenti"), @@ -436,6 +436,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Strong", "Forte"), ("Switch Sides", "Cambia lato"), ("Please confirm if you want to share your desktop?", "Vuoi condividere il tuo desktop?"), - ("Closed as expected", ""), + ("Closed as expected", "Chiuso come previsto"), ].iter().cloned().collect(); } From 733a43df07d6710f24999df6eb376aeea2736532 Mon Sep 17 00:00:00 2001 From: csf Date: Sat, 28 Jan 2023 21:24:49 +0900 Subject: [PATCH 06/83] 1. fix get_api_server. 2. add device info in LoginRequest --- flutter/lib/common/hbbs/hbbs.dart | 32 ++++++++++++++++--------------- src/common.rs | 13 +++++++++++-- src/flutter_ffi.rs | 4 ++++ 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/flutter/lib/common/hbbs/hbbs.dart b/flutter/lib/common/hbbs/hbbs.dart index 27238db67..4717143fd 100644 --- a/flutter/lib/common/hbbs/hbbs.dart +++ b/flutter/lib/common/hbbs/hbbs.dart @@ -1,5 +1,9 @@ +import 'dart:io'; + import 'package:flutter_hbb/models/peer_model.dart'; +import '../../models/platform_model.dart'; + class HttpType { static const kAuthReqTypeAccount = "account"; static const kAuthReqTypeMobile = "mobile"; @@ -48,6 +52,16 @@ class PeerPayload { } } +class DeviceInfo { + static Map toJson() { + final Map data = {}; + data['os'] = Platform.operatingSystem; + data['type'] = "client"; + data['name'] = bind.mainGetHostname(); + return data; + } +} + class LoginRequest { String? username; String? password; @@ -56,7 +70,7 @@ class LoginRequest { bool? autoLogin; String? type; String? verificationCode; - String? deviceInfo; + Map deviceInfo = DeviceInfo.toJson(); LoginRequest( {this.username, @@ -65,19 +79,7 @@ class LoginRequest { this.uuid, this.autoLogin, this.type, - this.verificationCode, - this.deviceInfo}); - - LoginRequest.fromJson(Map json) { - username = json['username']; - password = json['password']; - id = json['id']; - uuid = json['uuid']; - autoLogin = json['autoLogin']; - type = json['type']; - verificationCode = json['verificationCode']; - deviceInfo = json['deviceInfo']; - } + this.verificationCode}); Map toJson() { final Map data = {}; @@ -88,7 +90,7 @@ class LoginRequest { data['autoLogin'] = autoLogin ?? ''; data['type'] = type ?? ''; data['verificationCode'] = verificationCode ?? ''; - data['deviceInfo'] = deviceInfo ?? ''; + data['deviceInfo'] = deviceInfo; return data; } } diff --git a/src/common.rs b/src/common.rs index cdf57ae3d..2bf287feb 100644 --- a/src/common.rs +++ b/src/common.rs @@ -451,6 +451,7 @@ pub fn run_me>(args: Vec) -> std::io::Result String { // fix bug of whoami #[cfg(not(any(target_os = "android", target_os = "ios")))] @@ -459,6 +460,14 @@ pub fn username() -> String { return DEVICE_NAME.lock().unwrap().clone(); } +#[inline] +pub fn hostname() -> String { + #[cfg(not(any(target_os = "android", target_os = "ios")))] + return whoami::hostname(); + #[cfg(any(target_os = "android", target_os = "ios"))] + return DEVICE_NAME.lock().unwrap().clone(); +} + #[inline] pub fn check_port(host: T, port: i32) -> String { hbb_common::socket_client::check_port(host, port) @@ -581,9 +590,9 @@ pub fn get_api_server(api: String, custom: String) -> String { if !s0.is_empty() { let s = crate::increase_port(&s0, -2); if s == s0 { - format!("http://{}:{}", s, config::RENDEZVOUS_PORT - 2); + return format!("http://{}:{}", s, config::RENDEZVOUS_PORT - 2); } else { - format!("http://{}", s); + return format!("http://{}", s); } } "https://admin.rustdesk.com".to_owned() diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index c30c6c847..ebaa160f1 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -523,6 +523,10 @@ pub fn main_get_sound_inputs() -> Vec { vec![String::from("")] } +pub fn main_get_hostname() -> SyncReturn { + SyncReturn(crate::common::hostname()) +} + pub fn main_change_id(new_id: String) { change_id(new_id) } From 813b9ea79def023dc39982ba16befbf89c2a2f08 Mon Sep 17 00:00:00 2001 From: csf Date: Sat, 28 Jan 2023 22:02:42 +0900 Subject: [PATCH 07/83] fix logout failed --- flutter/lib/models/user_model.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/flutter/lib/models/user_model.dart b/flutter/lib/models/user_model.dart index b0eebee53..6694d8c5c 100644 --- a/flutter/lib/models/user_model.dart +++ b/flutter/lib/models/user_model.dart @@ -80,13 +80,15 @@ class UserModel { final tag = gFFI.dialogManager.showLoading(translate('Waiting')); try { final url = await bind.mainGetApiServer(); + final authHeaders = getHttpHeaders(); + authHeaders['Content-Type'] = "application/json"; await http .post(Uri.parse('$url/api/logout'), - body: { + body: jsonEncode({ 'id': await bind.mainGetMyId(), 'uuid': await bind.mainGetUuid(), - }, - headers: getHttpHeaders()) + }), + headers: authHeaders) .timeout(Duration(seconds: 2)); } catch (e) { print("request /api/logout failed: err=$e"); From d04f047d14a543b36fe372481b924922348898ad Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 28 Jan 2023 21:11:03 +0800 Subject: [PATCH 08/83] feat mouse click and move through monitor widget Signed-off-by: fufesou --- flutter/lib/common/widgets/overlay.dart | 8 ++- flutter/lib/desktop/pages/remote_page.dart | 60 ++++++++++++++-------- flutter/lib/mobile/pages/remote_page.dart | 6 ++- 3 files changed, 46 insertions(+), 28 deletions(-) diff --git a/flutter/lib/common/widgets/overlay.dart b/flutter/lib/common/widgets/overlay.dart index 81797962e..d9684bace 100644 --- a/flutter/lib/common/widgets/overlay.dart +++ b/flutter/lib/common/widgets/overlay.dart @@ -324,10 +324,8 @@ class QualityMonitor extends StatelessWidget { Widget build(BuildContext context) => ChangeNotifierProvider.value( value: qualityMonitorModel, child: Consumer( - builder: (context, qualityMonitorModel, child) => Positioned( - top: 10, - right: 10, - child: qualityMonitorModel.show + builder: (context, qualityMonitorModel, child) => + qualityMonitorModel.show ? Container( padding: const EdgeInsets.all(8), color: MyTheme.canvasColor.withAlpha(120), @@ -357,5 +355,5 @@ class QualityMonitor extends StatelessWidget { ], ), ) - : const SizedBox.shrink()))); + : const SizedBox.shrink())); } diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index fb67154bc..2e4668159 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -279,6 +279,34 @@ class _RemotePageState extends State } } + Widget _buildRawPointerMouseRegion( + Widget child, + PointerEnterEventListener? onEnter, + PointerExitEventListener? onExit, + ) { + return RawPointerMouseRegion( + onEnter: enterView, + onExit: leaveView, + onPointerDown: (event) { + // A double check for blur status. + // Note: If there's an `onPointerDown` event is triggered, `_isWindowBlur` is expected being false. + // Sometimes the system does not send the necessary focus event to flutter. We should manually + // handle this inconsistent status by setting `_isWindowBlur` to false. So we can + // ensure the grab-key thread is running when our users are clicking the remote canvas. + if (_isWindowBlur) { + debugPrint( + "Unexpected status: onPointerDown is triggered while the remote window is in blur status"); + _isWindowBlur = false; + } + if (!_rawKeyFocusNode.hasFocus) { + _rawKeyFocusNode.requestFocus(); + } + }, + inputModel: _ffi.inputModel, + child: child, + ); + } + Widget getBodyForDesktop(BuildContext context) { var paints = [ MouseRegion(onEnter: (evt) { @@ -295,27 +323,8 @@ class _RemotePageState extends State cursorOverImage: _cursorOverImage, keyboardEnabled: _keyboardEnabled, remoteCursorMoved: _remoteCursorMoved, - listenerBuilder: (child) => RawPointerMouseRegion( - onEnter: enterView, - onExit: leaveView, - onPointerDown: (event) { - // A double check for blur status. - // Note: If there's an `onPointerDown` event is triggered, `_isWindowBlur` is expected being false. - // Sometimes the system does not send the necessary focus event to flutter. We should manually - // handle this inconsistent status by setting `_isWindowBlur` to false. So we can - // ensure the grab-key thread is running when our users are clicking the remote canvas. - if (_isWindowBlur) { - debugPrint( - "Unexpected status: onPointerDown is triggered while the remote window is in blur status"); - _isWindowBlur = false; - } - if (!_rawKeyFocusNode.hasFocus) { - _rawKeyFocusNode.requestFocus(); - } - }, - inputModel: _ffi.inputModel, - child: child, - ), + listenerBuilder: (child) => + _buildRawPointerMouseRegion(child, enterView, leaveView), ); })) ]; @@ -328,7 +337,14 @@ class _RemotePageState extends State zoomCursor: _zoomCursor, )))); } - paints.add(QualityMonitor(_ffi.qualityMonitorModel)); + paints.add( + Positioned( + top: 10, + right: 10, + child: _buildRawPointerMouseRegion( + QualityMonitor(_ffi.qualityMonitorModel), null, null), + ), + ); paints.add(RemoteMenubar( id: widget.id, ffi: _ffi, diff --git a/flutter/lib/mobile/pages/remote_page.dart b/flutter/lib/mobile/pages/remote_page.dart index 0a10d8011..c4b07b375 100644 --- a/flutter/lib/mobile/pages/remote_page.dart +++ b/flutter/lib/mobile/pages/remote_page.dart @@ -497,7 +497,11 @@ class _RemotePageState extends State { child: Stack(children: () { final paints = [ ImagePaint(), - QualityMonitor(gFFI.qualityMonitorModel), + Positioned( + top: 10, + right: 10, + child: QualityMonitor(gFFI.qualityMonitorModel), + ), getHelpTools(), SizedBox( width: 0, From eb831a912a8250e2f735bbffb419378c71527319 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sat, 28 Jan 2023 21:52:19 +0100 Subject: [PATCH 09/83] Update de.rs --- src/lang/de.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lang/de.rs b/src/lang/de.rs index 15e98e529..11ce96f6b 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -42,9 +42,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Slogan_tip", "Mit Herzblut programmiert - in einer Welt, die im Chaos versinkt!"), ("Privacy Statement", "Datenschutz"), ("Mute", "Stummschalten"), - ("Build Date", ""), - ("Version", ""), - ("Home", ""), + ("Build Date", "Erstelldatum"), + ("Version", "Version"), + ("Home", "Startseite"), ("Audio Input", "Audioeingang"), ("Enhancements", "Verbesserungen"), ("Hardware Codec", "Hardware-Codec"), @@ -244,7 +244,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Remote ID", "Entfernte ID"), ("Paste", "Einfügen"), ("Paste here?", "Hier einfügen?"), - ("Are you sure to close the connection?", "Möchten Sie diese Verbindung wirklich trennen?"), + ("Are you sure to close the connection?", "Möchten Sie diese Verbindung wirklich schließen?"), ("Download new version", "Neue Version herunterladen"), ("Touch mode", "Touch-Modus"), ("Mouse mode", "Mausmodus"), @@ -267,8 +267,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Hinweis"), ("Connection", "Verbindung"), ("Share Screen", "Bildschirm freigeben"), - ("CLOSE", "DEAKTIV."), - ("OPEN", "AKTIVIER."), + ("CLOSE", "SCHLIEẞEN"), + ("OPEN", "ÖFFNEN"), ("Chat", "Chat"), ("Total", "Gesamt"), ("items", "Einträge"), @@ -387,7 +387,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("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)."), + ("Please Select the screen to be shared(Operate on the peer side).", "Bitte wählen Sie den freizugebenden Bildschirm aus (Bedienung auf der Peer-Seite)."), ("Show RustDesk", "RustDesk anzeigen"), ("This PC", "Dieser PC"), ("or", "oder"), @@ -410,7 +410,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Add to Address Book", "Zum Adressbuch hinzufügen"), ("Group", "Gruppe"), ("Search", "Suchen"), - ("Closed manually by web console", "Manuell über die Webkonsole beendet"), + ("Closed manually by web console", "Manuell über die Webkonsole geschlossen"), ("Local keyboard type", "Lokaler Tastaturtyp"), ("Select local keyboard type", "Lokalen Tastaturtyp auswählen"), ("software_render_tip", "Wenn Sie eine Nvidia-Grafikkarte haben und sich das entfernte Fenster sofort nach dem Herstellen der Verbindung schließt, kann es helfen, den Nouveau-Treiber zu installieren und Software-Rendering zu verwenden. Ein Neustart der Software ist erforderlich."), @@ -436,6 +436,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Strong", "Stark"), ("Switch Sides", "Seiten wechseln"), ("Please confirm if you want to share your desktop?", "Bitte bestätigen Sie, ob Sie Ihren Desktop freigeben möchten."), - ("Closed as expected", ""), + ("Closed as expected", "Wie erwartet geschlossen"), ].iter().cloned().collect(); } From 7e0c9e17df28710387249e7daf34fee107ce8f7a Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 28 Jan 2023 20:32:46 +0800 Subject: [PATCH 10/83] set cursor mode according to availible modes Signed-off-by: fufesou --- libs/scrap/src/wayland/pipewire.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/libs/scrap/src/wayland/pipewire.rs b/libs/scrap/src/wayland/pipewire.rs index c1c84f98e..d1a8d9f85 100644 --- a/libs/scrap/src/wayland/pipewire.rs +++ b/libs/scrap/src/wayland/pipewire.rs @@ -473,7 +473,17 @@ fn request_screen_cast( args.insert("multiple".into(), Variant(Box::new(true))); args.insert("types".into(), Variant(Box::new(1u32))); //| 2u32))); - let cursor_mode = if capture_cursor { 2u32 } else { 1u32 }; + let mut cursor_mode = 0u32; + let mut available_cursor_modes = 0u32; + if let Ok(modes) = portal.available_cursor_modes() { + available_cursor_modes = modes; + } + if capture_cursor { + cursor_mode = 2u32 & available_cursor_modes; + } + if cursor_mode == 0 { + cursor_mode = 1u32 & available_cursor_modes; + } let plasma = std::env::var("DESKTOP_SESSION").map_or(false, |s| s.contains("plasma")); if plasma && capture_cursor { // Warn the user if capturing the cursor is tried on kde as this can crash @@ -483,7 +493,9 @@ fn request_screen_cast( desktop, see https://bugs.kde.org/show_bug.cgi?id=435042 for details! \ You have been warned."); } - args.insert("cursor_mode".into(), Variant(Box::new(cursor_mode))); + if cursor_mode > 0 { + args.insert("cursor_mode".into(), Variant(Box::new(cursor_mode))); + } let session: dbus::Path = r .results .get("session_handle") From b84f3ba1ee7708d8150e53c6a674bbcf1ffc1bc4 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 28 Jan 2023 22:19:28 +0800 Subject: [PATCH 11/83] init wayland to update var 'cursor embeded' Signed-off-by: fufesou --- libs/scrap/src/common/mod.rs | 4 ++-- libs/scrap/src/common/wayland.rs | 18 ++++++++++++++++-- libs/scrap/src/wayland/pipewire.rs | 6 ++++++ src/common.rs | 2 +- src/server/wayland.rs | 5 +++-- 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/libs/scrap/src/common/mod.rs b/libs/scrap/src/common/mod.rs index 1de2f89d6..1df96f511 100644 --- a/libs/scrap/src/common/mod.rs +++ b/libs/scrap/src/common/mod.rs @@ -12,7 +12,7 @@ cfg_if! { mod x11; pub use self::linux::*; pub use self::x11::Frame; - pub use self::wayland::set_map_err; + pub use self::wayland::{set_map_err, detect_cursor_embeded}; } else { mod x11; pub use self::x11::*; @@ -76,7 +76,7 @@ pub fn is_cursor_embedded() -> bool { if is_x11() { x11::IS_CURSOR_EMBEDDED } else { - wayland::IS_CURSOR_EMBEDDED + unsafe { wayland::IS_CURSOR_EMBEDDED } } } diff --git a/libs/scrap/src/common/wayland.rs b/libs/scrap/src/common/wayland.rs index e625fca7e..c807479f1 100644 --- a/libs/scrap/src/common/wayland.rs +++ b/libs/scrap/src/common/wayland.rs @@ -4,12 +4,26 @@ use std::{io, sync::RwLock, time::Duration}; pub struct Capturer(Display, Box, bool, Vec); -pub const IS_CURSOR_EMBEDDED: bool = true; +pub static mut IS_CURSOR_EMBEDDED: bool = true; lazy_static::lazy_static! { static ref MAP_ERR: RwLock io::Error>> = Default::default(); } +pub fn detect_cursor_embeded() { + if unsafe { IS_CURSOR_EMBEDDED } { + use crate::common::wayland::pipewire::get_available_cursor_modes; + match get_available_cursor_modes() { + Ok(modes) => unsafe { + IS_CURSOR_EMBEDDED = (modes & 0x02) > 0; + }, + Err(..) => unsafe { + IS_CURSOR_EMBEDDED = false; + }, + } + } +} + pub fn set_map_err(f: fn(err: String) -> io::Error) { *MAP_ERR.write().unwrap() = Some(f); } @@ -74,7 +88,7 @@ impl Display { } pub fn all() -> io::Result> { - Ok(pipewire::get_capturables(true) + Ok(pipewire::get_capturables(unsafe { IS_CURSOR_EMBEDDED }) .map_err(map_err)? .drain(..) .map(|x| Display(x)) diff --git a/libs/scrap/src/wayland/pipewire.rs b/libs/scrap/src/wayland/pipewire.rs index d1a8d9f85..fefab9b77 100644 --- a/libs/scrap/src/wayland/pipewire.rs +++ b/libs/scrap/src/wayland/pipewire.rs @@ -415,6 +415,12 @@ static mut INIT: bool = false; const RESTORE_TOKEN: &str = "restore_token"; const RESTORE_TOKEN_CONF_KEY: &str = "wayland-restore-token"; +pub fn get_available_cursor_modes() -> Result { + let conn = SyncConnection::new_session()?; + let portal = get_portal(&conn); + portal.available_cursor_modes() +} + // mostly inspired by https://gitlab.gnome.org/snippets/19 fn request_screen_cast( capture_cursor: bool, diff --git a/src/common.rs b/src/common.rs index 2bf287feb..c2d5a81f0 100644 --- a/src/common.rs +++ b/src/common.rs @@ -52,7 +52,7 @@ pub fn global_init() -> bool { #[cfg(target_os = "linux")] { if !*IS_X11 { - crate::server::wayland::set_wayland_scrap_map_err(); + crate::server::wayland::init(); } } true diff --git a/src/server/wayland.rs b/src/server/wayland.rs index 68b9c37cf..96fc2fff6 100644 --- a/src/server/wayland.rs +++ b/src/server/wayland.rs @@ -1,6 +1,6 @@ use super::*; use hbb_common::{allow_err, platform::linux::DISTRO}; -use scrap::{set_map_err, Capturer, Display, Frame, TraitCapturer}; +use scrap::{detect_cursor_embeded, set_map_err, Capturer, Display, Frame, TraitCapturer}; use std::io; use super::video_service::{ @@ -12,7 +12,8 @@ lazy_static::lazy_static! { static ref LOG_SCRAP_COUNT: Mutex = Mutex::new(0); } -pub fn set_wayland_scrap_map_err() { +pub fn init() { + detect_cursor_embeded(); set_map_err(map_err_scrap); } From c0adc142159bea13e72db9b986a2f54b7ebeb9a5 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 29 Jan 2023 09:26:55 +0800 Subject: [PATCH 12/83] misspelling Signed-off-by: fufesou --- libs/scrap/src/common/mod.rs | 2 +- libs/scrap/src/common/wayland.rs | 2 +- src/server/wayland.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/scrap/src/common/mod.rs b/libs/scrap/src/common/mod.rs index 1df96f511..af1bc4d5e 100644 --- a/libs/scrap/src/common/mod.rs +++ b/libs/scrap/src/common/mod.rs @@ -12,7 +12,7 @@ cfg_if! { mod x11; pub use self::linux::*; pub use self::x11::Frame; - pub use self::wayland::{set_map_err, detect_cursor_embeded}; + pub use self::wayland::{set_map_err, detect_cursor_embedded}; } else { mod x11; pub use self::x11::*; diff --git a/libs/scrap/src/common/wayland.rs b/libs/scrap/src/common/wayland.rs index c807479f1..9d62b87d2 100644 --- a/libs/scrap/src/common/wayland.rs +++ b/libs/scrap/src/common/wayland.rs @@ -10,7 +10,7 @@ lazy_static::lazy_static! { static ref MAP_ERR: RwLock io::Error>> = Default::default(); } -pub fn detect_cursor_embeded() { +pub fn detect_cursor_embedded() { if unsafe { IS_CURSOR_EMBEDDED } { use crate::common::wayland::pipewire::get_available_cursor_modes; match get_available_cursor_modes() { diff --git a/src/server/wayland.rs b/src/server/wayland.rs index 96fc2fff6..eada6971a 100644 --- a/src/server/wayland.rs +++ b/src/server/wayland.rs @@ -1,6 +1,6 @@ use super::*; use hbb_common::{allow_err, platform::linux::DISTRO}; -use scrap::{detect_cursor_embeded, set_map_err, Capturer, Display, Frame, TraitCapturer}; +use scrap::{detect_cursor_embedded, set_map_err, Capturer, Display, Frame, TraitCapturer}; use std::io; use super::video_service::{ @@ -13,7 +13,7 @@ lazy_static::lazy_static! { } pub fn init() { - detect_cursor_embeded(); + detect_cursor_embedded(); set_map_err(map_err_scrap); } From 340897ab1805a5ccc2d9b2c7c8af224643e4017f Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 29 Jan 2023 09:57:05 +0800 Subject: [PATCH 13/83] set cursor embedded Signed-off-by: fufesou --- src/server/wayland.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/server/wayland.rs b/src/server/wayland.rs index eada6971a..817b8adb7 100644 --- a/src/server/wayland.rs +++ b/src/server/wayland.rs @@ -1,6 +1,9 @@ use super::*; use hbb_common::{allow_err, platform::linux::DISTRO}; -use scrap::{detect_cursor_embedded, set_map_err, Capturer, Display, Frame, TraitCapturer}; +use scrap::{ + detect_cursor_embedded, is_cursor_embedded, set_map_err, Capturer, Display, Frame, + TraitCapturer, +}; use std::io; use super::video_service::{ @@ -130,7 +133,7 @@ pub(super) async fn check_init() -> ResultType<()> { let num = all.len(); let (primary, mut displays) = super::video_service::get_displays_2(&all); for display in displays.iter_mut() { - display.cursor_embedded = true; + display.cursor_embedded = is_cursor_embedded(); } let mut rects: Vec<((i32, i32), usize, usize)> = Vec::new(); From d1090fc62c7d62d0bcf26d45b4675360118ba756 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 29 Jan 2023 10:58:04 +0800 Subject: [PATCH 14/83] ensure init cursor embedded Signed-off-by: fufesou --- libs/scrap/src/common/mod.rs | 4 ++-- libs/scrap/src/common/wayland.rs | 31 +++++++++++++++++++------------ src/server/wayland.rs | 6 +----- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/libs/scrap/src/common/mod.rs b/libs/scrap/src/common/mod.rs index af1bc4d5e..45aafe7c5 100644 --- a/libs/scrap/src/common/mod.rs +++ b/libs/scrap/src/common/mod.rs @@ -12,7 +12,7 @@ cfg_if! { mod x11; pub use self::linux::*; pub use self::x11::Frame; - pub use self::wayland::{set_map_err, detect_cursor_embedded}; + pub use self::wayland::set_map_err; } else { mod x11; pub use self::x11::*; @@ -76,7 +76,7 @@ pub fn is_cursor_embedded() -> bool { if is_x11() { x11::IS_CURSOR_EMBEDDED } else { - unsafe { wayland::IS_CURSOR_EMBEDDED } + wayland::is_cursor_embedded() } } diff --git a/libs/scrap/src/common/wayland.rs b/libs/scrap/src/common/wayland.rs index 9d62b87d2..86afd5d82 100644 --- a/libs/scrap/src/common/wayland.rs +++ b/libs/scrap/src/common/wayland.rs @@ -4,22 +4,29 @@ use std::{io, sync::RwLock, time::Duration}; pub struct Capturer(Display, Box, bool, Vec); -pub static mut IS_CURSOR_EMBEDDED: bool = true; +static mut IS_CURSOR_EMBEDDED: Option = None; lazy_static::lazy_static! { static ref MAP_ERR: RwLock io::Error>> = Default::default(); } -pub fn detect_cursor_embedded() { - if unsafe { IS_CURSOR_EMBEDDED } { - use crate::common::wayland::pipewire::get_available_cursor_modes; - match get_available_cursor_modes() { - Ok(modes) => unsafe { - IS_CURSOR_EMBEDDED = (modes & 0x02) > 0; - }, - Err(..) => unsafe { - IS_CURSOR_EMBEDDED = false; - }, +pub fn is_cursor_embedded() -> bool { + unsafe { + if IS_CURSOR_EMBEDDED.is_none() { + init_cursor_embedded(); + } + IS_CURSOR_EMBEDDED.unwrap_or(false) + } +} + +unsafe fn init_cursor_embedded() { + use crate::common::wayland::pipewire::get_available_cursor_modes; + match get_available_cursor_modes() { + Ok(modes) => { + IS_CURSOR_EMBEDDED = Some((modes & 0x02) > 0); + } + Err(..) => { + IS_CURSOR_EMBEDDED = Some(false); } } } @@ -88,7 +95,7 @@ impl Display { } pub fn all() -> io::Result> { - Ok(pipewire::get_capturables(unsafe { IS_CURSOR_EMBEDDED }) + Ok(pipewire::get_capturables(is_cursor_embedded()) .map_err(map_err)? .drain(..) .map(|x| Display(x)) diff --git a/src/server/wayland.rs b/src/server/wayland.rs index 817b8adb7..954f1ed1d 100644 --- a/src/server/wayland.rs +++ b/src/server/wayland.rs @@ -1,9 +1,6 @@ use super::*; use hbb_common::{allow_err, platform::linux::DISTRO}; -use scrap::{ - detect_cursor_embedded, is_cursor_embedded, set_map_err, Capturer, Display, Frame, - TraitCapturer, -}; +use scrap::{is_cursor_embedded, set_map_err, Capturer, Display, Frame, TraitCapturer}; use std::io; use super::video_service::{ @@ -16,7 +13,6 @@ lazy_static::lazy_static! { } pub fn init() { - detect_cursor_embedded(); set_map_err(map_err_scrap); } From 176847c51eda697839468b23f1ac679c2b73e618 Mon Sep 17 00:00:00 2001 From: 21pages Date: Sun, 29 Jan 2023 14:27:57 +0800 Subject: [PATCH 15/83] fix warning Signed-off-by: 21pages --- libs/scrap/src/dxgi/mod.rs | 7 +++++++ src/platform/windows.rs | 3 +++ src/server/connection.rs | 7 +++---- src/ui_session_interface.rs | 1 - 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/libs/scrap/src/dxgi/mod.rs b/libs/scrap/src/dxgi/mod.rs index 152f502a3..4a0a53402 100644 --- a/libs/scrap/src/dxgi/mod.rs +++ b/libs/scrap/src/dxgi/mod.rs @@ -58,6 +58,7 @@ impl Capturer { let mut device = ptr::null_mut(); let mut context = ptr::null_mut(); let mut duplication = ptr::null_mut(); + #[allow(invalid_value)] let mut desc = unsafe { mem::MaybeUninit::uninit().assume_init() }; let mut gdi_capturer = None; @@ -176,6 +177,7 @@ impl Capturer { unsafe fn load_frame(&mut self, timeout: UINT) -> io::Result<(*const u8, i32)> { let mut frame = ptr::null_mut(); + #[allow(invalid_value)] let mut info = mem::MaybeUninit::uninit().assume_init(); wrap_hresult((*self.duplication.0).AcquireNextFrame(timeout, &mut info, &mut frame))?; @@ -185,6 +187,7 @@ impl Capturer { return Err(std::io::ErrorKind::WouldBlock.into()); } + #[allow(invalid_value)] let mut rect = mem::MaybeUninit::uninit().assume_init(); if self.fastlane { wrap_hresult((*self.duplication.0).MapDesktopSurface(&mut rect))?; @@ -204,6 +207,7 @@ impl Capturer { ); let texture = ComPtr(texture); + #[allow(invalid_value)] let mut texture_desc = mem::MaybeUninit::uninit().assume_init(); (*texture.0).GetDesc(&mut texture_desc); @@ -362,6 +366,7 @@ impl Displays { let mut all = Vec::new(); let mut i: DWORD = 0; loop { + #[allow(invalid_value)] let mut d: DISPLAY_DEVICEW = unsafe { std::mem::MaybeUninit::uninit().assume_init() }; d.cb = std::mem::size_of::() as _; let ok = unsafe { EnumDisplayDevicesW(std::ptr::null(), i, &mut d as _, 0) }; @@ -382,6 +387,7 @@ impl Displays { gdi: true, }; disp.desc.DeviceName = d.DeviceName; + #[allow(invalid_value)] let mut m: DEVMODEW = unsafe { std::mem::MaybeUninit::uninit().assume_init() }; m.dmSize = std::mem::size_of::() as _; m.dmDriverExtra = 0; @@ -441,6 +447,7 @@ impl Displays { // We get the display's details. let desc = unsafe { + #[allow(invalid_value)] let mut desc = mem::MaybeUninit::uninit().assume_init(); (*output.0).GetDesc(&mut desc); desc diff --git a/src/platform/windows.rs b/src/platform/windows.rs index a77b92e07..b778283a5 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -49,6 +49,7 @@ use winreg::RegKey; pub fn get_cursor_pos() -> Option<(i32, i32)> { unsafe { + #[allow(invalid_value)] let mut out = mem::MaybeUninit::uninit().assume_init(); if GetCursorPos(&mut out) == FALSE { return None; @@ -61,6 +62,7 @@ pub fn reset_input_cache() {} pub fn get_cursor() -> ResultType> { unsafe { + #[allow(invalid_value)] let mut ci: CURSORINFO = mem::MaybeUninit::uninit().assume_init(); ci.cbSize = std::mem::size_of::() as _; if crate::portable_service::client::get_cursor_info(&mut ci) == FALSE { @@ -79,6 +81,7 @@ struct IconInfo(ICONINFO); impl IconInfo { fn new(icon: HICON) -> ResultType { unsafe { + #[allow(invalid_value)] let mut ii = mem::MaybeUninit::uninit().assume_init(); if GetIconInfo(icon, &mut ii) == FALSE { Err(io::Error::last_os_error().into()) diff --git a/src/server/connection.rs b/src/server/connection.rs index c7aa7fe0c..e4b667d54 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -138,7 +138,6 @@ const MILLI1: Duration = Duration::from_millis(1); const SEND_TIMEOUT_VIDEO: u64 = 12_000; const SEND_TIMEOUT_OTHER: u64 = SEND_TIMEOUT_VIDEO * 10; const SESSION_TIMEOUT: Duration = Duration::from_secs(30); -const SWITCH_SIDES_TIMEOUT: Duration = Duration::from_secs(10); impl Connection { pub async fn start( @@ -1231,7 +1230,7 @@ impl Connection { SWITCH_SIDES_UUID .lock() .unwrap() - .retain(|_, v| v.0.elapsed() < SWITCH_SIDES_TIMEOUT); + .retain(|_, v| v.0.elapsed() < Duration::from_secs(10)); let uuid_old = SWITCH_SIDES_UUID.lock().unwrap().remove(&lr.my_id); if let Ok(uuid) = uuid::Uuid::from_slice(_s.uuid.to_vec().as_ref()) { if let Some((_instant, uuid_old)) = uuid_old { @@ -1538,8 +1537,8 @@ impl Connection { uuid.to_string().as_ref(), ]) .ok(); - self.send_close_reason_no_retry("Closed as expected"); - self.on_close("switch sides", false); + self.send_close_reason_no_retry("Closed as expected").await; + self.on_close("switch sides", false).await; return false; } } diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 48f6c1090..4fc5db743 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -6,7 +6,6 @@ use crate::client::{ }; use crate::common::{self, GrabState}; use crate::keyboard; -use crate::ui_interface::using_public_server; use crate::{client::Data, client::Interface}; use async_trait::async_trait; use bytes::Bytes; From d1070b88bb3dbdaee6dac4a7f3950e027e9595fd Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 29 Jan 2023 14:36:20 +0800 Subject: [PATCH 16/83] dismiss menu after switching monitor Signed-off-by: fufesou --- flutter/lib/desktop/widgets/remote_menubar.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index b9d793744..07944649c 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -362,6 +362,9 @@ class _RemoteMenubarState extends State { ), )), onPressed: () { + if (Navigator.canPop(context)) { + Navigator.pop(context); + } RxInt display = CurrentDisplayState.find(widget.id); if (display.value != i) { bind.sessionSwitchDisplay(id: widget.id, value: i); From fc15209d08b980a5e367e2bb8c530a0f91c94aeb Mon Sep 17 00:00:00 2001 From: mehdi-song Date: Sun, 29 Jan 2023 14:02:06 +0330 Subject: [PATCH 17/83] Update fa.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "Closed as expected"-> "طبق انتظار بسته شد" --- src/lang/fa.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 3b1bcfaf5..15ef1b843 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -436,6 +436,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Strong", "قوی"), ("Switch Sides", "طرفین را عوض کنید"), ("Please confirm if you want to share your desktop?", "لطفاً تأیید کنید که آیا می خواهید دسکتاپ خود را به اشتراک بگذارید؟"), - ("Closed as expected", ""), + ("Closed as expected", "طبق انتظار بسته شد"), ].iter().cloned().collect(); } From 92748f7ef4d49112f1512b57879bb735034e870d Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sun, 29 Jan 2023 23:30:49 +0800 Subject: [PATCH 18/83] adjust tab colors to fix issue #2957 --- .../lib/desktop/widgets/tabbar_widget.dart | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index ddc0e7729..598b2cc4c 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -765,7 +765,7 @@ class _ListView extends StatelessWidget { tabBuilder: tabBuilder, tabMenuBuilder: tabMenuBuilder, maxLabelWidth: maxLabelWidth, - selectedTabBackgroundColor: selectedTabBackgroundColor, + selectedTabBackgroundColor: selectedTabBackgroundColor ?? MyTheme.tabbar(context).selectedTabBackgroundColor, unSelectedTabBackgroundColor: unSelectedTabBackgroundColor, ); }).toList())); @@ -910,7 +910,7 @@ class _TabState extends State<_Tab> with RestorationMixin { tabSelected: isSelected, onClose: () => widget.onClose(), ))) - ])).paddingSymmetric(horizontal: 10), + ])).paddingOnly(left: 10, right: 5), Offstage( offstage: !showDivider, child: VerticalDivider( @@ -956,6 +956,7 @@ class _CloseButton extends StatelessWidget { child: Offstage( offstage: !visible, child: InkWell( + hoverColor: MyTheme.tabbar(context).closeHoverColor, customBorder: const RoundedRectangleBorder(), onTap: () => onClose(), child: Icon( @@ -966,7 +967,7 @@ class _CloseButton extends StatelessWidget { : MyTheme.tabbar(context).unSelectedIconColor, ), ), - )).paddingOnly(left: 5); + )).paddingOnly(left: 10); } } @@ -1055,6 +1056,8 @@ class TabbarTheme extends ThemeExtension { final Color? unSelectedIconColor; final Color? dividerColor; final Color? hoverColor; + final Color? closeHoverColor; + final Color? selectedTabBackgroundColor; const TabbarTheme( {required this.selectedTabIconColor, @@ -1064,27 +1067,33 @@ class TabbarTheme extends ThemeExtension { required this.selectedIconColor, required this.unSelectedIconColor, required this.dividerColor, - required this.hoverColor}); + required this.hoverColor, + required this.closeHoverColor, + required this.selectedTabBackgroundColor}); static const light = TabbarTheme( selectedTabIconColor: MyTheme.accent, unSelectedTabIconColor: Color.fromARGB(255, 162, 203, 241), - selectedTextColor: Color.fromARGB(255, 26, 26, 26), - unSelectedTextColor: Color.fromARGB(255, 96, 96, 96), + selectedTextColor: Colors.black, + unSelectedTextColor: Color.fromARGB(255, 112, 112, 112), selectedIconColor: Color.fromARGB(255, 26, 26, 26), unSelectedIconColor: Color.fromARGB(255, 96, 96, 96), dividerColor: Color.fromARGB(255, 238, 238, 238), - hoverColor: Color.fromARGB(51, 158, 158, 158)); + hoverColor: Color.fromARGB(51, 158, 158, 158), + closeHoverColor: Colors.black, + selectedTabBackgroundColor: Color.fromARGB(255, 240, 240, 240)); static const dark = TabbarTheme( selectedTabIconColor: MyTheme.accent, unSelectedTabIconColor: Color.fromARGB(255, 30, 65, 98), selectedTextColor: Color.fromARGB(255, 255, 255, 255), - unSelectedTextColor: Color.fromARGB(255, 207, 207, 207), - selectedIconColor: Color.fromARGB(255, 215, 215, 215), + unSelectedTextColor: Color.fromARGB(255, 192, 192, 192), + selectedIconColor: Color.fromARGB(255, 192, 192, 192), unSelectedIconColor: Color.fromARGB(255, 255, 255, 255), dividerColor: Color.fromARGB(255, 64, 64, 64), - hoverColor: Colors.black26); + hoverColor: Colors.black26, + closeHoverColor: Colors.black, + selectedTabBackgroundColor: Colors.black26); @override ThemeExtension copyWith({ @@ -1096,6 +1105,8 @@ class TabbarTheme extends ThemeExtension { Color? unSelectedIconColor, Color? dividerColor, Color? hoverColor, + Color? closeHoverColor, + Color? selectedTabBackgroundColor, }) { return TabbarTheme( selectedTabIconColor: selectedTabIconColor ?? this.selectedTabIconColor, @@ -1107,6 +1118,8 @@ class TabbarTheme extends ThemeExtension { unSelectedIconColor: unSelectedIconColor ?? this.unSelectedIconColor, dividerColor: dividerColor ?? this.dividerColor, hoverColor: hoverColor ?? this.hoverColor, + closeHoverColor: closeHoverColor ?? this.closeHoverColor, + selectedTabBackgroundColor: selectedTabBackgroundColor ?? this.selectedTabBackgroundColor, ); } @@ -1131,6 +1144,8 @@ class TabbarTheme extends ThemeExtension { Color.lerp(unSelectedIconColor, other.unSelectedIconColor, t), dividerColor: Color.lerp(dividerColor, other.dividerColor, t), hoverColor: Color.lerp(hoverColor, other.hoverColor, t), + closeHoverColor: Color.lerp(closeHoverColor, other.closeHoverColor, t), + selectedTabBackgroundColor: Color.lerp(selectedTabBackgroundColor, other.selectedTabBackgroundColor, t), ); } From f12de3fec0034a944857503c9a8e3cb8bdb364d3 Mon Sep 17 00:00:00 2001 From: Mateusz Prais Date: Sun, 29 Jan 2023 22:40:17 +0100 Subject: [PATCH 19/83] Update pl.rs --- src/lang/pl.rs | 118 ++++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/src/lang/pl.rs b/src/lang/pl.rs index f953c5c0b..467d918b6 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -3,7 +3,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = [ ("Status", "Status"), ("Your Desktop", "Twój pulpit"), - ("desk_tip", "W celu zestawienia połączenia z tym urządzeniem należy poniższego ID i hasła."), + ("desk_tip", "W celu połączenia się z tym urządzeniem należy użyć poniższego ID i hasła"), ("Password", "Hasło"), ("Ready", "Gotowe"), ("Established", "Nawiązano"), @@ -38,12 +38,12 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop service", "Zatrzymaj usługę"), ("Change ID", "Zmień ID"), ("Website", "Strona internetowa"), - ("About", "O"), - ("Slogan_tip", ""), - ("Privacy Statement", ""), - ("Build Date", ""), - ("Version", ""), - ("Home", ""), + ("About", "O aplikacji"), + ("Slogan_tip", "Tworzone z miłością w tym pełnym chaosu świecie!"), + ("Privacy Statement", "Oświadczenie o ochronie prywatności"), + ("Build Date", "Zbudowano"), + ("Version", "Wersja"), + ("Home", "Pulpit"), ("Mute", "Wycisz"), ("Audio Input", "Wejście audio"), ("Enhancements", "Ulepszenia"), @@ -99,7 +99,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Empty Directory", "Pusty katalog"), ("Not an empty directory", "Katalog nie jest pusty"), ("Are you sure you want to delete this file?", "Czy na pewno chcesz usunąć ten plik?"), - ("Are you sure you want to delete this empty directory?", "Czy na pewno chcesz usunać ten pusty katalog?"), + ("Are you sure you want to delete this empty directory?", "Czy na pewno chcesz usunąć ten pusty katalog?"), ("Are you sure you want to delete the file of this directory?", "Czy na pewno chcesz usunąć pliki z tego katalogu?"), ("Do this for all conflicts", "wykonaj dla wszystkich konfliktów"), ("This is irreversible!", "To jest nieodwracalne!"), @@ -121,7 +121,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Good image quality", "Dobra jakość obrazu"), ("Balanced", "Zrównoważony"), ("Optimize reaction time", "Zoptymalizuj czas reakcji"), - ("Custom", "Własne"), + ("Custom", "Niestandardowe"), ("Show remote cursor", "Pokazuj zdalny kursor"), ("Show quality monitor", "Parametry połączenia"), ("Disable clipboard", "Wyłącz schowek"), @@ -141,10 +141,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Failed to make direct connection to remote desktop", "Nie udało się nawiązać bezpośredniego połączenia z pulpitem zdalnym"), ("Set Password", "Ustaw hasło"), ("OS Password", "Hasło systemu operacyjnego"), - ("install_tip", "RustDesk może nie działać poprawnie na maszynie zdalnej z przyczyn związanych z UAC. W celu uniknięcią problemów z UAC, kliknij poniższy przycisk by zainstalować RustDesk w swoim systemie."), + ("install_tip", "RustDesk może nie działać poprawnie na maszynie zdalnej z przyczyn związanych z UAC. W celu uniknięcia problemów z UAC, kliknij poniższy przycisk by zainstalować RustDesk w swoim systemie."), ("Click to upgrade", "Zaktualizuj"), ("Click to download", "Pobierz"), - ("Click to update", "Uaktualinij"), + ("Click to update", "Uaktualnij"), ("Configure", "Konfiguruj"), ("config_acc", "Konfiguracja konta"), ("config_screen", "Konfiguracja ekranu"), @@ -211,13 +211,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Run without install", "Uruchom bez instalacji"), ("Always connected via relay", "Zawsze połączony pośrednio"), ("Always connect via relay", "Zawsze łącz pośrednio"), - ("whitelist_tip", "Zezwlaj na łączenie z tym komputerem tylko z adresów IP znajdujących się na białej liście"), + ("whitelist_tip", "Zezwalaj na łączenie z tym komputerem tylko z adresów IP znajdujących się na białej liście"), ("Login", "Zaloguj"), - ("Verify", ""), - ("Remember me", ""), - ("Trust this device", ""), - ("Verification code", ""), - ("verification_tip", ""), + ("Verify", "Zweryfikuj"), + ("Remember me", "Zapamiętaj mnie"), + ("Trust this device", "Dodaj to urządzenie do zaufanych"), + ("Verification code", "Kod weryfikacyjny"), + ("verification_tip", "Nastąpiło logowanie z nowego urządzenia, kod weryfikacyjny został wysłany na podany adres email, wprowadź kod by kontynuować proces logowania"), ("Logout", "Wyloguj"), ("Tags", "Tagi"), ("Search ID", "Szukaj ID"), @@ -235,7 +235,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Favorites", "Ulubione"), ("Add to Favorites", "Dodaj do ulubionych"), ("Remove from Favorites", "Usuń z ulubionych"), - ("Empty", "Pusty"), + ("Empty", "Pusto"), ("Invalid folder name", "Nieprawidłowa nazwa folderu"), ("Socks5 Proxy", "Socks5 Proxy"), ("Hostname", "Nazwa hosta"), @@ -334,7 +334,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scroll Style", "Styl przewijania"), ("Show Menubar", "Pokaż pasek menu"), ("Hide Menubar", "Ukryj pasek menu"), - ("Direct Connection", "Połącznie bezpośrednie"), + ("Direct Connection", "Połączenie bezpośrednie"), ("Relay Connection", "Połączenie przez bramkę"), ("Secure Connection", "Połączenie szyfrowane"), ("Insecure Connection", "Połączenie nieszyfrowane"), @@ -347,12 +347,12 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Dark", "Ciemny"), ("Light", "Jasny"), ("Follow System", "Zgodne z systemem"), - ("Enable hardware codec", "Włącz wsparcie sprzętowe dla kodeków"), - ("Unlock Security Settings", "Odblokuj Ustawienia Zabezpieczeń"), - ("Enable Audio", "Włącz Dźwięk"), + ("Enable hardware codec", "Włącz akcelerację sprzętową kodeków"), + ("Unlock Security Settings", "Odblokuj ustawienia zabezpieczeń"), + ("Enable Audio", "Włącz dźwięk"), ("Unlock Network Settings", "Odblokuj ustawienia Sieciowe"), ("Server", "Serwer"), - ("Direct IP Access", "Bezpośredni Adres IP"), + ("Direct IP Access", "Bezpośredni adres IP"), ("Proxy", "Proxy"), ("Apply", "Zastosuj"), ("Disconnect all devices?", "Czy rozłączyć wszystkie urządzenia?"), @@ -364,20 +364,20 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable RDP", "Włącz RDP"), ("Pin menubar", "Przypnij pasek menu"), ("Unpin menubar", "Odepnij pasek menu"), - ("Recording", "Trwa nagrywanie"), + ("Recording", "Nagrywanie"), ("Directory", "Katalog"), ("Automatically record incoming sessions", "Automatycznie nagrywaj sesje przychodzące"), ("Change", "Zmień"), ("Start session recording", "Zacznij nagrywać sesję"), ("Stop session recording", "Zatrzymaj nagrywanie sesji"), - ("Enable Recording Session", "Włącz Nagrywanie Sesji"), + ("Enable Recording Session", "Włącz nagrywanie Sesji"), ("Allow recording session", "Zezwól na nagrywanie sesji"), ("Enable LAN Discovery", "Włącz wykrywanie urządzenia w sieci LAN"), ("Deny LAN Discovery", "Zablokuj wykrywanie urządzenia w sieci LAN"), ("Write a message", "Napisz wiadomość"), ("Prompt", "Monit"), - ("Please wait for confirmation of UAC...", "Oczekuje potwierdzenia ustawień UAC"), - ("elevated_foreground_window_tip", ""), + ("Please wait for confirmation of UAC...", "Poczekaj na potwierdzenie uprawnień UAC"), + ("elevated_foreground_window_tip", "Aktualne okno zdalnego urządzenia wymaga wyższych uprawnień by poprawnie działać, chwilowo niemożliwym jest korzystanie z myszy i klawiatury. Możesz poprosić zdalnego użytkownika o minimalizację okna, lub nacisnąć przycisk podniesienia uprawnień w oknie zarządzania połączeniami. By uniknąć tego problemu, rekomendujemy instalację oprogramowania na urządzeniu zdalnym."), ("Disconnected", "Rozłączone"), ("Other", "Inne"), ("Confirm before closing multiple tabs", "Potwierdź przed zamknięciem wielu kart"), @@ -385,7 +385,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Full Access", "Pełny dostęp"), ("Screen Share", "Udostępnianie ekranu"), ("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."), + ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland wymaga nowszej 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)."), ("Show RustDesk", "Pokaż RustDesk"), @@ -403,39 +403,39 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("One-time password length", "Długość hasła jednorazowego"), ("Request access to your device", "Żądanie dostępu do Twojego urządzenia"), ("Hide connection management window", "Ukryj okno zarządzania połączeniem"), - ("hide_cm_tip", ""), - ("wayland_experiment_tip", ""), - ("Right click to select tabs", ""), - ("Skipped", ""), + ("hide_cm_tip", "Pozwalaj na ukrycie tylko gdy akceptujesz sesje za pośrednictwem hasła i używasz hasła permanentnego"), + ("wayland_experiment_tip", "Wsparcie dla Wayland jest niekompletne, użyj X11 jeżeli chcesz korzystać z dostępu nienadzorowanego"), + ("Right click to select tabs", "Kliknij prawym przyciskiem myszy by wybrać zakładkę"), + ("Skipped", "Pominięte"), ("Add to Address Book", "Dodaj do Książki Adresowej"), ("Group", "Grypy"), ("Search", "Szukaj"), - ("Closed manually by web console", ""), - ("Local keyboard type", ""), - ("Select local keyboard type", ""), - ("software_render_tip", ""), - ("Always use software rendering", ""), - ("config_input", ""), - ("request_elevation_tip", ""), - ("Wait", ""), - ("Elevation Error", ""), - ("Ask the remote user for authentication", ""), - ("Choose this if the remote account is administrator", ""), - ("Transmit the username and password of administrator", ""), - ("still_click_uac_tip", ""), - ("Request Elevation", ""), - ("wait_accept_uac_tip", ""), - ("Elevate successfully", ""), - ("uppercase", ""), - ("lowercase", ""), - ("digit", ""), - ("special character", ""), - ("length>=8", ""), - ("Weak", ""), - ("Medium", ""), - ("Strong", ""), - ("Switch Sides", ""), - ("Please confirm if you want to share your desktop?", ""), - ("Closed as expected", ""), + ("Closed manually by web console", "Zakończone manualnie z konsoli Web"), + ("Local keyboard type", "Lokalny typ klawiatury"), + ("Select local keyboard type", "Wybierz lokalny typ klawiatury"), + ("software_render_tip", "Jeżeli posiadasz kartę graficzną Nvidia i okno zamyka się natychmiast po nawiązaniu połączenia, instalacja sterownika nouveau i wybór renderowania programowego mogą pomóc. Restart aplikacji jest wymagany."), + ("Always use software rendering", "Zawsze używaj renderowania programowego"), + ("config_input", "By kontrolować zdalne urządzenie przy pomocy klawiatury, musisz udzielić aplikacji RustDesk uprawnień do \"Urządzeń Wejściowych\"."), + ("request_elevation_tip", "Możesz poprosić o podniesienie uprawnień jeżeli ktoś posiada dostęp do zdalnego urządzenia."), + ("Wait", "Czekaj"), + ("Elevation Error", "Błąd przy podnoszeniu uprawnień"), + ("Ask the remote user for authentication", "Poproś użytkownika zdalnego o uwierzytelnienie"), + ("Choose this if the remote account is administrator", "Wybierz to jeżeli zdalne konto jest administratorem"), + ("Transmit the username and password of administrator", "Prześlij nazwę użytkownika i hasło administratora"), + ("still_click_uac_tip", "Nadal wymaga od zdalnego użytkownika potwierdzenia uprawnień UAC."), + ("Request Elevation", "Poproś o podniesienie uprawnień"), + ("wait_accept_uac_tip", "Prosimy czekać aż zdalny użytkownik potwierdzi uprawnienia UAC."), + ("Elevate successfully", "Pomyślnie podniesiono uprawnienia"), + ("uppercase", "wielkie litery"), + ("lowercase", "małe litery"), + ("digit", "cyfra"), + ("special character", "znak specjalny"), + ("length>=8", "długość>=8"), + ("Weak", "Słabe"), + ("Medium", "Średnie"), + ("Strong", "Mocne"), + ("Switch Sides", "Zmień Strony"), + ("Please confirm if you want to share your desktop?", "Czy na pewno chcesz udostępnić swój ekran?"), + ("Closed as expected", "Zamknięto pomyślnie"), ].iter().cloned().collect(); } From 6db94983a181a942474554c78b9fbb554df21f24 Mon Sep 17 00:00:00 2001 From: Simon Spannagel Date: Mon, 30 Jan 2023 08:06:48 +0100 Subject: [PATCH 20/83] Remove wayland fix for good Signed-off-by: simonspa --- src/platform/linux.rs | 93 ------------------------------------------- src/ui.rs | 10 ----- src/ui/index.tis | 13 ------ src/ui_interface.rs | 14 ------- 4 files changed, 130 deletions(-) diff --git a/src/platform/linux.rs b/src/platform/linux.rs index 34276426d..ac3b32a49 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -426,104 +426,11 @@ pub fn is_login_wayland() -> bool { } } -pub fn fix_login_wayland() { - let mut file = "/etc/gdm3/custom.conf".to_owned(); - if !std::path::Path::new(&file).exists() { - file = "/etc/gdm/custom.conf".to_owned(); - } - match std::process::Command::new("pkexec") - .args(vec![ - "sed", - "-i", - "s/#WaylandEnable=false/WaylandEnable=false/g", - &file, - ]) - .output() - { - Ok(x) => { - let x = String::from_utf8_lossy(&x.stderr); - if !x.is_empty() { - log::error!("fix_login_wayland failed: {}", x); - } - } - Err(err) => { - log::error!("fix_login_wayland failed: {}", err); - } - } -} - pub fn current_is_wayland() -> bool { let dtype = get_display_server(); return "wayland" == dtype && unsafe { UNMODIFIED }; } -pub fn modify_default_login() -> String { - let dsession = std::env::var("DESKTOP_SESSION").unwrap(); - let user_name = std::env::var("USERNAME").unwrap(); - if let Ok(x) = run_cmds("ls /usr/share/* | grep ${DESKTOP_SESSION}-xorg.desktop".to_owned()) { - if x.trim_end().to_string() != "" { - match std::process::Command::new("pkexec") - .args(vec![ - "sed", - "-i", - &format!("s/={0}$/={0}-xorg/g", &dsession), - &format!("/var/lib/AccountsService/users/{}", &user_name), - ]) - .output() - { - Ok(x) => { - let x = String::from_utf8_lossy(&x.stderr); - if !x.is_empty() { - log::error!("modify_default_login failed: {}", x); - return "Fix failed! Please re-login with X server manually".to_owned(); - } else { - unsafe { - UNMODIFIED = false; - } - return "".to_owned(); - } - } - Err(err) => { - log::error!("modify_default_login failed: {}", err); - return "Fix failed! Please re-login with X server manually".to_owned(); - } - } - } else if let Ok(z) = - run_cmds("ls /usr/share/* | grep ${DESKTOP_SESSION:0:-8}.desktop".to_owned()) - { - if z.trim_end().to_string() != "" { - match std::process::Command::new("pkexec") - .args(vec![ - "sed", - "-i", - &format!("s/={}$/={}/g", &dsession, &dsession[..dsession.len() - 8]), - &format!("/var/lib/AccountsService/users/{}", &user_name), - ]) - .output() - { - Ok(x) => { - let x = String::from_utf8_lossy(&x.stderr); - if !x.is_empty() { - log::error!("modify_default_login failed: {}", x); - return "Fix failed! Please re-login with X server manually".to_owned(); - } else { - unsafe { - UNMODIFIED = false; - } - return "".to_owned(); - } - } - Err(err) => { - log::error!("modify_default_login failed: {}", err); - return "Fix failed! Please re-login with X server manually".to_owned(); - } - } - } - } - } - return "Fix failed! Please re-login with X server manually".to_owned(); -} - // to-do: test the other display manager fn _get_display_manager() -> String { if let Ok(x) = std::fs::read_to_string("/etc/X11/default-display-manager") { diff --git a/src/ui.rs b/src/ui.rs index b8473072d..637fc66be 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -434,18 +434,10 @@ impl UI { is_login_wayland() } - fn fix_login_wayland(&mut self) { - fix_login_wayland() - } - fn current_is_wayland(&mut self) -> bool { current_is_wayland() } - fn modify_default_login(&mut self) -> String { - modify_default_login() - } - fn get_software_update_url(&self) -> String { get_software_update_url() } @@ -590,9 +582,7 @@ impl sciter::EventHandler for UI { fn is_installed_daemon(bool); fn get_error(); fn is_login_wayland(); - fn fix_login_wayland(); fn current_is_wayland(); - fn modify_default_login(); fn get_options(); fn get_option(String); fn get_local_option(String); diff --git a/src/ui/index.tis b/src/ui/index.tis index 2d77b1eec..e718e4380 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -755,11 +755,6 @@ class FixWayland: Reactor.Component { ; } - event click $(#fix-wayland) { - handler.fix_login_wayland(); - app.update(); - } - event click $(#help-me) { handler.open_url(translate("doc_fix_wayland")); } @@ -774,14 +769,6 @@ class ModifyDefaultLogin: Reactor.Component { ; } - event click $(#modify-default-login) { - if (var r = handler.modify_default_login()) { - // without handler, will fail, fucking stupid sciter - handler.msgbox("custom-error", "Error", r); - } - app.update(); - } - event click $(#help-me) { handler.open_url(translate("doc_fix_wayland")); } diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 403951eaa..4e0fd7744 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -614,12 +614,6 @@ pub fn is_login_wayland() -> bool { return false; } -#[inline] -pub fn fix_login_wayland() { - #[cfg(target_os = "linux")] - crate::platform::linux::fix_login_wayland(); -} - #[inline] pub fn current_is_wayland() -> bool { #[cfg(target_os = "linux")] @@ -628,14 +622,6 @@ pub fn current_is_wayland() -> bool { return false; } -#[inline] -pub fn modify_default_login() -> String { - #[cfg(target_os = "linux")] - return crate::platform::linux::modify_default_login(); - #[cfg(not(target_os = "linux"))] - return "".to_owned(); -} - #[inline] pub fn get_software_update_url() -> String { SOFTWARE_UPDATE_URL.lock().unwrap().clone() From baa30a49b9ace2e45831b6162baa5b511bfd4954 Mon Sep 17 00:00:00 2001 From: Simon Spannagel Date: Mon, 30 Jan 2023 08:39:54 +0100 Subject: [PATCH 21/83] Remove remnant documentation for wayland fix --- src/lang/en.rs | 1 - src/ui/index.tis | 30 ------------------------------ 2 files changed, 31 deletions(-) diff --git a/src/lang/en.rs b/src/lang/en.rs index 6eed43a77..bacef699c 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -25,7 +25,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_version_audio_tip", "The current Android version does not support audio capture, please upgrade to Android 10 or higher."), ("android_start_service_tip", "Tap [Start Service] or OPEN [Screen Capture] permission to start the screen sharing service."), ("doc_mac_permission", "https://rustdesk.com/docs/en/manual/mac/#enable-permissions"), - ("doc_fix_wayland", "https://rustdesk.com/docs/en/manual/linux/#x11-required"), ("server_not_support", "Not yet supported by the server"), ("android_open_battery_optimizations_tip", "If you want to disable this feature, please go to the next RustDesk application settings page, find and enter [Battery], Uncheck [Unrestricted]"), ("remote_restarting_tip", "Remote device is restarting, please close this message box and reconnect with permanent password after a while"), diff --git a/src/ui/index.tis b/src/ui/index.tis index e718e4380..68787c86f 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -558,8 +558,6 @@ class App: Reactor.Component {is_can_screen_recording && !handler.is_process_trusted(false) ? : ""} {!service_stopped && is_can_screen_recording && handler.is_process_trusted(false) && handler.is_installed() && !handler.is_installed_daemon(false) ? : ""} {system_error ? : ""} - {!system_error && handler.is_login_wayland() && !handler.current_is_wayland() ? : ""} - {!system_error && handler.current_is_wayland() ? : ""}
@@ -746,34 +744,6 @@ class InstallDaemon: Reactor.Component { } } -class FixWayland: Reactor.Component { - function render() { - return
-
{translate('Warning')}
-
{translate('Login screen using Wayland is not supported')}
-
{translate('Help')}
-
; - } - - event click $(#help-me) { - handler.open_url(translate("doc_fix_wayland")); - } -} - -class ModifyDefaultLogin: Reactor.Component { - function render() { - return
-
{translate('Warning')}
-
{translate('Current Wayland display server is not supported')}
-
{translate('Help')}
-
; - } - - event click $(#help-me) { - handler.open_url(translate("doc_fix_wayland")); - } -} - function watch_trust() { // not use TrustMe::update, because it is buggy var trusted = handler.is_process_trusted(false); From 91244ea610d94a328ebdd3fcaac420c6da7426a7 Mon Sep 17 00:00:00 2001 From: RustDesk <71636191+rustdesk@users.noreply.github.com> Date: Mon, 30 Jan 2023 15:40:03 +0800 Subject: [PATCH 22/83] Update cn.rs --- src/lang/cn.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/lang/cn.rs b/src/lang/cn.rs index c028ed36c..8126e0081 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -281,12 +281,12 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Do you accept?", "是否接受?"), ("Open System Setting", "打开系统设置"), ("How to get Android input permission?", "如何获取安卓的输入权限?"), - ("android_input_permission_tip1", "为了让远程设备通过鼠标或触屏控制您的安卓设备,你需要允許RustDesk使用\"无障碍\"服务。"), + ("android_input_permission_tip1", "为了让远程设备通过鼠标或触屏控制您的安卓设备,你需要允許 RustDesk 使用\"无障碍\"服务。"), ("android_input_permission_tip2", "请在接下来的系统设置页面里,找到并进入 [已安装的服务] 页面,将 [RustDesk Input] 服务开启。"), ("android_new_connection_tip", "收到新的连接控制请求,对方想要控制你当前的设备。"), ("android_service_will_start_tip", "开启录屏权限将自动开启服务,允许其他设备向此设备请求建立连接。"), ("android_stop_service_tip", "关闭服务将自动关闭所有已建立的连接。"), - ("android_version_audio_tip", "当前安卓版本不支持音频录制,请升级至安卓10或更高。"), + ("android_version_audio_tip", "当前安卓版本不支持音频录制,请升级至安卓 10 或更高。"), ("android_start_service_tip", "点击 [启动服务] 或打开 [屏幕录制] 权限开启手机屏幕共享服务。"), ("Account", "账户"), ("Overwrite", "覆盖"), @@ -376,7 +376,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Deny LAN Discovery", "拒绝局域网发现"), ("Write a message", "输入聊天消息"), ("Prompt", "提示"), - ("Please wait for confirmation of UAC...", "请等待对方确认UAC..."), + ("Please wait for confirmation of UAC...", "请等待对方确认 UAC ..."), ("elevated_foreground_window_tip", "远端桌面的当前窗口需要更高的权限才能操作, 暂时无法使用鼠标键盘, 可以请求对方最小化当前窗口, 或者在连接管理窗口点击提升。为避免这个问题,建议在远端设备上安装本软件。"), ("Disconnected", "会话已结束"), ("Other", "其他"), @@ -404,16 +404,16 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Request access to your device", "请求访问你的设备"), ("Hide connection management window", "隐藏连接管理窗口"), ("hide_cm_tip", "在只允许密码连接并且只用固定密码的情况下才允许隐藏"), - ("wayland_experiment_tip", "Wayland支持处于实验阶段,如果你需要使用无人值守访问,请使用X11。"), + ("wayland_experiment_tip", "Wayland 支持处于实验阶段,如果你需要使用无人值守访问,请使用X11。"), ("Right click to select tabs", "右键选择选项卡"), ("Skipped", "已跳过"), ("Add to Address Book", "添加到地址簿"), ("Group", "小组"), ("Search", "搜索"), - ("Closed manually by web console", "被web控制台手动关闭"), + ("Closed manually by web console", "被 web 控制台手动关闭"), ("Local keyboard type", "本地键盘类型"), ("Select local keyboard type", "请选择本地键盘类型"), - ("software_render_tip", "如果你使用英伟达显卡, 并且远程窗口在会话建立后会立刻关闭, 那么安装nouveau驱动并且选择使用软件渲染可能会有帮助。重启软件后生效。"), + ("software_render_tip", "如果你使用英伟达显卡, 并且远程窗口在会话建立后会立刻关闭, 那么安装 nouveau 驱动并且选择使用软件渲染可能会有帮助。重启软件后生效。"), ("Always use software rendering", "使用软件渲染"), ("config_input", "为了能够通过键盘控制远程桌面, 请给予 RustDesk \"输入监控\" 权限。"), ("request_elevation_tip", "如果对面有人, 也可以请求提升权限。"), @@ -422,9 +422,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Ask the remote user for authentication", "请求远端用户授权"), ("Choose this if the remote account is administrator", "当对面电脑是管理员账号时选择该选项"), ("Transmit the username and password of administrator", "发送管理员账号的用户名密码"), - ("still_click_uac_tip", "依然需要被控端用戶在運行RustDesk的UAC窗口點擊確認。"), + ("still_click_uac_tip", "依然需要被控端用戶在運行 RustDesk 的 UAC 窗口點擊確認。"), ("Request Elevation", "请求提权"), - ("wait_accept_uac_tip", "请等待远端用户确认UAC对话框。"), + ("wait_accept_uac_tip", "请等待远端用户确认 UAC 对话框。"), ("Elevate successfully", "提权成功"), ("uppercase", "大写字母"), ("lowercase", "小写字母"), From 39515f3ed3e91d02732b5786fc34811a735b52f6 Mon Sep 17 00:00:00 2001 From: RustDesk <71636191+rustdesk@users.noreply.github.com> Date: Mon, 30 Jan 2023 15:48:54 +0800 Subject: [PATCH 23/83] Revert "Remove remnant documentation for wayland fix" --- src/lang/en.rs | 1 + src/ui/index.tis | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/lang/en.rs b/src/lang/en.rs index bacef699c..6eed43a77 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -25,6 +25,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_version_audio_tip", "The current Android version does not support audio capture, please upgrade to Android 10 or higher."), ("android_start_service_tip", "Tap [Start Service] or OPEN [Screen Capture] permission to start the screen sharing service."), ("doc_mac_permission", "https://rustdesk.com/docs/en/manual/mac/#enable-permissions"), + ("doc_fix_wayland", "https://rustdesk.com/docs/en/manual/linux/#x11-required"), ("server_not_support", "Not yet supported by the server"), ("android_open_battery_optimizations_tip", "If you want to disable this feature, please go to the next RustDesk application settings page, find and enter [Battery], Uncheck [Unrestricted]"), ("remote_restarting_tip", "Remote device is restarting, please close this message box and reconnect with permanent password after a while"), diff --git a/src/ui/index.tis b/src/ui/index.tis index 68787c86f..e718e4380 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -558,6 +558,8 @@ class App: Reactor.Component {is_can_screen_recording && !handler.is_process_trusted(false) ? : ""} {!service_stopped && is_can_screen_recording && handler.is_process_trusted(false) && handler.is_installed() && !handler.is_installed_daemon(false) ? : ""} {system_error ? : ""} + {!system_error && handler.is_login_wayland() && !handler.current_is_wayland() ? : ""} + {!system_error && handler.current_is_wayland() ? : ""}
@@ -744,6 +746,34 @@ class InstallDaemon: Reactor.Component { } } +class FixWayland: Reactor.Component { + function render() { + return
+
{translate('Warning')}
+
{translate('Login screen using Wayland is not supported')}
+
{translate('Help')}
+
; + } + + event click $(#help-me) { + handler.open_url(translate("doc_fix_wayland")); + } +} + +class ModifyDefaultLogin: Reactor.Component { + function render() { + return
+
{translate('Warning')}
+
{translate('Current Wayland display server is not supported')}
+
{translate('Help')}
+
; + } + + event click $(#help-me) { + handler.open_url(translate("doc_fix_wayland")); + } +} + function watch_trust() { // not use TrustMe::update, because it is buggy var trusted = handler.is_process_trusted(false); From f4d030524231c7150044bef2cea45928fd55ac35 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Mon, 30 Jan 2023 15:57:27 +0800 Subject: [PATCH 24/83] remove unused tip --- src/lang/ca.rs | 1 - src/lang/cn.rs | 1 - src/lang/cs.rs | 1 - src/lang/da.rs | 1 - src/lang/de.rs | 1 - src/lang/eo.rs | 1 - src/lang/es.rs | 1 - src/lang/fa.rs | 1 - src/lang/fr.rs | 1 - src/lang/gr.rs | 1 - src/lang/hu.rs | 1 - src/lang/id.rs | 1 - src/lang/it.rs | 1 - src/lang/ja.rs | 1 - src/lang/ko.rs | 1 - src/lang/kz.rs | 1 - src/lang/pl.rs | 1 - src/lang/pt_PT.rs | 1 - src/lang/ptbr.rs | 1 - src/lang/ro.rs | 1 - src/lang/ru.rs | 1 - src/lang/sk.rs | 1 - src/lang/sl.rs | 1 - src/lang/sq.rs | 1 - src/lang/sr.rs | 1 - src/lang/sv.rs | 1 - src/lang/template.rs | 1 - src/lang/th.rs | 1 - src/lang/tr.rs | 1 - src/lang/tw.rs | 1 - src/lang/ua.rs | 1 - src/lang/vn.rs | 1 - src/ui/index.tis | 2 +- 33 files changed, 1 insertion(+), 33 deletions(-) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 9d2938b2d..cd8fba24d 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Sortir"), ("Tags", ""), ("Search ID", "Cerca ID"), - ("Current Wayland display server is not supported", "El servidor de visualització actual de Wayland no és compatible"), ("whitelist_sep", ""), ("Add ID", "Afegir ID"), ("Add Tag", "Afegir tag"), diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 8126e0081..41fa7fc26 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "登出"), ("Tags", "标签"), ("Search ID", "查找ID"), - ("Current Wayland display server is not supported", "不支持 Wayland 显示服务器"), ("whitelist_sep", "可以使用逗号,分号,空格或者换行符作为分隔符"), ("Add ID", "增加ID"), ("Add Tag", "增加标签"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 842c47762..5e59a86f1 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Odhlásit se"), ("Tags", "Štítky"), ("Search ID", "Hledat identifikátor"), - ("Current Wayland display server is not supported", "Zobrazovací server Wayland zatím není podporován"), ("whitelist_sep", "Odělováno čárkou, středníkem, mezerou nebo koncem řádku"), ("Add ID", "Přidat identifikátor"), ("Add Tag", "Přidat štítek"), diff --git a/src/lang/da.rs b/src/lang/da.rs index 8e6d622a1..8eddaf0b9 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "logger af"), ("Tags", "Nøgleord"), ("Search ID", "Søg ID"), - ("Current Wayland display server is not supported", "Den aktuelle Wayland-Anzege-server understøttes ikke"), ("whitelist_sep", "Adskilt af komma, semikolon, rum eller linjepaus"), ("Add ID", "Tilføj ID"), ("Add Tag", "Tilføj nøgleord"), diff --git a/src/lang/de.rs b/src/lang/de.rs index 11ce96f6b..3418ea9f5 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Abmelden"), ("Tags", "Schlagworte"), ("Search ID", "Suche ID"), - ("Current Wayland display server is not supported", "Der aktuelle Wayland-Anzeigeserver wird nicht unterstützt."), ("whitelist_sep", "Getrennt durch Komma, Semikolon, Leerzeichen oder Zeilenumbruch"), ("Add ID", "ID hinzufügen"), ("Add Tag", "Stichwort hinzufügen"), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 9086c809a..b034c0394 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Malkonekti"), ("Tags", "Etikedi"), ("Search ID", "Serĉi ID"), - ("Current Wayland display server is not supported", "La aktuala bilda servilo Wayland ne estas subtenita"), ("whitelist_sep", "Vi povas uzi komon, punktokomon, spacon aŭ linsalton kiel apartigilo"), ("Add ID", "Aldoni identigilo"), ("Add Tag", "Aldoni etikedo"), diff --git a/src/lang/es.rs b/src/lang/es.rs index e7bf83b25..8f4275d5d 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Salir"), ("Tags", "Tags"), ("Search ID", "Buscar ID"), - ("Current Wayland display server is not supported", "El servidor de visualización actual de Wayland no es compatible"), ("whitelist_sep", "Separados por coma, punto y coma, espacio o nueva línea"), ("Add ID", "Agregar ID"), ("Add Tag", "Agregar tag"), diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 15ef1b843..316885082 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "خروج"), ("Tags", "برچسب ها"), ("Search ID", "جستجوی شناسه"), - ("Current Wayland display server is not supported", "پشتیبانی نمی شود Wayland سرور نمایش فعلی"), ("whitelist_sep", "با کاما، نقطه ویرگول، فاصله یا خط جدید از هم جدا می شوند"), ("Add ID", "افزودن شناسه"), ("Add Tag", "افزودن برچسب"), diff --git a/src/lang/fr.rs b/src/lang/fr.rs index aa752f54e..097091e75 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Déconnexion"), ("Tags", "Étiqueter"), ("Search ID", "Rechercher un ID"), - ("Current Wayland display server is not supported", "Le serveur d'affichage Wayland n'est pas pris en charge"), ("whitelist_sep", "Vous pouvez utiliser une virgule, un point-virgule, un espace ou une nouvelle ligne comme séparateur"), ("Add ID", "Ajouter un ID"), ("Add Tag", "Ajouter une balise"), diff --git a/src/lang/gr.rs b/src/lang/gr.rs index 8e73542e5..53f9dca08 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Αποσύνδεση"), ("Tags", "Ετικέτες"), ("Search ID", "Αναζήτηση ID"), - ("Current Wayland display server is not supported", "Ο τρέχων διακομιστής εμφάνισης Wayland δεν υποστηρίζεται"), ("whitelist_sep", "Διαχωρίζονται με κόμμα, ερωτηματικό, διάστημα ή νέα γραμμή"), ("Add ID", "Προσθήκη αναγνωριστικού ID"), ("Add Tag", "Προσθήκη ετικέτας"), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 5ae8e0dca..f86e83012 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Kilépés"), ("Tags", "Tagok"), ("Search ID", "Azonosító keresése..."), - ("Current Wayland display server is not supported", "A Wayland display szerver nem támogatott"), ("whitelist_sep", "A címeket veszővel, pontosvesszővel, szóközzel, vagy új sorral válassza el"), ("Add ID", "Azonosító hozzáadása"), ("Add Tag", "Címke hozzáadása"), diff --git a/src/lang/id.rs b/src/lang/id.rs index f4555fa32..6ae39f108 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Keluar"), ("Tags", "Tag"), ("Search ID", "Cari ID"), - ("Current Wayland display server is not supported", "Server tampilan Wayland saat ini tidak didukung"), ("whitelist_sep", "Dipisahkan dengan koma, titik koma, spasi, atau baris baru"), ("Add ID", "Tambah ID"), ("Add Tag", "Tambah Tag"), diff --git a/src/lang/it.rs b/src/lang/it.rs index 322c324ce..0ec6c52b9 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Esci"), ("Tags", "Tag"), ("Search ID", "Cerca ID"), - ("Current Wayland display server is not supported", "Questo display server Wayland non è supportato"), ("whitelist_sep", "Separati da virgola, punto e virgola, spazio o a capo"), ("Add ID", "Aggiungi ID"), ("Add Tag", "Aggiungi tag"), diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 65368bfba..8e8a5ed95 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "ログアウト"), ("Tags", "タグ"), ("Search ID", "IDを検索"), - ("Current Wayland display server is not supported", "現在のWaylandディスプレイサーバーはサポートされていません"), ("whitelist_sep", "カンマやセミコロン、空白、改行で区切ってください"), ("Add ID", "IDを追加"), ("Add Tag", "タグを追加"), diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 01b30adc0..7b56202a0 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "로그아웃"), ("Tags", "태그"), ("Search ID", "ID 검색"), - ("Current Wayland display server is not supported", "현재 Wayland 디스플레이 서버가 지원되지 않습니다"), ("whitelist_sep", "다음 글자로 구분합니다. ',(콤마) ;(세미콜론) 띄어쓰기 혹은 줄바꿈'"), ("Add ID", "ID 추가"), ("Add Tag", "태그 추가"), diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 48d94c266..dcf62ff10 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Шығу"), ("Tags", "Тақтар"), ("Search ID", "ID Іздеу"), - ("Current Wayland display server is not supported", "Ағымдағы Wayland дисплей серберіне қолдау көрсетілмейді"), ("whitelist_sep", "Үтір, нүктелі үтір, бос орын және жаңа жолал арқылы бөлінеді"), ("Add ID", "ID Қосу"), ("Add Tag", "Тақ Қосу"), diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 467d918b6..085e74d3a 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Wyloguj"), ("Tags", "Tagi"), ("Search ID", "Szukaj ID"), - ("Current Wayland display server is not supported", "Obecny serwer wyświetlania Wayland nie jest obsługiwany"), ("whitelist_sep", "Oddzielone przecinkiem, średnikiem, spacją lub w nowej linii"), ("Add ID", "Dodaj ID"), ("Add Tag", "Dodaj Tag"), diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 3b6f02854..aea9acd2a 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Sair"), ("Tags", "Tags"), ("Search ID", "Procurar ID"), - ("Current Wayland display server is not supported", "Servidor de display Wayland atual não é suportado"), ("whitelist_sep", "Separado por vírcula, ponto-e-vírgula, espaços ou nova linha"), ("Add ID", "Adicionar ID"), ("Add Tag", "Adicionar Tag"), diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 9a69d1547..28683c8d5 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Sair"), ("Tags", "Tags"), ("Search ID", "Pesquisar ID"), - ("Current Wayland display server is not supported", "Servidor de display Wayland atual não é suportado"), ("whitelist_sep", "Separado por vírcula, ponto-e-vírgula, espaços ou nova linha"), ("Add ID", "Adicionar ID"), ("Add Tag", "Adicionar Tag"), diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 148723a5b..3009e9b06 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -218,7 +218,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Deconectare"), ("Tags", "Etichetare"), ("Search ID", "Caută după ID"), - ("Current Wayland display server is not supported", "Serverul de afișaj Wayland nu este acceptat"), ("whitelist_sep", "Poți folosi ca separator virgula, punctul și virgula, spațiul sau linia nouă"), ("Add ID", "Adaugă ID"), ("Add Tag", "Adaugă etichetă"), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 5ab0e6af4..7a7445534 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Выйти"), ("Tags", "Метки"), ("Search ID", "Поиск по ID"), - ("Current Wayland display server is not supported", "Текущий сервер отображения Wayland не поддерживается"), ("whitelist_sep", "Раздельно запятой, точкой с запятой, пробелом или новой строкой"), ("Add ID", "Добавить ID"), ("Add Tag", "Добавить ключевое слово"), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index b996295f2..2062b57a5 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Odhlásenie"), ("Tags", "Štítky"), ("Search ID", "Hľadať ID"), - ("Current Wayland display server is not supported", "Zobrazovací (display) server Wayland nie je podporovaný"), ("whitelist_sep", "Oddelené čiarkou, bodkočiarkou, medzerou alebo koncom riadku"), ("Add ID", "Pridať ID"), ("Add Tag", "Pridať štítok"), diff --git a/src/lang/sl.rs b/src/lang/sl.rs index cca53c830..1ff78818c 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Odjavi"), ("Tags", "Oznake"), ("Search ID", "Išči ID"), - ("Current Wayland display server is not supported", "Trenutni Wayland zaslonski strežnik ni podprt"), ("whitelist_sep", "Naslovi ločeni z vejico, podpičjem, presledkom ali novo vrstico"), ("Add ID", "Dodaj ID"), ("Add Tag", "Dodaj oznako"), diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 3bec54dd8..225652056 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Dalje"), ("Tags", "Tage"), ("Search ID", "Kerko ID"), - ("Current Wayland display server is not supported", "Serveri aktual i ekranit Wayland nuk mbështetet"), ("whitelist_sep", "Të ndara me presje, pikëpresje, hapësira ose rresht të ri"), ("Add ID", "Shto ID"), ("Add Tag", "Shto Tag"), diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 413d3e165..57c528fdb 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Odjava"), ("Tags", "Oznake"), ("Search ID", "Traži ID"), - ("Current Wayland display server is not supported", "Tekući Wazland server za prikaz nije podržan"), ("whitelist_sep", "Odvojeno zarezima, tačka zarezima, praznim mestima ili novim redovima"), ("Add ID", "Dodaj ID"), ("Add Tag", "Dodaj oznaku"), diff --git a/src/lang/sv.rs b/src/lang/sv.rs index baf3c3725..f98d7f005 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Logga ut"), ("Tags", "Taggar"), ("Search ID", "Sök ID"), - ("Current Wayland display server is not supported", "Nuvarande Wayland displayserver stöds inte"), ("whitelist_sep", "Separerat av ett comma, semikolon, mellanslag eller ny linje"), ("Add ID", "Lägg till ID"), ("Add Tag", "Lägg till Tagg"), diff --git a/src/lang/template.rs b/src/lang/template.rs index 1c5305976..358444986 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", ""), ("Tags", ""), ("Search ID", ""), - ("Current Wayland display server is not supported", ""), ("whitelist_sep", ""), ("Add ID", ""), ("Add Tag", ""), diff --git a/src/lang/th.rs b/src/lang/th.rs index 6fc94ca2a..d35cbdfe7 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "ออกจากระบบ"), ("Tags", "แท็ก"), ("Search ID", "ค้นหา ID"), - ("Current Wayland display server is not supported", "เซิร์ฟเวอร์การแสดงผล Wayland ปัจจุบันไม่รองรับ"), ("whitelist_sep", "คั่นโดยเครื่องหมาย comma semicolon เว้นวรรค หรือ ขึ้นบรรทัดใหม่"), ("Add ID", "เพิ่ม ID"), ("Add Tag", "เพิ่มแท็ก"), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 4ed9b2213..1e2068fb6 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Çıkış yap"), ("Tags", "Etiketler"), ("Search ID", "ID Arama"), - ("Current Wayland display server is not supported", "Mevcut Wayland görüntüleme sunucusu desteklenmiyor"), ("whitelist_sep", "Virgül, noktalı virgül, boşluk veya yeni satır ile ayrılmış"), ("Add ID", "ID Ekle"), ("Add Tag", "Etiket Ekle"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index cb68254bb..370c9fbed 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "登出"), ("Tags", "標籤"), ("Search ID", "搜尋 ID"), - ("Current Wayland display server is not supported", "目前不支援 Wayland 顯示伺服器"), ("whitelist_sep", "使用逗號、分號、空白,或是換行來分隔"), ("Add ID", "新增 ID"), ("Add Tag", "新增標籤"), diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 78b611ea4..bdba09b5b 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Вийти"), ("Tags", "Ключові слова"), ("Search ID", "Пошук за ID"), - ("Current Wayland display server is not supported", "Поточний графічний сервер Wayland не підтримується"), ("whitelist_sep", "Розділені комою, крапкою з комою, пробілом або новим рядком"), ("Add ID", "Додати ID"), ("Add Tag", "Додати ключове слово"), diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 044e2e9e6..840739765 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -221,7 +221,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Logout", "Đăng xuất"), ("Tags", "Tags"), ("Search ID", "Tìm ID"), - ("Current Wayland display server is not supported", "Máy chủ hình ảnh Wayland hiện không đuợc hỗ trợ"), ("whitelist_sep", "Đuợc cách nhau bởi dấu phẩy, dấu chấm phẩy, dấu cách hay dòng mới"), ("Add ID", "Thêm ID"), ("Add Tag", "Thêm Tag"), diff --git a/src/ui/index.tis b/src/ui/index.tis index e718e4380..ec2e0a748 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -764,7 +764,7 @@ class ModifyDefaultLogin: Reactor.Component { function render() { return
{translate('Warning')}
-
{translate('Current Wayland display server is not supported')}
+
{translate('wayland_experiment_tip')}
{translate('Help')}
; } From dec1820694ad2f55e7df6178d5cacc6425ee9a1e Mon Sep 17 00:00:00 2001 From: 21pages Date: Mon, 30 Jan 2023 17:56:35 +0800 Subject: [PATCH 25/83] opt dialog style Signed-off-by: 21pages --- flutter/lib/common.dart | 92 +++++++++--- .../lib/desktop/widgets/remote_menubar.dart | 8 +- flutter/lib/mobile/widgets/dialog.dart | 138 ++++++++++-------- flutter/lib/models/model.dart | 7 +- src/client/io_loop.rs | 2 +- 5 files changed, 155 insertions(+), 92 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 6ee57ef50..ab7728af1 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -613,6 +613,7 @@ class CustomAlertDialog extends StatelessWidget { Future.delayed(Duration.zero, () { if (!scopeNode.hasFocus) scopeNode.requestFocus(); }); + const double padding = 16; return FocusScope( node: scopeNode, autofocus: true, @@ -637,8 +638,8 @@ class CustomAlertDialog extends StatelessWidget { child: AlertDialog( scrollable: true, title: title, - contentPadding: EdgeInsets.symmetric( - horizontal: contentPadding ?? 25, vertical: 10), + contentPadding: EdgeInsets.fromLTRB( + contentPadding ?? padding, 25, contentPadding ?? padding, 10), content: ConstrainedBox( constraints: contentBoxConstraints, child: Theme( @@ -648,6 +649,7 @@ class CustomAlertDialog extends StatelessWidget { ), child: content)), actions: actions, + actionsPadding: EdgeInsets.fromLTRB(0, 0, padding, padding), ), ); } @@ -701,9 +703,8 @@ void msgBox(String id, String type, String title, String text, String link, } dialogManager.show( (setState, close) => CustomAlertDialog( - title: _msgBoxTitle(title), - content: - SelectableText(translate(text), style: const TextStyle(fontSize: 15)), + title: null, + content: msgboxContent(type, title, text), actions: buttons, onSubmit: hasOk ? submit : null, onCancel: hasCancel == true ? cancel : null, @@ -712,30 +713,74 @@ void msgBox(String id, String type, String title, String text, String link, ); } -Widget msgBoxButton(String text, void Function() onPressed) { - return ButtonTheme( - padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - //limits the touch area to the button area - minWidth: 0, - //wraps child's width - height: 0, - child: TextButton( - style: flatButtonStyle, - onPressed: onPressed, - child: - Text(translate(text), style: TextStyle(color: MyTheme.accent)))); +Color? _msgboxColor(String type) { + if (type == "input-password" || type == "custom-os-password") { + return Color(0xFFAD448E); + } + if (type.contains("success")) { + return Color(0xFF32bea6); + } + if (type.contains("error") || type == "re-input-password") { + return Color(0xFFE04F5F); + } + return Color(0xFF2C8CFF); } -Widget _msgBoxTitle(String title) => - Text(translate(title), style: TextStyle(fontSize: 21)); +Widget msgboxIcon(String type) { + IconData? iconData; + if (type.contains("error") || type == "re-input-password") { + iconData = Icons.cancel; + } + if (type.contains("success")) { + iconData = Icons.check_circle; + } + if (type == "wait-uac" || type == "wait-remote-accept-nook") { + iconData = Icons.hourglass_top; + } + if (type == 'on-uac' || type == 'on-foreground-elevated') { + iconData = Icons.admin_panel_settings; + } + if (type == "info") { + iconData = Icons.info; + } + if (iconData != null) { + return Icon(iconData, size: 50, color: _msgboxColor(type)) + .marginOnly(right: 16); + } + + return Offstage(); +} + +// title should be null +Widget msgboxContent(String type, String title, String text) { + return Row( + children: [ + msgboxIcon(type), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + translate(title), + style: TextStyle(fontSize: 21), + ).marginOnly(bottom: 10), + Text(translate(text), style: const TextStyle(fontSize: 15)), + ], + ), + ), + ], + ); +} void msgBoxCommon(OverlayDialogManager dialogManager, String title, Widget content, List buttons, {bool hasCancel = true}) { dialogManager.dismissAll(); dialogManager.show((setState, close) => CustomAlertDialog( - title: _msgBoxTitle(title), + title: Text( + translate(title), + style: TextStyle(fontSize: 21), + ), content: content, actions: buttons, onCancel: hasCancel ? close : null, @@ -1589,7 +1634,8 @@ class ServerConfig { Widget dialogButton(String text, {required VoidCallback? onPressed, bool isOutline = false, - TextStyle? style}) { + TextStyle? style, + ButtonStyle? buttonStyle}) { if (isDesktop) { if (isOutline) { return OutlinedButton( @@ -1598,7 +1644,7 @@ Widget dialogButton(String text, ); } else { return ElevatedButton( - style: ElevatedButton.styleFrom(elevation: 0), + style: ElevatedButton.styleFrom(elevation: 0).merge(buttonStyle), onPressed: onPressed, child: Text(translate(text), style: style), ); diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 07944649c..3598b2fb0 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -1426,12 +1426,8 @@ void showConfirmSwitchSidesDialog( } return CustomAlertDialog( - title: Text(translate('Switch Sides')), - content: Column( - children: [ - Text(translate('Please confirm if you want to share your desktop?')), - ], - ), + content: msgboxContent('info', 'Switch Sides', + 'Please confirm if you want to share your desktop?'), actions: [ dialogButton('Cancel', onPressed: close, isOutline: true), dialogButton('OK', onPressed: submit), diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index 0eb403833..bded6d069 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -9,7 +9,7 @@ import '../../models/model.dart'; import '../../models/platform_model.dart'; void clientClose(String id, OverlayDialogManager dialogManager) { - msgBox(id, '', 'Close', 'Are you sure to close the connection?', '', + msgBox(id, 'info', 'Close', 'Are you sure to close the connection?', '', dialogManager); } @@ -33,8 +33,10 @@ void showRestartRemoteDevice( ]), content: Text( "${translate('Are you sure you want to restart')} \n${pi.username}@${pi.hostname}($id) ?"), + onCancel: close, + onSubmit: () => close(true), actions: [ - dialogButton("Cancel", onPressed: () => close(), isOutline: true), + dialogButton("Cancel", onPressed: close, isOutline: true), dialogButton("OK", onPressed: () => close(true)), ], )); @@ -48,6 +50,18 @@ void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async { var validateLength = false; var validateSame = false; dialogManager.show((setState, close) { + submit() async { + close(); + dialogManager.showLoading(translate("Waiting")); + if (await gFFI.serverModel.setPermanentPassword(p0.text)) { + dialogManager.dismissAll(); + showSuccess(); + } else { + dialogManager.dismissAll(); + showError(); + } + } + return CustomAlertDialog( title: Text(translate('Set your own password')), content: Form( @@ -94,29 +108,17 @@ void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async { }, ), ])), + onCancel: close, + onSubmit: (validateLength && validateSame) ? submit : null, actions: [ dialogButton( 'Cancel', - onPressed: () { - close(); - }, + onPressed: close, isOutline: true, ), dialogButton( 'OK', - onPressed: (validateLength && validateSame) - ? () async { - close(); - dialogManager.showLoading(translate("Waiting")); - if (await gFFI.serverModel.setPermanentPassword(p0.text)) { - dialogManager.dismissAll(); - showSuccess(); - } else { - dialogManager.dismissAll(); - showError(); - } - } - : null, + onPressed: (validateLength && validateSame) ? submit : null, ), ], ); @@ -205,26 +207,36 @@ void enterPasswordDialog(String id, OverlayDialogManager dialogManager) async { }); } -void wrongPasswordDialog(String id, OverlayDialogManager dialogManager) { - dialogManager.show((setState, close) => CustomAlertDialog( - title: Text(translate('Wrong Password')), - content: Text(translate('Do you want to enter again?')), - actions: [ - dialogButton( - 'Cancel', - onPressed: () { - close(); - closeConnection(); - }, - isOutline: true, - ), - dialogButton( - 'Retry', - onPressed: () { - enterPasswordDialog(id, dialogManager); - }, - ), - ])); +void wrongPasswordDialog( + String id, OverlayDialogManager dialogManager, type, title, text) { + dialogManager.dismissAll(); + dialogManager.show((setState, close) { + cancel() { + close(); + closeConnection(); + } + + submit() { + enterPasswordDialog(id, dialogManager); + } + + return CustomAlertDialog( + title: null, + content: msgboxContent(type, title, text), + onSubmit: submit, + onCancel: cancel, + actions: [ + dialogButton( + 'Cancel', + onPressed: cancel, + isOutline: true, + ), + dialogButton( + 'Retry', + onPressed: submit, + ), + ]); + }); } void showServerSettingsWithValue( @@ -352,13 +364,15 @@ void showServerSettingsWithValue( }); } -void showWaitUacDialog(String id, OverlayDialogManager dialogManager) { +void showWaitUacDialog( + String id, OverlayDialogManager dialogManager, String type) { dialogManager.dismissAll(); dialogManager.show( tag: '$id-wait-uac', (setState, close) => CustomAlertDialog( - title: Text(translate('Wait')), - content: Text(translate('wait_accept_uac_tip')).marginAll(10), + title: null, + content: msgboxContent(type, 'Wait', 'wait_accept_uac_tip') + .marginOnly(bottom: 10), )); } @@ -516,16 +530,6 @@ void showOnBlockDialog( dialogManager.existing('$id-request-elevation')) { return; } - var content = Column(children: [ - Align( - alignment: Alignment.centerLeft, - child: Text( - "${translate(text)}${type.contains('uac') ? '\n' : '\n\n'}${translate('request_elevation_tip')}", - textAlign: TextAlign.left, - style: TextStyle(fontWeight: FontWeight.w400), - ).marginSymmetric(vertical: 15), - ), - ]); dialogManager.show(tag: '$id-$type', (setState, close) { void submit() { close(); @@ -533,12 +537,11 @@ void showOnBlockDialog( } return CustomAlertDialog( - title: Text(translate(title)), - content: content, + title: null, + content: msgboxContent(type, title, + "${translate(text)}${type.contains('uac') ? '\n' : '\n\n'}${translate('request_elevation_tip')}"), actions: [ - dialogButton('Wait', onPressed: () { - close(); - }, isOutline: true), + dialogButton('Wait', onPressed: close, isOutline: true), dialogButton('Request Elevation', onPressed: submit), ], onSubmit: submit, @@ -556,8 +559,8 @@ void showElevationError(String id, String type, String title, String text, } return CustomAlertDialog( - title: Text(translate(title)), - content: Text(translate(text)), + title: null, + content: msgboxContent(type, title, text), actions: [ dialogButton('Cancel', onPressed: () { close(); @@ -570,6 +573,25 @@ void showElevationError(String id, String type, String title, String text, }); } +void showWaitAcceptDialog(String id, String type, String title, String text, + OverlayDialogManager dialogManager) { + dialogManager.dismissAll(); + dialogManager.show((setState, close) { + onCancel() { + closeConnection(); + } + + return CustomAlertDialog( + title: null, + content: msgboxContent(type, title, text), + actions: [ + dialogButton('Cancel', onPressed: onCancel, isOutline: true), + ], + onCancel: onCancel, + ); + }); +} + Future validateAsync(String value) async { value = value.trim(); if (value.isEmpty) { diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 986d93fe8..def9c82bc 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -263,19 +263,18 @@ class FfiModel with ChangeNotifier { final text = evt['text']; final link = evt['link']; if (type == 're-input-password') { - wrongPasswordDialog(id, dialogManager); + wrongPasswordDialog(id, dialogManager, type, title, text); } else if (type == 'input-password') { enterPasswordDialog(id, dialogManager); } else if (type == 'restarting') { showMsgBox(id, type, title, text, link, false, dialogManager, hasCancel: false); } else if (type == 'wait-remote-accept-nook') { - msgBoxCommon(dialogManager, title, Text(translate(text)), - [dialogButton("Cancel", onPressed: closeConnection)]); + showWaitAcceptDialog(id, type, title, text, dialogManager); } else if (type == 'on-uac' || type == 'on-foreground-elevated') { showOnBlockDialog(id, type, title, text, dialogManager); } else if (type == 'wait-uac') { - showWaitUacDialog(id, dialogManager); + showWaitUacDialog(id, dialogManager, type); } else if (type == 'elevation-error') { showElevationError(id, type, title, text, dialogManager); } else { diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index ff6d6c004..f4ecbded5 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -1104,7 +1104,7 @@ impl Remote { Some(misc::Union::PortableServiceRunning(b)) => { if b { self.handler.msgbox( - "custom-nocancel", + "custom-nocancel-success", "Successful", "Elevate successfully", "", From 87de9eb726418d208f77dfc5bb5dcc96c0993655 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Mon, 30 Jan 2023 18:30:38 +0800 Subject: [PATCH 26/83] a workaround of issue #2886, following the behavior address input of chrome --- flutter/lib/common/widgets/peer_tab_page.dart | 5 ++++- flutter/lib/desktop/pages/connection_page.dart | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index 0c24fe7ea..278f5861c 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -419,7 +419,10 @@ class _PeerSearchBarState extends State { Widget _buildSearchBar() { RxBool focused = false.obs; FocusNode focusNode = FocusNode(); - focusNode.addListener(() => focused.value = focusNode.hasFocus); + focusNode.addListener(() { + focused.value = focusNode.hasFocus; + peerSearchTextController.selection = TextSelection(baseOffset: 0, extentOffset: peerSearchTextController.value.text.length); + }); return Container( width: 120, decoration: BoxDecoration( diff --git a/flutter/lib/desktop/pages/connection_page.dart b/flutter/lib/desktop/pages/connection_page.dart index 2dae03250..699cc4495 100644 --- a/flutter/lib/desktop/pages/connection_page.dart +++ b/flutter/lib/desktop/pages/connection_page.dart @@ -64,6 +64,8 @@ class _ConnectionPageState extends State }); _idFocusNode.addListener(() { _idInputFocused.value = _idFocusNode.hasFocus; + // select all to faciliate removing text, just following the behavior of address input of chrome + _idController.selection = TextSelection(baseOffset: 0, extentOffset: _idController.value.text.length); }); windowManager.addListener(this); } From 00a3b04aab8659ef175d9c16715ad7c1be19647f Mon Sep 17 00:00:00 2001 From: 21pages Date: Mon, 30 Jan 2023 19:38:50 +0800 Subject: [PATCH 27/83] fix theme Signed-off-by: 21pages --- flutter/lib/common.dart | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index ab7728af1..cf7de0fa2 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -205,6 +205,9 @@ class MyTheme { splashColor: Colors.transparent, highlightColor: Colors.transparent, splashFactory: isDesktop ? NoSplash.splashFactory : null, + outlinedButtonTheme: OutlinedButtonThemeData( + style: + OutlinedButton.styleFrom(side: BorderSide(color: Colors.white38))), textButtonTheme: isDesktop ? TextButtonThemeData( style: ButtonStyle(splashFactory: NoSplash.splashFactory), @@ -641,13 +644,13 @@ class CustomAlertDialog extends StatelessWidget { contentPadding: EdgeInsets.fromLTRB( contentPadding ?? padding, 25, contentPadding ?? padding, 10), content: ConstrainedBox( - constraints: contentBoxConstraints, - child: Theme( - data: ThemeData( + constraints: contentBoxConstraints, + child: Theme( + data: Theme.of(context).copyWith( inputDecorationTheme: InputDecorationTheme( - isDense: true, contentPadding: EdgeInsets.all(15)), - ), - child: content)), + isDense: true, contentPadding: EdgeInsets.all(15))), + child: content), + ), actions: actions, actionsPadding: EdgeInsets.fromLTRB(0, 0, padding, padding), ), From d99b0bed0a4f9202e53c472f6dff86e188d92627 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Mon, 30 Jan 2023 21:42:58 +0800 Subject: [PATCH 28/83] fix: set edge size to zero when in fullscreen mode --- flutter/lib/desktop/pages/connection_page.dart | 13 +++++++++++++ flutter/lib/desktop/pages/remote_tab_page.dart | 17 +++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/flutter/lib/desktop/pages/connection_page.dart b/flutter/lib/desktop/pages/connection_page.dart index 699cc4495..eee4c6a20 100644 --- a/flutter/lib/desktop/pages/connection_page.dart +++ b/flutter/lib/desktop/pages/connection_page.dart @@ -8,6 +8,7 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/consts.dart'; import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart'; +import 'package:flutter_hbb/models/state_model.dart'; import 'package:get/get.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'package:window_manager/window_manager.dart'; @@ -92,6 +93,18 @@ class _ConnectionPageState extends State } } + @override + void onWindowEnterFullScreen() { + // Remove edge border by setting the value to zero. + stateGlobal.resizeEdgeSize.value = 0; + } + + @override + void onWindowLeaveFullScreen() { + // Restore edge border to default edge size. + stateGlobal.resizeEdgeSize.value = kWindowEdgeSize; + } + @override void onWindowClose() { super.onWindowClose(); diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index 83928c3fe..7ceacd539 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -38,8 +38,9 @@ class ConnectionTabPage extends StatefulWidget { } class _ConnectionTabPageState extends State { - final tabController = Get.put(DesktopTabController( - tabType: DesktopTabType.remoteScreen)); + final tabController = + Get.put(DesktopTabController(tabType: DesktopTabType.remoteScreen)); + final contentKey = UniqueKey(); static const IconData selectedIcon = Icons.desktop_windows_sharp; static const IconData unselectedIcon = Icons.desktop_windows_outlined; @@ -80,7 +81,6 @@ class _ConnectionTabPageState extends State { super.initState(); tabController.onRemoved = (_, id) => onRemoveId(id); - rustDeskWinManager.setMethodHandler((call, fromWindowId) async { print( @@ -197,11 +197,12 @@ class _ConnectionTabPageState extends State { ); return Platform.isMacOS ? tabWidget - : SubWindowDragToResizeArea( - child: tabWidget, - resizeEdgeSize: stateGlobal.resizeEdgeSize.value, - windowId: stateGlobal.windowId, - ); + : Obx(() => SubWindowDragToResizeArea( + key: contentKey, + child: tabWidget, + resizeEdgeSize: stateGlobal.resizeEdgeSize.value, + windowId: stateGlobal.windowId, + )); } // Note: Some dup code to ../widgets/remote_menubar From 0765f7057f3adf7c196f50c630f415878c771096 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 30 Jan 2023 22:12:36 +0800 Subject: [PATCH 29/83] try fix https://github.com/rustdesk/rustdesk/issues/2923 Signed-off-by: fufesou --- flutter/lib/desktop/widgets/remote_menubar.dart | 12 +++++++++--- flutter/lib/models/input_model.dart | 7 +++++++ flutter/lib/models/model.dart | 1 + 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 07944649c..7695bc51c 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -379,9 +379,15 @@ class _RemoteMenubarState extends State { mod_menu.PopupMenuItem( height: _MenubarTheme.height, padding: EdgeInsets.zero, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: rowChildren), + child: Listener( + onPointerHover: (PointerHoverEvent e) => + widget.ffi.inputModel.lastMousePos = e.position, + child: MouseRegion( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: rowChildren), + ), + ), ) ]; }, diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index 7356c6ec8..49115cb3f 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -408,6 +408,13 @@ class InputModel { } } + void refreshMousePos() => handleMouse({ + 'x': lastMousePos.dx, + 'y': lastMousePos.dy, + 'buttons': 0, + 'type': _kMouseEventMove, + }); + void handleMouse(Map evt) { double x = evt['x']; double y = max(0.0, evt['y']); diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 986d93fe8..1f4fbb8f0 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -244,6 +244,7 @@ class FfiModel with ChangeNotifier { parent.target?.canvasModel.updateViewStyle(); } parent.target?.recordingModel.onSwitchDisplay(); + parent.target?.inputModel.refreshMousePos(); notifyListeners(); } From 55318c2393a44d539d9d92445e05876bf27272ce Mon Sep 17 00:00:00 2001 From: jimmyGALLAND <64364019+jimmyGALLAND@users.noreply.github.com> Date: Mon, 30 Jan 2023 17:10:05 +0100 Subject: [PATCH 30/83] Update desktop_tab_page.dart --- flutter/lib/desktop/pages/desktop_tab_page.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/lib/desktop/pages/desktop_tab_page.dart b/flutter/lib/desktop/pages/desktop_tab_page.dart index 57c7fe4b8..c1965921c 100644 --- a/flutter/lib/desktop/pages/desktop_tab_page.dart +++ b/flutter/lib/desktop/pages/desktop_tab_page.dart @@ -23,7 +23,7 @@ class DesktopTabPage extends StatefulWidget { DesktopTabController tabController = Get.find(); tabController.add(TabInfo( key: kTabLabelSettingPage, - label: kTabLabelSettingPage, + label: translate(kTabLabelSettingPage), selectedIcon: Icons.build_sharp, unselectedIcon: Icons.build_outlined, page: DesktopSettingPage( @@ -46,7 +46,7 @@ class _DesktopTabPageState extends State { RemoteCountState.init(); tabController.add(TabInfo( key: kTabLabelHomePage, - label: kTabLabelHomePage, + label: translate(kTabLabelHomePage), selectedIcon: Icons.home_sharp, unselectedIcon: Icons.home_outlined, closable: false, From 61389bc11fd9b00a8fb742d4239376f8b74ac629 Mon Sep 17 00:00:00 2001 From: 21pages Date: Mon, 30 Jan 2023 21:40:13 +0800 Subject: [PATCH 31/83] adjust quality monitor ui Signed-off-by: 21pages --- flutter/lib/common/widgets/overlay.dart | 72 +++++++++++++------------ src/ui/remote.css | 2 +- 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/flutter/lib/common/widgets/overlay.dart b/flutter/lib/common/widgets/overlay.dart index d9684bace..aaf52fb07 100644 --- a/flutter/lib/common/widgets/overlay.dart +++ b/flutter/lib/common/widgets/overlay.dart @@ -1,3 +1,4 @@ +import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; import 'package:provider/provider.dart'; @@ -316,44 +317,49 @@ class _DraggableState extends State { } class QualityMonitor extends StatelessWidget { - static const textStyle = TextStyle(color: MyTheme.grayBg); final QualityMonitorModel qualityMonitorModel; QualityMonitor(this.qualityMonitorModel); + Widget _row(String info, String? value) { + return Row( + children: [ + Expanded( + flex: 8, + child: AutoSizeText(info, + style: TextStyle(color: MyTheme.grayBg), + textAlign: TextAlign.right, + maxLines: 1)), + Spacer(flex: 1), + Expanded( + flex: 8, + child: AutoSizeText(value ?? '', + style: TextStyle(color: MyTheme.grayBg), maxLines: 1)), + ], + ); + } + @override Widget build(BuildContext context) => ChangeNotifierProvider.value( value: qualityMonitorModel, child: Consumer( - builder: (context, qualityMonitorModel, child) => - qualityMonitorModel.show - ? Container( - padding: const EdgeInsets.all(8), - color: MyTheme.canvasColor.withAlpha(120), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Speed: ${qualityMonitorModel.data.speed ?? ''}", - style: textStyle, - ), - Text( - "FPS: ${qualityMonitorModel.data.fps ?? ''}", - style: textStyle, - ), - Text( - "Delay: ${qualityMonitorModel.data.delay ?? ''} ms", - style: textStyle, - ), - Text( - "Target Bitrate: ${qualityMonitorModel.data.targetBitrate ?? ''}kb", - style: textStyle, - ), - Text( - "Codec: ${qualityMonitorModel.data.codecFormat ?? ''}", - style: textStyle, - ), - ], - ), - ) - : const SizedBox.shrink())); + builder: (context, qualityMonitorModel, child) => qualityMonitorModel + .show + ? Container( + constraints: BoxConstraints(maxWidth: 200), + padding: const EdgeInsets.all(8), + color: MyTheme.canvasColor.withAlpha(120), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _row("Speed", qualityMonitorModel.data.speed ?? ''), + _row("FPS", qualityMonitorModel.data.fps ?? ''), + _row( + "Delay", "${qualityMonitorModel.data.delay ?? ''}ms"), + _row("Target Bitrate", + "${qualityMonitorModel.data.targetBitrate ?? ''}kb"), + _row("Codec", qualityMonitorModel.data.codecFormat ?? ''), + ], + ), + ) + : const SizedBox.shrink())); } diff --git a/src/ui/remote.css b/src/ui/remote.css index 66c5ce80f..71b2c1682 100644 --- a/src/ui/remote.css +++ b/src/ui/remote.css @@ -16,7 +16,7 @@ div#quality-monitor { padding: 5px; min-width: 150px; color: azure; - border: solid azure; + border: 0.5px solid azure; } video#handler { From fb81f206b7e471f659a07ed0b7a2842e18ec89ad Mon Sep 17 00:00:00 2001 From: 21pages Date: Sun, 29 Jan 2023 17:36:37 +0800 Subject: [PATCH 32/83] opt flink creation Signed-off-by: 21pages --- src/platform/windows.rs | 10 +++++ src/server/portable_service.rs | 68 ++++++++++++++-------------------- 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/src/platform/windows.rs b/src/platform/windows.rs index b778283a5..2e0d56eab 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1745,3 +1745,13 @@ pub fn create_process_with_logon(user: &str, pwd: &str, exe: &str, arg: &str) -> } return Ok(()); } + +pub fn set_path_permission(dir: &PathBuf, permission: &str) -> ResultType<()> { + std::process::Command::new("icacls") + .arg(dir.as_os_str()) + .arg("/grant") + .arg(format!("Everyone:(OI)(CI){}", permission)) + .arg("/T") + .spawn()?; + Ok(()) +} diff --git a/src/server/portable_service.rs b/src/server/portable_service.rs index 748cb39e4..a2f6fb829 100644 --- a/src/server/portable_service.rs +++ b/src/server/portable_service.rs @@ -2,9 +2,7 @@ use core::slice; use hbb_common::{ allow_err, anyhow::anyhow, - bail, - config::Config, - log, + bail, log, message_proto::{KeyEvent, MouseEvent}, protobuf::Message, tokio::{self, sync::mpsc}, @@ -15,6 +13,7 @@ use shared_memory::*; use std::{ mem::size_of, ops::{Deref, DerefMut}, + path::PathBuf, sync::{Arc, Mutex}, time::Duration, }; @@ -25,6 +24,7 @@ use winapi::{ use crate::{ ipc::{self, new_listener, Connection, Data, DataPortableService}, + platform::set_path_permission, video_service::get_current_display, }; @@ -72,7 +72,7 @@ impl DerefMut for SharedMemory { impl SharedMemory { pub fn create(name: &str, size: usize) -> ResultType { - let flink = Self::flink(name.to_string()); + let flink = Self::flink(name.to_string())?; let shmem = match ShmemConf::new() .size(size) .flink(&flink) @@ -91,12 +91,12 @@ impl SharedMemory { } }; log::info!("Create shared memory, size:{}, flink:{}", size, flink); - Self::set_all_perm(&flink); + set_path_permission(&PathBuf::from(flink), "F").ok(); Ok(SharedMemory { inner: shmem }) } pub fn open_existing(name: &str) -> ResultType { - let flink = Self::flink(name.to_string()); + let flink = Self::flink(name.to_string())?; let shmem = match ShmemConf::new().flink(&flink).allow_raw(true).open() { Ok(m) => m, Err(e) => { @@ -116,30 +116,29 @@ impl SharedMemory { } } - fn flink(name: String) -> String { - let mut shmem_flink = format!("shared_memory{}", name); - if cfg!(windows) { - let df = "C:\\ProgramData"; - let df = if std::path::Path::new(df).exists() { - df.to_owned() - } else { - std::env::var("TEMP").unwrap_or("C:\\Windows\\TEMP".to_owned()) - }; - let df = format!("{}\\{}", df, *hbb_common::config::APP_NAME.read().unwrap()); - std::fs::create_dir(&df).ok(); - shmem_flink = format!("{}\\{}", df, shmem_flink); + fn flink(name: String) -> ResultType { + let disk = std::env::var("SystemDrive").unwrap_or("C:".to_string()); + let mut dir = PathBuf::from(disk); + let dir1 = dir.join("ProgramData"); + let dir2 = std::env::var("TEMP") + .map(|d| PathBuf::from(d)) + .unwrap_or(dir.join("Windows").join("Temp")); + if dir1.exists() { + dir = dir1; + } else if dir2.exists() { + dir = dir2; } else { - shmem_flink = Config::ipc_path("").replace("ipc", "") + &shmem_flink; + bail!("no vaild flink directory"); } - return shmem_flink; - } - - fn set_all_perm(_p: &str) { - #[cfg(not(windows))] - { - use std::os::unix::fs::PermissionsExt; - std::fs::set_permissions(_p, std::fs::Permissions::from_mode(0o0777)).ok(); + dir = dir.join(hbb_common::config::APP_NAME.read().unwrap().clone()); + if !dir.exists() { + std::fs::create_dir(&dir)?; + set_path_permission(&dir, "F").ok(); } + Ok(dir + .join(format!("shared_memory{}", name)) + .to_string_lossy() + .to_string()) } } @@ -451,7 +450,6 @@ pub mod server { // functions called in main process. pub mod client { use hbb_common::anyhow::Context; - use std::path::PathBuf; use super::*; @@ -515,7 +513,7 @@ pub mod client { #[cfg(feature = "flutter")] { if let Some(dir) = PathBuf::from(&exe).parent() { - if !set_dir_permission(&PathBuf::from(dir)) { + if set_path_permission(&PathBuf::from(dir), "RX").is_err() { *SHMEM.lock().unwrap() = None; bail!("Failed to set permission of {:?}", dir); } @@ -533,7 +531,7 @@ pub mod client { let dst = dir.join("rustdesk.exe"); if std::fs::copy(&exe, &dst).is_ok() { if dst.exists() { - if set_dir_permission(&dir) { + if set_path_permission(&dir, "RX").is_ok() { exe = dst.to_string_lossy().to_string(); } } @@ -566,16 +564,6 @@ pub mod client { *QUICK_SUPPORT.lock().unwrap() = v; } - fn set_dir_permission(dir: &PathBuf) -> bool { - // // give Everyone RX permission - std::process::Command::new("icacls") - .arg(dir.as_os_str()) - .arg("/grant") - .arg("Everyone:(OI)(CI)RX") - .arg("/T") - .spawn() - .is_ok() - } pub struct CapturerPortable; impl CapturerPortable { From 74a73b7ffd6008be1d49c67a0642fc1938e4b790 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 31 Jan 2023 17:51:20 +0800 Subject: [PATCH 33/83] add default position for portal streams Signed-off-by: fufesou --- libs/scrap/src/wayland/pipewire.rs | 31 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/libs/scrap/src/wayland/pipewire.rs b/libs/scrap/src/wayland/pipewire.rs index fefab9b77..9c0ad9774 100644 --- a/libs/scrap/src/wayland/pipewire.rs +++ b/libs/scrap/src/wayland/pipewire.rs @@ -386,21 +386,22 @@ fn streams_from_response(response: OrgFreedesktopPortalRequestResponse) -> Vec

>(), - ) - }) - .next(); - if let Some(v) = v { - if v.len() == 2 { - info.position.0 = v[0] as _; - info.position.1 = v[1] as _; + if let Some(pos) = attributes.get("position") { + let v = pos + .as_iter()? + .filter_map(|v| { + Some( + v.as_iter()? + .map(|x| x.as_i64().unwrap_or(0)) + .collect::>(), + ) + }) + .next(); + if let Some(v) = v { + if v.len() == 2 { + info.position.0 = v[0] as _; + info.position.1 = v[1] as _; + } } } Some(info) From c1ae4a6028c8b0b99d0fc0840da0cdad26e5ebd6 Mon Sep 17 00:00:00 2001 From: sjpark Date: Wed, 1 Feb 2023 08:10:57 +0900 Subject: [PATCH 34/83] tray bug fix --- src/core_main.rs | 2 +- src/ui.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core_main.rs b/src/core_main.rs index 4a2f6164c..8658b736c 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -198,7 +198,7 @@ pub fn core_main() -> Option> { { std::thread::spawn(move || crate::start_server(true)); crate::platform::macos::hide_dock(); - crate::tray::make_tray(); + crate::ui::macos::make_tray(); return None; } #[cfg(target_os = "linux")] diff --git a/src/ui.rs b/src/ui.rs index b8473072d..db1cac074 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -21,7 +21,7 @@ mod cm; #[cfg(feature = "inline")] pub mod inline; #[cfg(target_os = "macos")] -mod macos; +pub mod macos; pub mod remote; #[cfg(target_os = "windows")] pub mod win_privacy; From ec1da900ec6bfa35b7f1302c34871f58604d5e5e Mon Sep 17 00:00:00 2001 From: rustdesk Date: Wed, 1 Feb 2023 10:42:02 +0800 Subject: [PATCH 35/83] fix issue #2963: run gen_version no matter debug or release --- libs/hbb_common/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/libs/hbb_common/src/lib.rs b/libs/hbb_common/src/lib.rs index 9e004376c..c9f9e90d7 100644 --- a/libs/hbb_common/src/lib.rs +++ b/libs/hbb_common/src/lib.rs @@ -197,9 +197,6 @@ pub fn get_version_from_url(url: &str) -> String { } pub fn gen_version() { - if Ok("release".to_owned()) != std::env::var("PROFILE") { - return; - } println!("cargo:rerun-if-changed=Cargo.toml"); use std::io::prelude::*; let mut file = File::create("./src/version.rs").unwrap(); From 2f26b2a355f896e54f24abba44689ce77ef050b9 Mon Sep 17 00:00:00 2001 From: solokot Date: Wed, 1 Feb 2023 09:08:54 +0300 Subject: [PATCH 36/83] Update ru.rs --- src/lang/ru.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 7a7445534..22f938ec5 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -41,9 +41,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "О программе"), ("Slogan_tip", "Сделано с душой в этом безумном мире!"), ("Privacy Statement", "Заявление о конфиденциальности"), - ("Build Date", ""), - ("Version", ""), - ("Home", ""), + ("Build Date", "Дата сборки"), + ("Version", "Версия"), + ("Home", "Главная"), ("Mute", "Отключить звук"), ("Audio Input", "Аудиовход"), ("Enhancements", "Улучшения"), @@ -434,7 +434,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Medium", "Средний"), ("Strong", "Стойкий"), ("Switch Sides", "Переключить стороны"), - ("Please confirm if you want to share your desktop?", "Подтвердите, что хотите поделиться своим рабочим столом?"), - ("Closed as expected", ""), + ("Please confirm if you want to share your desktop?", "Подтверждаете, что хотите поделиться своим рабочим столом?"), + ("Closed as expected", "Закрыто по ожиданию"), ].iter().cloned().collect(); } From 60ff4982ca6337a96cf80630d02aa9a7c76ab120 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Wed, 1 Feb 2023 14:03:55 +0800 Subject: [PATCH 37/83] fix: macos location restore incorrectly --- .../desktop/pages/file_manager_tab_page.dart | 3 --- .../desktop/pages/port_forward_tab_page.dart | 3 --- flutter/lib/main.dart | 24 +++++++++---------- flutter/pubspec.yaml | 2 +- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_tab_page.dart b/flutter/lib/desktop/pages/file_manager_tab_page.dart index b2566e267..95bf0b182 100644 --- a/flutter/lib/desktop/pages/file_manager_tab_page.dart +++ b/flutter/lib/desktop/pages/file_manager_tab_page.dart @@ -71,9 +71,6 @@ class _FileManagerTabPageState extends State { reloadCurrentWindow(); } }); - Future.delayed(Duration.zero, () { - restoreWindowPosition(WindowType.FileTransfer, windowId: windowId()); - }); } @override diff --git a/flutter/lib/desktop/pages/port_forward_tab_page.dart b/flutter/lib/desktop/pages/port_forward_tab_page.dart index ca354f297..c29ad64b0 100644 --- a/flutter/lib/desktop/pages/port_forward_tab_page.dart +++ b/flutter/lib/desktop/pages/port_forward_tab_page.dart @@ -79,9 +79,6 @@ class _PortForwardTabPageState extends State { reloadCurrentWindow(); } }); - Future.delayed(Duration.zero, () { - restoreWindowPosition(WindowType.PortForward, windowId: windowId()); - }); } @override diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index 1ec963f22..4579ef223 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -122,20 +122,20 @@ void runMainApp(bool startService) async { } gFFI.userModel.refreshCurrentUser(); runApp(App()); - // restore the location of the main window before window hide or show - await restoreWindowPosition(WindowType.Main); - // check the startup argument, if we successfully handle the argument, we keep the main window hidden. - if (checkArguments()) { - windowManager.hide(); - } else { - windowManager.show(); - windowManager.focus(); - // move registration of active main window here to prevent async visible check. - rustDeskWinManager.registerActiveWindow(kWindowMainId); - } - // set window option + // Set window option. WindowOptions windowOptions = getHiddenTitleBarWindowOptions(); windowManager.waitUntilReadyToShow(windowOptions, () async { + // Restore the location of the main window before window hide or show. + await restoreWindowPosition(WindowType.Main); + // Check the startup argument, if we successfully handle the argument, we keep the main window hidden. + if (checkArguments()) { + windowManager.hide(); + } else { + windowManager.show(); + windowManager.focus(); + // Move registration of active main window here to prevent from async visible check. + rustDeskWinManager.registerActiveWindow(kWindowMainId); + } windowManager.setOpacity(1); }); windowManager.setTitle(getWindowName()); diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 0189ad9e4..3d08033bb 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -59,7 +59,7 @@ dependencies: desktop_multi_window: git: url: https://github.com/Kingtous/rustdesk_desktop_multi_window - ref: 057e6eb1bc7dcbcf9dafd1384274a611e4fe7124 + ref: bc8604a88e52b2b6e64d2661ae49a71450a47af8 freezed_annotation: ^2.0.3 flutter_custom_cursor: ^0.0.2 window_size: From bf71e38426159e8c85e2d5dbfbaba99675dfa25c Mon Sep 17 00:00:00 2001 From: Kingtous Date: Wed, 1 Feb 2023 14:13:53 +0800 Subject: [PATCH 38/83] fix: linux sub-window pos for double-check pos --- flutter/lib/desktop/pages/file_manager_tab_page.dart | 3 +++ flutter/lib/desktop/pages/port_forward_tab_page.dart | 3 +++ flutter/lib/desktop/pages/remote_tab_page.dart | 3 +++ 3 files changed, 9 insertions(+) diff --git a/flutter/lib/desktop/pages/file_manager_tab_page.dart b/flutter/lib/desktop/pages/file_manager_tab_page.dart index 95bf0b182..b2566e267 100644 --- a/flutter/lib/desktop/pages/file_manager_tab_page.dart +++ b/flutter/lib/desktop/pages/file_manager_tab_page.dart @@ -71,6 +71,9 @@ class _FileManagerTabPageState extends State { reloadCurrentWindow(); } }); + Future.delayed(Duration.zero, () { + restoreWindowPosition(WindowType.FileTransfer, windowId: windowId()); + }); } @override diff --git a/flutter/lib/desktop/pages/port_forward_tab_page.dart b/flutter/lib/desktop/pages/port_forward_tab_page.dart index c29ad64b0..ca354f297 100644 --- a/flutter/lib/desktop/pages/port_forward_tab_page.dart +++ b/flutter/lib/desktop/pages/port_forward_tab_page.dart @@ -79,6 +79,9 @@ class _PortForwardTabPageState extends State { reloadCurrentWindow(); } }); + Future.delayed(Duration.zero, () { + restoreWindowPosition(WindowType.PortForward, windowId: windowId()); + }); } @override diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index 7ceacd539..55124fbcc 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -113,6 +113,9 @@ class _ConnectionTabPageState extends State { } _update_remote_count(); }); + Future.delayed(Duration.zero, () { + restoreWindowPosition(WindowType.RemoteDesktop, windowId: windowId()); + }); } @override From cbf0da61956f19478ef87984845aaf73649a5c7a Mon Sep 17 00:00:00 2001 From: Kingtous Date: Wed, 1 Feb 2023 16:29:13 +0800 Subject: [PATCH 39/83] feat: add trackpad listener support based on flutter 3.3 --- flutter/lib/common/widgets/remote_input.dart | 2 -- flutter/lib/models/input_model.dart | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/flutter/lib/common/widgets/remote_input.dart b/flutter/lib/common/widgets/remote_input.dart index 2d0dcacdf..2fb409970 100644 --- a/flutter/lib/common/widgets/remote_input.dart +++ b/flutter/lib/common/widgets/remote_input.dart @@ -64,11 +64,9 @@ class RawPointerMouseRegion extends StatelessWidget { }, onPointerMove: inputModel.onPointMoveImage, onPointerSignal: inputModel.onPointerSignalImage, - /* onPointerPanZoomStart: inputModel.onPointerPanZoomStart, onPointerPanZoomUpdate: inputModel.onPointerPanZoomUpdate, onPointerPanZoomEnd: inputModel.onPointerPanZoomEnd, - */ child: MouseRegion( cursor: cursor ?? MouseCursor.defer, onEnter: onEnter, diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index 49115cb3f..d2f671cdc 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -310,7 +310,7 @@ class InputModel { } } -/* + int _signOrZero(num x) { if (x == 0) { return 0; @@ -361,7 +361,7 @@ class InputModel { trackpadScrollDistance = Offset.zero; } -*/ + void onPointDownImage(PointerDownEvent e) { debugPrint("onPointDownImage"); From 5149b90e539a05756b38e14672848bcbcd94ec7c Mon Sep 17 00:00:00 2001 From: rustdesk Date: Wed, 1 Feb 2023 17:11:24 +0800 Subject: [PATCH 40/83] fix hide docker (can not call too early) --- flutter/lib/main.dart | 1 + flutter/macos/Podfile.lock | 15 +- .../macos/Runner.xcodeproj/project.pbxproj | 5 +- flutter/pubspec.lock | 671 +++++++++++------- src/core_main.rs | 2 - src/flutter_ffi.rs | 6 + 6 files changed, 440 insertions(+), 260 deletions(-) diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index 4579ef223..53ae2f5dd 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -88,6 +88,7 @@ Future main(List args) async { debugPrint("--cm started"); desktopType = DesktopType.cm; await windowManager.ensureInitialized(); + bind.mainHideDocker(); runConnectionManagerScreen(args.contains('--hide')); } else if (args.contains('--install')) { runInstallPage(); diff --git a/flutter/macos/Podfile.lock b/flutter/macos/Podfile.lock index 8d41945c8..3187c6349 100644 --- a/flutter/macos/Podfile.lock +++ b/flutter/macos/Podfile.lock @@ -13,7 +13,8 @@ PODS: - FMDB/standard (2.7.5) - package_info_plus_macos (0.0.1): - FlutterMacOS - - path_provider_macos (0.0.1): + - path_provider_foundation (0.0.1): + - Flutter - FlutterMacOS - screen_retriever (0.0.1): - FlutterMacOS @@ -38,7 +39,7 @@ DEPENDENCIES: - flutter_custom_cursor (from `Flutter/ephemeral/.symlinks/plugins/flutter_custom_cursor/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - package_info_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos`) - - path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`) + - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos`) - screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) - uni_links_desktop (from `Flutter/ephemeral/.symlinks/plugins/uni_links_desktop/macos`) @@ -64,8 +65,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral package_info_plus_macos: :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos - path_provider_macos: - :path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos + path_provider_foundation: + :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos screen_retriever: :path: Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos sqflite: @@ -86,14 +87,14 @@ SPEC CHECKSUMS: desktop_multi_window: 566489c048b501134f9d7fb6a2354c60a9126486 device_info_plus_macos: 1ad388a1ef433505c4038e7dd9605aadd1e2e9c7 flutter_custom_cursor: 629957115075c672287bd0fa979d863ccf6024f7 - FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424 + FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a package_info_plus_macos: f010621b07802a241d96d01876d6705f15e77c1c - path_provider_macos: 3c0c3b4b0d4a76d2bf989a913c2de869c5641a19 + path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852 screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38 sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea uni_links_desktop: 45900fb319df48fcdea2df0756e9c2626696b026 - url_launcher_macos: 597e05b8e514239626bcf4a850fcf9ef5c856ec3 + url_launcher_macos: c04e4fa86382d4f94f6b38f14625708be3ae52e2 wakelock_macos: bc3f2a9bd8d2e6c89fee1e1822e7ddac3bd004a9 window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 window_size: 339dafa0b27a95a62a843042038fa6c3c48de195 diff --git a/flutter/macos/Runner.xcodeproj/project.pbxproj b/flutter/macos/Runner.xcodeproj/project.pbxproj index fbf52403c..7a17c3de1 100644 --- a/flutter/macos/Runner.xcodeproj/project.pbxproj +++ b/flutter/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -279,6 +279,7 @@ /* Begin PBXShellScriptBuildPhase section */ 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -429,7 +430,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = NO; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index 15a1a23ac..c193c0651 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -5,288 +5,328 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + sha256: "0c80aeab9bc807ab10022cd3b2f4cf2ecdf231949dc1ddd9442406a003f19201" + url: "https://pub.dev" source: hosted - version: "50.0.0" + version: "52.0.0" after_layout: dependency: transitive description: name: after_layout - url: "https://pub.dartlang.org" + sha256: "95a1cb2ca1464f44f14769329fbf15987d20ab6c88f8fc5d359bd362be625f29" + url: "https://pub.dev" source: hosted version: "1.2.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + sha256: cd8ee83568a77f3ae6b913a36093a1c9b1264e7cb7f834d9ddd2311dade9c1f4 + url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.4.0" animations: dependency: transitive description: name: animations - url: "https://pub.dartlang.org" + sha256: fe8a6bdca435f718bb1dc8a11661b2c22504c6da40ef934cee8327ed77934164 + url: "https://pub.dev" source: hosted version: "2.0.7" archive: dependency: transitive description: name: archive - url: "https://pub.dartlang.org" + sha256: d6347d54a2d8028e0437e3c099f66fdb8ae02c4720c1e7534c9f24c10351f85d + url: "https://pub.dev" source: hosted - version: "3.3.5" + version: "3.3.6" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" + url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.10.0" auto_size_text: dependency: "direct main" description: name: auto_size_text - url: "https://pub.dartlang.org" + sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599" + url: "https://pub.dev" source: hosted version: "3.0.0" back_button_interceptor: dependency: "direct main" description: name: back_button_interceptor - url: "https://pub.dartlang.org" + sha256: e47660f2178a4392eb72001f9594d3fdcb5efde93e59d2819d61fda499e781c8 + url: "https://pub.dev" source: hosted version: "6.0.2" bot_toast: dependency: "direct main" description: name: bot_toast - url: "https://pub.dartlang.org" + sha256: "19306147033316a7873c5d261b874fca3f341c05e4e1c12be56153ad11187edd" + url: "https://pub.dev" source: hosted version: "4.0.3" build: dependency: transitive description: name: build - url: "https://pub.dartlang.org" + sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + url: "https://pub.dev" source: hosted version: "2.3.1" build_cli_annotations: dependency: transitive description: name: build_cli_annotations - url: "https://pub.dartlang.org" + sha256: b59d2769769efd6c9ff6d4c4cede0be115a566afc591705c2040b707534b1172 + url: "https://pub.dev" source: hosted version: "2.1.0" build_config: dependency: transitive description: name: build_config - url: "https://pub.dartlang.org" + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" source: hosted version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - url: "https://pub.dartlang.org" + sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + url: "https://pub.dev" source: hosted version: "3.1.0" build_resolvers: dependency: transitive description: name: build_resolvers - url: "https://pub.dartlang.org" + sha256: "7c35a3a7868626257d8aee47b51c26b9dba11eaddf3431117ed2744951416aab" + url: "https://pub.dev" source: hosted - version: "2.0.10" + version: "2.1.0" build_runner: dependency: "direct dev" description: name: build_runner - url: "https://pub.dartlang.org" + sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + url: "https://pub.dev" source: hosted version: "2.3.3" build_runner_core: dependency: transitive description: name: build_runner_core - url: "https://pub.dartlang.org" + sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" + url: "https://pub.dev" source: hosted version: "7.2.7" built_collection: dependency: transitive description: name: built_collection - url: "https://pub.dartlang.org" + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" source: hosted version: "5.1.1" built_value: dependency: transitive description: name: built_value - url: "https://pub.dartlang.org" + sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" + url: "https://pub.dev" source: hosted - version: "8.4.2" + version: "8.4.3" cached_network_image: dependency: transitive description: name: cached_network_image - url: "https://pub.dartlang.org" + sha256: fd3d0dc1d451f9a252b32d95d3f0c3c487bc41a75eba2e6097cb0b9c71491b15 + url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.3" cached_network_image_platform_interface: dependency: transitive description: name: cached_network_image_platform_interface - url: "https://pub.dartlang.org" + sha256: bb2b8403b4ccdc60ef5f25c70dead1f3d32d24b9d6117cfc087f496b178594a7 + url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "2.0.0" cached_network_image_web: dependency: transitive description: name: cached_network_image_web - url: "https://pub.dartlang.org" + sha256: b8eb814ebfcb4dea049680f8c1ffb2df399e4d03bf7a352c775e26fa06e02fa0 + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.2" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" charcode: dependency: transitive description: name: charcode - url: "https://pub.dartlang.org" + sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 + url: "https://pub.dev" source: hosted version: "1.3.1" checked_yaml: dependency: transitive description: name: checked_yaml - url: "https://pub.dartlang.org" + sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" cli_util: dependency: transitive description: name: cli_util - url: "https://pub.dartlang.org" + sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c" + url: "https://pub.dev" source: hosted version: "0.3.5" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" code_builder: dependency: transitive description: name: code_builder - url: "https://pub.dartlang.org" + sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + url: "https://pub.dev" source: hosted version: "4.4.0" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" colorize: dependency: transitive description: name: colorize - url: "https://pub.dartlang.org" + sha256: "584746cd6ba1cba0633b6720f494fe6f9601c4170f0666c1579d2aa2a61071ba" + url: "https://pub.dev" source: hosted version: "3.0.0" contextmenu: dependency: "direct main" description: name: contextmenu - url: "https://pub.dartlang.org" + sha256: e0c7d60e2fc9f316f5b03f5fe2c0f977d65125345d1a1f77eea02be612e32d0c + url: "https://pub.dev" source: hosted version: "3.0.0" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.1" cross_file: dependency: transitive description: name: cross_file - url: "https://pub.dartlang.org" + sha256: f71079978789bc2fe78d79227f1f8cfe195b31bbd8db2399b0d15a4b96fb843b + url: "https://pub.dev" source: hosted version: "0.3.3+2" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" source: hosted version: "3.0.2" csslib: dependency: transitive description: name: csslib - url: "https://pub.dartlang.org" + sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745 + url: "https://pub.dev" source: hosted version: "0.17.2" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" source: hosted version: "1.0.5" dart_style: dependency: transitive description: name: dart_style - url: "https://pub.dartlang.org" + sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" + url: "https://pub.dev" source: hosted version: "2.2.4" dash_chat_2: dependency: "direct main" description: name: dash_chat_2 - url: "https://pub.dartlang.org" + sha256: "7ffdeb023fb2c9e194e2147ef8e967d36e4481493178051ceb36d98c62396ddd" + url: "https://pub.dev" source: hosted version: "0.0.15" debounce_throttle: dependency: "direct main" description: name: debounce_throttle - url: "https://pub.dartlang.org" + sha256: c95cf47afda975fc507794a52040a16756fb2f31ad3027d4e691c41862ff5692 + url: "https://pub.dev" source: hosted version: "2.0.0" desktop_drop: dependency: "direct main" description: name: desktop_drop - url: "https://pub.dartlang.org" + sha256: "0cd056191b701a2b5ba040f2306349e461fafdaa5df4569b2228cdf87b58eced" + url: "https://pub.dev" source: hosted version: "0.3.3" desktop_multi_window: dependency: "direct main" description: path: "." - ref: "057e6eb1bc7dcbcf9dafd1384274a611e4fe7124" - resolved-ref: "057e6eb1bc7dcbcf9dafd1384274a611e4fe7124" + ref: bc8604a88e52b2b6e64d2661ae49a71450a47af8 + resolved-ref: bc8604a88e52b2b6e64d2661ae49a71450a47af8 url: "https://github.com/Kingtous/rustdesk_desktop_multi_window" source: git version: "0.1.0" @@ -294,98 +334,112 @@ packages: dependency: "direct main" description: name: device_info_plus - url: "https://pub.dartlang.org" + sha256: b809c4ed5f7fcdb325ccc70b80ad934677dc4e2aa414bf46859a42bfdfafcbb6 + url: "https://pub.dev" source: hosted version: "4.1.3" device_info_plus_linux: dependency: transitive description: name: device_info_plus_linux - url: "https://pub.dartlang.org" + sha256: "77a8b3c4af06bc46507f89304d9f49dfc64b4ae004b994532ed23b34adeae4b3" + url: "https://pub.dev" source: hosted version: "3.0.0" device_info_plus_macos: dependency: transitive description: name: device_info_plus_macos - url: "https://pub.dartlang.org" + sha256: "37961762fbd46d3620c7b69ca606671014db55fc1b7a11e696fd90ed2e8fe03d" + url: "https://pub.dev" source: hosted version: "3.0.0" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface - url: "https://pub.dartlang.org" + sha256: "83fdba24fcf6846d3b10f10dfdc8b6c6d7ada5f8ed21d62ea2909c2dfa043773" + url: "https://pub.dev" source: hosted version: "3.0.0" device_info_plus_web: dependency: transitive description: name: device_info_plus_web - url: "https://pub.dartlang.org" + sha256: "5890f6094df108181c7a29720bc23d0fd6159f17d82787fac093d1fefcaf6325" + url: "https://pub.dev" source: hosted version: "3.0.0" device_info_plus_windows: dependency: transitive description: name: device_info_plus_windows - url: "https://pub.dartlang.org" + sha256: "23a2874af0e23ee6e3a2a0ebcecec3a9da13241f2cb93a93a44c8764df123dd7" + url: "https://pub.dev" source: hosted version: "4.1.0" draggable_float_widget: dependency: "direct main" description: name: draggable_float_widget - url: "https://pub.dartlang.org" + sha256: f3b291b335b7f7c7b721a6f42aeb6209fdfb055ea87980bff68c551b250795ea + url: "https://pub.dev" source: hosted version: "0.0.2" event_bus: dependency: transitive description: name: event_bus - url: "https://pub.dartlang.org" + sha256: "44baa799834f4c803921873e7446a2add0f3efa45e101a054b1f0ab9b95f8edc" + url: "https://pub.dev" source: hosted version: "2.0.0" external_path: dependency: "direct main" description: name: external_path - url: "https://pub.dartlang.org" + sha256: "2095c626fbbefe70d5a4afc9b1137172a68ee2c276e51c3c1283394485bea8f4" + url: "https://pub.dev" source: hosted version: "1.0.3" ffi: dependency: "direct main" description: name: ffi - url: "https://pub.dartlang.org" + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + url: "https://pub.dev" source: hosted version: "2.0.1" ffigen: dependency: "direct dev" description: name: ffigen - url: "https://pub.dartlang.org" + sha256: "42bbfddebacef09c9a4eb2d9ef4049fa6a39edb8622b72ca69200cb6f1e3a6c0" + url: "https://pub.dev" source: hosted version: "7.2.4" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" source: hosted version: "6.1.4" file_picker: dependency: "direct main" description: name: file_picker - url: "https://pub.dartlang.org" + sha256: d090ae03df98b0247b82e5928f44d1b959867049d18d73635e2e0bc3f49542b9 + url: "https://pub.dev" source: hosted - version: "5.2.4" + version: "5.2.5" fixnum: dependency: transitive description: name: fixnum - url: "https://pub.dartlang.org" + sha256: "04be3e934c52e082558cc9ee21f42f5c1cd7a1262f4c63cd0357c08d5bba81ec" + url: "https://pub.dev" source: hosted version: "1.0.1" flutter: @@ -397,42 +451,49 @@ packages: dependency: transitive description: name: flutter_blurhash - url: "https://pub.dartlang.org" + sha256: "05001537bd3fac7644fa6558b09ec8c0a3f2eba78c0765f88912882b1331a5c6" + url: "https://pub.dev" source: hosted version: "0.7.0" flutter_breadcrumb: dependency: "direct main" description: name: flutter_breadcrumb - url: "https://pub.dartlang.org" + sha256: "1531680034def621878562ad763079933dabe9f9f5d5add5a094190edc33259b" + url: "https://pub.dev" source: hosted version: "1.0.1" flutter_cache_manager: dependency: transitive description: name: flutter_cache_manager - url: "https://pub.dartlang.org" + sha256: "32cd900555219333326a2d0653aaaf8671264c29befa65bbd9856d204a4c9fb3" + url: "https://pub.dev" source: hosted version: "3.3.0" flutter_custom_cursor: dependency: "direct main" description: name: flutter_custom_cursor - url: "https://pub.dartlang.org" + sha256: "6c5204cf6a16650355b8aa47a8402e79922c07641390a32021a1069b561909ec" + url: "https://pub.dev" source: hosted - version: "0.0.2" + version: "0.0.3" flutter_improved_scrolling: dependency: "direct main" description: - name: flutter_improved_scrolling - url: "https://pub.dartlang.org" - source: hosted + path: "." + ref: "62f09545149f320616467c306c8c5f71714a18e6" + resolved-ref: "62f09545149f320616467c306c8c5f71714a18e6" + url: "https://github.com/Kingtous/flutter_improved_scrolling" + source: git version: "0.0.3" flutter_lints: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" source: hosted version: "2.0.1" flutter_localizations: @@ -444,28 +505,32 @@ packages: dependency: transitive description: name: flutter_parsed_text - url: "https://pub.dartlang.org" + sha256: "529cf5793b7acdf16ee0f97b158d0d4ba0bf06e7121ef180abe1a5b59e32c1e2" + url: "https://pub.dev" source: hosted version: "2.2.1" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - url: "https://pub.dartlang.org" + sha256: "60fc7b78455b94e6de2333d2f95196d32cf5c22f4b0b0520a628804cb463503b" + url: "https://pub.dev" source: hosted version: "2.0.7" flutter_rust_bridge: dependency: "direct main" description: name: flutter_rust_bridge - url: "https://pub.dartlang.org" + sha256: "5aea0f3980dcd314f1890ef0d2392263817899cc15e543734b5d4dbe66b761eb" + url: "https://pub.dev" source: hosted - version: "1.61.1" + version: "1.62.0" flutter_svg: dependency: "direct main" description: name: flutter_svg - url: "https://pub.dartlang.org" + sha256: "6ff9fa12892ae074092de2fa6a9938fb21dbabfdaa2ff57dc697ff912fc8d4b2" + url: "https://pub.dev" source: hosted version: "1.1.6" flutter_web_plugins: @@ -477,427 +542,480 @@ packages: dependency: "direct dev" description: name: freezed - url: "https://pub.dartlang.org" + sha256: e819441678f1679b719008ff2ff0ef045d66eed9f9ec81166ca0d9b02a187454 + url: "https://pub.dev" source: hosted version: "2.3.2" freezed_annotation: dependency: "direct main" description: name: freezed_annotation - url: "https://pub.dartlang.org" + sha256: aeac15850ef1b38ee368d4c53ba9a847e900bb2c53a4db3f6881cbb3cb684338 + url: "https://pub.dev" source: hosted version: "2.2.0" frontend_server_client: dependency: transitive description: name: frontend_server_client - url: "https://pub.dartlang.org" + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" source: hosted version: "3.2.0" get: dependency: "direct main" description: name: get - url: "https://pub.dartlang.org" + sha256: "2ba20a47c8f1f233bed775ba2dd0d3ac97b4cf32fc17731b3dfc672b06b0e92a" + url: "https://pub.dev" source: hosted version: "4.6.5" glob: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + url: "https://pub.dev" source: hosted version: "2.1.1" graphs: dependency: transitive description: name: graphs - url: "https://pub.dartlang.org" + sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 + url: "https://pub.dev" source: hosted version: "2.2.0" html: dependency: transitive description: name: html - url: "https://pub.dartlang.org" + sha256: d9793e10dbe0e6c364f4c59bf3e01fb33a9b2a674bc7a1081693dba0614b6269 + url: "https://pub.dev" source: hosted version: "0.15.1" http: dependency: "direct main" description: name: http - url: "https://pub.dartlang.org" + sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + url: "https://pub.dev" source: hosted version: "0.13.5" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" source: hosted version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" source: hosted version: "4.0.2" icons_launcher: dependency: "direct dev" description: name: icons_launcher - url: "https://pub.dartlang.org" + sha256: c8e3ae1263822feafaec8a3c666ec84c2143470e1612f5481f1c875024c5f37e + url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.0.6" image: dependency: "direct main" description: name: image - url: "https://pub.dartlang.org" + sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6" + url: "https://pub.dev" source: hosted - version: "3.2.2" + version: "3.3.0" image_picker: dependency: "direct main" description: name: image_picker - url: "https://pub.dartlang.org" + sha256: f98d76672d309c8b7030c323b3394669e122d52b307d2bbd8d06bd70f5b2aabe + url: "https://pub.dev" source: hosted - version: "0.8.6" + version: "0.8.6+1" image_picker_android: dependency: transitive description: name: image_picker_android - url: "https://pub.dartlang.org" + sha256: b1cbfec0f5aef427a18eb573f5445af8c9c568626bf3388553e40c263d3f7368 + url: "https://pub.dev" source: hosted - version: "0.8.5+4" + version: "0.8.5+5" image_picker_for_web: dependency: transitive description: name: image_picker_for_web - url: "https://pub.dartlang.org" + sha256: "7d319fb74955ca46d9bf7011497860e3923bb67feebcf068f489311065863899" + url: "https://pub.dev" source: hosted version: "2.1.10" image_picker_ios: dependency: transitive description: name: image_picker_ios - url: "https://pub.dartlang.org" + sha256: "39c013200046d14c58b71dc4fa3d00e425fc9c699d589136cd3ca018727c0493" + url: "https://pub.dev" source: hosted - version: "0.8.6+3" + version: "0.8.6+6" image_picker_platform_interface: dependency: transitive description: name: image_picker_platform_interface - url: "https://pub.dartlang.org" + sha256: "7cef2f28f4f2fef99180f636c3d446b4ccbafd6ba0fad2adc9a80c4040f656b8" + url: "https://pub.dev" source: hosted version: "2.6.2" intl: dependency: transitive description: name: intl - url: "https://pub.dartlang.org" + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + url: "https://pub.dev" source: hosted version: "0.17.0" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "0.6.5" json_annotation: dependency: transitive description: name: json_annotation - url: "https://pub.dartlang.org" + sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 + url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "4.8.0" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" source: hosted version: "2.0.1" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: c94db23593b89766cda57aab9ac311e3616cf87c6fa4e9749df032f66f30dcb8 + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.14" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.1.4" + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + url: "https://pub.dev" source: hosted - version: "1.7.0" + version: "1.8.0" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" nested: dependency: transitive description: name: nested - url: "https://pub.dartlang.org" + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" source: hosted version: "1.0.0" octo_image: dependency: transitive description: name: octo_image - url: "https://pub.dartlang.org" + sha256: "107f3ed1330006a3bea63615e81cf637433f5135a52466c7caa0e7152bca9143" + url: "https://pub.dev" source: hosted version: "1.0.2" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" source: hosted version: "2.1.0" package_info_plus: dependency: "direct main" description: name: package_info_plus - url: "https://pub.dartlang.org" + sha256: f62d7253edc197fe3c88d7c2ddab82d68f555e778d55390ccc3537eca8e8d637 + url: "https://pub.dev" source: hosted version: "1.4.3+1" package_info_plus_linux: dependency: transitive description: name: package_info_plus_linux - url: "https://pub.dartlang.org" + sha256: "04b575f44233d30edbb80a94e57cad9107aada334fc02aabb42b6becd13c43fc" + url: "https://pub.dev" source: hosted version: "1.0.5" package_info_plus_macos: dependency: transitive description: name: package_info_plus_macos - url: "https://pub.dartlang.org" + sha256: a2ad8b4acf4cd479d4a0afa5a74ea3f5b1c7563b77e52cc32b3ee6956d5482a6 + url: "https://pub.dev" source: hosted version: "1.3.0" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - url: "https://pub.dartlang.org" + sha256: f7a0c8f1e7e981bc65f8b64137a53fd3c195b18d429fba960babc59a5a1c7ae8 + url: "https://pub.dev" source: hosted version: "1.0.2" package_info_plus_web: dependency: transitive description: name: package_info_plus_web - url: "https://pub.dartlang.org" + sha256: f0829327eb534789e0a16ccac8936a80beed4e2401c4d3a74f3f39094a822d3b + url: "https://pub.dev" source: hosted version: "1.0.6" package_info_plus_windows: dependency: transitive description: name: package_info_plus_windows - url: "https://pub.dartlang.org" + sha256: "79524f11c42dd9078b96d797b3cf79c0a2883a50c4920dc43da8562c115089bc" + url: "https://pub.dev" source: hosted version: "2.1.0" password_strength: dependency: "direct main" description: name: password_strength - url: "https://pub.dartlang.org" + sha256: "0e51e3d864e37873a1347e658147f88b66e141ee36c58e19828dc5637961e1ce" + url: "https://pub.dev" source: hosted version: "0.2.0" path: dependency: "direct main" description: name: path - url: "https://pub.dartlang.org" + sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + url: "https://pub.dev" source: hosted - version: "1.8.1" + version: "1.8.2" path_drawing: dependency: transitive description: name: path_drawing - url: "https://pub.dartlang.org" + sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 + url: "https://pub.dev" source: hosted version: "1.0.1" path_parsing: dependency: transitive description: name: path_parsing - url: "https://pub.dartlang.org" + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" source: hosted version: "1.0.1" path_provider: dependency: "direct main" description: name: path_provider - url: "https://pub.dartlang.org" + sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + url: "https://pub.dev" source: hosted - version: "2.0.11" + version: "2.0.12" path_provider_android: dependency: transitive description: name: path_provider_android - url: "https://pub.dartlang.org" + sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + url: "https://pub.dev" source: hosted version: "2.0.22" - path_provider_ios: + path_provider_foundation: dependency: transitive description: - name: path_provider_ios - url: "https://pub.dartlang.org" + name: path_provider_foundation + sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + url: "https://pub.dev" source: hosted - version: "2.0.11" + version: "2.1.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.dartlang.org" + sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + url: "https://pub.dev" source: hosted version: "2.1.7" - path_provider_macos: - dependency: transitive - description: - name: path_provider_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.6" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dartlang.org" + sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + url: "https://pub.dev" source: hosted version: "2.0.5" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dartlang.org" + sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + url: "https://pub.dev" source: hosted version: "2.1.3" pedantic: dependency: transitive description: name: pedantic - url: "https://pub.dartlang.org" + sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" + url: "https://pub.dev" source: hosted version: "1.11.1" petitparser: dependency: transitive description: name: petitparser - url: "https://pub.dartlang.org" + sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "5.1.0" platform: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" source: hosted version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + url: "https://pub.dev" source: hosted version: "2.1.3" pointycastle: dependency: transitive description: name: pointycastle - url: "https://pub.dartlang.org" + sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 + url: "https://pub.dev" source: hosted version: "3.6.2" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" source: hosted version: "1.5.1" process: dependency: transitive description: name: process - url: "https://pub.dartlang.org" + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" source: hosted version: "4.2.4" provider: dependency: "direct main" description: name: provider - url: "https://pub.dartlang.org" + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + url: "https://pub.dev" source: hosted version: "6.0.5" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + url: "https://pub.dev" source: hosted version: "2.1.3" pubspec_parse: dependency: transitive description: name: pubspec_parse - url: "https://pub.dartlang.org" + sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a" + url: "https://pub.dev" source: hosted version: "1.2.1" puppeteer: dependency: transitive description: name: puppeteer - url: "https://pub.dartlang.org" + sha256: "4e235aaf9a338a45c9eb1ee38956e0ba369867bf144d7a27fdaf245409b2b87b" + url: "https://pub.dev" source: hosted - version: "2.12.0" + version: "2.21.0" qr_code_scanner: dependency: "direct main" description: name: qr_code_scanner - url: "https://pub.dartlang.org" + sha256: f23b68d893505a424f0bd2e324ebea71ed88465d572d26bb8d2e78a4749591fd + url: "https://pub.dev" source: hosted version: "1.0.1" quiver: dependency: transitive description: name: quiver - url: "https://pub.dartlang.org" + sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + url: "https://pub.dev" source: hosted version: "3.2.1" rxdart: dependency: transitive description: name: rxdart - url: "https://pub.dartlang.org" + sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + url: "https://pub.dev" source: hosted version: "0.27.7" screen_retriever: @@ -913,42 +1031,48 @@ packages: dependency: "direct main" description: name: scroll_pos - url: "https://pub.dartlang.org" + sha256: cfca311b6b8d51538ff90e206fbe6ce3b36e7125ea6da4a40eb626c7f9f083b1 + url: "https://pub.dev" source: hosted version: "0.3.0" settings_ui: dependency: "direct main" description: name: settings_ui - url: "https://pub.dartlang.org" + sha256: d9838037cb554b24b4218b2d07666fbada3478882edefae375ee892b6c820ef3 + url: "https://pub.dev" source: hosted version: "2.0.2" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + url: "https://pub.dev" source: hosted version: "1.4.0" shelf_static: dependency: transitive description: name: shelf_static - url: "https://pub.dartlang.org" + sha256: e792b76b96a36d4a41b819da593aff4bdd413576b3ba6150df5d8d9996d2e74c + url: "https://pub.dev" source: hosted version: "1.1.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + url: "https://pub.dev" source: hosted version: "1.0.3" simple_observable: dependency: transitive description: name: simple_observable - url: "https://pub.dartlang.org" + sha256: b392795c48f8b5f301b4c8f73e15f56e38fe70f42278c649d8325e859a783301 + url: "https://pub.dev" source: hosted version: "2.0.0" sky_engine: @@ -960,308 +1084,352 @@ packages: dependency: transitive description: name: source_gen - url: "https://pub.dartlang.org" + sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d" + url: "https://pub.dev" source: hosted version: "1.2.6" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted version: "1.9.1" sqflite: dependency: transitive description: name: sqflite - url: "https://pub.dartlang.org" + sha256: "78324387dc81df14f78df06019175a86a2ee0437624166c382e145d0a7fd9a4f" + url: "https://pub.dev" source: hosted - version: "2.0.3+1" + version: "2.2.4+1" sqflite_common: dependency: transitive description: name: sqflite_common - url: "https://pub.dartlang.org" + sha256: bfd6973aaeeb93475bc0d875ac9aefddf7965ef22ce09790eb963992ffc5183f + url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.2+2" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted version: "2.1.1" stream_transform: dependency: transitive description: name: stream_transform - url: "https://pub.dartlang.org" + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" source: hosted version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" synchronized: dependency: transitive description: name: synchronized - url: "https://pub.dartlang.org" + sha256: "33b31b6beb98100bf9add464a36a8dd03eb10c7a8cf15aeec535e9b054aaf04b" + url: "https://pub.dev" source: hosted - version: "3.0.0+3" + version: "3.0.1" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" timing: dependency: transitive description: name: timing - url: "https://pub.dartlang.org" + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.1" toggle_switch: dependency: "direct main" description: name: toggle_switch - url: "https://pub.dartlang.org" + sha256: "3814548f25ee11f88d3b1905e2e7c8e47e4a406752f553ed287f6d86a2dcf91d" + url: "https://pub.dev" source: hosted version: "1.4.0" tuple: dependency: "direct main" description: name: tuple - url: "https://pub.dartlang.org" + sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa" + url: "https://pub.dev" source: hosted version: "2.0.1" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" source: hosted version: "1.3.1" uni_links: dependency: "direct main" description: name: uni_links - url: "https://pub.dartlang.org" + sha256: "051098acfc9e26a9fde03b487bef5d3d228ca8f67693480c6f33fd4fbb8e2b6e" + url: "https://pub.dev" source: hosted version: "0.5.1" uni_links_desktop: dependency: "direct main" description: name: uni_links_desktop - url: "https://pub.dartlang.org" + sha256: "205484c01890259b56d9271bcf299adf9889e881616c976f13061e29e94bb9f0" + url: "https://pub.dev" source: hosted version: "0.1.4" uni_links_platform_interface: dependency: transitive description: name: uni_links_platform_interface - url: "https://pub.dartlang.org" + sha256: "929cf1a71b59e3b7c2d8a2605a9cf7e0b125b13bc858e55083d88c62722d4507" + url: "https://pub.dev" source: hosted version: "1.0.0" uni_links_web: dependency: transitive description: name: uni_links_web - url: "https://pub.dartlang.org" + sha256: "7539db908e25f67de2438e33cc1020b30ab94e66720b5677ba6763b25f6394df" + url: "https://pub.dev" source: hosted version: "0.1.0" universal_io: dependency: transitive description: name: universal_io - url: "https://pub.dartlang.org" + sha256: "79f78ddad839ee3aae3ec7c01eb4575faf0d5c860f8e5223bc9f9c17f7f03cef" + url: "https://pub.dev" source: hosted version: "2.0.4" url_launcher: dependency: "direct main" description: name: url_launcher - url: "https://pub.dartlang.org" + sha256: "698fa0b4392effdc73e9e184403b627362eb5fbf904483ac9defbb1c2191d809" + url: "https://pub.dev" source: hosted - version: "6.1.7" + version: "6.1.8" url_launcher_android: dependency: transitive description: name: url_launcher_android - url: "https://pub.dartlang.org" + sha256: "3e2f6dfd2c7d9cd123296cab8ef66cfc2c1a13f5845f42c7a0f365690a8a7dd1" + url: "https://pub.dev" source: hosted - version: "6.0.22" + version: "6.0.23" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - url: "https://pub.dartlang.org" + sha256: bb328b24d3bccc20bdf1024a0990ac4f869d57663660de9c936fb8c043edefe3 + url: "https://pub.dev" source: hosted - version: "6.0.17" + version: "6.0.18" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - url: "https://pub.dartlang.org" + sha256: "318c42cba924e18180c029be69caf0a1a710191b9ec49bb42b5998fdcccee3cc" + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - url: "https://pub.dartlang.org" + sha256: "41988b55570df53b3dd2a7fc90c76756a963de6a8c5f8e113330cb35992e2094" + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - url: "https://pub.dartlang.org" + sha256: "4eae912628763eb48fc214522e58e942fd16ce195407dbf45638239523c759a6" + url: "https://pub.dev" source: hosted version: "2.1.1" url_launcher_web: dependency: transitive description: name: url_launcher_web - url: "https://pub.dartlang.org" + sha256: "44d79408ce9f07052095ef1f9a693c258d6373dc3944249374e30eff7219ccb0" + url: "https://pub.dev" source: hosted - version: "2.0.13" + version: "2.0.14" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - url: "https://pub.dartlang.org" + sha256: b6217370f8eb1fd85c8890c539f5a639a01ab209a36db82c921ebeacefc7a615 + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.3" uuid: dependency: transitive description: name: uuid - url: "https://pub.dartlang.org" + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" source: hosted version: "3.0.7" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" video_player: dependency: transitive description: name: video_player - url: "https://pub.dartlang.org" + sha256: "59f7f31c919c59cbedd37c617317045f5f650dc0eeb568b0b0de9a36472bdb28" + url: "https://pub.dev" source: hosted - version: "2.4.10" + version: "2.5.1" video_player_android: dependency: transitive description: name: video_player_android - url: "https://pub.dartlang.org" + sha256: "984388511230bac63feb53b2911a70e829fe0976b6b2213f5c579c4e0a882db3" + url: "https://pub.dev" source: hosted version: "2.3.10" video_player_avfoundation: dependency: transitive description: name: video_player_avfoundation - url: "https://pub.dartlang.org" + sha256: d9f7a46d6a77680adb03ec05a381025d6e890ebe636637c6c3014cc3926b97e9 + url: "https://pub.dev" source: hosted version: "2.3.8" video_player_platform_interface: dependency: transitive description: name: video_player_platform_interface - url: "https://pub.dartlang.org" + sha256: "42bb75de5e9b79e1f20f1d95f688fac0f95beac4d89c6eb2cd421724d4432dae" + url: "https://pub.dev" source: hosted version: "6.0.1" video_player_web: dependency: transitive description: name: video_player_web - url: "https://pub.dartlang.org" + sha256: b649b07b8f8f553bee4a97a0a53d0fe78a70b115eafaf0105b612b32b05ddb99 + url: "https://pub.dev" source: hosted version: "2.0.13" visibility_detector: dependency: "direct main" description: name: visibility_detector - url: "https://pub.dartlang.org" + sha256: "15c54a459ec2c17b4705450483f3d5a2858e733aee893dcee9d75fd04814940d" + url: "https://pub.dev" source: hosted version: "0.3.3" wakelock: dependency: "direct main" description: name: wakelock - url: "https://pub.dartlang.org" + sha256: "769ecf42eb2d07128407b50cb93d7c10bd2ee48f0276ef0119db1d25cc2f87db" + url: "https://pub.dev" source: hosted version: "0.6.2" wakelock_macos: dependency: transitive description: name: wakelock_macos - url: "https://pub.dartlang.org" + sha256: "047c6be2f88cb6b76d02553bca5a3a3b95323b15d30867eca53a19a0a319d4cd" + url: "https://pub.dev" source: hosted version: "0.4.0" wakelock_platform_interface: dependency: transitive description: name: wakelock_platform_interface - url: "https://pub.dartlang.org" + sha256: "1f4aeb81fb592b863da83d2d0f7b8196067451e4df91046c26b54a403f9de621" + url: "https://pub.dev" source: hosted version: "0.3.0" wakelock_web: dependency: transitive description: name: wakelock_web - url: "https://pub.dartlang.org" + sha256: "1b256b811ee3f0834888efddfe03da8d18d0819317f20f6193e2922b41a501b5" + url: "https://pub.dev" source: hosted version: "0.4.0" wakelock_windows: dependency: transitive description: name: wakelock_windows - url: "https://pub.dartlang.org" + sha256: "857f77b3fe6ae82dd045455baa626bc4b93cb9bb6c86bf3f27c182167c3a5567" + url: "https://pub.dev" source: hosted version: "0.2.1" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + url: "https://pub.dev" source: hosted version: "1.0.2" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" win32: dependency: "direct main" description: name: win32 - url: "https://pub.dartlang.org" + sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 + url: "https://pub.dev" source: hosted version: "3.1.3" win32_registry: dependency: transitive description: name: win32_registry - url: "https://pub.dartlang.org" + sha256: "66e78552f17501aced68fe77425b13156998f1bd3d58f1cd8cd0af2dbe4520e3" + url: "https://pub.dev" source: hosted version: "1.0.2" window_manager: @@ -1286,37 +1454,42 @@ packages: dependency: transitive description: name: xdg_directories - url: "https://pub.dartlang.org" + sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + url: "https://pub.dev" source: hosted - version: "0.2.0+2" + version: "0.2.0+3" xml: dependency: transitive description: name: xml - url: "https://pub.dartlang.org" + sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.2.2" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + url: "https://pub.dev" source: hosted version: "3.1.1" yaml_edit: dependency: transitive description: name: yaml_edit - url: "https://pub.dartlang.org" + sha256: "4240d1b19841b8af5786121e4e357735cc2a8ffb19176bff5769d73c34e2a8a5" + url: "https://pub.dev" source: hosted version: "2.0.3" zxing2: dependency: "direct main" description: name: zxing2 - url: "https://pub.dartlang.org" + sha256: "1913c33844c68b62573741134ef5f987f1e15e331c95ac7dc327afbb9896e9ec" + url: "https://pub.dev" source: hosted - version: "0.1.0" + version: "0.1.1" sdks: - dart: ">=2.17.1 <3.0.0" - flutter: ">=3.0.0" + dart: ">=2.18.0 <4.0.0" + flutter: ">=3.3.0" diff --git a/src/core_main.rs b/src/core_main.rs index 8658b736c..d5b56bc1f 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -247,8 +247,6 @@ pub fn core_main() -> Option> { #[cfg(feature = "flutter")] crate::flutter::connection_manager::start_listen_ipc_thread(); crate::ui_interface::start_option_status_sync(); - #[cfg(target_os = "macos")] - crate::platform::macos::hide_dock(); } } //_async_logger_holder.map(|x| x.flush()); diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index ebaa160f1..c2ae2b6b0 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -1241,6 +1241,12 @@ pub fn main_is_login_wayland() -> SyncReturn { SyncReturn(is_login_wayland()) } +pub fn main_hide_docker() -> SyncReturn { + #[cfg(target_os = "macos")] + crate::platform::macos::hide_dock(); + SyncReturn(true) +} + #[cfg(target_os = "android")] pub mod server_side { use jni::{ From 20003841d080de149ca96a798d99d8719e5d0458 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Wed, 1 Feb 2023 17:36:05 +0800 Subject: [PATCH 41/83] bind.mainHideDocker must be put in windowManager.waitUntilReadyToShow --- flutter/lib/main.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index 53ae2f5dd..ff7a72124 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -88,7 +88,6 @@ Future main(List args) async { debugPrint("--cm started"); desktopType = DesktopType.cm; await windowManager.ensureInitialized(); - bind.mainHideDocker(); runConnectionManagerScreen(args.contains('--hide')); } else if (args.contains('--install')) { runInstallPage(); @@ -224,6 +223,7 @@ void showCmWindow() { WindowOptions windowOptions = getHiddenTitleBarWindowOptions(size: kConnectionManagerWindowSize); windowManager.waitUntilReadyToShow(windowOptions, () async { + bind.mainHideDocker(); await windowManager.show(); await Future.wait([windowManager.focus(), windowManager.setOpacity(1)]); // ensure initial window size to be changed @@ -237,6 +237,7 @@ void hideCmWindow() { getHiddenTitleBarWindowOptions(size: kConnectionManagerWindowSize); windowManager.setOpacity(0); windowManager.waitUntilReadyToShow(windowOptions, () async { + bind.mainHideDocker(); await windowManager.hide(); }); } From 2e53580caaf069e4e044b03d45331ab6ddfe2ce6 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Wed, 1 Feb 2023 19:36:36 +0800 Subject: [PATCH 42/83] beautify quality monitor --- flutter/lib/common/widgets/overlay.dart | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/flutter/lib/common/widgets/overlay.dart b/flutter/lib/common/widgets/overlay.dart index aaf52fb07..4b4172ffd 100644 --- a/flutter/lib/common/widgets/overlay.dart +++ b/flutter/lib/common/widgets/overlay.dart @@ -320,20 +320,21 @@ class QualityMonitor extends StatelessWidget { final QualityMonitorModel qualityMonitorModel; QualityMonitor(this.qualityMonitorModel); - Widget _row(String info, String? value) { + Widget _row(String info, String? value, {Color? rightColor}) { return Row( children: [ Expanded( flex: 8, child: AutoSizeText(info, - style: TextStyle(color: MyTheme.grayBg), + style: TextStyle(color: MyTheme.darkGray), textAlign: TextAlign.right, maxLines: 1)), Spacer(flex: 1), Expanded( flex: 8, child: AutoSizeText(value ?? '', - style: TextStyle(color: MyTheme.grayBg), maxLines: 1)), + style: TextStyle(color: rightColor ?? Colors.white), + maxLines: 1)), ], ); } @@ -351,13 +352,15 @@ class QualityMonitor extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _row("Speed", qualityMonitorModel.data.speed ?? ''), - _row("FPS", qualityMonitorModel.data.fps ?? ''), + _row("Speed", qualityMonitorModel.data.speed ?? '-'), + _row("FPS", qualityMonitorModel.data.fps ?? '-'), _row( - "Delay", "${qualityMonitorModel.data.delay ?? ''}ms"), + "Delay", "${qualityMonitorModel.data.delay ?? '-'}ms", + rightColor: Colors.green), _row("Target Bitrate", - "${qualityMonitorModel.data.targetBitrate ?? ''}kb"), - _row("Codec", qualityMonitorModel.data.codecFormat ?? ''), + "${qualityMonitorModel.data.targetBitrate ?? '-'}kb"), + _row( + "Codec", qualityMonitorModel.data.codecFormat ?? '-'), ], ), ) From 6f95c38f854ed95536843aeeef84791ef29ae216 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Wed, 1 Feb 2023 20:36:14 +0800 Subject: [PATCH 43/83] chore: remove useless code --- src/core_main.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/core_main.rs b/src/core_main.rs index d5b56bc1f..b34047f86 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -290,10 +290,6 @@ fn import_config(path: &str) { /// If it returns [`Some`], then the process will continue, and flutter gui will be started. #[cfg(feature = "flutter")] fn core_main_invoke_new_connection(mut args: std::env::Args) -> Option> { - args.position(|element| { - return element == "--connect"; - }) - .unwrap(); let peer_id = args.next().unwrap_or("".to_string()); if peer_id.is_empty() { eprintln!("please provide a valid peer id"); From fdfda2a982c68d5d7e889a1d29b6b12f78235f9a Mon Sep 17 00:00:00 2001 From: rustdesk Date: Wed, 1 Feb 2023 20:40:09 +0800 Subject: [PATCH 44/83] chore: revert last commit and change unwrap to ? --- src/core_main.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core_main.rs b/src/core_main.rs index b34047f86..714502e85 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -290,6 +290,9 @@ fn import_config(path: &str) { /// If it returns [`Some`], then the process will continue, and flutter gui will be started. #[cfg(feature = "flutter")] fn core_main_invoke_new_connection(mut args: std::env::Args) -> Option> { + args.position(|element| { + return element == "--connect"; + })?; let peer_id = args.next().unwrap_or("".to_string()); if peer_id.is_empty() { eprintln!("please provide a valid peer id"); From 68cc667f475ee66c445fe66380c98c4ef9f9d934 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Wed, 1 Feb 2023 21:28:26 +0800 Subject: [PATCH 45/83] partially fix issue #2747: text selectable, more top margin of buttons on dialog --- flutter/lib/common.dart | 3 ++- flutter/lib/common/widgets/chat_page.dart | 3 ++- .../lib/desktop/pages/desktop_setting_page.dart | 15 +++++++++------ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index cf7de0fa2..ee7353c12 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -707,7 +707,8 @@ void msgBox(String id, String type, String title, String text, String link, dialogManager.show( (setState, close) => CustomAlertDialog( title: null, - content: msgboxContent(type, title, text), + content: SelectionArea( + child: msgboxContent(type, title, text).paddingOnly(bottom: 10)), actions: buttons, onSubmit: hasOk ? submit : null, onCancel: hasCancel == true ? cancel : null, diff --git a/flutter/lib/common/widgets/chat_page.dart b/flutter/lib/common/widgets/chat_page.dart index 510ce1f73..d1d96199a 100644 --- a/flutter/lib/common/widgets/chat_page.dart +++ b/flutter/lib/common/widgets/chat_page.dart @@ -51,7 +51,7 @@ class ChatPage extends StatelessWidget implements PageShape { return Stack( children: [ LayoutBuilder(builder: (context, constraints) { - return DashChat( + final chat = DashChat( onSend: (chatMsg) { chatModel.send(chatMsg); chatModel.inputNode.requestFocus(); @@ -108,6 +108,7 @@ class ChatPage extends StatelessWidget implements PageShape { borderBottomLeft: 8, )), ); + return SelectionArea(child: chat); }), desktopType == DesktopType.cm || chatModel.currentID == ChatModel.clientModeID diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index df87a0ead..06300cda4 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -1113,10 +1113,12 @@ class _AboutState extends State<_About> { const SizedBox( height: 8.0, ), - Text('${translate('Version')}: $version') - .marginSymmetric(vertical: 4.0), - Text('${translate('Build Date')}: $buildDate') - .marginSymmetric(vertical: 4.0), + SelectionArea( + child: Text('${translate('Version')}: $version') + .marginSymmetric(vertical: 4.0)), + SelectionArea( + child: Text('${translate('Build Date')}: $buildDate') + .marginSymmetric(vertical: 4.0)), InkWell( onTap: () { launchUrlString('https://rustdesk.com/privacy'); @@ -1137,7 +1139,8 @@ class _AboutState extends State<_About> { decoration: const BoxDecoration(color: Color(0xFF2c8cff)), padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 8), - child: Row( + child: SelectionArea( + child: Row( children: [ Expanded( child: Column( @@ -1157,7 +1160,7 @@ class _AboutState extends State<_About> { ), ), ], - ), + )), ).marginSymmetric(vertical: 4.0) ], ).marginOnly(left: _kContentHMargin) From a9f2144638db5b1c9736fbc63928b9bec55b7b84 Mon Sep 17 00:00:00 2001 From: "Miguel F. G" <116861809+flusheDData@users.noreply.github.com> Date: Wed, 1 Feb 2023 15:42:28 +0100 Subject: [PATCH 46/83] Update es.rs new term added --- src/lang/es.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/es.rs b/src/lang/es.rs index 8f4275d5d..3848d1925 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -435,6 +435,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Strong", "Fuerte"), ("Switch Sides", "Intercambiar lados"), ("Please confirm if you want to share your desktop?", "Por favor, confirma si quieres compartir tu escritorio"), - ("Closed as expected", ""), + ("Closed as expected", "Cerrado como se esperaba"), ].iter().cloned().collect(); } From 8d60bcd51a503a06e3c9e95b716d8be5dbd06a28 Mon Sep 17 00:00:00 2001 From: 21pages Date: Wed, 1 Feb 2023 19:49:41 +0800 Subject: [PATCH 47/83] remove useless empty --switch_uuid Signed-off-by: 21pages --- flutter/lib/utils/multi_window_manager.dart | 9 ++++++--- src/core_main.rs | 8 ++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/flutter/lib/utils/multi_window_manager.dart b/flutter/lib/utils/multi_window_manager.dart index 224052bff..550e9ab08 100644 --- a/flutter/lib/utils/multi_window_manager.dart +++ b/flutter/lib/utils/multi_window_manager.dart @@ -43,11 +43,14 @@ class RustDeskMultiWindowManager { Future newRemoteDesktop(String remoteId, {String? switch_uuid}) async { - final msg = jsonEncode({ + var params = { "type": WindowType.RemoteDesktop.index, "id": remoteId, - "switch_uuid": switch_uuid ?? "" - }); + }; + if (switch_uuid != null) { + params['switch_uuid'] = switch_uuid; + } + final msg = jsonEncode(params); try { final ids = await DesktopMultiWindow.getAllSubWindowIds(); diff --git a/src/core_main.rs b/src/core_main.rs index 714502e85..89a962f1d 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -304,9 +304,13 @@ fn core_main_invoke_new_connection(mut args: std::env::Args) -> Option Date: Wed, 1 Feb 2023 19:56:57 +0800 Subject: [PATCH 48/83] default display settings Signed-off-by: 21pages --- .../desktop/pages/desktop_setting_page.dart | 215 +++++++++++++++++- .../lib/desktop/widgets/remote_menubar.dart | 44 ++-- libs/hbb_common/src/config.rs | 107 ++++++++- src/flutter_ffi.rs | 8 + src/lang/ca.rs | 10 +- src/lang/cn.rs | 8 + src/lang/cs.rs | 8 + src/lang/da.rs | 8 + src/lang/de.rs | 8 + src/lang/eo.rs | 10 +- src/lang/es.rs | 10 +- src/lang/fa.rs | 10 +- src/lang/fr.rs | 10 +- src/lang/gr.rs | 10 +- src/lang/hu.rs | 8 + src/lang/id.rs | 10 +- src/lang/it.rs | 10 +- src/lang/ja.rs | 10 +- src/lang/ko.rs | 10 +- src/lang/kz.rs | 10 +- src/lang/pl.rs | 10 +- src/lang/pt_PT.rs | 10 +- src/lang/ptbr.rs | 10 +- src/lang/ro.rs | 11 + src/lang/ru.rs | 10 +- src/lang/sk.rs | 10 +- src/lang/sl.rs | 10 +- src/lang/sq.rs | 10 +- src/lang/sr.rs | 10 +- src/lang/sv.rs | 10 +- src/lang/template.rs | 10 +- src/lang/th.rs | 10 +- src/lang/tr.rs | 10 +- src/lang/tw.rs | 10 +- src/lang/ua.rs | 10 +- src/lang/vn.rs | 10 +- src/ui_interface.rs | 12 + 37 files changed, 643 insertions(+), 54 deletions(-) diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 06300cda4..e4a7e1a25 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -33,6 +33,7 @@ const double _kContentFontSize = 15; const Color _accentColor = MyTheme.accent; const String _kSettingPageControllerTag = 'settingPageController'; const String _kSettingPageIndexTag = 'settingPageIndex'; +const int _kPageCount = 6; class _TabInfo { late final String label; @@ -51,7 +52,7 @@ class DesktopSettingPage extends StatefulWidget { State createState() => _DesktopSettingPageState(); static void switch2page(int page) { - if (page >= 5) return; + if (page >= _kPageCount) return; try { if (Get.isRegistered(tag: _kSettingPageControllerTag)) { DesktopTabPage.onAddSetting(initialPage: page); @@ -75,6 +76,7 @@ class _DesktopSettingPageState extends State _TabInfo('Security', Icons.enhanced_encryption_outlined, Icons.enhanced_encryption), _TabInfo('Network', Icons.link_outlined, Icons.link), + _TabInfo('Display', Icons.desktop_windows_outlined, Icons.desktop_windows), _TabInfo('Account', Icons.person_outline, Icons.person), _TabInfo('About', Icons.info_outline, Icons.info) ]; @@ -88,7 +90,8 @@ class _DesktopSettingPageState extends State @override void initState() { super.initState(); - selectedIndex = (widget.initialPage < 5 ? widget.initialPage : 0).obs; + selectedIndex = + (widget.initialPage < _kPageCount ? widget.initialPage : 0).obs; Get.put(selectedIndex, tag: _kSettingPageIndexTag); controller = PageController(initialPage: widget.initialPage); Get.put(controller, tag: _kSettingPageControllerTag); @@ -130,6 +133,7 @@ class _DesktopSettingPageState extends State _General(), _Safety(), _Network(), + _Display(), _Account(), _About(), ], @@ -1047,6 +1051,213 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin { } } +class _Display extends StatefulWidget { + const _Display({Key? key}) : super(key: key); + + @override + State<_Display> createState() => _DisplayState(); +} + +class _DisplayState extends State<_Display> { + @override + Widget build(BuildContext context) { + final scrollController = ScrollController(); + return DesktopScrollWrapper( + scrollController: scrollController, + child: ListView( + controller: scrollController, + physics: NeverScrollableScrollPhysics(), + children: [ + viewStyle(context), + scrollStyle(context), + imageQuality(context), + codec(context), + ]).marginOnly(bottom: _kListViewBottomMargin)); + } + + Widget viewStyle(BuildContext context) { + final key = 'view_style'; + onChanged(String value) async { + await bind.mainSetUserDefaultOption(key: key, value: value); + setState(() {}); + } + + final groupValue = bind.mainGetUserDefaultOption(key: key); + return _Card(title: 'Default View Style', children: [ + _Radio(context, + value: kRemoteViewStyleOriginal, + groupValue: groupValue, + label: 'Scale original', + onChanged: onChanged), + _Radio(context, + value: kRemoteViewStyleAdaptive, + groupValue: groupValue, + label: 'Scale adaptive', + onChanged: onChanged), + ]); + } + + Widget scrollStyle(BuildContext context) { + final key = 'scroll_style'; + onChanged(String value) async { + await bind.mainSetUserDefaultOption(key: key, value: value); + setState(() {}); + } + + final groupValue = bind.mainGetUserDefaultOption(key: key); + return _Card(title: 'Default Scroll Style', children: [ + _Radio(context, + value: kRemoteScrollStyleAuto, + groupValue: groupValue, + label: 'ScrollAuto', + onChanged: onChanged), + _Radio(context, + value: kRemoteScrollStyleBar, + groupValue: groupValue, + label: 'Scrollbar', + onChanged: onChanged), + ]); + } + + Widget imageQuality(BuildContext context) { + final key = 'image_quality'; + onChanged(String value) async { + await bind.mainSetUserDefaultOption(key: key, value: value); + setState(() {}); + } + + final groupValue = bind.mainGetUserDefaultOption(key: key); + final qualityKey = 'custom_image_quality'; + final qualityValue = + (double.tryParse(bind.mainGetUserDefaultOption(key: qualityKey)) ?? + 50.0) + .obs; + final fpsKey = 'custom-fps'; + final fpsValue = + (double.tryParse(bind.mainGetUserDefaultOption(key: fpsKey)) ?? 30.0) + .obs; + return _Card(title: 'Default Image Quality', children: [ + _Radio(context, + value: kRemoteImageQualityBest, + groupValue: groupValue, + label: 'Good image quality', + onChanged: onChanged), + _Radio(context, + value: kRemoteImageQualityBalanced, + groupValue: groupValue, + label: 'Balanced', + onChanged: onChanged), + _Radio(context, + value: kRemoteImageQualityLow, + groupValue: groupValue, + label: 'Optimize reaction time', + onChanged: onChanged), + _Radio(context, + value: kRemoteImageQualityCustom, + groupValue: groupValue, + label: 'Custom', + onChanged: onChanged), + Offstage( + offstage: groupValue != kRemoteImageQualityCustom, + child: Column( + children: [ + Obx(() => Row( + children: [ + Slider( + value: qualityValue.value, + min: 10.0, + max: 100.0, + divisions: 18, + onChanged: (double value) async { + qualityValue.value = value; + await bind.mainSetUserDefaultOption( + key: qualityKey, value: value.toString()); + }, + ), + SizedBox( + width: 40, + child: Text( + '${qualityValue.value.round()}%', + style: const TextStyle(fontSize: 15), + )), + SizedBox( + width: 50, + child: Text( + translate('Bitrate'), + style: const TextStyle(fontSize: 15), + )) + ], + )), + Obx(() => Row( + children: [ + Slider( + value: fpsValue.value, + min: 10.0, + max: 120.0, + divisions: 22, + onChanged: (double value) async { + fpsValue.value = value; + await bind.mainSetUserDefaultOption( + key: fpsKey, value: value.toString()); + }, + ), + SizedBox( + width: 40, + child: Text( + '${fpsValue.value.round()}', + style: const TextStyle(fontSize: 15), + )), + SizedBox( + width: 50, + child: Text( + translate('FPS'), + style: const TextStyle(fontSize: 15), + )) + ], + )), + ], + ), + ) + ]); + } + + Widget codec(BuildContext context) { + if (!bind.mainHasHwcodec()) { + return Offstage(); + } + final key = 'codec-preference'; + onChanged(String value) async { + await bind.mainSetUserDefaultOption(key: key, value: value); + setState(() {}); + } + + final groupValue = bind.mainGetUserDefaultOption(key: key); + + return _Card(title: 'Default Codec', children: [ + _Radio(context, + value: 'auto', + groupValue: groupValue, + label: 'Auto', + onChanged: onChanged), + _Radio(context, + value: 'vp9', + groupValue: groupValue, + label: 'VP9', + onChanged: onChanged), + _Radio(context, + value: 'h264', + groupValue: groupValue, + label: 'H264', + onChanged: onChanged), + _Radio(context, + value: 'h265', + groupValue: groupValue, + label: 'H265', + onChanged: onChanged), + ]); + } +} + class _Account extends StatefulWidget { const _Account({Key? key}) : super(key: key); diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 517dc9750..64d289fcc 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -867,18 +867,24 @@ class _RemoteMenubarState extends State { value: qualitySliderValue.value, min: qualityMinValue, max: qualityMaxValue, - divisions: 90, + divisions: 18, onChanged: (double value) { qualitySliderValue.value = value; debouncerQuality.value = value; }, ), SizedBox( - width: 90, - child: Obx(() => Text( - '${qualitySliderValue.value.round()}% Bitrate', - style: const TextStyle(fontSize: 15), - ))) + width: 40, + child: Text( + '${qualitySliderValue.value.round()}%', + style: const TextStyle(fontSize: 15), + )), + SizedBox( + width: 50, + child: Text( + translate('Bitrate'), + style: const TextStyle(fontSize: 15), + )) ], )); // fps @@ -919,20 +925,17 @@ class _RemoteMenubarState extends State { }, ))), SizedBox( - width: 90, - child: Obx(() { - final fps = fpsSliderValue.value.round(); - String text; - if (fps < 100) { - text = '$fps FPS'; - } else { - text = '$fps FPS'; - } - return Text( - text, - style: const TextStyle(fontSize: 15), - ); - })) + width: 40, + child: Obx(() => Text( + '${fpsSliderValue.value.round()}', + style: const TextStyle(fontSize: 15), + ))), + SizedBox( + width: 50, + child: Text( + translate('FPS'), + style: const TextStyle(fontSize: 15), + )) ], ), ); @@ -1111,6 +1114,7 @@ class _RemoteMenubarState extends State { )); } } + displayMenu.add(MenuEntryDivider()); /// Show remote cursor if (!widget.ffi.canvasModel.cursorEmbedded) { diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 8bea99106..ce4be6119 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -192,7 +192,10 @@ pub struct PeerConfig { deserialize_with = "PeerConfig::deserialize_image_quality" )] pub image_quality: String, - #[serde(default)] + #[serde( + default = "PeerConfig::default_custom_image_quality", + deserialize_with = "PeerConfig::deserialize_custom_image_quality" + )] pub custom_image_quality: Vec, #[serde(default)] pub show_remote_cursor: bool, @@ -961,26 +964,51 @@ impl PeerConfig { serde_field_string!( default_view_style, deserialize_view_style, - "original".to_owned() + UserDefaultConfig::load().get("view_style") ); serde_field_string!( default_scroll_style, deserialize_scroll_style, - "scrollauto".to_owned() + UserDefaultConfig::load().get("scroll_style") ); serde_field_string!( default_image_quality, deserialize_image_quality, - "balanced".to_owned() + UserDefaultConfig::load().get("image_quality") ); + fn default_custom_image_quality() -> Vec { + let f: f64 = UserDefaultConfig::load() + .get("custom_image_quality") + .parse() + .unwrap_or(50.0); + vec![f as _] + } + + fn deserialize_custom_image_quality<'de, D>(deserializer: D) -> Result, D::Error> + where + D: de::Deserializer<'de>, + { + let v: Vec = de::Deserialize::deserialize(deserializer)?; + if v.len() == 1 && v[0] >= 10 && v[0] <= 100 { + Ok(v) + } else { + Ok(Self::default_custom_image_quality()) + } + } + fn deserialize_options<'de, D>(deserializer: D) -> Result, D::Error> where D: de::Deserializer<'de>, { let mut mp: HashMap = de::Deserialize::deserialize(deserializer)?; - if !mp.contains_key("codec-preference") { - mp.insert("codec-preference".to_owned(), "auto".to_owned()); + let mut key = "codec-preference"; + if !mp.contains_key(key) { + mp.insert(key.to_owned(), UserDefaultConfig::load().get(key)); + } + key = "custom-fps"; + if !mp.contains_key(key) { + mp.insert(key.to_owned(), UserDefaultConfig::load().get(key)); } Ok(mp) } @@ -1192,6 +1220,73 @@ impl HwCodecConfig { } } +#[derive(Debug, Default, Serialize, Deserialize, Clone)] +pub struct UserDefaultConfig { + #[serde(default)] + options: HashMap, +} + +impl UserDefaultConfig { + pub fn load() -> UserDefaultConfig { + Config::load_::("_default") + } + + #[inline] + fn store(&self) { + Config::store_(self, "_default"); + } + + pub fn get(&self, key: &str) -> String { + match key { + "view_style" => self.get_string(key, "original", vec!["adaptive"]), + "scroll_style" => self.get_string(key, "scrollauto", vec!["scrollbar"]), + "image_quality" => self.get_string(key, "balanced", vec!["best", "low", "custom"]), + "codec-preference" => self.get_string(key, "auto", vec!["vp9", "h264", "h265"]), + "custom_image_quality" => self.get_double_string(key, 50.0, 10.0, 100.0), + "custom-fps" => self.get_double_string(key, 30.0, 10.0, 120.0), + _ => self + .options + .get(key) + .map(|v| v.to_string()) + .unwrap_or_default(), + } + } + + pub fn set(&mut self, key: String, value: String) { + self.options.insert(key, value); + self.store(); + } + + #[inline] + fn get_string(&self, key: &str, default: &str, others: Vec<&str>) -> String { + match self.options.get(key) { + Some(option) => { + if others.contains(&option.as_str()) { + option.to_owned() + } else { + default.to_owned() + } + } + None => default.to_owned(), + } + } + + #[inline] + fn get_double_string(&self, key: &str, default: f64, min: f64, max: f64) -> String { + match self.options.get(key) { + Some(option) => { + let v: f64 = option.parse().unwrap_or(default); + if v >= min && v <= max { + v.to_string() + } else { + default.to_string() + } + } + None => default.to_string(), + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index c2ae2b6b0..d40c66d19 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -791,6 +791,14 @@ pub fn main_default_video_save_directory() -> String { default_video_save_directory() } +pub fn main_set_user_default_option(key: String, value: String) { + set_user_default_option(key, value); +} + +pub fn main_get_user_default_option(key: String) -> SyncReturn { + SyncReturn(get_user_default_option(key)) +} + pub fn session_add_port_forward( id: String, local_port: i32, diff --git a/src/lang/ca.rs b/src/lang/ca.rs index cd8fba24d..ac3dba290 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Sobre"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "Silenciar"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Silenciar"), ("Audio Input", "Entrada d'àudio"), ("Enhancements", "Millores"), ("Hardware Codec", "Còdec de hardware"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 41fa7fc26..5f03ba759 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", "反转访问方向"), ("Please confirm if you want to share your desktop?", "请确认要让对方访问你的桌面?"), ("Closed as expected", "正常关闭"), + ("Display", "显示"), + ("Default View Style", "默认显示方式"), + ("Default Scroll Style", "默认滚动方式"), + ("Default Image Quality", "默认图像质量"), + ("Default Codec", "默认编解码"), + ("Bitrate", "波特率"), + ("FPS", "帧率"), + ("Auto", "自动"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 5e59a86f1..43f3b423a 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 8eddaf0b9..5f9e49265 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 3418ea9f5..a683ae44d 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", "Seiten wechseln"), ("Please confirm if you want to share your desktop?", "Bitte bestätigen Sie, ob Sie Ihren Desktop freigeben möchten."), ("Closed as expected", "Wie erwartet geschlossen"), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index b034c0394..7f92a9b19 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Pri"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "Muta"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Muta"), ("Audio Input", "Aŭdia enigo"), ("Enhancements", ""), ("Hardware Codec", ""), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 3848d1925..505149759 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Acerca de"), ("Slogan_tip", "Hecho con corazón en este mundo caótico!"), ("Privacy Statement", "Declaración de privacidad"), + ("Mute", "Silenciar"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Silenciar"), ("Audio Input", "Entrada de audio"), ("Enhancements", "Mejoras"), ("Hardware Codec", "Códec de hardware"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", "Intercambiar lados"), ("Please confirm if you want to share your desktop?", "Por favor, confirma si quieres compartir tu escritorio"), ("Closed as expected", "Cerrado como se esperaba"), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 316885082..7e1264939 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "درباره"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "بستن صدا"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "بستن صدا"), ("Audio Input", "ورودی صدا"), ("Enhancements", "بهبودها"), ("Hardware Codec", "کدک سخت افزاری"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", "طرفین را عوض کنید"), ("Please confirm if you want to share your desktop?", "لطفاً تأیید کنید که آیا می خواهید دسکتاپ خود را به اشتراک بگذارید؟"), ("Closed as expected", "طبق انتظار بسته شد"), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 097091e75..9b50c8db7 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "À propos de"), ("Slogan_tip", "Fait avec cœur dans ce monde chaotique!"), ("Privacy Statement", "Déclaration de confidentialité"), + ("Mute", "Muet"), ("Build Date", "Date de compilation"), ("Version", "Version"), ("Home", "Accueil"), - ("Mute", "Muet"), ("Audio Input", "Entrée audio"), ("Enhancements", "Améliorations"), ("Hardware Codec", "Transcodage matériel"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", "Inverser la prise de contrôle"), ("Please confirm if you want to share your desktop?", "Veuillez confirmer le partager de votre bureau ?"), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/gr.rs b/src/lang/gr.rs index 53f9dca08..82e90a117 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Πληροφορίες"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "Σίγαση"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Σίγαση"), ("Audio Input", "Είσοδος ήχου"), ("Enhancements", "Βελτιώσεις"), ("Hardware Codec", "Κωδικοποιητής υλικού"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index f86e83012..f1b231d3c 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 6ae39f108..e7b3c2cce 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Tentang"), ("Slogan_tip", ""), ("Privacy Statement", "Pernyataan Privasi"), + ("Mute", "Bisukan"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Bisukan"), ("Audio Input", "Masukkan Audio"), ("Enhancements", "Peningkatan"), ("Hardware Codec", "Codec Perangkat Keras"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 0ec6c52b9..ec7e07312 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Informazioni"), ("Slogan_tip", "Fatta con il cuore in questo mondo caotico!"), ("Privacy Statement", "Informativa sulla privacy"), + ("Mute", "Silenzia"), ("Build Date", "Data della build"), ("Version", "Versione"), ("Home", "Home"), - ("Mute", "Silenzia"), ("Audio Input", "Input audio"), ("Enhancements", "Miglioramenti"), ("Hardware Codec", "Codifica Hardware"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", "Cambia lato"), ("Please confirm if you want to share your desktop?", "Vuoi condividere il tuo desktop?"), ("Closed as expected", "Chiuso come previsto"), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 8e8a5ed95..a65f3d56a 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "情報"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "ミュート"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "ミュート"), ("Audio Input", "音声入力デバイス"), ("Enhancements", "追加機能"), ("Hardware Codec", "ハードウェア コーデック"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 7b56202a0..8f7167df4 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "정보"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "음소거"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "음소거"), ("Audio Input", "오디오 입력"), ("Enhancements", ""), ("Hardware Codec", "하드웨어 코덱"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index dcf62ff10..1651beb92 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Туралы"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "Дыбыссыздандыру"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Дыбыссыздандыру"), ("Audio Input", "Аудио Еңгізу"), ("Enhancements", "Жақсартулар"), ("Hardware Codec", "Hardware Codec"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 085e74d3a..0b0c454c0 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "O aplikacji"), ("Slogan_tip", "Tworzone z miłością w tym pełnym chaosu świecie!"), ("Privacy Statement", "Oświadczenie o ochronie prywatności"), + ("Mute", "Wycisz"), ("Build Date", "Zbudowano"), ("Version", "Wersja"), ("Home", "Pulpit"), - ("Mute", "Wycisz"), ("Audio Input", "Wejście audio"), ("Enhancements", "Ulepszenia"), ("Hardware Codec", "Kodek sprzętowy"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", "Zmień Strony"), ("Please confirm if you want to share your desktop?", "Czy na pewno chcesz udostępnić swój ekran?"), ("Closed as expected", "Zamknięto pomyślnie"), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index aea9acd2a..d327011fe 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Sobre"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "Silenciar"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Silenciar"), ("Audio Input", "Entrada de Áudio"), ("Enhancements", "Melhorias"), ("Hardware Codec", ""), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 28683c8d5..a442b5858 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Sobre"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "Desativar som"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Desativar som"), ("Audio Input", "Entrada de Áudio"), ("Enhancements", "Melhorias"), ("Hardware Codec", "Codec de hardware"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 3009e9b06..b90a21cea 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -42,6 +42,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Slogan_tip", ""), ("Privacy Statement", ""), ("Mute", "Fără sunet"), + ("Build Date", ""), + ("Version", ""), + ("Home", ""), ("Audio Input", "Intrare audio"), ("Enhancements", "Îmbunătățiri"), ("Hardware Codec", "Codec hardware"), @@ -433,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 22f938ec5..f92815137 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "О программе"), ("Slogan_tip", "Сделано с душой в этом безумном мире!"), ("Privacy Statement", "Заявление о конфиденциальности"), + ("Mute", "Отключить звук"), ("Build Date", "Дата сборки"), ("Version", "Версия"), ("Home", "Главная"), - ("Mute", "Отключить звук"), ("Audio Input", "Аудиовход"), ("Enhancements", "Улучшения"), ("Hardware Codec", "Аппаратный кодек"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", "Переключить стороны"), ("Please confirm if you want to share your desktop?", "Подтверждаете, что хотите поделиться своим рабочим столом?"), ("Closed as expected", "Закрыто по ожиданию"), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 2062b57a5..a6b5b7b4f 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "O RustDesk"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "Stíšiť"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Stíšiť"), ("Audio Input", "Zvukový vstup"), ("Enhancements", ""), ("Hardware Codec", ""), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 1ff78818c..1cabf9bbc 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "O programu"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "Izklopi zvok"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Izklopi zvok"), ("Audio Input", "Avdio vhod"), ("Enhancements", "Izboljšave"), ("Hardware Codec", "Strojni kodek"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 225652056..6bfdc8230 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Rreth"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "Pa zë"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Pa zë"), ("Audio Input", "Inputi zërit"), ("Enhancements", "Përmirësimet"), ("Hardware Codec", "Kodeku Harduerik"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 57c528fdb..cfdb3712b 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "O programu"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "Utišaj"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Utišaj"), ("Audio Input", "Audio ulaz"), ("Enhancements", "Proširenja"), ("Hardware Codec", "Hardverski kodek"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index f98d7f005..5d25b6a14 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Om"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "Tyst"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Tyst"), ("Audio Input", "Ljud input"), ("Enhancements", "Förbättringar"), ("Hardware Codec", "Hårdvarucodec"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 358444986..0e77eca0d 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", ""), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", ""), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", ""), ("Audio Input", ""), ("Enhancements", ""), ("Hardware Codec", ""), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index d35cbdfe7..da4b7fba5 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "เกี่ยวกับ"), ("Slogan_tip", "ทำด้วยใจ ในโลกใบนี้ที่ยุ่งเหยิง!"), ("Privacy Statement", "คำแถลงเกี่ยวกับความเป็นส่วนตัว"), + ("Mute", "ปิดเสียง"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "ปิดเสียง"), ("Audio Input", "ออดิโออินพุท"), ("Enhancements", "การปรับปรุง"), ("Hardware Codec", "ฮาร์ดแวร์ codec"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 1e2068fb6..717072bfb 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Hakkında"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "Sustur"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Sustur"), ("Audio Input", "Ses Girişi"), ("Enhancements", "Geliştirmeler"), ("Hardware Codec", "Donanımsal Codec"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 370c9fbed..0076a7a81 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "關於"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "靜音"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "靜音"), ("Audio Input", "音訊輸入"), ("Enhancements", "增強功能"), ("Hardware Codec", "硬件編解碼"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", "正常關閉"), + ("Display", "顯示"), + ("Default View Style", "默認顯示方式"), + ("Default Scroll Style", "默認滾動方式"), + ("Default Image Quality", "默認圖像質量"), + ("Default Codec", "默認編解碼"), + ("Bitrate", "波特率"), + ("FPS", "幀率"), + ("Auto", "自動"), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index bdba09b5b..980febc97 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Про RustDesk"), ("Slogan_tip", "Створено з душею в цьому хаотичному світі!"), ("Privacy Statement", "Декларація про конфіденційність"), + ("Mute", "Вимкнути звук"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Вимкнути звук"), ("Audio Input", "Аудіовхід"), ("Enhancements", "Покращення"), ("Hardware Codec", "Апаратний кодек"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 840739765..8785acfc3 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -41,10 +41,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "About"), ("Slogan_tip", ""), ("Privacy Statement", ""), + ("Mute", "Tắt tiếng"), ("Build Date", ""), ("Version", ""), ("Home", ""), - ("Mute", "Tắt tiếng"), ("Audio Input", "Đầu vào âm thanh"), ("Enhancements", "Các tiện itchs"), ("Hardware Codec", "Codec phần cứng"), @@ -436,5 +436,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", ""), ("Please confirm if you want to share your desktop?", ""), ("Closed as expected", ""), + ("Display", ""), + ("Default View Style", ""), + ("Default Scroll Style", ""), + ("Default Image Quality", ""), + ("Default Codec", ""), + ("Bitrate", ""), + ("FPS", ""), + ("Auto", ""), ].iter().cloned().collect(); } diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 4e0fd7744..d357c9cef 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -917,6 +917,18 @@ pub fn account_auth_result() -> String { serde_json::to_string(&account::OidcSession::get_result()).unwrap_or_default() } +#[cfg(feature = "flutter")] +pub fn set_user_default_option(key: String, value: String) { + use hbb_common::config::UserDefaultConfig; + UserDefaultConfig::load().set(key, value); +} + +#[cfg(feature = "flutter")] +pub fn get_user_default_option(key: String) -> String { + use hbb_common::config::UserDefaultConfig; + UserDefaultConfig::load().get(&key) +} + // notice: avoiding create ipc connection repeatedly, // because windows named pipe has serious memory leak issue. #[tokio::main(flavor = "current_thread")] From 92145eeb717f1eba07c7298c4bca13e37aad6857 Mon Sep 17 00:00:00 2001 From: 21pages Date: Thu, 2 Feb 2023 09:39:14 +0800 Subject: [PATCH 49/83] other bool default display settings Signed-off-by: 21pages --- .../desktop/pages/desktop_setting_page.dart | 34 ++++++++ libs/hbb_common/src/config.rs | 80 +++++++++++++++---- src/client.rs | 40 +++++----- src/client/io_loop.rs | 14 ++-- src/lang/ca.rs | 1 + src/lang/cn.rs | 1 + src/lang/cs.rs | 1 + src/lang/da.rs | 1 + src/lang/de.rs | 1 + src/lang/eo.rs | 1 + src/lang/es.rs | 1 + src/lang/fa.rs | 1 + src/lang/fr.rs | 1 + src/lang/gr.rs | 1 + src/lang/hu.rs | 1 + src/lang/id.rs | 1 + src/lang/it.rs | 1 + src/lang/ja.rs | 1 + src/lang/ko.rs | 1 + src/lang/kz.rs | 1 + src/lang/pl.rs | 1 + src/lang/pt_PT.rs | 1 + src/lang/ptbr.rs | 1 + src/lang/ro.rs | 1 + src/lang/ru.rs | 1 + src/lang/sk.rs | 1 + src/lang/sl.rs | 1 + src/lang/sq.rs | 1 + src/lang/sr.rs | 1 + src/lang/sv.rs | 1 + src/lang/template.rs | 1 + src/lang/th.rs | 1 + src/lang/tr.rs | 1 + src/lang/tw.rs | 1 + src/lang/ua.rs | 1 + src/lang/vn.rs | 1 + 36 files changed, 159 insertions(+), 41 deletions(-) diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index e4a7e1a25..4b6cf2a62 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -1072,6 +1072,7 @@ class _DisplayState extends State<_Display> { scrollStyle(context), imageQuality(context), codec(context), + other(context), ]).marginOnly(bottom: _kListViewBottomMargin)); } @@ -1256,6 +1257,39 @@ class _DisplayState extends State<_Display> { onChanged: onChanged), ]); } + + Widget otherRow(String label, String key) { + final value = bind.mainGetUserDefaultOption(key: key) == 'Y'; + onChanged(bool b) async { + await bind.mainSetUserDefaultOption(key: key, value: b ? 'Y' : ''); + setState(() {}); + } + + return GestureDetector( + child: Row( + children: [ + Checkbox(value: value, onChanged: (_) => onChanged(!value)) + .marginOnly(right: 5), + Expanded( + child: Text(translate(label)), + ) + ], + ).marginOnly(left: _kCheckBoxLeftMargin), + onTap: () => onChanged(!value)); + } + + Widget other(BuildContext context) { + return _Card(title: 'Other Default Options', children: [ + otherRow('Show remote cursor', 'show_remote_cursor'), + otherRow('Zoom cursor', 'zoom-cursor'), + otherRow('Show quality monitor', 'show_quality_monitor'), + otherRow('Mute', 'disable_audio'), + otherRow('Allow file copy and paste', 'enable_file_transfer'), + otherRow('Disable clipboard', 'disable_clipboard'), + otherRow('Lock after session end', 'lock_after_session_end'), + otherRow('Privacy mode', 'privacy_mode'), + ]); + } } class _Account extends StatefulWidget { diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index ce4be6119..71dd9a5c6 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -115,6 +115,26 @@ macro_rules! serde_field_string { }; } +macro_rules! serde_field_bool { + ($struct_name: ident, $field_name: literal, $func: ident) => { + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] + pub struct $struct_name { + #[serde(rename = $field_name)] + pub v: bool, + } + impl Default for $struct_name { + fn default() -> Self { + Self { v: Self::$func() } + } + } + impl $struct_name { + pub fn $func() -> bool { + UserDefaultConfig::load().get($field_name) == "Y" + } + } + }; +} + #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum NetworkType { Direct, @@ -197,24 +217,24 @@ pub struct PeerConfig { deserialize_with = "PeerConfig::deserialize_custom_image_quality" )] pub custom_image_quality: Vec, - #[serde(default)] - pub show_remote_cursor: bool, - #[serde(default)] - pub lock_after_session_end: bool, - #[serde(default)] - pub privacy_mode: bool, + #[serde(flatten)] + pub show_remote_cursor: ShowRemoteCursor, + #[serde(flatten)] + pub lock_after_session_end: LockAfterSessionEnd, + #[serde(flatten)] + pub privacy_mode: PrivacyMode, #[serde(default)] pub port_forwards: Vec<(i32, String, i32)>, #[serde(default)] pub direct_failures: i32, - #[serde(default)] - pub disable_audio: bool, - #[serde(default)] - pub disable_clipboard: bool, - #[serde(default)] - pub enable_file_transfer: bool, - #[serde(default)] - pub show_quality_monitor: bool, + #[serde(flatten)] + pub disable_audio: DisableAudio, + #[serde(flatten)] + pub disable_clipboard: DisableClipboard, + #[serde(flatten)] + pub enable_file_transfer: EnableFileTransfer, + #[serde(flatten)] + pub show_quality_monitor: ShowQualityMonitor, #[serde(default)] pub keyboard_mode: String, @@ -1010,10 +1030,42 @@ impl PeerConfig { if !mp.contains_key(key) { mp.insert(key.to_owned(), UserDefaultConfig::load().get(key)); } + key = "zoom-cursor"; + if !mp.contains_key(key) { + mp.insert(key.to_owned(), UserDefaultConfig::load().get(key)); + } Ok(mp) } } +serde_field_bool!( + ShowRemoteCursor, + "show_remote_cursor", + default_show_remote_cursor +); +serde_field_bool!( + ShowQualityMonitor, + "show_quality_monitor", + default_show_quality_monitor +); +serde_field_bool!(DisableAudio, "disable_audio", default_disable_audio); +serde_field_bool!( + EnableFileTransfer, + "enable_file_transfer", + default_enable_file_transfer +); +serde_field_bool!( + DisableClipboard, + "disable_clipboard", + default_disable_clipboard +); +serde_field_bool!( + LockAfterSessionEnd, + "lock_after_session_end", + default_lock_after_session_end +); +serde_field_bool!(PrivacyMode, "privacy_mode", default_privacy_mode); + #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct LocalConfig { #[serde(default)] diff --git a/src/client.rs b/src/client.rs index a6df6dbec..fb42ce840 100644 --- a/src/client.rs +++ b/src/client.rs @@ -956,7 +956,7 @@ impl LoginConfigHandler { /// Check if the client should auto login. /// Return password if the client should auto login, otherwise return empty string. pub fn should_auto_login(&self) -> String { - let l = self.lock_after_session_end; + let l = self.lock_after_session_end.v; let a = !self.get_option("auto-login").is_empty(); let p = self.get_option("os-password"); if !p.is_empty() && l && a { @@ -1063,32 +1063,32 @@ impl LoginConfigHandler { let mut option = OptionMessage::default(); let mut config = self.load_config(); if name == "show-remote-cursor" { - config.show_remote_cursor = !config.show_remote_cursor; - option.show_remote_cursor = (if config.show_remote_cursor { + config.show_remote_cursor.v = !config.show_remote_cursor.v; + option.show_remote_cursor = (if config.show_remote_cursor.v { BoolOption::Yes } else { BoolOption::No }) .into(); } else if name == "disable-audio" { - config.disable_audio = !config.disable_audio; - option.disable_audio = (if config.disable_audio { + config.disable_audio.v = !config.disable_audio.v; + option.disable_audio = (if config.disable_audio.v { BoolOption::Yes } else { BoolOption::No }) .into(); } else if name == "disable-clipboard" { - config.disable_clipboard = !config.disable_clipboard; - option.disable_clipboard = (if config.disable_clipboard { + config.disable_clipboard.v = !config.disable_clipboard.v; + option.disable_clipboard = (if config.disable_clipboard.v { BoolOption::Yes } else { BoolOption::No }) .into(); } else if name == "lock-after-session-end" { - config.lock_after_session_end = !config.lock_after_session_end; - option.lock_after_session_end = (if config.lock_after_session_end { + config.lock_after_session_end.v = !config.lock_after_session_end.v; + option.lock_after_session_end = (if config.lock_after_session_end.v { BoolOption::Yes } else { BoolOption::No @@ -1096,15 +1096,15 @@ impl LoginConfigHandler { .into(); } else if name == "privacy-mode" { // try toggle privacy mode - option.privacy_mode = (if config.privacy_mode { + option.privacy_mode = (if config.privacy_mode.v { BoolOption::No } else { BoolOption::Yes }) .into(); } else if name == "enable-file-transfer" { - config.enable_file_transfer = !config.enable_file_transfer; - option.enable_file_transfer = (if config.enable_file_transfer { + config.enable_file_transfer.v = !config.enable_file_transfer.v; + option.enable_file_transfer = (if config.enable_file_transfer.v { BoolOption::Yes } else { BoolOption::No @@ -1115,7 +1115,7 @@ impl LoginConfigHandler { } else if name == "unblock-input" { option.block_input = BoolOption::No.into(); } else if name == "show-quality-monitor" { - config.show_quality_monitor = !config.show_quality_monitor; + config.show_quality_monitor.v = !config.show_quality_monitor.v; } else { let v = self.options.get(&name).is_some(); if v { @@ -1252,19 +1252,19 @@ impl LoginConfigHandler { /// * `name` - The name of the toggle option. pub fn get_toggle_option(&self, name: &str) -> bool { if name == "show-remote-cursor" { - self.config.show_remote_cursor + self.config.show_remote_cursor.v } else if name == "lock-after-session-end" { - self.config.lock_after_session_end + self.config.lock_after_session_end.v } else if name == "privacy-mode" { - self.config.privacy_mode + self.config.privacy_mode.v } else if name == "enable-file-transfer" { - self.config.enable_file_transfer + self.config.enable_file_transfer.v } else if name == "disable-audio" { - self.config.disable_audio + self.config.disable_audio.v } else if name == "disable-clipboard" { - self.config.disable_clipboard + self.config.disable_clipboard.v } else if name == "show-quality-monitor" { - self.config.show_quality_monitor + self.config.show_quality_monitor.v } else { !self.get_option(name).is_empty() } diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index f4ecbded5..0178fe9e8 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -277,7 +277,7 @@ impl Remote { } if !SERVER_CLIPBOARD_ENABLED.load(Ordering::SeqCst) || !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst) - || lc.read().unwrap().disable_clipboard + || lc.read().unwrap().disable_clipboard.v { continue; } @@ -778,7 +778,7 @@ impl Remote { || self.handler.is_port_forward() || !SERVER_CLIPBOARD_ENABLED.load(Ordering::SeqCst) || !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst) - || self.handler.lc.read().unwrap().disable_clipboard) + || self.handler.lc.read().unwrap().disable_clipboard.v) { let txt = self.old_clipboard.lock().unwrap().clone(); if !txt.is_empty() { @@ -808,7 +808,7 @@ impl Remote { self.handler.set_cursor_position(cp); } Some(message::Union::Clipboard(cb)) => { - if !self.handler.lc.read().unwrap().disable_clipboard { + if !self.handler.lc.read().unwrap().disable_clipboard.v { #[cfg(not(any(target_os = "android", target_os = "ios")))] update_clipboard(cb, Some(&self.old_clipboard)); #[cfg(any(target_os = "android", target_os = "ios"))] @@ -1121,7 +1121,7 @@ impl Remote { self.handler.handle_test_delay(t, peer).await; } Some(message::Union::AudioFrame(frame)) => { - if !self.handler.lc.read().unwrap().disable_audio { + if !self.handler.lc.read().unwrap().disable_audio.v { self.audio_sender.send(MediaData::AudioFrame(frame)).ok(); } } @@ -1204,7 +1204,7 @@ impl Remote { #[inline(always)] fn update_privacy_mode(&mut self, on: bool) { let mut config = self.handler.load_config(); - config.privacy_mode = on; + config.privacy_mode.v = on; self.handler.save_config(config); self.handler.update_privacy_mode(); @@ -1278,14 +1278,14 @@ impl Remote { #[cfg(windows)] { let enabled = SERVER_FILE_TRANSFER_ENABLED.load(Ordering::SeqCst) - && self.handler.lc.read().unwrap().enable_file_transfer; + && self.handler.lc.read().unwrap().enable_file_transfer.v; ContextSend::enable(enabled); } } #[cfg(windows)] fn handle_cliprdr_msg(&self, clip: hbb_common::message_proto::Cliprdr) { - if !self.handler.lc.read().unwrap().disable_clipboard { + if !self.handler.lc.read().unwrap().disable_clipboard.v { #[cfg(feature = "flutter")] if let Some(hbb_common::message_proto::cliprdr::Union::FormatList(_)) = &clip.union { if self.client_conn_id diff --git a/src/lang/ca.rs b/src/lang/ca.rs index ac3dba290..f2210f971 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 5f03ba759..00d62946f 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", "波特率"), ("FPS", "帧率"), ("Auto", "自动"), + ("Other Default Options", "其它默认选项"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 43f3b423a..453ecefb3 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 5f9e49265..dcaeb3eaa 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index a683ae44d..5b68c0e7a 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 7f92a9b19..0c7f13d7e 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 505149759..6f866845c 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 7e1264939..72cde49f9 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 9b50c8db7..19b932d2f 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/gr.rs b/src/lang/gr.rs index 82e90a117..bc25ab6c6 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index f1b231d3c..49ce8f140 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index e7b3c2cce..0fa6e0293 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index ec7e07312..6edd4a461 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index a65f3d56a..35e20d7fd 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 8f7167df4..d03b07992 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 1651beb92..2006c67d1 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 0b0c454c0..daf4a7846 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index d327011fe..64e5e9315 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index a442b5858..0f64ae67f 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index b90a21cea..7e209dff8 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index f92815137..7ec6c1554 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index a6b5b7b4f..a703c0799 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 1cabf9bbc..16c948ceb 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 6bfdc8230..285a51732 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index cfdb3712b..dd943e0e6 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 5d25b6a14..3050ff635 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 0e77eca0d..7572da9de 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index da4b7fba5..535e4e772 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 717072bfb..80b384c6c 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 0076a7a81..f5d9539d8 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", "波特率"), ("FPS", "幀率"), ("Auto", "自動"), + ("Other Default Options", "其它默認選項"), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 980febc97..37a7d6bcd 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 8785acfc3..d78f5aa7b 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -444,5 +444,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Bitrate", ""), ("FPS", ""), ("Auto", ""), + ("Other Default Options", ""), ].iter().cloned().collect(); } From 6119e040067530a32b3dc70bac6b5eb9ae4941f6 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Thu, 2 Feb 2023 13:57:20 +0800 Subject: [PATCH 50/83] fix: synchronize macOS window theme on flutter theme changed. --- flutter/lib/common.dart | 20 +++++++++++ .../lib/desktop/widgets/refresh_wrapper.dart | 4 +++ flutter/lib/main.dart | 4 +++ flutter/lib/utils/platform_channel.dart | 34 +++++++++++++++++++ flutter/macos/Runner/MainFlutterWindow.swift | 31 +++++++++++++++++ flutter/pubspec.yaml | 2 +- 6 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 flutter/lib/utils/platform_channel.dart diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index ee7353c12..2a4441d36 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -9,6 +9,7 @@ import 'package:back_button_interceptor/back_button_interceptor.dart'; import 'package:desktop_multi_window/desktop_multi_window.dart'; import 'package:ffi/ffi.dart'; import 'package:flutter/foundation.dart'; +import 'package:flutter_hbb/utils/platform_channel.dart'; import 'package:win32/win32.dart' as win32; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; @@ -235,6 +236,12 @@ class MyTheme { } bind.mainChangeTheme(dark: mode.toShortString()); } + // Synchronize the window theme of the system. + if (Platform.isMacOS) { + final isDark = mode == ThemeMode.dark; + RdPlatformChannel.instance.changeSystemWindowTheme( + isDark ? SystemWindowTheme.dark : SystemWindowTheme.light); + } } static ThemeMode currentThemeMode() { @@ -1686,3 +1693,16 @@ String getWindowName({WindowType? overrideType}) { String getWindowNameWithId(String id, {WindowType? overrideType}) { return "${DesktopTab.labelGetterAlias(id).value} - ${getWindowName(overrideType: overrideType)}"; } + +void updateSystemWindowTheme() { + // Set system window theme for macOS + final userPreference = MyTheme.getThemeModePreference(); + if (userPreference != ThemeMode.system) { + if (Platform.isMacOS) { + RdPlatformChannel.instance.changeSystemWindowTheme( + userPreference == ThemeMode.light + ? SystemWindowTheme.light + : SystemWindowTheme.dark); + } + } +} \ No newline at end of file diff --git a/flutter/lib/desktop/widgets/refresh_wrapper.dart b/flutter/lib/desktop/widgets/refresh_wrapper.dart index 60e816044..b4ea14d01 100644 --- a/flutter/lib/desktop/widgets/refresh_wrapper.dart +++ b/flutter/lib/desktop/widgets/refresh_wrapper.dart @@ -1,9 +1,11 @@ import 'package:flutter/material.dart'; +import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/main.dart'; import 'package:get/get.dart'; class RefreshWrapper extends StatefulWidget { final Widget Function(BuildContext context) builder; + const RefreshWrapper({super.key, required this.builder}); @override @@ -30,6 +32,8 @@ class RefreshWrapperState extends State { if (Get.context != null) { (context as Element).visitChildren(_rebuildElement); } + // Synchronize the window theme of the system. + updateSystemWindowTheme(); setState(() {}); } diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index ff7a72124..5b1e0c37c 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -108,6 +108,8 @@ Future initEnv(String appType) async { await initGlobalFFI(); // await Firebase.initializeApp(); _registerEventHandler(); + // Update the system theme. + updateSystemWindowTheme(); } void runMainApp(bool startService) async { @@ -327,6 +329,8 @@ class _AppState extends State { to = ThemeMode.light; } Get.changeThemeMode(to); + // Synchronize the window theme of the system. + updateSystemWindowTheme(); if (desktopType == DesktopType.main) { bind.mainChangeTheme(dark: to.toShortString()); } diff --git a/flutter/lib/utils/platform_channel.dart b/flutter/lib/utils/platform_channel.dart new file mode 100644 index 000000000..21f08f53f --- /dev/null +++ b/flutter/lib/utils/platform_channel.dart @@ -0,0 +1,34 @@ +import 'dart:io'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_hbb/main.dart'; + +enum SystemWindowTheme { light, dark } + +/// The platform channel for RustDesk +class RdPlatformChannel { + RdPlatformChannel._(); + + static final RdPlatformChannel _windowUtil = RdPlatformChannel._(); + + static RdPlatformChannel get instance => _windowUtil; + + final MethodChannel _osxMethodChannel = + MethodChannel("org.rustdesk.rustdesk/macos"); + final MethodChannel _winMethodChannel = + MethodChannel("org.rustdesk.rustdesk/windows"); + final MethodChannel _linuxMethodChannel = + MethodChannel("org.rustdesk.rustdesk/linux"); + + /// Change the theme of the system window + Future changeSystemWindowTheme(SystemWindowTheme theme) { + assert(Platform.isMacOS); + if (kDebugMode) { + print( + "[Window ${kWindowId ?? 'Main'}] change system window theme to ${theme.name}"); + } + return _osxMethodChannel + .invokeMethod("setWindowTheme", {"themeName": theme.name}); + } +} diff --git a/flutter/macos/Runner/MainFlutterWindow.swift b/flutter/macos/Runner/MainFlutterWindow.swift index 108f5a5f8..cea1e94bb 100644 --- a/flutter/macos/Runner/MainFlutterWindow.swift +++ b/flutter/macos/Runner/MainFlutterWindow.swift @@ -27,12 +27,16 @@ class MainFlutterWindow: NSWindow { let windowFrame = self.frame self.contentViewController = flutterViewController self.setFrame(windowFrame, display: true) + // register self method handler + let registrar = flutterViewController.registrar(forPlugin: "RustDeskPlugin") + setMethodHandler(registrar: registrar) RegisterGeneratedPlugins(registry: flutterViewController) FlutterMultiWindowPlugin.setOnWindowCreatedCallback { controller in // Register the plugin which you want access from other isolate. // DesktopLifecyclePlugin.register(with: controller.registrar(forPlugin: "DesktopLifecyclePlugin")) + self.setMethodHandler(registrar: controller.registrar(forPlugin: "RustDeskPlugin")) DesktopDropPlugin.register(with: controller.registrar(forPlugin: "DesktopDropPlugin")) DeviceInfoPlusMacosPlugin.register(with: controller.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) FlutterCustomCursorPlugin.register(with: controller.registrar(forPlugin: "FlutterCustomCursorPlugin")) @@ -53,4 +57,31 @@ class MainFlutterWindow: NSWindow { super.order(place, relativeTo: otherWin) hiddenWindowAtLaunch() } + + /// Override window theme. + public func setWindowInterfaceMode(window: NSWindow, themeName: String) { + window.appearance = NSAppearance(named: themeName == "light" ? .aqua : .darkAqua) + } + + public func setMethodHandler(registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "org.rustdesk.rustdesk/macos", binaryMessenger: registrar.messenger) + channel.setMethodCallHandler({ + (call, result) -> Void in + switch call.method { + case "setWindowTheme": + let arg = call.arguments as! [String: Any] + let themeName = arg["themeName"] as? String + guard let window = registrar.view?.window else { + result(nil) + return + } + self.setWindowInterfaceMode(window: window,themeName: themeName ?? "light") + result(nil) + break; + default: + result(FlutterMethodNotImplemented) + } + }) + } } + diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 3d08033bb..95449e611 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -61,7 +61,7 @@ dependencies: url: https://github.com/Kingtous/rustdesk_desktop_multi_window ref: bc8604a88e52b2b6e64d2661ae49a71450a47af8 freezed_annotation: ^2.0.3 - flutter_custom_cursor: ^0.0.2 + flutter_custom_cursor: ^0.0.4 window_size: git: url: https://github.com/google/flutter-desktop-embedding.git From 205f37cd56a715b07c2379a32171f32349b21fdf Mon Sep 17 00:00:00 2001 From: Kingtous Date: Thu, 2 Feb 2023 14:03:50 +0800 Subject: [PATCH 51/83] opt: shrink unnecessary theme code --- flutter/lib/common.dart | 22 +++++++++------------- flutter/lib/utils/platform_channel.dart | 2 +- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 2a4441d36..a2623ff15 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -225,22 +225,18 @@ class MyTheme { return themeModeFromString(bind.mainGetLocalOption(key: kCommConfKeyTheme)); } - static void changeDarkMode(ThemeMode mode) { + static void changeDarkMode(ThemeMode mode) async { Get.changeThemeMode(mode); if (desktopType == DesktopType.main) { if (mode == ThemeMode.system) { - bind.mainSetLocalOption(key: kCommConfKeyTheme, value: ''); + await bind.mainSetLocalOption(key: kCommConfKeyTheme, value: ''); } else { - bind.mainSetLocalOption( + await bind.mainSetLocalOption( key: kCommConfKeyTheme, value: mode.toShortString()); } - bind.mainChangeTheme(dark: mode.toShortString()); - } - // Synchronize the window theme of the system. - if (Platform.isMacOS) { - final isDark = mode == ThemeMode.dark; - RdPlatformChannel.instance.changeSystemWindowTheme( - isDark ? SystemWindowTheme.dark : SystemWindowTheme.light); + await bind.mainChangeTheme(dark: mode.toShortString()); + // Synchronize the window theme of the system. + updateSystemWindowTheme(); } } @@ -1694,12 +1690,12 @@ String getWindowNameWithId(String id, {WindowType? overrideType}) { return "${DesktopTab.labelGetterAlias(id).value} - ${getWindowName(overrideType: overrideType)}"; } -void updateSystemWindowTheme() { - // Set system window theme for macOS +Future updateSystemWindowTheme() async { + // Set system window theme for macOS. final userPreference = MyTheme.getThemeModePreference(); if (userPreference != ThemeMode.system) { if (Platform.isMacOS) { - RdPlatformChannel.instance.changeSystemWindowTheme( + await RdPlatformChannel.instance.changeSystemWindowTheme( userPreference == ThemeMode.light ? SystemWindowTheme.light : SystemWindowTheme.dark); diff --git a/flutter/lib/utils/platform_channel.dart b/flutter/lib/utils/platform_channel.dart index 21f08f53f..1a36fb7a5 100644 --- a/flutter/lib/utils/platform_channel.dart +++ b/flutter/lib/utils/platform_channel.dart @@ -6,7 +6,7 @@ import 'package:flutter_hbb/main.dart'; enum SystemWindowTheme { light, dark } -/// The platform channel for RustDesk +/// The platform channel for RustDesk. class RdPlatformChannel { RdPlatformChannel._(); From 8dba3942052b322b2772fb929821940e8437f239 Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 1 Feb 2023 20:58:21 +0800 Subject: [PATCH 52/83] scale system cursor image Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 1 - .../lib/desktop/widgets/remote_menubar.dart | 37 +++++++++---------- flutter/lib/models/model.dart | 34 ++++++++--------- 3 files changed, 32 insertions(+), 40 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 2e4668159..1687f348e 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'dart:ui' as ui; import 'package:desktop_multi_window/desktop_multi_window.dart'; -import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_custom_cursor/cursor_manager.dart' diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 517dc9750..4f16f8227 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -1133,26 +1133,23 @@ class _RemoteMenubarState extends State { }()); } - /// Show remote cursor scaling with image - if (widget.state.viewStyle.value != kRemoteViewStyleOriginal) { - displayMenu.add(() { - final opt = 'zoom-cursor'; - final state = PeerBoolOption.find(widget.id, opt); - return MenuEntrySwitch2( - switchType: SwitchType.scheckbox, - text: translate('Zoom cursor'), - getter: () { - return state; - }, - setter: (bool v) async { - state.value = v; - await bind.sessionToggleOption(id: widget.id, value: opt); - }, - padding: padding, - dismissOnClicked: true, - ); - }()); - } + displayMenu.add(() { + final opt = 'zoom-cursor'; + final state = PeerBoolOption.find(widget.id, opt); + return MenuEntrySwitch2( + switchType: SwitchType.scheckbox, + text: translate('Zoom cursor'), + getter: () { + return state; + }, + setter: (bool v) async { + state.value = v; + await bind.sessionToggleOption(id: widget.id, value: opt); + }, + padding: padding, + dismissOnClicked: true, + ); + }()); /// Show quality monitor displayMenu.add(MenuEntrySwitch( diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 1eac1be39..78e6ce6af 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -778,28 +778,24 @@ class CursorData { scale = 1.0; } else { // Update data if scale changed. - if (Platform.isWindows) { - final tgtWidth = (width * scale).toInt(); - final tgtHeight = (width * scale).toInt(); - if (tgtWidth < kMinCursorSize || tgtHeight < kMinCursorSize) { - double sw = kMinCursorSize.toDouble() / width; - double sh = kMinCursorSize.toDouble() / height; - scale = sw < sh ? sh : sw; - } + final tgtWidth = (width * scale).toInt(); + final tgtHeight = (width * scale).toInt(); + if (tgtWidth < kMinCursorSize || tgtHeight < kMinCursorSize) { + double sw = kMinCursorSize.toDouble() / width; + double sh = kMinCursorSize.toDouble() / height; + scale = sw < sh ? sh : sw; } } - if (Platform.isWindows) { - if (_doubleToInt(oldScale) != _doubleToInt(scale)) { - data = img2 - .copyResize( - image!, - width: (width * scale).toInt(), - height: (height * scale).toInt(), - interpolation: img2.Interpolation.average, - ) - .getBytes(format: img2.Format.bgra); - } + if (_doubleToInt(oldScale) != _doubleToInt(scale)) { + data = img2 + .copyResize( + image!, + width: (width * scale).toInt(), + height: (height * scale).toInt(), + interpolation: img2.Interpolation.average, + ) + .getBytes(format: img2.Format.bgra); } this.scale = scale; From 8881462f748068a6118196212c9f98aebe4e3a31 Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 1 Feb 2023 22:12:28 +0800 Subject: [PATCH 53/83] debug macos Signed-off-by: fufesou --- flutter/lib/models/model.dart | 37 +++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 78e6ce6af..b2df5faac 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -747,7 +747,7 @@ class CanvasModel with ChangeNotifier { class CursorData { final String peerId; final int id; - final img2.Image? image; + final img2.Image image; double scale; Uint8List? data; final double hotxOrigin; @@ -788,14 +788,27 @@ class CursorData { } if (_doubleToInt(oldScale) != _doubleToInt(scale)) { - data = img2 - .copyResize( - image!, - width: (width * scale).toInt(), - height: (height * scale).toInt(), - interpolation: img2.Interpolation.average, - ) - .getBytes(format: img2.Format.bgra); + if (Platform.isWindows) { + data = img2 + .copyResize( + image, + width: (width * scale).toInt(), + height: (height * scale).toInt(), + interpolation: img2.Interpolation.average, + ) + .getBytes(format: img2.Format.bgra); + } else { + data = Uint8List.fromList( + img2.encodePng( + img2.copyResize( + image, + width: (width * scale).toInt(), + height: (height * scale).toInt(), + interpolation: img2.Interpolation.average, + ), + ), + ); + } } this.scale = scale; @@ -863,7 +876,7 @@ class PredefinedCursor { _cache = CursorData( peerId: '', id: id, - image: _image2?.clone(), + image: _image2!.clone(), scale: scale, data: data, hotxOrigin: @@ -1063,9 +1076,9 @@ class CursorModel with ChangeNotifier { Future _updateCache( Uint8List rgba, ui.Image image, int id, int w, int h) async { Uint8List? data; - img2.Image? imgOrigin; + img2.Image imgOrigin = + img2.Image.fromBytes(w, h, rgba, format: img2.Format.rgba); if (Platform.isWindows) { - imgOrigin = img2.Image.fromBytes(w, h, rgba, format: img2.Format.rgba); data = imgOrigin.getBytes(format: img2.Format.bgra); } else { ByteData? imgBytes = From b5fbc23cb9b9fc7ba915e1024085d8ac7ad1bf18 Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 2 Feb 2023 12:39:39 +0800 Subject: [PATCH 54/83] zoom system cursor when view scale is adaptive Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 21 ++++++----- .../lib/desktop/widgets/remote_menubar.dart | 37 ++++++++++--------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 1687f348e..1ce9dec4a 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -362,10 +362,10 @@ class _RemotePageState extends State class ImagePaint extends StatefulWidget { final String id; - final Rx zoomCursor; - final Rx cursorOverImage; - final Rx keyboardEnabled; - final Rx remoteCursorMoved; + final RxBool zoomCursor; + final RxBool cursorOverImage; + final RxBool keyboardEnabled; + final RxBool remoteCursorMoved; final Widget Function(Widget)? listenerBuilder; ImagePaint( @@ -388,10 +388,10 @@ class _ImagePaintState extends State { final ScrollController _vertical = ScrollController(); String get id => widget.id; - Rx get zoomCursor => widget.zoomCursor; - Rx get cursorOverImage => widget.cursorOverImage; - Rx get keyboardEnabled => widget.keyboardEnabled; - Rx get remoteCursorMoved => widget.remoteCursorMoved; + RxBool get zoomCursor => widget.zoomCursor; + RxBool get cursorOverImage => widget.cursorOverImage; + RxBool get keyboardEnabled => widget.keyboardEnabled; + RxBool get remoteCursorMoved => widget.remoteCursorMoved; Widget Function(Widget)? get listenerBuilder => widget.listenerBuilder; @override @@ -466,7 +466,10 @@ class _ImagePaintState extends State { if (cache == null) { return MouseCursor.defer; } else { - final key = cache.updateGetKey(scale, zoomCursor.value); + final isViewAdaptive = + Provider.of(context, listen: false).viewStyle.style == + kRemoteViewStyleAdaptive; + final key = cache.updateGetKey(scale, zoomCursor.value && isViewAdaptive); if (!cursor.cachedKeys.contains(key)) { debugPrint("Register custom cursor with key $key"); // [Safety] diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 4f16f8227..517dc9750 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -1133,23 +1133,26 @@ class _RemoteMenubarState extends State { }()); } - displayMenu.add(() { - final opt = 'zoom-cursor'; - final state = PeerBoolOption.find(widget.id, opt); - return MenuEntrySwitch2( - switchType: SwitchType.scheckbox, - text: translate('Zoom cursor'), - getter: () { - return state; - }, - setter: (bool v) async { - state.value = v; - await bind.sessionToggleOption(id: widget.id, value: opt); - }, - padding: padding, - dismissOnClicked: true, - ); - }()); + /// Show remote cursor scaling with image + if (widget.state.viewStyle.value != kRemoteViewStyleOriginal) { + displayMenu.add(() { + final opt = 'zoom-cursor'; + final state = PeerBoolOption.find(widget.id, opt); + return MenuEntrySwitch2( + switchType: SwitchType.scheckbox, + text: translate('Zoom cursor'), + getter: () { + return state; + }, + setter: (bool v) async { + state.value = v; + await bind.sessionToggleOption(id: widget.id, value: opt); + }, + padding: padding, + dismissOnClicked: true, + ); + }()); + } /// Show quality monitor displayMenu.add(MenuEntrySwitch( From 77ee60c8dc730af4b6658119b452cd1d417bba66 Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 2 Feb 2023 12:47:39 +0800 Subject: [PATCH 55/83] scale remote cursor when view style is adaptive Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 1ce9dec4a..858157853 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -635,7 +635,8 @@ class CursorPaint extends StatelessWidget { double x = (m.x - hotx) * c.scale + cx; double y = (m.y - hoty) * c.scale + cy; double scale = 1.0; - if (zoomCursor.isTrue) { + final isViewAdaptive = c.viewStyle.style == kRemoteViewStyleAdaptive; + if (zoomCursor.isTrue && isViewAdaptive) { x = m.x - hotx + cx / c.scale; y = m.y - hoty + cy / c.scale; scale = c.scale; From aafc2e0a8e4d0525b19ad011936354d6802bfb84 Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 2 Feb 2023 13:08:41 +0800 Subject: [PATCH 56/83] zoom cursor on different OSs Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 28 +++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 858157853..dd71797f3 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -466,10 +466,19 @@ class _ImagePaintState extends State { if (cache == null) { return MouseCursor.defer; } else { - final isViewAdaptive = - Provider.of(context, listen: false).viewStyle.style == - kRemoteViewStyleAdaptive; - final key = cache.updateGetKey(scale, zoomCursor.value && isViewAdaptive); + bool shouldScale = false; + if (Platform.isWindows) { + final isViewAdaptive = + Provider.of(context, listen: false).viewStyle.style == + kRemoteViewStyleAdaptive; + shouldScale = zoomCursor.value && isViewAdaptive; + } else { + final isViewOriginal = + Provider.of(context, listen: false).viewStyle.style == + kRemoteViewStyleOriginal; + shouldScale = zoomCursor.value || isViewOriginal; + } + final key = cache.updateGetKey(scale, shouldScale); if (!cursor.cachedKeys.contains(key)) { debugPrint("Register custom cursor with key $key"); // [Safety] @@ -635,8 +644,15 @@ class CursorPaint extends StatelessWidget { double x = (m.x - hotx) * c.scale + cx; double y = (m.y - hoty) * c.scale + cy; double scale = 1.0; - final isViewAdaptive = c.viewStyle.style == kRemoteViewStyleAdaptive; - if (zoomCursor.isTrue && isViewAdaptive) { + bool shouldScale = false; + if (Platform.isWindows) { + final isViewAdaptive = c.viewStyle.style == kRemoteViewStyleAdaptive; + shouldScale = zoomCursor.value && isViewAdaptive; + } else { + final isViewOriginal = c.viewStyle.style == kRemoteViewStyleOriginal; + shouldScale = zoomCursor.value || isViewOriginal; + } + if (shouldScale) { x = m.x - hotx + cx / c.scale; y = m.y - hoty + cy / c.scale; scale = c.scale; From d511d1e27a024847a50d31ec85392478907dccd6 Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 2 Feb 2023 13:40:13 +0800 Subject: [PATCH 57/83] zoom remote cursor when view style is original Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index dd71797f3..f38cdfb6e 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -644,15 +644,8 @@ class CursorPaint extends StatelessWidget { double x = (m.x - hotx) * c.scale + cx; double y = (m.y - hoty) * c.scale + cy; double scale = 1.0; - bool shouldScale = false; - if (Platform.isWindows) { - final isViewAdaptive = c.viewStyle.style == kRemoteViewStyleAdaptive; - shouldScale = zoomCursor.value && isViewAdaptive; - } else { - final isViewOriginal = c.viewStyle.style == kRemoteViewStyleOriginal; - shouldScale = zoomCursor.value || isViewOriginal; - } - if (shouldScale) { + final isViewOriginal = c.viewStyle.style == kRemoteViewStyleOriginal; + if (zoomCursor.value || isViewOriginal) { x = m.x - hotx + cx / c.scale; y = m.y - hoty + cy / c.scale; scale = c.scale; From f9e3a3f074ffc3cfc43e398abb712d631497e930 Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 2 Feb 2023 14:39:58 +0800 Subject: [PATCH 58/83] zoom cursor with dpi Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 32 ++++++++++++---------- flutter/lib/models/model.dart | 15 +++++----- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index f38cdfb6e..f7889d008 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -399,6 +399,20 @@ class _ImagePaintState extends State { final m = Provider.of(context); var c = Provider.of(context); final s = c.scale; + var cursorScale = 1.0; + + if (Platform.isWindows) { + // debug win10 + final isViewAdaptive = c.viewStyle.style == kRemoteViewStyleAdaptive; + if (zoomCursor.value && isViewAdaptive) { + cursorScale = s * c.devicePixelRatio; + } + } else { + final isViewOriginal = c.viewStyle.style == kRemoteViewStyleOriginal; + if (zoomCursor.value || isViewOriginal) { + cursorScale = s; + } + } mouseRegion({child}) => Obx(() => MouseRegion( cursor: cursorOverImage.isTrue @@ -414,10 +428,10 @@ class _ImagePaintState extends State { _lastRemoteCursorMoved = false; _firstEnterImage.value = true; } - return _buildCustomCursor(context, s); + return _buildCustomCursor(context, cursorScale); } }()) - : _buildDisabledCursor(context, s) + : _buildDisabledCursor(context, cursorScale) : MouseCursor.defer, onHover: (evt) {}, child: child)); @@ -466,19 +480,7 @@ class _ImagePaintState extends State { if (cache == null) { return MouseCursor.defer; } else { - bool shouldScale = false; - if (Platform.isWindows) { - final isViewAdaptive = - Provider.of(context, listen: false).viewStyle.style == - kRemoteViewStyleAdaptive; - shouldScale = zoomCursor.value && isViewAdaptive; - } else { - final isViewOriginal = - Provider.of(context, listen: false).viewStyle.style == - kRemoteViewStyleOriginal; - shouldScale = zoomCursor.value || isViewOriginal; - } - final key = cache.updateGetKey(scale, shouldScale); + final key = cache.updateGetKey(scale); if (!cursor.cachedKeys.contains(key)) { debugPrint("Register custom cursor with key $key"); // [Safety] diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index b2df5faac..f49bb270c 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -540,6 +540,7 @@ class CanvasModel with ChangeNotifier { double _y = 0; // image scale double _scale = 1.0; + double _devicePixelRatio = 1.0; Size _size = Size.zero; // the tabbar over the image // double tabBarHeight = 0.0; @@ -563,6 +564,7 @@ class CanvasModel with ChangeNotifier { double get x => _x; double get y => _y; double get scale => _scale; + double get devicePixelRatio => _devicePixelRatio; Size get size => _size; ScrollStyle get scrollStyle => _scrollStyle; ViewStyle get viewStyle => _lastViewStyle; @@ -611,8 +613,9 @@ class CanvasModel with ChangeNotifier { _lastViewStyle = viewStyle; _scale = viewStyle.scale; + _devicePixelRatio = ui.window.devicePixelRatio; if (kIgnoreDpi && style == kRemoteViewStyleOriginal) { - _scale = 1.0 / ui.window.devicePixelRatio; + _scale = 1.0 / _devicePixelRatio; } _x = (size.width - displayWidth * _scale) / 2; _y = (size.height - displayHeight * _scale) / 2; @@ -772,11 +775,9 @@ class CursorData { int _doubleToInt(double v) => (v * 10e6).round().toInt(); - double _checkUpdateScale(double scale, bool shouldScale) { + double _checkUpdateScale(double scale) { double oldScale = this.scale; - if (!shouldScale) { - scale = 1.0; - } else { + if (scale != 1.0) { // Update data if scale changed. final tgtWidth = (width * scale).toInt(); final tgtHeight = (width * scale).toInt(); @@ -817,8 +818,8 @@ class CursorData { return scale; } - String updateGetKey(double scale, bool shouldScale) { - scale = _checkUpdateScale(scale, shouldScale); + String updateGetKey(double scale) { + scale = _checkUpdateScale(scale); return '${peerId}_${id}_${_doubleToInt(width * scale)}_${_doubleToInt(height * scale)}'; } } From 40a75e3dfab6707f3a87a36aee1a9f57460d8df1 Mon Sep 17 00:00:00 2001 From: "Miguel F. G" <116861809+flusheDData@users.noreply.github.com> Date: Thu, 2 Feb 2023 08:49:12 +0100 Subject: [PATCH 59/83] Update es.rs New 'Default' terms added. --- src/lang/es.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lang/es.rs b/src/lang/es.rs index 6f866845c..5fdb7ee2c 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -436,14 +436,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", "Intercambiar lados"), ("Please confirm if you want to share your desktop?", "Por favor, confirma si quieres compartir tu escritorio"), ("Closed as expected", "Cerrado como se esperaba"), - ("Display", ""), - ("Default View Style", ""), - ("Default Scroll Style", ""), - ("Default Image Quality", ""), - ("Default Codec", ""), - ("Bitrate", ""), + ("Display", "Pantalla"), + ("Default View Style", "Estilo de vista predeterminado"), + ("Default Scroll Style", "Estilo de desplazamiento predeterminado"), + ("Default Image Quality", "Calidad de imagen predeterminada"), + ("Default Codec", "Códec predeterminado"), + ("Bitrate", "Tasa de bits"), ("FPS", ""), ("Auto", ""), - ("Other Default Options", ""), + ("Other Default Options", "Otras opciones predeterminadas"), ].iter().cloned().collect(); } From 0d9d506dac843986685c69ca72fdfd553d217f78 Mon Sep 17 00:00:00 2001 From: NicKoehler <53040044+NicKoehler@users.noreply.github.com> Date: Thu, 2 Feb 2023 14:48:22 +0100 Subject: [PATCH 60/83] Update it.rs --- src/lang/it.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lang/it.rs b/src/lang/it.rs index 6edd4a461..d84b56a8a 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -436,14 +436,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", "Cambia lato"), ("Please confirm if you want to share your desktop?", "Vuoi condividere il tuo desktop?"), ("Closed as expected", "Chiuso come previsto"), - ("Display", ""), - ("Default View Style", ""), - ("Default Scroll Style", ""), - ("Default Image Quality", ""), - ("Default Codec", ""), - ("Bitrate", ""), - ("FPS", ""), - ("Auto", ""), - ("Other Default Options", ""), + ("Display", "Visualizzazione"), + ("Default View Style", "Stile Visualizzazione Predefinito"), + ("Default Scroll Style", "Stile Scorrimento Predefinito"), + ("Default Image Quality", "Qualità Immagine Predefinita"), + ("Default Codec", "Codec Predefinito"), + ("Bitrate", "Bitrate"), + ("FPS", "FPS"), + ("Auto", "Auto"), + ("Other Default Options", "Altre Opzioni Predefinite"), ].iter().cloned().collect(); } From 1a1bd1b5d8c6be911451e288b577092795d967f4 Mon Sep 17 00:00:00 2001 From: 21pages Date: Thu, 2 Feb 2023 16:45:29 +0800 Subject: [PATCH 61/83] recover reordered peer tab, because flutter 3.7.0 fix ReorderableListView crash Signed-off-by: 21pages --- flutter/lib/common/widgets/peer_tab_page.dart | 235 +++++++++++++----- 1 file changed, 168 insertions(+), 67 deletions(-) diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index 278f5861c..fff5e2ffd 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:ui' as ui; import 'package:bot_toast/bot_toast.dart'; @@ -20,7 +21,9 @@ const int groupTabIndex = 4; const String defaultGroupTabname = 'Group'; class StatePeerTab { - final RxInt currentTab = 0.obs; + final RxInt currentTab = 0.obs; // index in tabNames + final RxList visibleOrderedTabs = RxList.empty(growable: true); + List tabOrder = List.from([0, 1, 2, 3, 4]); // constant length final RxInt tabHiddenFlag = 0.obs; final RxList tabNames = [ 'Recent Sessions', @@ -31,53 +34,80 @@ class StatePeerTab { ].obs; StatePeerTab._() { + // init tabHiddenFlag tabHiddenFlag.value = (int.tryParse( bind.getLocalFlutterConfig(k: 'hidden-peer-card'), radix: 2) ?? 0); var tabs = _notHiddenTabs(); + // remove dynamic tabs + tabs.remove(groupTabIndex); + // init tabOrder + try { + final conf = bind.getLocalFlutterConfig(k: 'peer-tab-order'); + if (conf.isNotEmpty) { + final json = jsonDecode(conf); + if (json is List) { + final List list = + json.map((e) => int.tryParse(e.toString()) ?? -1).toList(); + if (list.length == tabOrder.length && + tabOrder.every((e) => list.contains(e))) { + tabOrder = list; + } + } + } + } catch (e) { + debugPrintStack(label: '$e'); + } + // init visibleOrderedTabs + var tempList = tabOrder.toList(); + tempList.removeWhere((e) => !tabs.contains(e)); + visibleOrderedTabs.value = tempList; + // init currentTab currentTab.value = int.tryParse(bind.getLocalFlutterConfig(k: 'peer-tab-index')) ?? 0; if (!tabs.contains(currentTab.value)) { - currentTab.value = 0; + if (tabs.isNotEmpty) { + currentTab.value = tabs[0]; + } else { + currentTab.value = 0; + } } } static final StatePeerTab instance = StatePeerTab._(); + // check dynamic tabs check() { - var tabs = _notHiddenTabs(); - if (filterGroupCard()) { - if (currentTab.value == groupTabIndex) { - currentTab.value = - tabs.firstWhereOrNull((e) => e != groupTabIndex) ?? 0; - bind.setLocalFlutterConfig( - k: 'peer-tab-index', v: currentTab.value.toString()); - } + tabOrder2visibleOrderedTabs(); + if (visibleOrderedTabs.contains(groupTabIndex) && + int.tryParse(bind.getLocalFlutterConfig(k: 'peer-tab-index')) == + groupTabIndex) { + currentTab.value = groupTabIndex; + } + if (gFFI.userModel.isAdmin.isFalse && gFFI.userModel.groupName.isNotEmpty) { + tabNames[groupTabIndex] = gFFI.userModel.groupName.value; } else { - if (gFFI.userModel.isAdmin.isFalse && - gFFI.userModel.groupName.isNotEmpty) { - tabNames[groupTabIndex] = gFFI.userModel.groupName.value; - } else { - tabNames[groupTabIndex] = defaultGroupTabname; - } - if (tabs.contains(groupTabIndex) && - int.tryParse(bind.getLocalFlutterConfig(k: 'peer-tab-index')) == - groupTabIndex) { - currentTab.value = groupTabIndex; - } + tabNames[groupTabIndex] = defaultGroupTabname; } } - List currentTabs() { - var v = List.empty(growable: true); - for (int i = 0; i < tabNames.length; i++) { - if (!_isTabHidden(i) && !_isTabFilter(i)) { - v.add(i); - } + visibleOrderedTabs2TabOrder() { + var tmpTabOrder = visibleOrderedTabs.toList(); + var left = tabOrder.where((e) => !tmpTabOrder.contains(e)).toList(); + for (var t in left) { + _addTabInOrder(tmpTabOrder, t); } - return v; + statePeerTab.tabOrder = tmpTabOrder; + bind.setLocalFlutterConfig(k: 'peer-tab-order', v: jsonEncode(tmpTabOrder)); } + tabOrder2visibleOrderedTabs() { + var visible = statePeerTab.visibleTabs(); + statePeerTab.visibleOrderedTabs.value = + statePeerTab.tabOrder.where((e) => visible.contains(e)).toList(); + } + + // return true if hide group card bool filterGroupCard() { if (gFFI.groupModel.users.isEmpty || (gFFI.userModel.isAdmin.isFalse && gFFI.userModel.groupName.isEmpty)) { @@ -87,6 +117,17 @@ class StatePeerTab { } } + // return index array of tabNames + List visibleTabs() { + var v = List.empty(growable: true); + for (int i = 0; i < tabNames.length; i++) { + if (!_isTabHidden(i) && !_isTabFilter(i)) { + v.add(i); + } + } + return v; + } + bool _isTabHidden(int tabindex) { return tabHiddenFlag & (1 << tabindex) != 0; } @@ -107,6 +148,41 @@ class StatePeerTab { } return v; } + + // add tabIndex to list + _addTabInOrder(List list, int tabIndex) { + if (!tabOrder.contains(tabIndex) || list.contains(tabIndex)) { + return; + } + bool sameOrder = true; + int lastIndex = -1; + for (int i = 0; i < list.length; i++) { + var index = tabOrder.lastIndexOf(list[i]); + if (index > lastIndex) { + lastIndex = index; + continue; + } else { + sameOrder = false; + break; + } + } + if (sameOrder) { + var indexInTabOrder = tabOrder.indexOf(tabIndex); + var left = List.empty(growable: true); + for (int i = 0; i < indexInTabOrder; i++) { + left.add(tabOrder[i]); + } + int insertIndex = list.lastIndexWhere((e) => left.contains(e)); + if (insertIndex < 0) { + insertIndex = 0; + } else { + insertIndex += 1; + } + list.insert(insertIndex, tabIndex); + } else { + list.add(tabIndex); + } + } } final statePeerTab = StatePeerTab.instance; @@ -177,11 +253,6 @@ class _PeerTabPageState extends State } } - @override - void dispose() { - super.dispose(); - } - @override Widget build(BuildContext context) { return Column( @@ -215,40 +286,57 @@ class _PeerTabPageState extends State Widget _createSwitchBar(BuildContext context) { final textColor = Theme.of(context).textTheme.titleLarge?.color; return Obx(() { - var tabs = statePeerTab.currentTabs(); - return ListView( + var tabs = statePeerTab.visibleOrderedTabs; + int indexCounter = -1; + return ReorderableListView( + buildDefaultDragHandles: false, + onReorder: (oldIndex, newIndex) { + if (oldIndex < newIndex) { + newIndex -= 1; + } + var list = tabs.toList(); + final int item = list.removeAt(oldIndex); + list.insert(newIndex, item); + tabs.value = list; + statePeerTab.visibleOrderedTabs2TabOrder(); + }, scrollDirection: Axis.horizontal, physics: NeverScrollableScrollPhysics(), - controller: ScrollController(), + scrollController: ScrollController(), children: tabs.map((t) { - return InkWell( - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 8), - decoration: BoxDecoration( - color: statePeerTab.currentTab.value == t - ? Theme.of(context).backgroundColor - : null, - borderRadius: BorderRadius.circular(isDesktop ? 2 : 6), - ), - child: Align( - alignment: Alignment.center, - child: Text( - translatedTabname(t), - textAlign: TextAlign.center, - style: TextStyle( - height: 1, - fontSize: 14, - color: statePeerTab.currentTab.value == t - ? textColor - : textColor - ?..withOpacity(0.5)), + indexCounter++; + return ReorderableDragStartListener( + key: ValueKey(t), + index: indexCounter, + child: InkWell( + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 8), + decoration: BoxDecoration( + color: statePeerTab.currentTab.value == t + ? Theme.of(context).backgroundColor + : null, + borderRadius: BorderRadius.circular(isDesktop ? 2 : 6), ), - )), - onTap: () async { - await handleTabSelection(t); - await bind.setLocalFlutterConfig( - k: 'peer-tab-index', v: t.toString()); - }, + child: Align( + alignment: Alignment.center, + child: Text( + translatedTabname(t), + textAlign: TextAlign.center, + style: TextStyle( + height: 1, + fontSize: 14, + color: statePeerTab.currentTab.value == t + ? textColor + : textColor + ?..withOpacity(0.5)), + ), + )), + onTap: () async { + await handleTabSelection(t); + await bind.setLocalFlutterConfig( + k: 'peer-tab-index', v: t.toString()); + }, + ), ); }).toList()); }); @@ -275,7 +363,7 @@ class _PeerTabPageState extends State final verticalMargin = isDesktop ? 12.0 : 6.0; return Expanded( child: Obx(() { - var tabs = statePeerTab.currentTabs(); + var tabs = statePeerTab.visibleOrderedTabs; if (tabs.isEmpty) { return visibleContextMenuListener(Center( child: Text(translate('Right click to select tabs')), @@ -322,7 +410,7 @@ class _PeerTabPageState extends State } adjustTab() { - var tabs = statePeerTab.currentTabs(); + var tabs = statePeerTab.visibleOrderedTabs; if (tabs.isNotEmpty && !tabs.contains(statePeerTab.currentTab.value)) { statePeerTab.currentTab.value = tabs[0]; } @@ -349,11 +437,13 @@ class _PeerTabPageState extends State Widget visibleContextMenu(CancelFunc cancelFunc) { return Obx(() { final List menu = List.empty(growable: true); + final List menuIndex = List.empty(growable: true); for (int i = 0; i < statePeerTab.tabNames.length; i++) { if (i == groupTabIndex && statePeerTab.filterGroupCard()) { continue; } int bitMask = 1 << i; + menuIndex.add(i); menu.add(MenuEntrySwitch( switchType: SwitchType.scheckbox, text: translatedTabname(i), @@ -369,12 +459,21 @@ class _PeerTabPageState extends State await bind.setLocalFlutterConfig( k: 'hidden-peer-card', v: statePeerTab.tabHiddenFlag.value.toRadixString(2)); + statePeerTab.tabOrder2visibleOrderedTabs(); cancelFunc(); adjustTab(); })); } + // show in tabOrder + List menu2 = List.empty(growable: true); + statePeerTab.tabOrder.map((e) { + final index = menuIndex.indexOf(e); + if (index >= 0) { + menu2.add(menu[index]); + } + }).toList(); return mod_menu.PopupMenu( - items: menu + items: menu2 .map((entry) => entry.build( context, const MenuConfig( @@ -421,7 +520,9 @@ class _PeerSearchBarState extends State { FocusNode focusNode = FocusNode(); focusNode.addListener(() { focused.value = focusNode.hasFocus; - peerSearchTextController.selection = TextSelection(baseOffset: 0, extentOffset: peerSearchTextController.value.text.length); + peerSearchTextController.selection = TextSelection( + baseOffset: 0, + extentOffset: peerSearchTextController.value.text.length); }); return Container( width: 120, From 50c8855d2816897527fb65c4cd01c8e1f7f16c6a Mon Sep 17 00:00:00 2001 From: rustdesk Date: Fri, 3 Feb 2023 16:18:08 +0800 Subject: [PATCH 62/83] unify peer tab text color with tab bar text color --- flutter/lib/common/widgets/peer_tab_page.dart | 5 ++--- flutter/pubspec.lock | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index fff5e2ffd..150121c59 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -284,7 +284,6 @@ class _PeerTabPageState extends State } Widget _createSwitchBar(BuildContext context) { - final textColor = Theme.of(context).textTheme.titleLarge?.color; return Obx(() { var tabs = statePeerTab.visibleOrderedTabs; int indexCounter = -1; @@ -326,8 +325,8 @@ class _PeerTabPageState extends State height: 1, fontSize: 14, color: statePeerTab.currentTab.value == t - ? textColor - : textColor + ? MyTheme.tabbar(context).selectedTextColor + : MyTheme.tabbar(context).unSelectedTextColor ?..withOpacity(0.5)), ), )), diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index c193c0651..ebb105178 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -475,10 +475,10 @@ packages: dependency: "direct main" description: name: flutter_custom_cursor - sha256: "6c5204cf6a16650355b8aa47a8402e79922c07641390a32021a1069b561909ec" + sha256: "3850a32ac6de351ccc5e4286b6d94ff70c10abecd44479ea6c5aaea17264285d" url: "https://pub.dev" source: hosted - version: "0.0.3" + version: "0.0.4" flutter_improved_scrolling: dependency: "direct main" description: From e05b95743c2f67bfaee077f4338007c9c6e16238 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 3 Feb 2023 17:02:28 +0800 Subject: [PATCH 63/83] cursor position and size update Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 77 +++++++++++-------- .../widgets/material_mod_popup_menu.dart | 16 +++- .../lib/desktop/widgets/remote_menubar.dart | 22 ++++-- flutter/lib/models/input_model.dart | 2 - flutter/lib/models/model.dart | 2 +- 5 files changed, 74 insertions(+), 45 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index f7889d008..0e0127312 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -399,42 +399,51 @@ class _ImagePaintState extends State { final m = Provider.of(context); var c = Provider.of(context); final s = c.scale; - var cursorScale = 1.0; - if (Platform.isWindows) { - // debug win10 - final isViewAdaptive = c.viewStyle.style == kRemoteViewStyleAdaptive; - if (zoomCursor.value && isViewAdaptive) { - cursorScale = s * c.devicePixelRatio; - } - } else { - final isViewOriginal = c.viewStyle.style == kRemoteViewStyleOriginal; - if (zoomCursor.value || isViewOriginal) { - cursorScale = s; - } - } + mouseRegion({child}) => Obx(() { + double getCursorScale() { + var c = Provider.of(context); + var cursorScale = 1.0; + if (Platform.isWindows) { + // debug win10 + final isViewAdaptive = + c.viewStyle.style == kRemoteViewStyleAdaptive; + if (zoomCursor.value && isViewAdaptive) { + cursorScale = s * c.devicePixelRatio; + } + } else { + final isViewOriginal = + c.viewStyle.style == kRemoteViewStyleOriginal; + if (zoomCursor.value || isViewOriginal) { + cursorScale = s; + } + } + return cursorScale; + } - mouseRegion({child}) => Obx(() => MouseRegion( - cursor: cursorOverImage.isTrue - ? c.cursorEmbedded - ? SystemMouseCursors.none - : keyboardEnabled.isTrue - ? (() { - if (remoteCursorMoved.isTrue) { - _lastRemoteCursorMoved = true; - return SystemMouseCursors.none; - } else { - if (_lastRemoteCursorMoved) { - _lastRemoteCursorMoved = false; - _firstEnterImage.value = true; - } - return _buildCustomCursor(context, cursorScale); - } - }()) - : _buildDisabledCursor(context, cursorScale) - : MouseCursor.defer, - onHover: (evt) {}, - child: child)); + return MouseRegion( + cursor: cursorOverImage.isTrue + ? c.cursorEmbedded + ? SystemMouseCursors.none + : keyboardEnabled.isTrue + ? (() { + if (remoteCursorMoved.isTrue) { + _lastRemoteCursorMoved = true; + return SystemMouseCursors.none; + } else { + if (_lastRemoteCursorMoved) { + _lastRemoteCursorMoved = false; + _firstEnterImage.value = true; + } + return _buildCustomCursor( + context, getCursorScale()); + } + }()) + : _buildDisabledCursor(context, getCursorScale()) + : MouseCursor.defer, + onHover: (evt) {}, + child: child); + }); if (c.imageOverflow.isTrue && c.scrollStyle == ScrollStyle.scrollbar) { final imageWidth = c.getDisplayWidth() * s; diff --git a/flutter/lib/desktop/widgets/material_mod_popup_menu.dart b/flutter/lib/desktop/widgets/material_mod_popup_menu.dart index a371e8f52..666c9a6e2 100644 --- a/flutter/lib/desktop/widgets/material_mod_popup_menu.dart +++ b/flutter/lib/desktop/widgets/material_mod_popup_menu.dart @@ -790,6 +790,7 @@ class _PopupMenuRoute extends PopupRoute { _PopupMenuRoute({ required this.position, required this.items, + this.menuWrapper, this.initialValue, this.elevation, required this.barrierLabel, @@ -802,6 +803,7 @@ class _PopupMenuRoute extends PopupRoute { final RelativeRect position; final List> items; + final MenuWrapper? menuWrapper; final List itemSizes; final T? initialValue; final double? elevation; @@ -844,11 +846,14 @@ class _PopupMenuRoute extends PopupRoute { } } - final Widget menu = _PopupMenu( + Widget menu = _PopupMenu( route: this, semanticLabel: semanticLabel, constraints: constraints, ); + if (this.menuWrapper != null) { + menu = this.menuWrapper!(menu); + } final MediaQueryData mediaQuery = MediaQuery.of(context); return MediaQuery.removePadding( context: context, @@ -1035,6 +1040,7 @@ Future showMenu({ required BuildContext context, required RelativeRect position, required List> items, + MenuWrapper? menuWrapper, T? initialValue, double? elevation, String? semanticLabel, @@ -1062,6 +1068,7 @@ Future showMenu({ return navigator.push(_PopupMenuRoute( position: position, items: items, + menuWrapper: menuWrapper, initialValue: initialValue, elevation: elevation, semanticLabel: semanticLabel, @@ -1094,6 +1101,8 @@ typedef PopupMenuCanceled = void Function(); typedef PopupMenuItemBuilder = List> Function( BuildContext context); +typedef MenuWrapper = Widget Function(Widget child); + /// Displays a menu when pressed and calls [onSelected] when the menu is dismissed /// because an item was selected. The value passed to [onSelected] is the value of /// the selected menu item. @@ -1124,6 +1133,7 @@ class PopupMenuButton extends StatefulWidget { const PopupMenuButton({ Key? key, required this.itemBuilder, + this.menuWrapper, this.initialValue, this.onHover, this.onSelected, @@ -1151,6 +1161,9 @@ class PopupMenuButton extends StatefulWidget { /// Called when the button is pressed to create the items to show in the menu. final PopupMenuItemBuilder itemBuilder; + /// Menu wrapper. + final MenuWrapper? menuWrapper; + /// The value of the menu item, if any, that should be highlighted when the menu opens. final T? initialValue; @@ -1333,6 +1346,7 @@ class PopupMenuButtonState extends State> { context: context, elevation: widget.elevation ?? popupMenuTheme.elevation, items: items, + menuWrapper: widget.menuWrapper, initialValue: widget.initialValue, position: position, shape: widget.shape ?? popupMenuTheme.shape, diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 64d289fcc..db1721d99 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -221,6 +221,16 @@ class _RemoteMenubarState extends State { } } + Widget _buildPointerTrackWidget(Widget child) { + return Listener( + onPointerHover: (PointerHoverEvent e) => + widget.ffi.inputModel.lastMousePos = e.position, + child: MouseRegion( + child: child, + ), + ); + } + Widget _buildMenubar(BuildContext context) { final List menubarItems = []; if (!isWebDesktop) { @@ -379,13 +389,10 @@ class _RemoteMenubarState extends State { mod_menu.PopupMenuItem( height: _MenubarTheme.height, padding: EdgeInsets.zero, - child: Listener( - onPointerHover: (PointerHoverEvent e) => - widget.ffi.inputModel.lastMousePos = e.position, - child: MouseRegion( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: rowChildren), + child: _buildPointerTrackWidget( + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: rowChildren, ), ), ) @@ -435,6 +442,7 @@ class _RemoteMenubarState extends State { ), tooltip: translate('Display Settings'), position: mod_menu.PopupMenuPosition.under, + menuWrapper: _buildPointerTrackWidget, itemBuilder: (BuildContext context) => _getDisplayMenu(snapshot.data!, remoteCount) .map((entry) => entry.build( diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index d2f671cdc..8c37f50bd 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -310,7 +310,6 @@ class InputModel { } } - int _signOrZero(num x) { if (x == 0) { return 0; @@ -362,7 +361,6 @@ class InputModel { trackpadScrollDistance = Offset.zero; } - void onPointDownImage(PointerDownEvent e) { debugPrint("onPointDownImage"); if (e.kind != ui.PointerDeviceKind.mouse) { diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index f49bb270c..da711bf13 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -244,7 +244,6 @@ class FfiModel with ChangeNotifier { parent.target?.canvasModel.updateViewStyle(); } parent.target?.recordingModel.onSwitchDisplay(); - parent.target?.inputModel.refreshMousePos(); notifyListeners(); } @@ -621,6 +620,7 @@ class CanvasModel with ChangeNotifier { _y = (size.height - displayHeight * _scale) / 2; _imageOverflow.value = _x < 0 || y < 0; notifyListeners(); + parent.target?.inputModel.refreshMousePos(); } updateScrollStyle() async { From 17aac13247a94bbf35a8a169a4b50f8a4b14a9f4 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 3 Feb 2023 18:28:47 +0800 Subject: [PATCH 64/83] ignore first update cursor postion Signed-off-by: fufesou --- flutter/lib/desktop/widgets/remote_menubar.dart | 3 ++- flutter/lib/models/model.dart | 7 ++++++- src/client.rs | 8 ++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index db1721d99..2a84dcf14 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -1157,8 +1157,9 @@ class _RemoteMenubarState extends State { return state; }, setter: (bool v) async { - state.value = v; await bind.sessionToggleOption(id: widget.id, value: opt); + state.value = + bind.sessionGetToggleOptionSync(id: widget.id, arg: opt); }, padding: padding, dismissOnClicked: true, diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index da711bf13..8a7a1005d 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -904,6 +904,7 @@ class CursorModel with ChangeNotifier { double _hoty = 0; double _displayOriginX = 0; double _displayOriginY = 0; + bool _firstUpdateMousePos = false; bool gotMouseControl = true; DateTime _lastPeerMouse = DateTime.now() .subtract(Duration(milliseconds: 2 * kMouseControlTimeoutMSec)); @@ -1121,7 +1122,11 @@ class CursorModel with ChangeNotifier { /// Update the cursor position. updateCursorPosition(Map evt, String id) async { - gotMouseControl = false; + if (!_firstUpdateMousePos) { + _firstUpdateMousePos = true; + } else { + gotMouseControl = false; + } _lastPeerMouse = DateTime.now(); _x = double.parse(evt['x']); _y = double.parse(evt['y']); diff --git a/src/client.rs b/src/client.rs index fb42ce840..e0ac68c5d 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1117,8 +1117,12 @@ impl LoginConfigHandler { } else if name == "show-quality-monitor" { config.show_quality_monitor.v = !config.show_quality_monitor.v; } else { - let v = self.options.get(&name).is_some(); - if v { + let is_set = self + .options + .get(&name) + .map(|o| !o.is_empty()) + .unwrap_or(false); + if is_set { self.config.options.remove(&name); } else { self.config.options.insert(name, "Y".to_owned()); From 66851efaa3ca2b9c5274ed80b7e43c155d4ff789 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Fri, 3 Feb 2023 17:08:40 +0800 Subject: [PATCH 65/83] fix: --connect command on macOS & window closing issues --- flutter/lib/common.dart | 22 ++++++++++-------- flutter/lib/consts.dart | 3 ++- .../lib/desktop/widgets/tabbar_widget.dart | 12 ++++++---- flutter/lib/main.dart | 8 +++---- flutter/lib/utils/multi_window_manager.dart | 23 ++++++++++++++++++- flutter/lib/utils/platform_channel.dart | 6 +++++ flutter/macos/Runner/AppDelegate.swift | 9 ++++---- flutter/macos/Runner/Info.plist | 10 ++++---- flutter/macos/Runner/MainFlutterWindow.swift | 3 +++ 9 files changed, 68 insertions(+), 28 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index a2623ff15..c058ec434 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -3,14 +3,11 @@ import 'dart:convert'; import 'dart:ffi' hide Size; import 'dart:io'; import 'dart:math'; -import 'dart:typed_data'; import 'package:back_button_interceptor/back_button_interceptor.dart'; import 'package:desktop_multi_window/desktop_multi_window.dart'; import 'package:ffi/ffi.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter_hbb/utils/platform_channel.dart'; -import 'package:win32/win32.dart' as win32; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -19,14 +16,17 @@ import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; import 'package:flutter_hbb/main.dart'; import 'package:flutter_hbb/models/peer_model.dart'; import 'package:flutter_hbb/utils/multi_window_manager.dart'; +import 'package:flutter_hbb/utils/platform_channel.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:uni_links/uni_links.dart'; import 'package:uni_links_desktop/uni_links_desktop.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 'package:win32/win32.dart' as win32; +import 'package:window_manager/window_manager.dart'; +import 'package:window_size/window_size.dart' as window_size; +import '../consts.dart'; import 'common/widgets/overlay.dart'; import 'mobile/pages/file_manager_page.dart'; import 'mobile/pages/remote_page.dart'; @@ -34,8 +34,6 @@ import 'models/input_model.dart'; import 'models/model.dart'; import 'models/platform_model.dart'; -import '../consts.dart'; - final globalKey = GlobalKey(); final navigationBarKey = GlobalKey(); @@ -1275,9 +1273,11 @@ Future restoreWindowPosition(WindowType type, {int? windowId}) async { /// initUniLinks should only be used on macos/windows. /// we use dbus for linux currently. Future initUniLinks() async { - if (!Platform.isWindows && !Platform.isMacOS) { + if (Platform.isLinux) { return; } + // Register uni links for Windows. The required info of url scheme is already + // declared in `Info.plist` for macOS. if (Platform.isWindows) { registerProtocol('rustdesk'); } @@ -1508,8 +1508,12 @@ Future onActiveWindowChanged() async { } catch (err) { debugPrintStack(label: "$err"); } finally { + debugPrint("Start closing RustDesk..."); await windowManager.setPreventClose(false); await windowManager.close(); + if (Platform.isMacOS) { + RdPlatformChannel.instance.terminate(); + } } } } diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index e4081d9a5..f48b612a8 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -1,9 +1,10 @@ -import 'package:flutter/material.dart'; import 'dart:io'; +import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; const double kDesktopRemoteTabBarHeight = 28.0; +const int kMainWindowId = 0; const String kPeerPlatformWindows = "Windows"; const String kPeerPlatformLinux = "Linux"; diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index 598b2cc4c..223076951 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -1,23 +1,23 @@ -import 'dart:io'; import 'dart:async'; +import 'dart:io'; import 'dart:math'; import 'dart:ui' as ui; +import 'package:bot_toast/bot_toast.dart'; import 'package:desktop_multi_window/desktop_multi_window.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart' hide TabBarTheme; import 'package:flutter_hbb/common.dart'; +import 'package:flutter_hbb/common/shared_state.dart'; import 'package:flutter_hbb/consts.dart'; import 'package:flutter_hbb/main.dart'; -import 'package:flutter_hbb/common/shared_state.dart'; import 'package:flutter_hbb/models/platform_model.dart'; import 'package:flutter_hbb/models/state_model.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart'; import 'package:scroll_pos/scroll_pos.dart'; import 'package:window_manager/window_manager.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:bot_toast/bot_toast.dart'; import '../../utils/multi_window_manager.dart'; @@ -527,7 +527,9 @@ class WindowActionPanelState extends State void onWindowClose() async { // hide window on close if (widget.isMainWindow) { - await rustDeskWinManager.unregisterActiveWindow(0); + if (rustDeskWinManager.getActiveWindows().contains(kMainWindowId)) { + await rustDeskWinManager.unregisterActiveWindow(kMainWindowId); + } // `hide` must be placed after unregisterActiveWindow, because once all windows are hidden, // flutter closes the application on macOS. We should ensure the post-run logic has ran successfully. // e.g.: saving window position. diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index 5b1e0c37c..b41cc17df 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -1,22 +1,22 @@ import 'dart:convert'; import 'dart:io'; +import 'package:bot_toast/bot_toast.dart'; import 'package:desktop_multi_window/desktop_multi_window.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_hbb/models/state_model.dart'; import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart'; -import 'package:flutter_hbb/desktop/pages/server_page.dart'; import 'package:flutter_hbb/desktop/pages/install_page.dart'; +import 'package:flutter_hbb/desktop/pages/server_page.dart'; import 'package:flutter_hbb/desktop/screen/desktop_file_transfer_screen.dart'; import 'package:flutter_hbb/desktop/screen/desktop_port_forward_screen.dart'; import 'package:flutter_hbb/desktop/screen/desktop_remote_screen.dart'; import 'package:flutter_hbb/desktop/widgets/refresh_wrapper.dart'; +import 'package:flutter_hbb/models/state_model.dart'; import 'package:flutter_hbb/utils/multi_window_manager.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; import 'package:window_manager/window_manager.dart'; -import 'package:bot_toast/bot_toast.dart'; // import 'package:window_manager/window_manager.dart'; @@ -139,8 +139,8 @@ void runMainApp(bool startService) async { rustDeskWinManager.registerActiveWindow(kWindowMainId); } windowManager.setOpacity(1); + windowManager.setTitle(getWindowName()); }); - windowManager.setTitle(getWindowName()); } void runMobileApp() async { diff --git a/flutter/lib/utils/multi_window_manager.dart b/flutter/lib/utils/multi_window_manager.dart index 550e9ab08..3af189ef6 100644 --- a/flutter/lib/utils/multi_window_manager.dart +++ b/flutter/lib/utils/multi_window_manager.dart @@ -160,6 +160,24 @@ class RustDeskMultiWindowManager { return null; } + void clearWindowType(WindowType type) { + switch (type) { + case WindowType.Main: + return; + case WindowType.RemoteDesktop: + _remoteDesktopWindowId = null; + break; + case WindowType.FileTransfer: + _fileTransferWindowId = null; + break; + case WindowType.PortForward: + _portForwardWindowId = null; + break; + case WindowType.Unknown: + break; + } + } + void setMethodHandler( Future Function(MethodCall call, int fromWindowId)? handler) { DesktopMultiWindow.setMethodHandler(handler); @@ -186,8 +204,11 @@ class RustDeskMultiWindowManager { } await WindowController.fromWindowId(wId).setPreventClose(false); await WindowController.fromWindowId(wId).close(); - } on Error { + } catch (e) { + debugPrint("$e"); return; + } finally { + clearWindowType(type); } } } diff --git a/flutter/lib/utils/platform_channel.dart b/flutter/lib/utils/platform_channel.dart index 1a36fb7a5..7b60ef63c 100644 --- a/flutter/lib/utils/platform_channel.dart +++ b/flutter/lib/utils/platform_channel.dart @@ -31,4 +31,10 @@ class RdPlatformChannel { return _osxMethodChannel .invokeMethod("setWindowTheme", {"themeName": theme.name}); } + + /// Terminate .app manually. + Future terminate() { + assert(Platform.isMacOS); + return _osxMethodChannel.invokeMethod("terminate"); + } } diff --git a/flutter/macos/Runner/AppDelegate.swift b/flutter/macos/Runner/AppDelegate.swift index 5708e35cb..3498decd3 100644 --- a/flutter/macos/Runner/AppDelegate.swift +++ b/flutter/macos/Runner/AppDelegate.swift @@ -3,21 +3,22 @@ import FlutterMacOS @NSApplicationMain class AppDelegate: FlutterAppDelegate { - var lauched = false; + var launched = false; override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { dummy_method_to_enforce_bundling() - return true + // https://github.com/leanflutter/window_manager/issues/214 + return false } override func applicationShouldOpenUntitledFile(_ sender: NSApplication) -> Bool { - if (lauched) { + if (launched) { handle_applicationShouldOpenUntitledFile(); } return true } override func applicationDidFinishLaunching(_ aNotification: Notification) { - lauched = true; + launched = true; NSApplication.shared.activate(ignoringOtherApps: true); } } diff --git a/flutter/macos/Runner/Info.plist b/flutter/macos/Runner/Info.plist index d1077e0e4..c926019ab 100644 --- a/flutter/macos/Runner/Info.plist +++ b/flutter/macos/Runner/Info.plist @@ -23,8 +23,10 @@ CFBundleTypeRole Editor - CFBundleURLName + CFBundleURLIconFile + CFBundleURLName + com.carriez.rustdesk CFBundleURLSchemes rustdesk @@ -35,13 +37,13 @@ $(FLUTTER_BUILD_NUMBER) LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) + LSUIElement + 1 NSHumanReadableCopyright $(PRODUCT_COPYRIGHT) NSMainNibFile MainMenu NSPrincipalClass - NSApplication - LSUIElement - 1 + NSApplication diff --git a/flutter/macos/Runner/MainFlutterWindow.swift b/flutter/macos/Runner/MainFlutterWindow.swift index cea1e94bb..042840569 100644 --- a/flutter/macos/Runner/MainFlutterWindow.swift +++ b/flutter/macos/Runner/MainFlutterWindow.swift @@ -78,6 +78,9 @@ class MainFlutterWindow: NSWindow { self.setWindowInterfaceMode(window: window,themeName: themeName ?? "light") result(nil) break; + case "terminate": + NSApplication.shared.terminate(self) + result(nil) default: result(FlutterMethodNotImplemented) } From c13c89c0d6f09a14daea21b4a2e4cf5dd4bd4dff Mon Sep 17 00:00:00 2001 From: Kingtous Date: Fri, 3 Feb 2023 18:52:22 +0800 Subject: [PATCH 66/83] fix: uni links cause main window show --- flutter/lib/common.dart | 17 ++++++++++------- flutter/lib/main.dart | 7 +++++-- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index c058ec434..7e22e0848 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -1272,9 +1272,9 @@ Future restoreWindowPosition(WindowType type, {int? windowId}) async { /// [Availability] /// initUniLinks should only be used on macos/windows. /// we use dbus for linux currently. -Future initUniLinks() async { +Future initUniLinks() async { if (Platform.isLinux) { - return; + return false; } // Register uni links for Windows. The required info of url scheme is already // declared in `Info.plist` for macOS. @@ -1285,11 +1285,12 @@ Future initUniLinks() async { try { final initialLink = await getInitialLink(); if (initialLink == null) { - return; + return false; } - parseRustdeskUri(initialLink); + return parseRustdeskUri(initialLink); } catch (err) { debugPrintStack(label: "$err"); + return false; } } @@ -1310,11 +1311,13 @@ StreamSubscription? listenUniLinks() { return sub; } -/// Returns true if we successfully handle the startup arguments. +/// Handle command line arguments +/// +/// * Returns true if we successfully handle the startup arguments. bool checkArguments() { // bootArgs:[--connect, 362587269, --switch_uuid, e3d531cc-5dce-41e0-bd06-5d4a2b1eec05] // check connect args - final connectIndex = kBootArgs.indexOf("--connect"); + var connectIndex = kBootArgs.indexOf("--connect"); if (connectIndex == -1) { return false; } @@ -1368,7 +1371,7 @@ bool callUniLinksUriHandler(Uri uri) { Future.delayed(Duration.zero, () { rustDeskWinManager.newRemoteDesktop(peerId, switch_uuid: switch_uuid); }); - return false; + return true; } return false; } diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index b41cc17df..67a243eff 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -114,7 +114,6 @@ Future initEnv(String appType) async { void runMainApp(bool startService) async { // register uni links - initUniLinks(); await initEnv(kAppTypeMain); // trigger connection status updater await bind.mainCheckConnectStatus(); @@ -130,7 +129,11 @@ void runMainApp(bool startService) async { // Restore the location of the main window before window hide or show. await restoreWindowPosition(WindowType.Main); // Check the startup argument, if we successfully handle the argument, we keep the main window hidden. - if (checkArguments()) { + final handledByUniLinks = await initUniLinks(); + final handledByCli = checkArguments(); + debugPrint( + "handled by uni links: $handledByUniLinks, handled by cli: $handledByCli"); + if (handledByUniLinks || handledByCli) { windowManager.hide(); } else { windowManager.show(); From ca97826b80e09979f29f2c96993e6125d42e0e36 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 3 Feb 2023 19:17:59 +0800 Subject: [PATCH 67/83] update cursor position when menu is dismissed Signed-off-by: fufesou --- flutter/lib/desktop/widgets/popup_menu.dart | 55 ++++++++++++++++--- .../lib/desktop/widgets/remote_menubar.dart | 45 ++++++++++++++- 2 files changed, 90 insertions(+), 10 deletions(-) diff --git a/flutter/lib/desktop/widgets/popup_menu.dart b/flutter/lib/desktop/widgets/popup_menu.dart index 0cbdad929..9833dcbca 100644 --- a/flutter/lib/desktop/widgets/popup_menu.dart +++ b/flutter/lib/desktop/widgets/popup_menu.dart @@ -109,13 +109,17 @@ class MenuConfig { this.boxWidth}); } +typedef DismissCallback = Function(); + abstract class MenuEntryBase { bool dismissOnClicked; + DismissCallback? dismissCallback; RxBool? enabled; MenuEntryBase({ this.dismissOnClicked = false, this.enabled, + this.dismissCallback, }); List> build(BuildContext context, MenuConfig conf); @@ -146,12 +150,14 @@ class MenuEntryRadioOption { String value; bool dismissOnClicked; RxBool? enabled; + DismissCallback? dismissCallback; MenuEntryRadioOption({ required this.text, required this.value, this.dismissOnClicked = false, this.enabled, + this.dismissCallback, }); } @@ -177,8 +183,13 @@ class MenuEntryRadios extends MenuEntryBase { required this.optionSetter, this.padding, dismissOnClicked = false, + dismissCallback, RxBool? enabled, - }) : super(dismissOnClicked: dismissOnClicked, enabled: enabled) { + }) : super( + dismissOnClicked: dismissOnClicked, + enabled: enabled, + dismissCallback: dismissCallback, + ) { () async { _curOption.value = await curOptionGetter(); }(); @@ -249,6 +260,9 @@ class MenuEntryRadios extends MenuEntryBase { onPressed() { if (opt.dismissOnClicked && Navigator.canPop(context)) { Navigator.pop(context); + if (opt.dismissCallback != null) { + opt.dismissCallback!(); + } } setOption(opt.value); } @@ -360,6 +374,9 @@ class MenuEntrySubRadios extends MenuEntryBase { onPressed: () { if (opt.dismissOnClicked && Navigator.canPop(context)) { Navigator.pop(context); + if (opt.dismissCallback != null) { + opt.dismissCallback!(); + } } setOption(opt.value); }, @@ -421,7 +438,12 @@ abstract class MenuEntrySwitchBase extends MenuEntryBase { this.textStyle, this.padding, RxBool? enabled, - }) : super(dismissOnClicked: dismissOnClicked, enabled: enabled); + dismissCallback, + }) : super( + dismissOnClicked: dismissOnClicked, + enabled: enabled, + dismissCallback: dismissCallback, + ); RxBool get curOption; Future setOption(bool? option); @@ -463,6 +485,9 @@ abstract class MenuEntrySwitchBase extends MenuEntryBase { if (super.dismissOnClicked && Navigator.canPop(context)) { Navigator.pop(context); + if (super.dismissCallback != null) { + super.dismissCallback!(); + } } setOption(v); }, @@ -474,6 +499,9 @@ abstract class MenuEntrySwitchBase extends MenuEntryBase { if (super.dismissOnClicked && Navigator.canPop(context)) { Navigator.pop(context); + if (super.dismissCallback != null) { + super.dismissCallback!(); + } } setOption(v); }, @@ -485,6 +513,9 @@ abstract class MenuEntrySwitchBase extends MenuEntryBase { onPressed: () { if (super.dismissOnClicked && Navigator.canPop(context)) { Navigator.pop(context); + if (super.dismissCallback != null) { + super.dismissCallback!(); + } } setOption(!curOption.value); }, @@ -508,6 +539,7 @@ class MenuEntrySwitch extends MenuEntrySwitchBase { EdgeInsets? padding, dismissOnClicked = false, RxBool? enabled, + dismissCallback, }) : super( switchType: switchType, text: text, @@ -515,6 +547,7 @@ class MenuEntrySwitch extends MenuEntrySwitchBase { padding: padding, dismissOnClicked: dismissOnClicked, enabled: enabled, + dismissCallback: dismissCallback, ) { () async { _curOption.value = await getter(); @@ -551,12 +584,15 @@ class MenuEntrySwitch2 extends MenuEntrySwitchBase { EdgeInsets? padding, dismissOnClicked = false, RxBool? enabled, + dismissCallback, }) : super( - switchType: switchType, - text: text, - textStyle: textStyle, - padding: padding, - dismissOnClicked: dismissOnClicked); + switchType: switchType, + text: text, + textStyle: textStyle, + padding: padding, + dismissOnClicked: dismissOnClicked, + dismissCallback: dismissCallback, + ); @override RxBool get curOption => getter(); @@ -627,9 +663,11 @@ class MenuEntryButton extends MenuEntryBase { this.padding, dismissOnClicked = false, RxBool? enabled, + dismissCallback, }) : super( dismissOnClicked: dismissOnClicked, enabled: enabled, + dismissCallback: dismissCallback, ); Widget _buildChild(BuildContext context, MenuConfig conf) { @@ -641,6 +679,9 @@ class MenuEntryButton extends MenuEntryBase { ? () { if (super.dismissOnClicked && Navigator.canPop(context)) { Navigator.pop(context); + if (super.dismissCallback != null) { + super.dismissCallback!(); + } } proc(); } diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 2a84dcf14..5b418bcc4 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -231,6 +231,8 @@ class _RemoteMenubarState extends State { ); } + _menuDismissCallback() => widget.ffi.inputModel.refreshMousePos(); + Widget _buildMenubar(BuildContext context) { final List menubarItems = []; if (!isWebDesktop) { @@ -374,6 +376,7 @@ class _RemoteMenubarState extends State { onPressed: () { if (Navigator.canPop(context)) { Navigator.pop(context); + _menuDismissCallback(); } RxInt display = CurrentDisplayState.find(widget.id); if (display.value != i) { @@ -551,6 +554,7 @@ class _RemoteMenubarState extends State { onPressed: () { if (Navigator.canPop(context)) { Navigator.pop(context); + _menuDismissCallback(); } showSetOSPassword( widget.id, false, widget.ffi.dialogManager); @@ -563,6 +567,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ), MenuEntryButton( childBuilder: (TextStyle? style) => Text( @@ -574,6 +579,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ), MenuEntryButton( childBuilder: (TextStyle? style) => Text( @@ -585,6 +591,7 @@ class _RemoteMenubarState extends State { connect(context, widget.id, isTcpTunneling: true); }, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ), ]); // {handler.get_audit_server() &&

  • {translate('Note')}
  • } @@ -602,6 +609,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ), ); } @@ -618,6 +626,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, )); } } @@ -635,6 +644,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, )); } @@ -649,6 +659,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, )); if (pi.platform == kPeerPlatformWindows) { @@ -667,6 +678,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, )); } if (pi.platform != kPeerPlatformAndroid && @@ -681,6 +693,7 @@ class _RemoteMenubarState extends State { showConfirmSwitchSidesDialog(widget.id, widget.ffi.dialogManager), padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, )); } } @@ -696,6 +709,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, )); } @@ -717,6 +731,7 @@ class _RemoteMenubarState extends State { // }, // padding: padding, // dismissOnClicked: true, + // dismissCallback: _menuDismissCallback, // )); // } } @@ -762,11 +777,13 @@ class _RemoteMenubarState extends State { text: translate('Scale original'), value: kRemoteViewStyleOriginal, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ), MenuEntryRadioOption( text: translate('Scale adaptive'), value: kRemoteViewStyleAdaptive, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ), ], curOptionGetter: () async { @@ -782,6 +799,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ), MenuEntryDivider(), MenuEntryRadios( @@ -791,21 +809,26 @@ class _RemoteMenubarState extends State { text: translate('Good image quality'), value: kRemoteImageQualityBest, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ), MenuEntryRadioOption( text: translate('Balanced'), value: kRemoteImageQualityBalanced, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ), MenuEntryRadioOption( text: translate('Optimize reaction time'), value: kRemoteImageQualityLow, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ), MenuEntryRadioOption( - text: translate('Custom'), - value: kRemoteImageQualityCustom, - dismissOnClicked: true), + text: translate('Custom'), + value: kRemoteImageQualityCustom, + dismissOnClicked: true, + dismissCallback: _menuDismissCallback, + ), ], curOptionGetter: () async => // null means peer id is not found, which there's no need to care about @@ -970,12 +993,14 @@ class _RemoteMenubarState extends State { text: translate('ScrollAuto'), value: kRemoteScrollStyleAuto, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, enabled: widget.ffi.canvasModel.imageOverflow, ), MenuEntryRadioOption( text: translate('Scrollbar'), value: kRemoteScrollStyleBar, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, enabled: widget.ffi.canvasModel.imageOverflow, ), ], @@ -988,6 +1013,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, )); displayMenu.insert(3, MenuEntryDivider()); @@ -1058,6 +1084,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ), ); } @@ -1084,11 +1111,13 @@ class _RemoteMenubarState extends State { text: translate('Auto'), value: 'auto', dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ), MenuEntryRadioOption( text: 'VP9', value: 'vp9', dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ), ]; if (codecs[0]) { @@ -1096,6 +1125,7 @@ class _RemoteMenubarState extends State { text: 'H264', value: 'h264', dismissOnClicked: true, + dismissCallback: _menuDismissCallback, )); } if (codecs[1]) { @@ -1103,6 +1133,7 @@ class _RemoteMenubarState extends State { text: 'H265', value: 'h265', dismissOnClicked: true, + dismissCallback: _menuDismissCallback, )); } return list; @@ -1119,6 +1150,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, )); } } @@ -1141,6 +1173,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ); }()); } @@ -1163,6 +1196,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, ); }()); } @@ -1182,6 +1216,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, )); final perms = widget.ffi.ffiModel.permissions; @@ -1219,6 +1254,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: true, + dismissCallback: _menuDismissCallback, )); } } @@ -1290,6 +1326,7 @@ class _RemoteMenubarState extends State { onPressed: () { if (Navigator.canPop(context)) { Navigator.pop(context); + _menuDismissCallback(); } showKBLayoutTypeChooser( localPlatform, widget.ffi.dialogManager); @@ -1302,6 +1339,7 @@ class _RemoteMenubarState extends State { proc: () {}, padding: EdgeInsets.zero, dismissOnClicked: false, + dismissCallback: _menuDismissCallback, ), ); } @@ -1321,6 +1359,7 @@ class _RemoteMenubarState extends State { }, padding: padding, dismissOnClicked: dismissOnClicked, + dismissCallback: _menuDismissCallback, ); } } From 0940c93a481b90652af890e320ace5c4e00dde3e Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 3 Feb 2023 20:27:05 +0800 Subject: [PATCH 68/83] show cursor on conn is established Signed-off-by: fufesou --- flutter/lib/models/model.dart | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 8a7a1005d..d032719e9 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -904,10 +904,10 @@ class CursorModel with ChangeNotifier { double _hoty = 0; double _displayOriginX = 0; double _displayOriginY = 0; - bool _firstUpdateMousePos = false; + DateTime? _firstUpdateMouseTime; bool gotMouseControl = true; DateTime _lastPeerMouse = DateTime.now() - .subtract(Duration(milliseconds: 2 * kMouseControlTimeoutMSec)); + .subtract(Duration(milliseconds: 3000 * kMouseControlTimeoutMSec)); String id = ''; WeakReference parent; @@ -926,6 +926,15 @@ class CursorModel with ChangeNotifier { DateTime.now().difference(_lastPeerMouse).inMilliseconds < kMouseControlTimeoutMSec; + bool isConnIn2Secs() { + if (_firstUpdateMouseTime == null) { + _firstUpdateMouseTime = DateTime.now(); + return true; + } else { + return DateTime.now().difference(_firstUpdateMouseTime!).inSeconds < 2; + } + } + CursorModel(this.parent); Set get cachedKeys => _cacheKeys; @@ -1122,12 +1131,10 @@ class CursorModel with ChangeNotifier { /// Update the cursor position. updateCursorPosition(Map evt, String id) async { - if (!_firstUpdateMousePos) { - _firstUpdateMousePos = true; - } else { + if (!isConnIn2Secs()) { gotMouseControl = false; + _lastPeerMouse = DateTime.now(); } - _lastPeerMouse = DateTime.now(); _x = double.parse(evt['x']); _y = double.parse(evt['y']); try { From 0d36166ea88847510426433dee115e17c693fe25 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 3 Feb 2023 23:07:47 +0800 Subject: [PATCH 69/83] sync option after toggle Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_tab_page.dart | 6 +++--- flutter/lib/desktop/widgets/remote_menubar.dart | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index 55124fbcc..d832db0c6 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -273,6 +273,7 @@ class _ConnectionTabPageState extends State { menu.add(MenuEntryDivider()); menu.add(() { final state = ShowRemoteCursorState.find(key); + final optKey = 'show-remote-cursor'; return MenuEntrySwitch2( switchType: SwitchType.scheckbox, text: translate('Show remote cursor'), @@ -280,9 +281,8 @@ class _ConnectionTabPageState extends State { return state; }, setter: (bool v) async { - state.value = v; - await bind.sessionToggleOption( - id: key, value: 'show-remote-cursor'); + await bind.sessionToggleOption(id: key, value: optKey); + state.value = bind.sessionGetToggleOptionSync(id: key, arg: optKey); cancelFunc(); }, padding: padding, diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 5b418bcc4..d6b1cec72 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -1160,6 +1160,7 @@ class _RemoteMenubarState extends State { if (!widget.ffi.canvasModel.cursorEmbedded) { displayMenu.add(() { final state = ShowRemoteCursorState.find(widget.id); + final optKey = 'show-remote-cursor'; return MenuEntrySwitch2( switchType: SwitchType.scheckbox, text: translate('Show remote cursor'), @@ -1167,9 +1168,9 @@ class _RemoteMenubarState extends State { return state; }, setter: (bool v) async { - state.value = v; - await bind.sessionToggleOption( - id: widget.id, value: 'show-remote-cursor'); + await bind.sessionToggleOption(id: widget.id, value: optKey); + state.value = + bind.sessionGetToggleOptionSync(id: widget.id, arg: optKey); }, padding: padding, dismissOnClicked: true, From 96a7182ff85ce35f47d46a4c5ff8c9a3258bad15 Mon Sep 17 00:00:00 2001 From: solokot Date: Fri, 3 Feb 2023 20:05:48 +0300 Subject: [PATCH 70/83] update ru.rs --- src/lang/ru.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 7ec6c1554..54b064c18 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -436,14 +436,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", "Переключить стороны"), ("Please confirm if you want to share your desktop?", "Подтверждаете, что хотите поделиться своим рабочим столом?"), ("Closed as expected", "Закрыто по ожиданию"), - ("Display", ""), - ("Default View Style", ""), - ("Default Scroll Style", ""), - ("Default Image Quality", ""), - ("Default Codec", ""), - ("Bitrate", ""), - ("FPS", ""), - ("Auto", ""), - ("Other Default Options", ""), + ("Display", "Отображение"), + ("Default View Style", "Стиль отображения по умолчанию"), + ("Default Scroll Style", "Стиль прокрутки по умолчанию"), + ("Default Image Quality", "Качество изображения по умолчанию"), + ("Default Codec", "Кодек по умолчанию"), + ("Bitrate", "Битрейт"), + ("FPS", "FPS"), + ("Auto", "Авто"), + ("Other Default Options", "Другие параметры по умолчанию"), ].iter().cloned().collect(); } From f9d106ea745017b1c7c2e8c69b2ea1ba6dc670c4 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Fri, 3 Feb 2023 22:36:50 +0100 Subject: [PATCH 71/83] Update de.rs --- src/lang/de.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/lang/de.rs b/src/lang/de.rs index 5b68c0e7a..2d6d3d069 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -200,7 +200,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Warnung"), ("Login screen using Wayland is not supported", "Anmeldebildschirm mit Wayland wird nicht unterstützt."), ("Reboot required", "Neustart erforderlich"), - ("Unsupported display server ", "Nicht unterstützter Display-Server"), + ("Unsupported display server ", "Nicht unterstützter Anzeigeserver"), ("x11 expected", "X11 erwartet"), ("Port", "Port"), ("Settings", "Einstellungen"), @@ -327,7 +327,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Mobile Actions", "Mobile Aktionen"), ("Select Monitor", "Bildschirm auswählen"), ("Control Actions", "Aktionen"), - ("Display Settings", "Bildschirmeinstellungen"), + ("Display Settings", "Anzeigeeinstellungen"), ("Ratio", "Verhältnis"), ("Image Quality", "Bildqualität"), ("Scroll Style", "Scroll-Stil"), @@ -338,7 +338,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Secure Connection", "Sichere Verbindung"), ("Insecure Connection", "Unsichere Verbindung"), ("Scale original", "Keine Skalierung"), - ("Scale adaptive", "Automatische Skalierung"), + ("Scale adaptive", "Anpassbare Skalierung"), ("General", "Allgemein"), ("Security", "Sicherheit"), ("Theme", "Farbgebung"), @@ -358,7 +358,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Clear", "Zurücksetzen"), ("Audio Input Device", "Audioeingabegerät"), ("Deny remote access", "Fernzugriff verbieten"), - ("Use IP Whitelisting", "IP-Whitelist benutzen"), + ("Use IP Whitelisting", "IP-Whitelist verwenden"), ("Network", "Netzwerk"), ("Enable RDP", "RDP aktivieren"), ("Pin menubar", "Menüleiste anpinnen"), @@ -436,14 +436,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", "Seiten wechseln"), ("Please confirm if you want to share your desktop?", "Bitte bestätigen Sie, ob Sie Ihren Desktop freigeben möchten."), ("Closed as expected", "Wie erwartet geschlossen"), - ("Display", ""), - ("Default View Style", ""), - ("Default Scroll Style", ""), - ("Default Image Quality", ""), - ("Default Codec", ""), - ("Bitrate", ""), - ("FPS", ""), - ("Auto", ""), - ("Other Default Options", ""), + ("Display", "Anzeige"), + ("Default View Style", "Standard-Ansichtsstil"), + ("Default Scroll Style", "Standard-Scroll-Stil"), + ("Default Image Quality", "Standard-Bildqualität"), + ("Default Codec", "Standard-Codec"), + ("Bitrate", "Bitrate"), + ("FPS", "fps"), + ("Auto", "Automatisch"), + ("Other Default Options", "Weitere Standardoptionen"), ].iter().cloned().collect(); } From 3a1b9781124e0a59f64c5ea4cbc30ebdf1fe742d Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sat, 4 Feb 2023 01:10:32 +0800 Subject: [PATCH 72/83] feat: add event handler on rust macos --- Cargo.lock | 41 +++++++++++++++++-- Cargo.toml | 2 + .../macos/Runner.xcodeproj/project.pbxproj | 5 ++- flutter/macos/Runner/MainFlutterWindow.swift | 1 - src/ui/macos.rs | 27 ++++++++++-- 5 files changed, 68 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5c4af56e9..e15641363 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1137,7 +1137,7 @@ checksum = "413487ef345ab5cdfbf23e66070741217a701bce70f2f397a54221b4f2b6056a" dependencies = [ "dconf_rs", "detect-desktop-environment", - "dirs", + "dirs 4.0.0", "objc", "rust-ini", "web-sys", @@ -1401,6 +1401,16 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" +dependencies = [ + "cfg-if 0.1.10", + "dirs-sys", +] + [[package]] name = "dirs" version = "4.0.0" @@ -1873,6 +1883,19 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fruitbasket" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "898289b8e0528c84fb9b88f15ac9d5109bcaf23e0e49bb6f64deee0d86b6a351" +dependencies = [ + "dirs 2.0.2", + "objc", + "objc-foundation", + "objc_id", + "time 0.1.45", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -3657,6 +3680,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" dependencies = [ "malloc_buf", + "objc_exception", ] [[package]] @@ -3670,6 +3694,15 @@ dependencies = [ "objc_id", ] +[[package]] +name = "objc_exception" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +dependencies = [ + "cc", +] + [[package]] name = "objc_id" version = "0.1.1" @@ -4655,6 +4688,7 @@ dependencies = [ "flexi_logger", "flutter_rust_bridge", "flutter_rust_bridge_codegen", + "fruitbasket", "glib 0.16.5", "gtk", "hbb_common", @@ -4673,6 +4707,7 @@ dependencies = [ "mouce", "num_cpus", "objc", + "objc_id", "parity-tokio-ipc", "rdev", "repng", @@ -4713,7 +4748,7 @@ name = "rustdesk-portable-packer" version = "0.1.0" dependencies = [ "brotli", - "dirs", + "dirs 4.0.0", "embed-resource", "md5", ] @@ -6591,7 +6626,7 @@ dependencies = [ "async-trait", "byteorder", "derivative", - "dirs", + "dirs 4.0.0", "enumflags2", "event-listener", "futures-core", diff --git a/Cargo.toml b/Cargo.toml index 1e9af30e5..936b9e349 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -106,6 +106,8 @@ core-graphics = "0.22" include_dir = "0.7.2" tray-item = "0.7" # looks better than trayicon dark-light = "0.2" +fruitbasket = "0.10.0" +objc_id = "0.1.1" [target.'cfg(target_os = "linux")'.dependencies] psimple = { package = "libpulse-simple-binding", version = "2.25" } diff --git a/flutter/macos/Runner.xcodeproj/project.pbxproj b/flutter/macos/Runner.xcodeproj/project.pbxproj index 7a17c3de1..066560203 100644 --- a/flutter/macos/Runner.xcodeproj/project.pbxproj +++ b/flutter/macos/Runner.xcodeproj/project.pbxproj @@ -227,7 +227,7 @@ TargetAttributes = { 33CC10EC2044A3C60003C045 = { CreatedOnToolsVersion = 9.2; - LastSwiftMigration = 1100; + LastSwiftMigration = 1420; ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.Sandbox = { @@ -463,6 +463,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.14; PRODUCT_BUNDLE_IDENTIFIER = com.carriez.rustdesk; PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = Profile; @@ -607,6 +608,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.14; PRODUCT_BUNDLE_IDENTIFIER = com.carriez.rustdesk; PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; "SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = Runner/bridge_generated.h; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -643,6 +645,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.carriez.rustdesk; PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; "SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = Runner/bridge_generated.h; SWIFT_VERSION = 5.0; }; diff --git a/flutter/macos/Runner/MainFlutterWindow.swift b/flutter/macos/Runner/MainFlutterWindow.swift index 042840569..97b46bb84 100644 --- a/flutter/macos/Runner/MainFlutterWindow.swift +++ b/flutter/macos/Runner/MainFlutterWindow.swift @@ -87,4 +87,3 @@ class MainFlutterWindow: NSWindow { }) } } - diff --git a/src/ui/macos.rs b/src/ui/macos.rs index 7daef8eab..39812cf90 100644 --- a/src/ui/macos.rs +++ b/src/ui/macos.rs @@ -1,3 +1,5 @@ +use std::{ffi::c_void, rc::Rc}; + #[cfg(target_os = "macos")] use cocoa::{ appkit::{NSApp, NSApplication, NSApplicationActivationPolicy::*, NSMenu, NSMenuItem}, @@ -8,11 +10,14 @@ use objc::{ class, declare::ClassDecl, msg_send, - runtime::{Object, Sel, BOOL}, + runtime::{BOOL, Object, Sel}, sel, sel_impl, }; -use sciter::{make_args, Host}; -use std::{ffi::c_void, rc::Rc}; +use objc::runtime::Class; +use objc_id::WeakId; +use sciter::{Host, make_args}; + +use hbb_common::log; static APP_HANDLER_IVAR: &str = "GoDeskAppHandler"; @@ -98,12 +103,21 @@ unsafe fn set_delegate(handler: Option>) { sel!(handleMenuItem:), handle_menu_item as extern "C" fn(&mut Object, Sel, id), ); + decl.add_method(sel!(handleEvent:withReplyEvent:), handle_apple_event as extern fn(&Object, Sel, u64, u64)); let decl = decl.register(); let delegate: id = msg_send![decl, alloc]; let () = msg_send![delegate, init]; let state = DelegateState { handler }; let handler_ptr = Box::into_raw(Box::new(state)); (*delegate).set_ivar(APP_HANDLER_IVAR, handler_ptr as *mut c_void); + // Set the url scheme handler + let cls = Class::get("NSAppleEventManager").unwrap(); + let manager: *mut Object = msg_send![cls, sharedAppleEventManager]; + let _: () = msg_send![manager, + setEventHandler: delegate + andSelector: sel!(handleEvent:withReplyEvent:) + forEventClass: fruitbasket::kInternetEventClass + andEventID: fruitbasket::kAEGetURL]; let () = msg_send![NSApp(), setDelegate: delegate]; } @@ -167,6 +181,13 @@ extern "C" fn handle_menu_item(this: &mut Object, _: Sel, item: id) { } } +extern fn handle_apple_event(this: &Object, _cmd: Sel, event: u64, _reply: u64) { + let event = event as *mut Object; + let url = fruitbasket::parse_url_event(event); + log::debug!("event found {}", url); + let _ = crate::run_me(vec![url]); +} + unsafe fn make_menu_item(title: &str, key: &str, tag: u32) -> *mut Object { let title = NSString::alloc(nil).init_str(title); let action = sel!(handleMenuItem:); From 7e69cbde26a1a62f3e319fdfebd12637a2dd2956 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sat, 4 Feb 2023 01:22:40 +0800 Subject: [PATCH 73/83] opt: support binary + uri links startup --- flutter/lib/common.dart | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 7e22e0848..9f3e2c740 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -1315,6 +1315,12 @@ StreamSubscription? listenUniLinks() { /// /// * Returns true if we successfully handle the startup arguments. bool checkArguments() { + if (kBootArgs.isNotEmpty) { + final ret = parseRustdeskUri(kBootArgs.first); + if (ret) { + return true; + } + } // bootArgs:[--connect, 362587269, --switch_uuid, e3d531cc-5dce-41e0-bd06-5d4a2b1eec05] // check connect args var connectIndex = kBootArgs.indexOf("--connect"); @@ -1352,7 +1358,7 @@ bool checkArguments() { bool parseRustdeskUri(String uriPath) { final uri = Uri.tryParse(uriPath); if (uri == null) { - print("uri is not valid: $uriPath"); + debugPrint("uri is not valid: $uriPath"); return false; } return callUniLinksUriHandler(uri); From a9fc63c34f6f0bb18701e9597d1a5d8568c35ccc Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sat, 4 Feb 2023 01:31:56 +0800 Subject: [PATCH 74/83] opt: add default url scheme handler for macos --- src/flutter_ffi.rs | 31 ++++++++++++++++++------------- src/ui/macos.rs | 9 +++++++-- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index d40c66d19..d001dd388 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -3,28 +3,29 @@ use std::{ ffi::{CStr, CString}, os::raw::c_char, }; +use std::str::FromStr; use flutter_rust_bridge::{StreamSink, SyncReturn, ZeroCopyBuffer}; use serde_json::json; -use crate::common::is_keyboard_mode_supported; -use hbb_common::message_proto::KeyboardMode; -use hbb_common::ResultType; use hbb_common::{ - config::{self, LocalConfig, PeerConfig, ONLINE}, + config::{self, LocalConfig, ONLINE, PeerConfig}, fs, log, }; -use std::str::FromStr; +use hbb_common::message_proto::KeyboardMode; +use hbb_common::ResultType; -// use crate::hbbs_http::account::AuthResult; - -use crate::flutter::{self, SESSIONS}; -use crate::ui_interface::{self, *}; use crate::{ client::file_trait::FileManager, common::make_fd_to_json, flutter::{session_add, session_start_}, }; +use crate::common::is_keyboard_mode_supported; +use crate::flutter::{self, SESSIONS}; +use crate::ui_interface::{self, *}; + +// use crate::hbbs_http::account::AuthResult; + fn initialize(app_dir: &str) { *config::APP_DIR.write().unwrap() = app_dir.to_owned(); #[cfg(target_os = "android")] @@ -910,6 +911,11 @@ pub fn main_start_dbus_server() { } } +pub fn osx_handle_uni_links(url: String) { + #![cfg(target_os = "macos")] + crate::ui::macos::handle_url_scheme(url); +} + pub fn session_send_mouse(id: String, msg: String) { if let Ok(m) = serde_json::from_str::>(&msg) { let alt = m.get("alt").is_some(); @@ -1257,13 +1263,12 @@ pub fn main_hide_docker() -> SyncReturn { #[cfg(target_os = "android")] pub mod server_side { + use hbb_common::log; use jni::{ + JNIEnv, objects::{JClass, JString}, sys::jstring, - JNIEnv, - }; - - use hbb_common::log; + }; use crate::start_server; diff --git a/src/ui/macos.rs b/src/ui/macos.rs index 39812cf90..94e75959c 100644 --- a/src/ui/macos.rs +++ b/src/ui/macos.rs @@ -181,11 +181,16 @@ extern "C" fn handle_menu_item(this: &mut Object, _: Sel, item: id) { } } -extern fn handle_apple_event(this: &Object, _cmd: Sel, event: u64, _reply: u64) { +/// The function to handle the url scheme sent by system. +pub fn handle_url_scheme(url: String) { + unimplemented!(); +} + +extern fn handle_apple_event(_this: &Object, _cmd: Sel, event: u64, _reply: u64) { let event = event as *mut Object; let url = fruitbasket::parse_url_event(event); log::debug!("event found {}", url); - let _ = crate::run_me(vec![url]); + handle_url_scheme(url); } unsafe fn make_menu_item(title: &str, key: &str, tag: u32) -> *mut Object { From 4dfae8da1075450346ae72927faac8fc659027d5 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sat, 4 Feb 2023 11:23:36 +0800 Subject: [PATCH 75/83] feat: add url scheme handler for macos --- flutter/lib/consts.dart | 3 +- flutter/lib/main.dart | 2 +- flutter/lib/models/model.dart | 3 ++ flutter/lib/models/native_model.dart | 10 +++- src/flutter_ffi.rs | 25 +++++++--- src/ipc.rs | 11 +++- src/server.rs | 75 ++++++++++++++++++++++------ src/ui/macos.rs | 18 +++++-- 8 files changed, 116 insertions(+), 31 deletions(-) diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index f48b612a8..1fc97f410 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -11,8 +11,9 @@ const String kPeerPlatformLinux = "Linux"; const String kPeerPlatformMacOS = "Mac OS"; const String kPeerPlatformAndroid = "Android"; -/// [kAppTypeMain] used by 'Desktop Main Page' , 'Mobile (Client and Server)' , 'Desktop CM Page', "Install Page" +/// [kAppTypeMain] used by 'Desktop Main Page' , 'Mobile (Client and Server)', "Install Page" const String kAppTypeMain = "main"; +const String kAppTypeConnectionManager = "cm"; const String kAppTypeDesktopRemote = "remote"; const String kAppTypeDesktopFileTransfer = "file transfer"; const String kAppTypeDesktopPortForward = "port forward"; diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index 67a243eff..86cc9d89b 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -211,7 +211,7 @@ void runMultiWindow( } void runConnectionManagerScreen(bool hide) async { - await initEnv(kAppTypeMain); + await initEnv(kAppTypeConnectionManager); _runApp( '', const DesktopServerPage(), diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index d032719e9..aae4c6a07 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -199,6 +199,9 @@ class FfiModel with ChangeNotifier { final peer_id = evt['peer_id'].toString(); await bind.sessionSwitchSides(id: peer_id); closeConnection(id: peer_id); + } else if (name == "on_url_scheme_received") { + final url = evt['url'].toString(); + parseRustdeskUri(url); } }; } diff --git a/flutter/lib/models/native_model.dart b/flutter/lib/models/native_model.dart index cf2de4219..d6885bfb0 100644 --- a/flutter/lib/models/native_model.dart +++ b/flutter/lib/models/native_model.dart @@ -8,6 +8,7 @@ import 'package:external_path/external_path.dart'; import 'package:ffi/ffi.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_hbb/consts.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:path_provider/path_provider.dart'; import 'package:win32/win32.dart' as win32; @@ -46,6 +47,8 @@ class PlatformFFI { static get localeName => Platform.localeName; + static get isMain => instance._appType == kAppTypeMain; + static Future getVersion() async { PackageInfo packageInfo = await PackageInfo.fromPlatform(); return packageInfo.version; @@ -112,8 +115,11 @@ class PlatformFFI { } _ffiBind = RustdeskImpl(dylib); if (Platform.isLinux) { - // start dbus service, no need to await - await _ffiBind.mainStartDbusServer(); + // Start a dbus service, no need to await + _ffiBind.mainStartDbusServer(); + } else if (Platform.isMacOS) { + // Start an ipc server for handling url schemes. + _ffiBind.mainStartIpcUrlServer(); } _startListenEvent(_ffiBind); // global event try { diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index d001dd388..5dccd9050 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -1,8 +1,4 @@ -use std::{ - collections::HashMap, - ffi::{CStr, CString}, - os::raw::c_char, -}; +use std::{collections::HashMap, ffi::{CStr, CString}, os::raw::c_char, thread}; use std::str::FromStr; use flutter_rust_bridge::{StreamSink, SyncReturn, ZeroCopyBuffer}; @@ -1261,6 +1257,23 @@ pub fn main_hide_docker() -> SyncReturn { SyncReturn(true) } +/// Start an ipc server for receiving the url scheme. +/// +/// * Should only be called in the main flutter window. +/// * macOS only +pub fn main_start_ipc_url_server() { + #[cfg(target_os = "macos")] + thread::spawn(move || crate::server::start_ipc_url_server()); +} + +/// Send a url scheme throught the ipc. +/// +/// * macOS only +pub fn send_url_scheme(url: String) { + #[cfg(target_os = "macos")] + thread::spawn(move || crate::ui::macos::handle_url_scheme(url)); +} + #[cfg(target_os = "android")] pub mod server_side { use hbb_common::log; @@ -1268,7 +1281,7 @@ pub mod server_side { JNIEnv, objects::{JClass, JString}, sys::jstring, - }; + }; use crate::start_server; diff --git a/src/ipc.rs b/src/ipc.rs index d4d803aec..d610fb84d 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -16,10 +16,10 @@ use hbb_common::{ config::{self, Config, Config2}, futures::StreamExt as _, futures_util::sink::SinkExt, - log, password_security as password, timeout, tokio, + log, password_security as password, ResultType, timeout, + tokio, tokio::io::{AsyncRead, AsyncWrite}, tokio_util::codec::Framed, - ResultType, }; use crate::rendezvous_mediator::RendezvousMediator; @@ -210,6 +210,7 @@ pub enum Data { DataPortableService(DataPortableService), SwitchSidesRequest(String), SwitchSidesBack, + UrlLink(String) } #[tokio::main(flavor = "current_thread")] @@ -832,3 +833,9 @@ pub async fn test_rendezvous_server() -> ResultType<()> { c.send(&Data::TestRendezvousServer).await?; Ok(()) } + +#[tokio::main(flavor = "current_thread")] +pub async fn send_url_scheme(url: String) -> ResultType<()> { + connect(1_000, "_url").await?.send(&Data::UrlLink(url)).await?; + Ok(()) +} diff --git a/src/server.rs b/src/server.rs index 381e3df90..de213ae5a 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,8 +1,13 @@ -use crate::ipc::Data; +use std::{ + collections::HashMap, + net::SocketAddr, + sync::{Arc, Mutex, RwLock, Weak}, + time::Duration, +}; + use bytes::Bytes; + pub use connection::*; -#[cfg(not(any(target_os = "android", target_os = "ios")))] -use hbb_common::config::Config2; use hbb_common::{ allow_err, anyhow::{anyhow, Context}, @@ -12,19 +17,19 @@ use hbb_common::{ message_proto::*, protobuf::{Enum, Message as _}, rendezvous_proto::*, + ResultType, socket_client, - sodiumoxide::crypto::{box_, secretbox, sign}, - timeout, tokio, ResultType, Stream, + sodiumoxide::crypto::{box_, secretbox, sign}, Stream, timeout, tokio, }; #[cfg(not(any(target_os = "android", target_os = "ios")))] -use service::ServiceTmpl; +use hbb_common::config::Config2; +use hbb_common::tcp::new_listener; use service::{GenericService, Service, Subscriber}; -use std::{ - collections::HashMap, - net::SocketAddr, - sync::{Arc, Mutex, RwLock, Weak}, - time::Duration, -}; +#[cfg(not(any(target_os = "android", target_os = "ios")))] +use service::ServiceTmpl; + +use crate::ipc::{connect, Data}; +use crate::ui_interface::SENDER; pub mod audio_service; cfg_if::cfg_if! { @@ -55,8 +60,6 @@ mod service; mod video_qos; pub mod video_service; -use hbb_common::tcp::new_listener; - pub type Childs = Arc>>; type ConnMap = HashMap; @@ -425,6 +428,50 @@ pub async fn start_server(is_server: bool) { } } +#[cfg(target_os = "macos")] +#[tokio::main(flavor = "current_thread")] +pub async fn start_ipc_url_server() { + log::debug!("Start an ipc server for listening to url schemes"); + match crate::ipc::new_listener("_url").await { + Ok(mut incoming) => { + while let Some(Ok(conn)) = incoming.next().await { + let mut conn = crate::ipc::Connection::new(conn); + match conn.next_timeout(1000).await { + Ok(Some(data)) => { + match data { + Data::UrlLink(url) => { + #[cfg(feature = "flutter")] + { + if let Some(stream) = crate::flutter::GLOBAL_EVENT_STREAM.read().unwrap().get( + crate::flutter::APP_TYPE_MAIN + ) { + let mut m = HashMap::new(); + m.insert("name", "on_url_scheme_received"); + m.insert("url", url.as_str()); + stream.add(serde_json::to_string(&m).unwrap()); + } else { + log::warn!("No main window app found!"); + } + } + } + _ => { + log::warn!("An unexpected data was sent to the ipc url server.") + } + } + } + Err(err) => { + log::error!("{}", err); + } + _ => {} + } + } + } + Err(err) => { + log::error!("{}", err); + } + } +} + #[cfg(target_os = "macos")] async fn sync_and_watch_config_dir() { if crate::platform::is_root() { diff --git a/src/ui/macos.rs b/src/ui/macos.rs index 94e75959c..98e355dc1 100644 --- a/src/ui/macos.rs +++ b/src/ui/macos.rs @@ -17,7 +17,9 @@ use objc::runtime::Class; use objc_id::WeakId; use sciter::{Host, make_args}; -use hbb_common::log; +use hbb_common::{log, tokio}; + +use crate::ui_cm_interface::start_ipc; static APP_HANDLER_IVAR: &str = "GoDeskAppHandler"; @@ -181,16 +183,22 @@ extern "C" fn handle_menu_item(this: &mut Object, _: Sel, item: id) { } } -/// The function to handle the url scheme sent by system. +/// The function to handle the url scheme sent by the system. +/// +/// 1. Try to send the url scheme from ipc. +/// 2. If failed to send the url scheme, we open a new main window to handle this url scheme. pub fn handle_url_scheme(url: String) { - unimplemented!(); + if let Err(err) = crate::ipc::send_url_scheme(url.clone()) { + log::debug!("Send the url to the existing flutter process failed, {}. Let's open a new program to handle this.", err); + let _ = crate::run_me(vec![url]); + } } extern fn handle_apple_event(_this: &Object, _cmd: Sel, event: u64, _reply: u64) { let event = event as *mut Object; let url = fruitbasket::parse_url_event(event); - log::debug!("event found {}", url); - handle_url_scheme(url); + log::debug!("an event was received: {}", url); + std::thread::spawn(move || handle_url_scheme(url)); } unsafe fn make_menu_item(title: &str, key: &str, tag: u32) -> *mut Object { From a349be6428cca3675d777821b71554e4e49b0952 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sat, 4 Feb 2023 11:33:08 +0800 Subject: [PATCH 76/83] opt: remove unnecessary ffi func --- src/flutter_ffi.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 5dccd9050..ca9314c43 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -907,11 +907,6 @@ pub fn main_start_dbus_server() { } } -pub fn osx_handle_uni_links(url: String) { - #![cfg(target_os = "macos")] - crate::ui::macos::handle_url_scheme(url); -} - pub fn session_send_mouse(id: String, msg: String) { if let Ok(m) = serde_json::from_str::>(&msg) { let alt = m.get("alt").is_some(); From 151b115fc900ad15fd2fc79319e166b48c9b6661 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sat, 4 Feb 2023 13:37:48 +0800 Subject: [PATCH 77/83] fix: android build --- src/server.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/server.rs b/src/server.rs index de213ae5a..109fc1e9a 100644 --- a/src/server.rs +++ b/src/server.rs @@ -29,7 +29,6 @@ use service::{GenericService, Service, Subscriber}; use service::ServiceTmpl; use crate::ipc::{connect, Data}; -use crate::ui_interface::SENDER; pub mod audio_service; cfg_if::cfg_if! { From dd00ea5abd24be98addc5444294f52908cbc729f Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sat, 4 Feb 2023 16:18:54 +0800 Subject: [PATCH 78/83] opt: reuse current main window when using url scheme --- src/core_main.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/core_main.rs b/src/core_main.rs index 89a962f1d..99d0e888e 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -1,4 +1,6 @@ -use hbb_common::log; +use std::future::Future; + +use hbb_common::{log, ResultType}; /// shared by flutter and sciter main function /// @@ -346,5 +348,11 @@ fn core_main_invoke_new_connection(mut args: std::env::Args) -> Option Date: Sun, 5 Feb 2023 07:59:29 +0330 Subject: [PATCH 79/83] Update fa.rs --- src/lang/fa.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 72cde49f9..dd1c75bac 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -436,14 +436,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Switch Sides", "طرفین را عوض کنید"), ("Please confirm if you want to share your desktop?", "لطفاً تأیید کنید که آیا می خواهید دسکتاپ خود را به اشتراک بگذارید؟"), ("Closed as expected", "طبق انتظار بسته شد"), - ("Display", ""), - ("Default View Style", ""), - ("Default Scroll Style", ""), - ("Default Image Quality", ""), - ("Default Codec", ""), - ("Bitrate", ""), - ("FPS", ""), - ("Auto", ""), - ("Other Default Options", ""), + ("Display", "نمایش دادن"), + ("Default View Style", "سبک نمایش پیش فرض"), + ("Default Scroll Style", "سبک پیش‌فرض اسکرول"), + ("Default Image Quality", "کیفیت تصویر پیش فرض"), + ("Default Codec", "کدک پیش فرض"), + ("Bitrate", "میزان بیت صفحه نمایش"), + ("FPS", "FPS"), + ("Auto", "خودکار"), + ("Other Default Options", "سایر گزینه های پیش فرض"), ].iter().cloned().collect(); } From afb76c63261ac5d2f1602ec3d7627a1168ee11c6 Mon Sep 17 00:00:00 2001 From: mehdi-song Date: Sun, 5 Feb 2023 10:20:05 +0330 Subject: [PATCH 80/83] Update README-FA.md --- docs/README-FA.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/README-FA.md b/docs/README-FA.md index 02b156dbb..496e81849 100644 --- a/docs/README-FA.md +++ b/docs/README-FA.md @@ -1,6 +1,6 @@

    RustDesk - Your remote desktop
    - تصاویر محیط نرم‌افزار • + تصاویر محیط نرم‌افزارساختارداکرساخت • @@ -9,12 +9,12 @@

    [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]

    برای ترجمه این سند (README)، رابط کاربری RustDesk، و مستندات آن به زبان مادری شما به کمکتان نیازمندیم.

    -با ما گپ بزنید: [Reddit](https://www.reddit.com/r/rustdesk) | [Twitter](https://twitter.com/rustdesk) | [Discord](https://discord.gg/nDceKgxnkV) +با ما گفتگو کنید: [Reddit](https://www.reddit.com/r/rustdesk) | [Twitter](https://twitter.com/rustdesk) | [Discord](https://discord.gg/nDceKgxnkV) [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09) -راست‌دسک (RustDesk) نرم‌افزاری برای گارکردن با رایانه‌ی رومیزی از راه دور است و با زبان برنامه‌نویسی Rust نوشته شده است. نیاز به تنظیمات چندانی ندارد و شما را قادر می سازد تا بدون نگرانی از امنیت اطلاعات خود بر آن‌ها کنترل کامل داشته باشید. +راست‌دسک (RustDesk) نرم‌افزاری برای کارکردن با رایانه‌ی رومیزی از راه دور است و با زبان برنامه‌نویسی Rust نوشته شده است. نیاز به تنظیمات چندانی ندارد و شما را قادر می سازد تا بدون نگرانی از امنیت اطلاعات خود بر آن‌ها کنترل کامل داشته باشید. می‌توانید از سرور rendezvous/relay ما استفاده کنید، [سرور خودتان را راه‌اندازی کنید](https://rustdesk.com/server) یا [ سرورrendezvous/relay خود را بنویسید](https://github.com/rustdesk/rustdesk). @@ -130,7 +130,7 @@ cd rustdesk docker build -t "rustdesk-builder" . ``` -سپس، هر بار که نیاز به ساخت ترم‌افزار داشتید، دستور زیر را اجرا کنید: +سپس، هر بار که نیاز به ساخت نرم‌افزار داشتید، دستور زیر را اجرا کنید: ```sh docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder From 3462756a11a8b69bed40246cd4a6362b291f7bfd Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sun, 5 Feb 2023 16:56:13 +0800 Subject: [PATCH 81/83] optimize dialog margin, fix password eye icon color --- flutter/lib/common.dart | 8 +++----- flutter/lib/consts.dart | 1 - flutter/lib/mobile/widgets/dialog.dart | 5 +---- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 9f3e2c740..8236597ff 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -694,7 +694,6 @@ void msgBox(String id, String type, String title, String text, String link, buttons.insert( 0, dialogButton('Cancel', onPressed: cancel, isOutline: true)); } - // TODO: test this button if (type.contains("hasclose")) { buttons.insert( 0, @@ -708,8 +707,7 @@ void msgBox(String id, String type, String title, String text, String link, dialogManager.show( (setState, close) => CustomAlertDialog( title: null, - content: SelectionArea( - child: msgboxContent(type, title, text).paddingOnly(bottom: 10)), + content: SelectionArea(child: msgboxContent(type, title, text)), actions: buttons, onSubmit: hasOk ? submit : null, onCancel: hasCancel == true ? cancel : null, @@ -774,7 +772,7 @@ Widget msgboxContent(String type, String title, String text) { ), ), ], - ); + ).marginOnly(bottom: 12); } void msgBoxCommon(OverlayDialogManager dialogManager, String title, @@ -1714,4 +1712,4 @@ Future updateSystemWindowTheme() async { : SystemWindowTheme.dark); } } -} \ No newline at end of file +} diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 1fc97f410..c95c62fcc 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -26,7 +26,6 @@ const String kWindowEventShow = "show"; const String kWindowConnect = "connect"; const String kUniLinksPrefix = "rustdesk://"; -const String kActionNewConnection = "connection/new/"; const String kTabLabelHomePage = "Home"; const String kTabLabelSettingPage = "Settings"; diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index bded6d069..2fbe40091 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; -import 'package:flutter_hbb/desktop/widgets/button.dart'; import 'package:get/get.dart'; import '../../common.dart'; @@ -371,8 +370,7 @@ void showWaitUacDialog( tag: '$id-wait-uac', (setState, close) => CustomAlertDialog( title: null, - content: msgboxContent(type, 'Wait', 'wait_accept_uac_tip') - .marginOnly(bottom: 10), + content: msgboxContent(type, 'Wait', 'wait_accept_uac_tip'), )); } @@ -647,7 +645,6 @@ class _PasswordWidgetState extends State { icon: Icon( // Based on passwordVisible state choose the icon _passwordVisible ? Icons.visibility : Icons.visibility_off, - color: Theme.of(context).primaryColorDark, ), onPressed: () { // Update the state i.e. toggle the state of passwordVisible variable From 255c58ef7b725ea64012073ae8d8cb48720d7b98 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sun, 5 Feb 2023 17:29:54 +0800 Subject: [PATCH 82/83] opt: close button color and corner on tab --- flutter/lib/desktop/widgets/tabbar_widget.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index 223076951..cfbddbafb 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -959,7 +959,7 @@ class _CloseButton extends StatelessWidget { offstage: !visible, child: InkWell( hoverColor: MyTheme.tabbar(context).closeHoverColor, - customBorder: const RoundedRectangleBorder(), + customBorder: const CircleBorder(), onTap: () => onClose(), child: Icon( Icons.close, @@ -1082,7 +1082,7 @@ class TabbarTheme extends ThemeExtension { unSelectedIconColor: Color.fromARGB(255, 96, 96, 96), dividerColor: Color.fromARGB(255, 238, 238, 238), hoverColor: Color.fromARGB(51, 158, 158, 158), - closeHoverColor: Colors.black, + closeHoverColor: Color.fromARGB(255, 224, 224, 224), selectedTabBackgroundColor: Color.fromARGB(255, 240, 240, 240)); static const dark = TabbarTheme( From 133fba573bea02d9a29b64e879d522f13d331069 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sun, 5 Feb 2023 18:20:22 +0800 Subject: [PATCH 83/83] confirmed issue #2935 is false report, set_bitrate was called, and bandwidth has obvious change if you watch car game video --- src/server/video_service.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/video_service.rs b/src/server/video_service.rs index d041a433c..55920e320 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -498,7 +498,7 @@ fn run(sp: GenericService) -> ResultType<()> { video_qos.target_bitrate, video_qos.fps ); - encoder.set_bitrate(video_qos.target_bitrate).unwrap(); + allow_err!(encoder.set_bitrate(video_qos.target_bitrate)); spf = video_qos.spf(); } drop(video_qos);