From ed9e92fc2e46fb3272cb4d694802ac8915a45ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bojan=20Nem=C4=8Di=C4=87?= Date: Fri, 9 Dec 2022 09:19:44 +0100 Subject: [PATCH 001/382] Enable reading ID from CLI --- src/core_main.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/core_main.rs b/src/core_main.rs index d0ce9e0d1..bf6ef7aac 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -221,6 +221,13 @@ pub fn core_main() -> Option> { } } return None; + } else if args[0] == "--id" { + if crate::platform::is_root() { + println!("{}", crate::ipc::get_id()); + } else { + println!("Permission denied!"); + } + return None; } else if args[0] == "--check-hwcodec-config" { #[cfg(feature = "hwcodec")] scrap::hwcodec::check_config(); From 4bd4fba533ea31c773342e279e7ac1c22b39a499 Mon Sep 17 00:00:00 2001 From: sjpark Date: Wed, 8 Feb 2023 21:45:10 +0900 Subject: [PATCH 002/382] allow swap key --- .../desktop/pages/desktop_setting_page.dart | 2 + memo.txt | 104 ++++++++++++++++++ src/flutter.rs | 2 + src/keyboard.rs | 47 ++++++++ src/server/connection.rs | 60 ++++++++++ src/ui/index.tis | 1 + src/ui/remote.rs | 2 + src/ui_session_interface.rs | 10 ++ 8 files changed, 228 insertions(+) create mode 100644 memo.txt diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 4b6cf2a62..67eb0234b 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -278,6 +278,8 @@ class _GeneralState extends State<_General> { _OptionCheckBox(context, 'Confirm before closing multiple tabs', 'enable-confirm-closing-tabs'), _OptionCheckBox(context, 'Adaptive Bitrate', 'enable-abr'), + if (Platform.isMacOS) + _OptionCheckBox(context, 'Swap control-command key', 'allow-swap-key'), if (Platform.isLinux) Tooltip( message: translate('software_render_tip'), diff --git a/memo.txt b/memo.txt new file mode 100644 index 000000000..da23ae423 --- /dev/null +++ b/memo.txt @@ -0,0 +1,104 @@ +#windows +python3 res/inline-sciter.py +cargo build --release --features inline,with_rc --target=aarch64-pc-windows-msvc -vv + +Push-Location flutter ; flutter pub get ; Pop-Location +~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart + +%comspec% /k "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsamd64_arm64.bat" +rustup update +rustup target add aarch64-pc-windows-msvc +rustup target list + +reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug" /v Auto /t REG_DWORD /d 1 /f +reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\rustdesk.exe" /v Debugger /t REG_SZ /d "vsjitdebugger.exe" /f + +#macos +pushd flutter && flutter pub get && popd +~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart +./build.py --flutter +codesign --force --options runtime -s "Developer ID Application" --deep ./flutter/build/macos/Build/Products/Release/RustDesk.app -v +rm -r /Applications/RustDesk.app +cp -r ./flutter/build/macos/Build/Products/Release/RustDesk.app /Applications/RustDesk.app +open -n /Applications/RustDesk.app --args --server + +cargo bundle --release --features inline +cp libsciter.dylib target/release/bundle/osx/RustDesk.app/Contents/MacOS +mv target/release/bundle/osx/RustDesk.app/Contents/Resources/res/* target/release/bundle/osx/RustDesk.app/Contents/Resources +rm -rf target/release/bundle/osx/RustDesk.app/Contents/Resources/res +target/release/bundle/osx/RustDesk.app/Contents/Info.plist + LSUIElement + 1 + +python3 res/inline-sciter.py +cargo build --release --features inline +cp target/release/rustdesk ../Documents/RustDesk.app/Contents/MacOS/rustdesk +codesign -s "Developer ID Application" --force --options runtime ../Documents/RustDesk.app/Contents/MacOS/* +codesign -s "Developer ID Application" --force --options runtime ../Documents/RustDesk.app +rm -r /Applications/RustDesk.app +cp -r ../Documents/RustDesk.app /Applications/RustDesk.app + +csrutil disable +file target\release\rustdesk +sudo lsof -i -n -P | grep rustdesk // netstat +https://github.com/create-dmg/create-dmg +security find-identity -p basic -v + +#android +BINDGEN_EXTRA_CLANG_ARGS_aarch64_linux_android="--target=arm64-apple-macos --sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk" RUST_LOG=debug cargo ndk --platform 21 --target aarch64-linux-android rustc --lib --features flutter --release +cp target/aarch64-linux-android/release/liblibrustdesk.so flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so +pushd flutter; flutter build apk --target-platform android-arm64 --release; popd +adb install flutter/build/app/outputs/flutter-apk/app-release.apk + +sudo mount -t drvfs '\\192.168.111.10\Macintosh HD' /mnt/mac +cp target/aarch64-linux-android/debug/liblibrustdesk.so /mnt/mac/Users/sjpark/rustdesk/flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so + +adb logcat | grep LOG_SERVICE +adb emu kill + +sudo apt install build-essential +sudo apt install gcc-multilib + +#ios +flutter/ios/Runnder.xcworkspace/View/Navigators/Project/targets:Runner/Signing & Capability/Teams +cargo build --target aarch64-apple-ios --features flutter --release +pushd flutter; flutter build ios --release; popd +xcode/Window/Devices and Simulators/INSTALLED APPS + +xcrun simctl list +open -a Simulator --args -CurrentDeviceUDID 5D1C39DD-708B-41D3-B89A-3F0D9B8E42BF + +# rustdesk +cd C:\Users\sjpark\Documents\rustdesk +set VCPKG_ROOT=C:\Users\sjpark\Documents\vcpkg +set LIBCLANG_PATH=C:\Program Files\LLVM\bin + +# ring +set path=C:\Program Files\LLVM\bin;C:\Strawberry\perl\bin\;%path%; +.\target\tools\windows\nasm\nasm.exe +set RING_PREGENERATE_ASM=1 + +#dependencies +ring = { git = "https://github.com/sj6219/ring", branch = "0.16.20_alpha" } + + +adb shell dumpsys package com.carriez.flutter_hbb +objdump -T ~/rustdesk/target/aarch64-linux-android/release/liblibrustdesk.so + +cat /Users/sjpark/Library/Android/sdk/ndk/22.0.7026061/toolchains/llvm/prebuilt/darwin-x86_64/lib64/clang/11.0.5/lib/linux/aarch64/lldb-server | adb shell sh -c 'cat > /data/local/tmp/lldb-server && chmod 755 /data/local/tmp/lldb-server' +adb shell run-as com.carriez.flutter_hbb mkdir -p /data/data/com.carriez.flutter_hbb/lldb/bin/ +adb shell "cat /data/local/tmp/lldb-server | run-as com.carriez.flutter_hbb sh -c 'cat > /data/data/com.carriez.flutter_hbb/lldb/bin/lldb-server && chmod 755 /data/data/com.carriez.flutter_hbb/lldb/bin/lldb-server'" + +adb shell ps -e -o PID -o NAME | grep com.carriez.flutter_hbb +adb forward tcp:10086 tcp:10086 +adb shell run-as com.carriez.flutter_hbb /data/data/com.carriez.flutter_hbb/lldb/bin/lldb-server platform --listen "*:10086" --server + +/Users/sjpark/Library/Android/sdk/ndk/22.0.7026061/toolchains/llvm/prebuilt/darwin-x86_64/bin/lldb +platform select remote-android +platform connect connect://localhost:10086 +attach +b connection.rs:624 + +add-dsym /Users/sjpark/ndk-samples/hello-gl2/app/build/intermediates/merged_native_libs/debug/out/lib/arm64-v8a/libgl2jni.so +b gl_code.cpp:151 + diff --git a/src/flutter.rs b/src/flutter.rs index 2d7d3fb86..bee585d93 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -428,8 +428,10 @@ pub fn session_add( let session_id = get_session_id(id.to_owned()); LocalConfig::set_remote_id(&session_id); + let allow_swap_key = hbb_common::config::Config::get_option("allow-swap-key") == "Y"; let session: Session = Session { id: session_id.clone(), + allow_swap_key, ..Default::default() }; diff --git a/src/keyboard.rs b/src/keyboard.rs index 91480ba30..2764a4408 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -210,6 +210,53 @@ pub fn start_grab_loop() { if key == Key::CapsLock || key == Key::NumLock { return Some(event); } + #[cfg(target_os = "macos")] + let mut event = event; + #[cfg(target_os = "macos")] { + let mut allow_swap_key = false; + #[cfg(not(any(feature = "flutter", feature = "cli")))] + if let Some(session) = CUR_SESSION.lock().unwrap().as_ref() { + allow_swap_key = session.allow_swap_key; + } + #[cfg(feature = "flutter")] + if let Some(session) = SESSIONS + .read() + .unwrap() + .get(&*CUR_SESSION_ID.read().unwrap()) + { + allow_swap_key = session.allow_swap_key; + } + if allow_swap_key { + match event.event_type { + EventType::KeyPress( key) => { + let key = match key { + rdev::Key::ControlLeft => rdev::Key::MetaLeft, + rdev::Key::MetaLeft => rdev::Key::ControlLeft, + rdev::Key::ControlRight => rdev::Key::MetaLeft, + rdev::Key::MetaRight => rdev::Key::ControlLeft, + _ => key, + }; + event.event_type = EventType::KeyPress(key); + event.scan_code = rdev::macos_keycode_from_key(key).unwrap_or_default(); + event.code = event.scan_code as _; + } + EventType::KeyRelease(key) => { + let key = match key { + rdev::Key::ControlLeft => rdev::Key::MetaLeft, + rdev::Key::MetaLeft => rdev::Key::ControlLeft, + rdev::Key::ControlRight => rdev::Key::MetaLeft, + rdev::Key::MetaRight => rdev::Key::ControlLeft, + _ => key, + }; + event.event_type = EventType::KeyRelease(key); + event.scan_code = rdev::macos_keycode_from_key(key).unwrap_or_default(); + event.code = event.scan_code as _; + } + _ => {} + }; + }; + }; + let mut _keyboard_mode = KeyboardMode::Map; let scan_code = event.scan_code; diff --git a/src/server/connection.rs b/src/server/connection.rs index 9ce53c960..17d4e3768 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -539,6 +539,9 @@ impl Connection { #[cfg(not(any(target_os = "android", target_os = "ios")))] fn handle_input(receiver: std_mpsc::Receiver, tx: Sender) { + #[cfg(target_os = "macos")] + let allow_swap_key = hbb_common::config::Config::get_option("allow-swap-key") == "Y"; + let mut block_input_mode = false; #[cfg(target_os = "windows")] { @@ -551,9 +554,66 @@ impl Connection { match receiver.recv_timeout(std::time::Duration::from_millis(500)) { Ok(v) => match v { MessageInput::Mouse((msg, id)) => { + #[cfg(target_os = "macos")] + let msg = { + let mut msg = msg; + if allow_swap_key { + msg.modifiers = msg.modifiers.iter().map(|ck| { + let ck = ck.enum_value_or_default(); + let ck = match ck { + ControlKey::Control => ControlKey::Meta, + ControlKey::Meta => ControlKey::Control, + ControlKey::RControl => ControlKey::Meta, + ControlKey::RWin => ControlKey::Control, + _ => ck, + }; + hbb_common::protobuf::EnumOrUnknown::new(ck) + }).collect(); + } + msg + }; + handle_mouse(&msg, id); } MessageInput::Key((mut msg, press)) => { + #[cfg(target_os = "macos")] + if allow_swap_key { + if let Some(key_event::Union::ControlKey(ck)) = msg.union { + let ck = ck.enum_value_or_default(); + let ck = match ck { + ControlKey::Control => ControlKey::Meta, + ControlKey::Meta => ControlKey::Control, + ControlKey::RControl => ControlKey::Meta, + ControlKey::RWin => ControlKey::Control, + _ => ck, + }; + msg.set_control_key(ck); + } + msg.modifiers = msg.modifiers.iter().map(|ck| { + let ck = ck.enum_value_or_default(); + let ck = match ck { + ControlKey::Control => ControlKey::Meta, + ControlKey::Meta => ControlKey::Control, + ControlKey::RControl => ControlKey::Meta, + ControlKey::RWin => ControlKey::Control, + _ => ck, + }; + hbb_common::protobuf::EnumOrUnknown::new(ck) + }).collect(); + + let code = msg.chr(); + if code != 0 { + let key = rdev::key_from_code(code); + let key = match key { + rdev::Key::ControlLeft => rdev::Key::MetaLeft, + rdev::Key::MetaLeft => rdev::Key::ControlLeft, + rdev::Key::ControlRight => rdev::Key::MetaLeft, + rdev::Key::MetaRight => rdev::Key::ControlLeft, + _ => key, + }; + msg.set_chr(rdev::macos_keycode_from_key(key).unwrap_or_default()); + } + } // todo: press and down have similar meanings. if press && msg.mode.unwrap() == KeyboardMode::Legacy { msg.down = true; diff --git a/src/ui/index.tis b/src/ui/index.tis index ec2e0a748..20228ea03 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -214,6 +214,7 @@ class Enhancements: Reactor.Component { {has_hwcodec ?
  • {svg_checkmark}{translate("Hardware Codec")} (beta)
  • : ""}
  • {svg_checkmark}{translate("Adaptive Bitrate")} (beta)
  • {translate("Recording")}
  • + {is_osx ?
  • {svg_checkmark}{translate("Swap control-command key")}
  • : "" } ; } diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 999b409e0..2d0d4d2c0 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -443,10 +443,12 @@ impl sciter::EventHandler for SciterSession { impl SciterSession { pub fn new(cmd: String, id: String, password: String, args: Vec) -> Self { + let allow_swap_key = hbb_common::config::Config::get_option("allow-swap-key") == "Y"; let session: Session = Session { id: id.clone(), password: password.clone(), args, + allow_swap_key, ..Default::default() }; diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index dc0e365ab..a0c4f06b0 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -36,6 +36,7 @@ pub struct Session { pub sender: Arc>>>, pub thread: Arc>>>, pub ui_handler: T, + pub allow_swap_key: bool, } impl Session { @@ -505,6 +506,15 @@ impl Session { shift: bool, command: bool, ) { + #[cfg(target_os = "macos")] + let (ctrl, command) = + if self.allow_swap_key { + (command, ctrl) + } + else { + (ctrl, command) + }; + #[allow(unused_mut)] let mut command = command; #[cfg(windows)] From 4261e988d2c4e37b2d8452d1ea623aeb81fd9d15 Mon Sep 17 00:00:00 2001 From: sjpark Date: Wed, 8 Feb 2023 21:49:53 +0900 Subject: [PATCH 003/382] delete memo --- memo.txt | 104 ------------------------------------------------------- 1 file changed, 104 deletions(-) delete mode 100644 memo.txt diff --git a/memo.txt b/memo.txt deleted file mode 100644 index da23ae423..000000000 --- a/memo.txt +++ /dev/null @@ -1,104 +0,0 @@ -#windows -python3 res/inline-sciter.py -cargo build --release --features inline,with_rc --target=aarch64-pc-windows-msvc -vv - -Push-Location flutter ; flutter pub get ; Pop-Location -~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart - -%comspec% /k "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsamd64_arm64.bat" -rustup update -rustup target add aarch64-pc-windows-msvc -rustup target list - -reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug" /v Auto /t REG_DWORD /d 1 /f -reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\rustdesk.exe" /v Debugger /t REG_SZ /d "vsjitdebugger.exe" /f - -#macos -pushd flutter && flutter pub get && popd -~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart -./build.py --flutter -codesign --force --options runtime -s "Developer ID Application" --deep ./flutter/build/macos/Build/Products/Release/RustDesk.app -v -rm -r /Applications/RustDesk.app -cp -r ./flutter/build/macos/Build/Products/Release/RustDesk.app /Applications/RustDesk.app -open -n /Applications/RustDesk.app --args --server - -cargo bundle --release --features inline -cp libsciter.dylib target/release/bundle/osx/RustDesk.app/Contents/MacOS -mv target/release/bundle/osx/RustDesk.app/Contents/Resources/res/* target/release/bundle/osx/RustDesk.app/Contents/Resources -rm -rf target/release/bundle/osx/RustDesk.app/Contents/Resources/res -target/release/bundle/osx/RustDesk.app/Contents/Info.plist - LSUIElement - 1 - -python3 res/inline-sciter.py -cargo build --release --features inline -cp target/release/rustdesk ../Documents/RustDesk.app/Contents/MacOS/rustdesk -codesign -s "Developer ID Application" --force --options runtime ../Documents/RustDesk.app/Contents/MacOS/* -codesign -s "Developer ID Application" --force --options runtime ../Documents/RustDesk.app -rm -r /Applications/RustDesk.app -cp -r ../Documents/RustDesk.app /Applications/RustDesk.app - -csrutil disable -file target\release\rustdesk -sudo lsof -i -n -P | grep rustdesk // netstat -https://github.com/create-dmg/create-dmg -security find-identity -p basic -v - -#android -BINDGEN_EXTRA_CLANG_ARGS_aarch64_linux_android="--target=arm64-apple-macos --sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk" RUST_LOG=debug cargo ndk --platform 21 --target aarch64-linux-android rustc --lib --features flutter --release -cp target/aarch64-linux-android/release/liblibrustdesk.so flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so -pushd flutter; flutter build apk --target-platform android-arm64 --release; popd -adb install flutter/build/app/outputs/flutter-apk/app-release.apk - -sudo mount -t drvfs '\\192.168.111.10\Macintosh HD' /mnt/mac -cp target/aarch64-linux-android/debug/liblibrustdesk.so /mnt/mac/Users/sjpark/rustdesk/flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so - -adb logcat | grep LOG_SERVICE -adb emu kill - -sudo apt install build-essential -sudo apt install gcc-multilib - -#ios -flutter/ios/Runnder.xcworkspace/View/Navigators/Project/targets:Runner/Signing & Capability/Teams -cargo build --target aarch64-apple-ios --features flutter --release -pushd flutter; flutter build ios --release; popd -xcode/Window/Devices and Simulators/INSTALLED APPS - -xcrun simctl list -open -a Simulator --args -CurrentDeviceUDID 5D1C39DD-708B-41D3-B89A-3F0D9B8E42BF - -# rustdesk -cd C:\Users\sjpark\Documents\rustdesk -set VCPKG_ROOT=C:\Users\sjpark\Documents\vcpkg -set LIBCLANG_PATH=C:\Program Files\LLVM\bin - -# ring -set path=C:\Program Files\LLVM\bin;C:\Strawberry\perl\bin\;%path%; -.\target\tools\windows\nasm\nasm.exe -set RING_PREGENERATE_ASM=1 - -#dependencies -ring = { git = "https://github.com/sj6219/ring", branch = "0.16.20_alpha" } - - -adb shell dumpsys package com.carriez.flutter_hbb -objdump -T ~/rustdesk/target/aarch64-linux-android/release/liblibrustdesk.so - -cat /Users/sjpark/Library/Android/sdk/ndk/22.0.7026061/toolchains/llvm/prebuilt/darwin-x86_64/lib64/clang/11.0.5/lib/linux/aarch64/lldb-server | adb shell sh -c 'cat > /data/local/tmp/lldb-server && chmod 755 /data/local/tmp/lldb-server' -adb shell run-as com.carriez.flutter_hbb mkdir -p /data/data/com.carriez.flutter_hbb/lldb/bin/ -adb shell "cat /data/local/tmp/lldb-server | run-as com.carriez.flutter_hbb sh -c 'cat > /data/data/com.carriez.flutter_hbb/lldb/bin/lldb-server && chmod 755 /data/data/com.carriez.flutter_hbb/lldb/bin/lldb-server'" - -adb shell ps -e -o PID -o NAME | grep com.carriez.flutter_hbb -adb forward tcp:10086 tcp:10086 -adb shell run-as com.carriez.flutter_hbb /data/data/com.carriez.flutter_hbb/lldb/bin/lldb-server platform --listen "*:10086" --server - -/Users/sjpark/Library/Android/sdk/ndk/22.0.7026061/toolchains/llvm/prebuilt/darwin-x86_64/bin/lldb -platform select remote-android -platform connect connect://localhost:10086 -attach -b connection.rs:624 - -add-dsym /Users/sjpark/ndk-samples/hello-gl2/app/build/intermediates/merged_native_libs/debug/out/lib/arm64-v8a/libgl2jni.so -b gl_code.cpp:151 - From edff4acbcbf1d932608765ad1ba1b5998517b10b Mon Sep 17 00:00:00 2001 From: sjpark Date: Thu, 9 Feb 2023 11:54:23 +0900 Subject: [PATCH 004/382] swap key update --- .../desktop/pages/desktop_setting_page.dart | 2 - .../lib/desktop/widgets/remote_menubar.dart | 3 + libs/hbb_common/src/config.rs | 4 ++ src/client.rs | 4 ++ src/flutter.rs | 2 - src/keyboard.rs | 23 ++++--- src/server/connection.rs | 60 ------------------- src/ui/header.tis | 1 + src/ui/index.tis | 1 - src/ui/remote.rs | 2 - src/ui_session_interface.rs | 4 +- 11 files changed, 27 insertions(+), 79 deletions(-) diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 67eb0234b..4b6cf2a62 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -278,8 +278,6 @@ class _GeneralState extends State<_General> { _OptionCheckBox(context, 'Confirm before closing multiple tabs', 'enable-confirm-closing-tabs'), _OptionCheckBox(context, 'Adaptive Bitrate', 'enable-abr'), - if (Platform.isMacOS) - _OptionCheckBox(context, 'Swap control-command key', 'allow-swap-key'), if (Platform.isLinux) Tooltip( message: translate('software_render_tip'), diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 6bb49000b..7db7d43aa 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -1580,6 +1580,9 @@ class _RemoteMenubarState extends State { ), ); } + keyboardMenu.add(_createSwitchMenuEntry( + 'Swap Control-Command Key', 'allow_swap_key', EdgeInsets.zero, true)); + return keyboardMenu; } diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 1e4d80c9f..8b08e1e21 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -223,6 +223,8 @@ pub struct PeerConfig { pub lock_after_session_end: LockAfterSessionEnd, #[serde(flatten)] pub privacy_mode: PrivacyMode, + #[serde(flatten)] + pub allow_swap_key: AllowSwapKey, #[serde(default)] pub port_forwards: Vec<(i32, String, i32)>, #[serde(default)] @@ -1066,6 +1068,8 @@ serde_field_bool!( ); serde_field_bool!(PrivacyMode, "privacy_mode", default_privacy_mode); +serde_field_bool!(AllowSwapKey, "allow_swap_key", default_swap_key); + #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct LocalConfig { #[serde(default)] diff --git a/src/client.rs b/src/client.rs index 020bea1f0..fb255176b 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1121,6 +1121,8 @@ impl LoginConfigHandler { option.block_input = BoolOption::No.into(); } else if name == "show-quality-monitor" { config.show_quality_monitor.v = !config.show_quality_monitor.v; + } else if name == "allow_swap_key" { + config.allow_swap_key.v = !config.allow_swap_key.v; } else { let is_set = self .options @@ -1274,6 +1276,8 @@ impl LoginConfigHandler { self.config.disable_clipboard.v } else if name == "show-quality-monitor" { self.config.show_quality_monitor.v + } else if name == "allow_swap_key" { + self.config.allow_swap_key.v } else { !self.get_option(name).is_empty() } diff --git a/src/flutter.rs b/src/flutter.rs index bee585d93..2d7d3fb86 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -428,10 +428,8 @@ pub fn session_add( let session_id = get_session_id(id.to_owned()); LocalConfig::set_remote_id(&session_id); - let allow_swap_key = hbb_common::config::Config::get_option("allow-swap-key") == "Y"; let session: Session = Session { id: session_id.clone(), - allow_swap_key, ..Default::default() }; diff --git a/src/keyboard.rs b/src/keyboard.rs index 18314dbc7..00a2edd74 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -205,18 +205,16 @@ static mut IS_0X021D_DOWN: bool = false; pub fn start_grab_loop() { #[cfg(any(target_os = "windows", target_os = "macos"))] std::thread::spawn(move || { - let try_handle_keyboard = move |event: Event, key: Key, is_press: bool| -> Option { + let try_handle_keyboard = move |mut event: Event, key: Key, is_press: bool| -> Option { // fix #2211:CAPS LOCK don't work if key == Key::CapsLock || key == Key::NumLock { return Some(event); } - #[cfg(target_os = "macos")] - let mut event = event; - #[cfg(target_os = "macos")] { + { let mut allow_swap_key = false; #[cfg(not(any(feature = "flutter", feature = "cli")))] if let Some(session) = CUR_SESSION.lock().unwrap().as_ref() { - allow_swap_key = session.allow_swap_key; + allow_swap_key = session.get_toggle_option("allow_swap_key".to_string()); } #[cfg(feature = "flutter")] if let Some(session) = SESSIONS @@ -224,7 +222,7 @@ pub fn start_grab_loop() { .unwrap() .get(&*CUR_SESSION_ID.read().unwrap()) { - allow_swap_key = session.allow_swap_key; + allow_swap_key = session.get_toggle_option("allow_swap_key".to_string()); } if allow_swap_key { match event.event_type { @@ -237,7 +235,11 @@ pub fn start_grab_loop() { _ => key, }; event.event_type = EventType::KeyPress(key); - event.scan_code = rdev::macos_keycode_from_key(key).unwrap_or_default(); + #[cfg(target_os = "windows")] + let scan_code = rdev::win_scancode_from_key(key).unwrap_or_default(); + #[cfg(target_os = "macos")] + let scan_code = rdev::macos_keycode_from_key(key).unwrap_or_default(); + event.scan_code = scan_code; event.code = event.scan_code as _; } EventType::KeyRelease(key) => { @@ -249,7 +251,11 @@ pub fn start_grab_loop() { _ => key, }; event.event_type = EventType::KeyRelease(key); - event.scan_code = rdev::macos_keycode_from_key(key).unwrap_or_default(); + #[cfg(target_os = "windows")] + let scan_code = rdev::win_scancode_from_key(key).unwrap_or_default(); + #[cfg(target_os = "macos")] + let scan_code = rdev::macos_keycode_from_key(key).unwrap_or_default(); + event.scan_code = scan_code; event.code = event.scan_code as _; } _ => {} @@ -257,7 +263,6 @@ pub fn start_grab_loop() { }; }; - let mut _keyboard_mode = KeyboardMode::Map; let _scan_code = event.scan_code; let res = if KEYBOARD_HOOKED.load(Ordering::SeqCst) { diff --git a/src/server/connection.rs b/src/server/connection.rs index 17d4e3768..9ce53c960 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -539,9 +539,6 @@ impl Connection { #[cfg(not(any(target_os = "android", target_os = "ios")))] fn handle_input(receiver: std_mpsc::Receiver, tx: Sender) { - #[cfg(target_os = "macos")] - let allow_swap_key = hbb_common::config::Config::get_option("allow-swap-key") == "Y"; - let mut block_input_mode = false; #[cfg(target_os = "windows")] { @@ -554,66 +551,9 @@ impl Connection { match receiver.recv_timeout(std::time::Duration::from_millis(500)) { Ok(v) => match v { MessageInput::Mouse((msg, id)) => { - #[cfg(target_os = "macos")] - let msg = { - let mut msg = msg; - if allow_swap_key { - msg.modifiers = msg.modifiers.iter().map(|ck| { - let ck = ck.enum_value_or_default(); - let ck = match ck { - ControlKey::Control => ControlKey::Meta, - ControlKey::Meta => ControlKey::Control, - ControlKey::RControl => ControlKey::Meta, - ControlKey::RWin => ControlKey::Control, - _ => ck, - }; - hbb_common::protobuf::EnumOrUnknown::new(ck) - }).collect(); - } - msg - }; - handle_mouse(&msg, id); } MessageInput::Key((mut msg, press)) => { - #[cfg(target_os = "macos")] - if allow_swap_key { - if let Some(key_event::Union::ControlKey(ck)) = msg.union { - let ck = ck.enum_value_or_default(); - let ck = match ck { - ControlKey::Control => ControlKey::Meta, - ControlKey::Meta => ControlKey::Control, - ControlKey::RControl => ControlKey::Meta, - ControlKey::RWin => ControlKey::Control, - _ => ck, - }; - msg.set_control_key(ck); - } - msg.modifiers = msg.modifiers.iter().map(|ck| { - let ck = ck.enum_value_or_default(); - let ck = match ck { - ControlKey::Control => ControlKey::Meta, - ControlKey::Meta => ControlKey::Control, - ControlKey::RControl => ControlKey::Meta, - ControlKey::RWin => ControlKey::Control, - _ => ck, - }; - hbb_common::protobuf::EnumOrUnknown::new(ck) - }).collect(); - - let code = msg.chr(); - if code != 0 { - let key = rdev::key_from_code(code); - let key = match key { - rdev::Key::ControlLeft => rdev::Key::MetaLeft, - rdev::Key::MetaLeft => rdev::Key::ControlLeft, - rdev::Key::ControlRight => rdev::Key::MetaLeft, - rdev::Key::MetaRight => rdev::Key::ControlLeft, - _ => key, - }; - msg.set_chr(rdev::macos_keycode_from_key(key).unwrap_or_default()); - } - } // todo: press and down have similar meanings. if press && msg.mode.unwrap() == KeyboardMode::Legacy { msg.down = true; diff --git a/src/ui/header.tis b/src/ui/header.tis index 009995f4f..414edab5a 100644 --- a/src/ui/header.tis +++ b/src/ui/header.tis @@ -156,6 +156,7 @@ class Header: Reactor.Component {
  • {svg_checkmark}{translate('Legacy mode')}
  • {svg_checkmark}{translate('Map mode')}
  • +
  • {svg_checkmark}{translate('Swap Control-Command Key')}
  • ; } diff --git a/src/ui/index.tis b/src/ui/index.tis index 20228ea03..ec2e0a748 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -214,7 +214,6 @@ class Enhancements: Reactor.Component { {has_hwcodec ?
  • {svg_checkmark}{translate("Hardware Codec")} (beta)
  • : ""}
  • {svg_checkmark}{translate("Adaptive Bitrate")} (beta)
  • {translate("Recording")}
  • - {is_osx ?
  • {svg_checkmark}{translate("Swap control-command key")}
  • : "" } ; } diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 2d0d4d2c0..999b409e0 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -443,12 +443,10 @@ impl sciter::EventHandler for SciterSession { impl SciterSession { pub fn new(cmd: String, id: String, password: String, args: Vec) -> Self { - let allow_swap_key = hbb_common::config::Config::get_option("allow-swap-key") == "Y"; let session: Session = Session { id: id.clone(), password: password.clone(), args, - allow_swap_key, ..Default::default() }; diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index f20d1470e..96cd98364 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -36,7 +36,6 @@ pub struct Session { pub sender: Arc>>>, pub thread: Arc>>>, pub ui_handler: T, - pub allow_swap_key: bool, } impl Session { @@ -506,9 +505,8 @@ impl Session { shift: bool, command: bool, ) { - #[cfg(target_os = "macos")] let (ctrl, command) = - if self.allow_swap_key { + if self.get_toggle_option("allow_swap_key".to_string()) { (command, ctrl) } else { From f438dd9fd0b3250417f7ccad9d54768298232320 Mon Sep 17 00:00:00 2001 From: sjpark Date: Thu, 9 Feb 2023 20:28:36 +0900 Subject: [PATCH 005/382] swap_modifier_key() --- src/keyboard.rs | 110 +++++++++++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 53 deletions(-) diff --git a/src/keyboard.rs b/src/keyboard.rs index 00a2edd74..56e11f321 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -202,66 +202,70 @@ pub fn update_grab_get_key_name() { #[cfg(target_os = "windows")] static mut IS_0X021D_DOWN: bool = false; +fn swap_modifier_key(mut event: Event) -> Event { + + let mut allow_swap_key = false; + #[cfg(not(any(feature = "flutter", feature = "cli")))] + if let Some(session) = CUR_SESSION.lock().unwrap().as_ref() { + allow_swap_key = session.get_toggle_option("allow_swap_key".to_string()); + } + #[cfg(feature = "flutter")] + if let Some(session) = SESSIONS + .read() + .unwrap() + .get(&*CUR_SESSION_ID.read().unwrap()) + { + allow_swap_key = session.get_toggle_option("allow_swap_key".to_string()); + } + if allow_swap_key { + match event.event_type { + EventType::KeyPress( key) => { + let key = match key { + rdev::Key::ControlLeft => rdev::Key::MetaLeft, + rdev::Key::MetaLeft => rdev::Key::ControlLeft, + rdev::Key::ControlRight => rdev::Key::MetaLeft, + rdev::Key::MetaRight => rdev::Key::ControlLeft, + _ => key, + }; + event.event_type = EventType::KeyPress(key); + #[cfg(target_os = "windows")] + let scan_code = rdev::win_scancode_from_key(key).unwrap_or_default(); + #[cfg(target_os = "macos")] + let scan_code = rdev::macos_keycode_from_key(key).unwrap_or_default(); + event.scan_code = scan_code; + event.code = event.scan_code as _; + } + EventType::KeyRelease(key) => { + let key = match key { + rdev::Key::ControlLeft => rdev::Key::MetaLeft, + rdev::Key::MetaLeft => rdev::Key::ControlLeft, + rdev::Key::ControlRight => rdev::Key::MetaLeft, + rdev::Key::MetaRight => rdev::Key::ControlLeft, + _ => key, + }; + event.event_type = EventType::KeyRelease(key); + #[cfg(target_os = "windows")] + let scan_code = rdev::win_scancode_from_key(key).unwrap_or_default(); + #[cfg(target_os = "macos")] + let scan_code = rdev::macos_keycode_from_key(key).unwrap_or_default(); + event.scan_code = scan_code; + event.code = event.scan_code as _; + } + _ => {} + }; + } + event +} + pub fn start_grab_loop() { #[cfg(any(target_os = "windows", target_os = "macos"))] std::thread::spawn(move || { - let try_handle_keyboard = move |mut event: Event, key: Key, is_press: bool| -> Option { + let try_handle_keyboard = move |event: Event, key: Key, is_press: bool| -> Option { // fix #2211:CAPS LOCK don't work if key == Key::CapsLock || key == Key::NumLock { return Some(event); } - { - let mut allow_swap_key = false; - #[cfg(not(any(feature = "flutter", feature = "cli")))] - if let Some(session) = CUR_SESSION.lock().unwrap().as_ref() { - allow_swap_key = session.get_toggle_option("allow_swap_key".to_string()); - } - #[cfg(feature = "flutter")] - if let Some(session) = SESSIONS - .read() - .unwrap() - .get(&*CUR_SESSION_ID.read().unwrap()) - { - allow_swap_key = session.get_toggle_option("allow_swap_key".to_string()); - } - if allow_swap_key { - match event.event_type { - EventType::KeyPress( key) => { - let key = match key { - rdev::Key::ControlLeft => rdev::Key::MetaLeft, - rdev::Key::MetaLeft => rdev::Key::ControlLeft, - rdev::Key::ControlRight => rdev::Key::MetaLeft, - rdev::Key::MetaRight => rdev::Key::ControlLeft, - _ => key, - }; - event.event_type = EventType::KeyPress(key); - #[cfg(target_os = "windows")] - let scan_code = rdev::win_scancode_from_key(key).unwrap_or_default(); - #[cfg(target_os = "macos")] - let scan_code = rdev::macos_keycode_from_key(key).unwrap_or_default(); - event.scan_code = scan_code; - event.code = event.scan_code as _; - } - EventType::KeyRelease(key) => { - let key = match key { - rdev::Key::ControlLeft => rdev::Key::MetaLeft, - rdev::Key::MetaLeft => rdev::Key::ControlLeft, - rdev::Key::ControlRight => rdev::Key::MetaLeft, - rdev::Key::MetaRight => rdev::Key::ControlLeft, - _ => key, - }; - event.event_type = EventType::KeyRelease(key); - #[cfg(target_os = "windows")] - let scan_code = rdev::win_scancode_from_key(key).unwrap_or_default(); - #[cfg(target_os = "macos")] - let scan_code = rdev::macos_keycode_from_key(key).unwrap_or_default(); - event.scan_code = scan_code; - event.code = event.scan_code as _; - } - _ => {} - }; - }; - }; + let event = swap_modifier_key(event); let mut _keyboard_mode = KeyboardMode::Map; let _scan_code = event.scan_code; From b29236da062bbba89ba3bdd6afeb70e7039100c0 Mon Sep 17 00:00:00 2001 From: sjpark Date: Sat, 11 Feb 2023 10:41:06 +0900 Subject: [PATCH 006/382] swap key renewal --- Cargo.toml | 5 ++ src/client.rs | 2 + src/keyboard.rs | 58 +------------------- src/ui_session_interface.rs | 103 ++++++++++++++++++++++++++++++++---- 4 files changed, 102 insertions(+), 66 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b315024e9..c171e84e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -167,3 +167,8 @@ panic = 'abort' strip = true #opt-level = 'z' # only have smaller size after strip rpath = true + +[patch."https://github.com/fufesou/rdev"] +#rdev = { path = "../rdev" } +rdev = { git = "https://github.com/sj6219/rdev", branch = "sigma" } + diff --git a/src/client.rs b/src/client.rs index fb255176b..b98f9fde4 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1702,6 +1702,7 @@ pub fn send_mouse( if check_scroll_on_mac(mask, x, y) { mouse_event.modifiers.push(ControlKey::Scroll.into()); } + interface.swap_modifier_mouse(&mut mouse_event); msg_out.set_mouse_event(mouse_event); interface.send(Data::Message(msg_out)); } @@ -1928,6 +1929,7 @@ pub trait Interface: Send + Clone + 'static + Sized { fn is_force_relay(&self) -> bool { self.get_login_config_handler().read().unwrap().force_relay } + fn swap_modifier_mouse(&self, msg : &mut hbb_common::protos::message::MouseEvent) {} } /// Data used by the client interface. diff --git a/src/keyboard.rs b/src/keyboard.rs index 56e11f321..105b84400 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -202,70 +202,14 @@ pub fn update_grab_get_key_name() { #[cfg(target_os = "windows")] static mut IS_0X021D_DOWN: bool = false; -fn swap_modifier_key(mut event: Event) -> Event { - - let mut allow_swap_key = false; - #[cfg(not(any(feature = "flutter", feature = "cli")))] - if let Some(session) = CUR_SESSION.lock().unwrap().as_ref() { - allow_swap_key = session.get_toggle_option("allow_swap_key".to_string()); - } - #[cfg(feature = "flutter")] - if let Some(session) = SESSIONS - .read() - .unwrap() - .get(&*CUR_SESSION_ID.read().unwrap()) - { - allow_swap_key = session.get_toggle_option("allow_swap_key".to_string()); - } - if allow_swap_key { - match event.event_type { - EventType::KeyPress( key) => { - let key = match key { - rdev::Key::ControlLeft => rdev::Key::MetaLeft, - rdev::Key::MetaLeft => rdev::Key::ControlLeft, - rdev::Key::ControlRight => rdev::Key::MetaLeft, - rdev::Key::MetaRight => rdev::Key::ControlLeft, - _ => key, - }; - event.event_type = EventType::KeyPress(key); - #[cfg(target_os = "windows")] - let scan_code = rdev::win_scancode_from_key(key).unwrap_or_default(); - #[cfg(target_os = "macos")] - let scan_code = rdev::macos_keycode_from_key(key).unwrap_or_default(); - event.scan_code = scan_code; - event.code = event.scan_code as _; - } - EventType::KeyRelease(key) => { - let key = match key { - rdev::Key::ControlLeft => rdev::Key::MetaLeft, - rdev::Key::MetaLeft => rdev::Key::ControlLeft, - rdev::Key::ControlRight => rdev::Key::MetaLeft, - rdev::Key::MetaRight => rdev::Key::ControlLeft, - _ => key, - }; - event.event_type = EventType::KeyRelease(key); - #[cfg(target_os = "windows")] - let scan_code = rdev::win_scancode_from_key(key).unwrap_or_default(); - #[cfg(target_os = "macos")] - let scan_code = rdev::macos_keycode_from_key(key).unwrap_or_default(); - event.scan_code = scan_code; - event.code = event.scan_code as _; - } - _ => {} - }; - } - event -} - pub fn start_grab_loop() { #[cfg(any(target_os = "windows", target_os = "macos"))] std::thread::spawn(move || { - let try_handle_keyboard = move |event: Event, key: Key, is_press: bool| -> Option { + let try_handle_keyboard = move |event: Event, key: Key, is_press: bool| -> Option { // fix #2211:CAPS LOCK don't work if key == Key::CapsLock || key == Key::NumLock { return Some(event); } - let event = swap_modifier_key(event); let mut _keyboard_mode = KeyboardMode::Map; let _scan_code = event.scan_code; diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 96cd98364..d55073b9d 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -335,10 +335,87 @@ impl Session { return "".to_owned(); } + pub fn swab_modifier_key(&self, msg: &mut KeyEvent) { + + let allow_swap_key = self.get_toggle_option("allow_swap_key".to_string()); + if allow_swap_key { + if let Some(key_event::Union::ControlKey(ck)) = msg.union { + let ck = ck.enum_value_or_default(); + let ck = match ck { + ControlKey::Control => ControlKey::Meta, + ControlKey::Meta => ControlKey::Control, + ControlKey::RControl => ControlKey::Meta, + ControlKey::RWin => ControlKey::Control, + _ => ck, + }; + msg.set_control_key(ck); + } + msg.modifiers = msg.modifiers.iter().map(|ck| { + let ck = ck.enum_value_or_default(); + let ck = match ck { + ControlKey::Control => ControlKey::Meta, + ControlKey::Meta => ControlKey::Control, + ControlKey::RControl => ControlKey::Meta, + ControlKey::RWin => ControlKey::Control, + _ => ck, + }; + hbb_common::protobuf::EnumOrUnknown::new(ck) + }).collect(); + + + let code = msg.chr(); + if code != 0 { + let mut peer = self.peer_platform().to_lowercase(); + peer.retain(|c| !c.is_whitespace()); + + let key = match peer.as_str() { + "windows" => { + let key = rdev::win_key_from_code(code); + let key = match key { + rdev::Key::ControlLeft => rdev::Key::MetaLeft, + rdev::Key::MetaLeft => rdev::Key::ControlLeft, + rdev::Key::ControlRight => rdev::Key::MetaLeft, + rdev::Key::MetaRight => rdev::Key::ControlLeft, + _ => key, + }; + rdev::win_keycode_from_key(key).unwrap_or_default() + } + "macos" => { + let key = rdev::macos_key_from_code(code); + let key = match key { + rdev::Key::ControlLeft => rdev::Key::MetaLeft, + rdev::Key::MetaLeft => rdev::Key::ControlLeft, + rdev::Key::ControlRight => rdev::Key::MetaLeft, + rdev::Key::MetaRight => rdev::Key::ControlLeft, + _ => key, + }; + rdev::macos_keycode_from_key(key).unwrap_or_default() + } + _ => { + let key = rdev::linux_key_from_code(code); + let key = match key { + rdev::Key::ControlLeft => rdev::Key::MetaLeft, + rdev::Key::MetaLeft => rdev::Key::ControlLeft, + rdev::Key::ControlRight => rdev::Key::MetaLeft, + rdev::Key::MetaRight => rdev::Key::ControlLeft, + _ => key, + }; + rdev::linux_keycode_from_key(key).unwrap_or_default() + } + }; + msg.set_chr(key); + } + } + + } + pub fn send_key_event(&self, evt: &KeyEvent) { // mode: legacy(0), map(1), translate(2), auto(3) + + let mut msg = evt.clone(); + self.swab_modifier_key(&mut msg); let mut msg_out = Message::new(); - msg_out.set_key_event(evt.clone()); + msg_out.set_key_event(msg); self.send(Data::Message(msg_out)); } @@ -505,14 +582,6 @@ impl Session { shift: bool, command: bool, ) { - let (ctrl, command) = - if self.get_toggle_option("allow_swap_key".to_string()) { - (command, ctrl) - } - else { - (ctrl, command) - }; - #[allow(unused_mut)] let mut command = command; #[cfg(windows)] @@ -851,6 +920,22 @@ impl Interface for Session { handle_test_delay(t, peer).await; } } + fn swap_modifier_mouse(&self, msg : &mut hbb_common::protos::message::MouseEvent) { + let allow_swap_key = self.get_toggle_option("allow_swap_key".to_string()); + if allow_swap_key { + msg.modifiers = msg.modifiers.iter().map(|ck| { + let ck = ck.enum_value_or_default(); + let ck = match ck { + ControlKey::Control => ControlKey::Meta, + ControlKey::Meta => ControlKey::Control, + ControlKey::RControl => ControlKey::Meta, + ControlKey::RWin => ControlKey::Control, + _ => ck, + }; + hbb_common::protobuf::EnumOrUnknown::new(ck) + }).collect(); + }; + } } impl Session { From 7fb78ebc743d0f3449cc2a397b3b80b26a55410f Mon Sep 17 00:00:00 2001 From: sjpark Date: Sun, 12 Feb 2023 06:24:04 +0900 Subject: [PATCH 007/382] bug fix --- src/client.rs | 2 +- src/ui_session_interface.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client.rs b/src/client.rs index b98f9fde4..78feceb7f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1929,7 +1929,7 @@ pub trait Interface: Send + Clone + 'static + Sized { fn is_force_relay(&self) -> bool { self.get_login_config_handler().read().unwrap().force_relay } - fn swap_modifier_mouse(&self, msg : &mut hbb_common::protos::message::MouseEvent) {} + fn swap_modifier_mouse(&self, _msg : &mut hbb_common::protos::message::MouseEvent) {} } /// Data used by the client interface. diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index d55073b9d..73f16478a 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -370,7 +370,7 @@ impl Session { let key = match peer.as_str() { "windows" => { - let key = rdev::win_key_from_code(code); + let key = rdev::win_key_from_scancode(code); let key = match key { rdev::Key::ControlLeft => rdev::Key::MetaLeft, rdev::Key::MetaLeft => rdev::Key::ControlLeft, @@ -378,7 +378,7 @@ impl Session { rdev::Key::MetaRight => rdev::Key::ControlLeft, _ => key, }; - rdev::win_keycode_from_key(key).unwrap_or_default() + rdev::win_scancode_from_key(key).unwrap_or_default() } "macos" => { let key = rdev::macos_key_from_code(code); From 1e387ce01917c7951f2b88dcb59c08bd59627cbf Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 24 Feb 2023 20:24:31 +0800 Subject: [PATCH 008/382] simple refact Signed-off-by: fufesou --- src/platform/linux.rs | 120 +++++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 53 deletions(-) diff --git a/src/platform/linux.rs b/src/platform/linux.rs index 08e343d49..47184e796 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -1,14 +1,22 @@ use super::{CursorData, ResultType}; -use hbb_common::libc::{c_char, c_int, c_long, c_void}; pub use hbb_common::platform::linux::*; -use hbb_common::{allow_err, anyhow::anyhow, bail, log, message_proto::Resolution}; +use hbb_common::{ + allow_err, + anyhow::anyhow, + bail, + libc::{c_char, c_int, c_long, c_void}, + log, + message_proto::Resolution, +}; use std::{ cell::RefCell, - path::PathBuf, + path::{Path, PathBuf}, + process::{Child, Command}, sync::{ atomic::{AtomicBool, Ordering}, Arc, }, + time::{Duration, Instant}, }; use xrandr_parser::Parser; @@ -162,10 +170,29 @@ fn start_uinput_service() { }); } -fn stop_server(server: &mut Option) { +#[inline] +fn try_start_server_(user: Option<(String, String)>) -> ResultType> { + if user.is_some() { + run_as_user(vec!["--server"], user) + } else { + Ok(Some(crate::run_me(vec!["--server"])?)) + } +} + +#[inline] +fn start_server(user: Option<(String, String)>, server: &mut Option) { + match try_start_server_(user) { + Ok(ps) => *server = ps, + Err(err) => { + log::error!("Failed to start server: {}", err); + } + } +} + +fn stop_server(server: &mut Option) { if let Some(mut ps) = server.take() { allow_err!(ps.kill()); - std::thread::sleep(std::time::Duration::from_millis(30)); + std::thread::sleep(Duration::from_millis(30)); match ps.try_wait() { Ok(Some(_status)) => {} Ok(None) => { @@ -182,7 +209,7 @@ fn set_x11_env(uid: &str) { let mut auth = get_env_tries("XAUTHORITY", uid, 10); // auth is another user's when uid = 0, https://github.com/rustdesk/rustdesk/issues/2468 if auth.is_empty() || uid == "0" { - auth = if std::path::Path::new(&gdm).exists() { + auth = if Path::new(&gdm).exists() { gdm } else { let username = get_active_username(); @@ -190,7 +217,7 @@ fn set_x11_env(uid: &str) { format!("/{}/.Xauthority", username) } else { let tmp = format!("/home/{}/.Xauthority", username); - if std::path::Path::new(&tmp).exists() { + if Path::new(&tmp).exists() { tmp } else { format!("/var/lib/{}/.Xauthority", username) @@ -223,8 +250,8 @@ fn should_start_server( uid: &mut String, cur_uid: String, cm0: &mut bool, - last_restart: &mut std::time::Instant, - server: &mut Option, + last_restart: &mut Instant, + server: &mut Option, ) -> bool { let cm = get_cm(); let mut start_new = false; @@ -235,8 +262,8 @@ fn should_start_server( } if let Some(ps) = server.as_mut() { allow_err!(ps.kill()); - std::thread::sleep(std::time::Duration::from_millis(30)); - *last_restart = std::time::Instant::now(); + std::thread::sleep(Duration::from_millis(30)); + *last_restart = Instant::now(); } } else if !cm && ((*cm0 && last_restart.elapsed().as_secs() > 60) @@ -247,8 +274,8 @@ fn should_start_server( // and x server get displays failure issue if let Some(ps) = server.as_mut() { allow_err!(ps.kill()); - std::thread::sleep(std::time::Duration::from_millis(30)); - *last_restart = std::time::Instant::now(); + std::thread::sleep(Duration::from_millis(30)); + *last_restart = Instant::now(); log::info!("restart server"); } } @@ -267,6 +294,13 @@ fn should_start_server( start_new } +// to-do: stop_server(&mut user_server); may not stop child correctly +// stop_rustdesk_servers() is just a temp solution here. +fn force_stop_server() { + stop_rustdesk_servers(); + std::thread::sleep(Duration::from_millis(super::SERVICE_INTERVAL)); +} + pub fn start_os_service() { stop_rustdesk_servers(); start_uinput_service(); @@ -274,8 +308,8 @@ pub fn start_os_service() { let running = Arc::new(AtomicBool::new(true)); let r = running.clone(); let mut uid = "".to_owned(); - let mut server: Option = None; - let mut user_server: Option = None; + let mut server: Option = None; + let mut user_server: Option = None; if let Err(err) = ctrlc::set_handler(move || { r.store(false, Ordering::SeqCst); }) { @@ -283,12 +317,13 @@ pub fn start_os_service() { } let mut cm0 = false; - let mut last_restart = std::time::Instant::now(); + let mut last_restart = Instant::now(); while running.load(Ordering::SeqCst) { let (cur_uid, cur_user) = get_active_user_id_name(); let is_wayland = current_is_wayland(); if cur_user == "root" || !is_wayland { + // try kill subprocess "--server" stop_server(&mut user_server); // try start subprocess "--server" if should_start_server( @@ -299,16 +334,8 @@ pub fn start_os_service() { &mut last_restart, &mut server, ) { - // to-do: stop_server(&mut user_server); may not stop child correctly - // stop_rustdesk_servers() is just a temp solution here. - stop_rustdesk_servers(); - std::thread::sleep(std::time::Duration::from_millis(super::SERVICE_INTERVAL)); - match crate::run_me(vec!["--server"]) { - Ok(ps) => server = Some(ps), - Err(err) => { - log::error!("Failed to start server: {}", err); - } - } + force_stop_server(); + start_server(None, &mut server); } } else if cur_user != "" { if cur_user != "gdm" { @@ -324,23 +351,16 @@ pub fn start_os_service() { &mut last_restart, &mut user_server, ) { - stop_rustdesk_servers(); - std::thread::sleep(std::time::Duration::from_millis(super::SERVICE_INTERVAL)); - match run_as_user(vec!["--server"], Some((cur_uid, cur_user))) { - Ok(ps) => user_server = ps, - Err(err) => { - log::error!("Failed to start server: {}", err); - } - } + force_stop_server(); + start_server(Some((cur_uid, cur_user)), &mut user_server); } } } else { - stop_rustdesk_servers(); - std::thread::sleep(std::time::Duration::from_millis(super::SERVICE_INTERVAL)); + force_stop_server(); stop_server(&mut user_server); stop_server(&mut server); } - std::thread::sleep(std::time::Duration::from_millis(super::SERVICE_INTERVAL)); + std::thread::sleep(Duration::from_millis(super::SERVICE_INTERVAL)); } if let Some(ps) = user_server.take().as_mut() { @@ -362,7 +382,7 @@ pub fn get_active_userid() -> String { } fn get_cm() -> bool { - if let Ok(output) = std::process::Command::new("ps").args(vec!["aux"]).output() { + if let Ok(output) = Command::new("ps").args(vec!["aux"]).output() { for line in String::from_utf8_lossy(&output.stdout).lines() { if line.contains(&format!( "{} --cm", @@ -380,7 +400,7 @@ fn get_cm() -> bool { fn get_display() -> String { let user = get_active_username(); log::debug!("w {}", &user); - if let Ok(output) = std::process::Command::new("w").arg(&user).output() { + if let Ok(output) = Command::new("w").arg(&user).output() { for line in String::from_utf8_lossy(&output.stdout).lines() { log::debug!(" {}", line); let mut iter = line.split_whitespace(); @@ -395,7 +415,7 @@ fn get_display() -> String { // above not work for gdm user log::debug!("ls -l /tmp/.X11-unix/"); let mut last = "".to_owned(); - if let Ok(output) = std::process::Command::new("ls") + if let Ok(output) = Command::new("ls") .args(vec!["-l", "/tmp/.X11-unix/"]) .output() { @@ -474,10 +494,7 @@ fn is_opensuse() -> bool { false } -pub fn run_as_user( - arg: Vec<&str>, - user: Option<(String, String)>, -) -> ResultType> { +pub fn run_as_user(arg: Vec<&str>, user: Option<(String, String)>) -> ResultType> { let (uid, username) = match user { Some(id_name) => id_name, None => get_active_user_id_name(), @@ -491,7 +508,7 @@ pub fn run_as_user( args.insert(0, "-E"); } - let task = std::process::Command::new("sudo").args(args).spawn()?; + let task = Command::new("sudo").args(args).spawn()?; Ok(Some(task)) } @@ -553,10 +570,7 @@ pub fn get_default_pa_source() -> Option<(String, String)> { } pub fn lock_screen() { - std::process::Command::new("xdg-screensaver") - .arg("lock") - .spawn() - .ok(); + Command::new("xdg-screensaver").arg("lock").spawn().ok(); } pub fn toggle_blank_screen(_v: bool) { @@ -577,7 +591,7 @@ fn get_env_tries(name: &str, uid: &str, n: usize) -> String { if !x.is_empty() { return x; } - std::thread::sleep(std::time::Duration::from_millis(300)); + std::thread::sleep(Duration::from_millis(300)); } "".to_owned() } @@ -604,12 +618,12 @@ pub fn quit_gui() { pub fn check_super_user_permission() -> ResultType { let file = "/usr/share/rustdesk/files/polkit"; let arg; - if std::path::Path::new(file).is_file() { + if Path::new(file).is_file() { arg = file; } else { arg = "echo"; } - let status = std::process::Command::new("pkexec").arg(arg).status()?; + let status = Command::new("pkexec").arg(arg).status()?; Ok(status.success() && status.code() == Some(0)) } @@ -684,7 +698,7 @@ pub fn current_resolution(name: &str) -> ResultType { } pub fn change_resolution(name: &str, width: usize, height: usize) -> ResultType<()> { - std::process::Command::new("xrandr") + Command::new("xrandr") .args(vec![ "--output", name, From 8d726f53aabf33652bb8efaa190bb24ca7093a28 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 24 Feb 2023 23:38:23 +0800 Subject: [PATCH 009/382] better mouse position Signed-off-by: fufesou --- flutter/lib/models/input_model.dart | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index 9a5b06b14..fca73eac7 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -459,17 +459,22 @@ class InputModel { } evt['type'] = type; if (isDesktop) { - y = y - stateGlobal.tabBarHeight; + y = y - stateGlobal.tabBarHeight - stateGlobal.windowBorderWidth.value; + x -= stateGlobal.windowBorderWidth.value; } final canvasModel = parent.target!.canvasModel; + final nearThr = 3; + var nearRight = (canvasModel.size.width - x) < nearThr; + var nearBottom = (canvasModel.size.height - y) < nearThr; + final ffiModel = parent.target!.ffiModel; if (isMove) { canvasModel.moveDesktopMouse(x, y); } final d = ffiModel.display; + final imageWidth = d.width * canvasModel.scale; + final imageHeight = d.height * canvasModel.scale; if (canvasModel.scrollStyle == ScrollStyle.scrollbar) { - final imageWidth = d.width * canvasModel.scale; - final imageHeight = d.height * canvasModel.scale; x += imageWidth * canvasModel.scrollX; y += imageHeight * canvasModel.scrollY; @@ -487,6 +492,15 @@ class InputModel { x /= canvasModel.scale; y /= canvasModel.scale; + if (canvasModel.scale > 0 && canvasModel.scale < 1) { + final step = 1.0 / canvasModel.scale - 1; + if (nearRight) { + x += step; + } + if (nearBottom) { + y += step; + } + } x += d.x; y += d.y; From ac2c7115344e1065cfc77efc8d6f516a2b660b58 Mon Sep 17 00:00:00 2001 From: ilGigioVr88 Date: Fri, 24 Feb 2023 17:04:05 +0100 Subject: [PATCH 010/382] Update it.rs --- src/lang/it.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/it.rs b/src/lang/it.rs index 7256b13d8..04b2488a7 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -454,7 +454,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Interrompi la chiamata vocale"), ("relay_hint_tip", "Se non è possibile connettersi direttamente, si può provare a farlo tramite relay.\nInoltre, se si desidera utilizzare il relay al primo tentativo, è possibile aggiungere il suffisso \"/r\" all'ID o selezionare l'opzione \"Collegati sempre tramite relay\" nella scheda peer."), ("Reconnect", "Riconnetti"), - ("Codec", ""), - ("Resolution", ""), + ("Codec", "Codec"), + ("Resolution", "Risoluzione"), ].iter().cloned().collect(); } From 0a51fff04c984355efcc30a1d5130d0174a591cc Mon Sep 17 00:00:00 2001 From: Michal Witek Date: Fri, 24 Feb 2023 17:19:33 +0100 Subject: [PATCH 011/382] Added additional intent-filter --- flutter/android/app/src/main/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/flutter/android/app/src/main/AndroidManifest.xml b/flutter/android/app/src/main/AndroidManifest.xml index 9b25f4973..ede6353ef 100644 --- a/flutter/android/app/src/main/AndroidManifest.xml +++ b/flutter/android/app/src/main/AndroidManifest.xml @@ -26,6 +26,7 @@ android:exported="false"> + From d76a1adfcce59652e3a17ba2d7dff6536ae9fdfa Mon Sep 17 00:00:00 2001 From: sjpark Date: Sat, 25 Feb 2023 11:41:02 +0900 Subject: [PATCH 012/382] swap key update --- .../lib/desktop/widgets/remote_menubar.dart | 18 ++++++++++++++++++ src/ui/header.tis | 4 ++-- src/ui_session_interface.rs | 1 + 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 4f9a227bd..329df4e19 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -895,6 +895,7 @@ class _DisplayMenuState extends State<_DisplayMenu> { disableClipboard(), lockAfterSessionEnd(), privacyMode(), + swapKey(), ]); } @@ -1501,6 +1502,23 @@ class _DisplayMenuState extends State<_DisplayMenu> { ffi: widget.ffi, child: Text(translate('Privacy mode'))); } + + swapKey() { + final visible = perms['keyboard'] != false && + ((Platform.isMacOS && pi.platform != kPeerPlatformMacOS) || + (!Platform.isMacOS && pi.platform == kPeerPlatformMacOS)); + if (!visible) return Offstage(); + final option = 'allow_swap_key'; + final value = bind.sessionGetToggleOptionSync(id: widget.id, arg: option); + return _CheckboxMenuButton( + value: value, + onChanged: (value) { + if (value == null) return; + bind.sessionToggleOption(id: widget.id, value: option); + }, + ffi: widget.ffi, + child: Text(translate('Swap control-command key'))); + } } class _KeyboardMenu extends StatelessWidget { diff --git a/src/ui/header.tis b/src/ui/header.tis index 01808a156..257ba417e 100644 --- a/src/ui/header.tis +++ b/src/ui/header.tis @@ -156,7 +156,6 @@ class Header: Reactor.Component {
  • {svg_checkmark}{translate('Legacy mode')}
  • {svg_checkmark}{translate('Map mode')}
  • -
  • {svg_checkmark}{translate('Swap Control-Command Key')}
  • ; } @@ -199,6 +198,7 @@ class Header: Reactor.Component { {keyboard_enabled && clipboard_enabled ?
  • {svg_checkmark}{translate('Disable clipboard')}
  • : ""} {keyboard_enabled ?
  • {svg_checkmark}{translate('Lock after session end')}
  • : ""} {keyboard_enabled && pi.platform == "Windows" ?
  • {svg_checkmark}{translate('Privacy mode')}
  • : ""} + {keyboard_enabled && ((is_osx && pi.platform != "Mac OS") || (!is_osx && pi.platform == "Mac OS")) ?
  • {svg_checkmark}{translate('Swap control-command key')}
  • : ""} ; } @@ -441,7 +441,7 @@ function toggleMenuState() { for (var el in $$(menu#keyboard-options>li)) { el.attributes.toggleClass("selected", values.indexOf(el.id) >= 0); } - for (var id in ["show-remote-cursor", "show-quality-monitor", "disable-audio", "enable-file-transfer", "disable-clipboard", "lock-after-session-end"]) { + for (var id in ["show-remote-cursor", "show-quality-monitor", "disable-audio", "enable-file-transfer", "disable-clipboard", "lock-after-session-end", "allow_swap_key"]) { var el = self.select('#' + id); if (el) { var value = handler.get_toggle_option(id); diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 37367c191..f764aa3ed 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -1010,6 +1010,7 @@ impl Interface for Session { handle_test_delay(t, peer).await; } } + fn swap_modifier_mouse(&self, msg : &mut hbb_common::protos::message::MouseEvent) { let allow_swap_key = self.get_toggle_option("allow_swap_key".to_string()); if allow_swap_key { From 218ce22fbd6f7d0d1c4acc9f03a10bb5419914e6 Mon Sep 17 00:00:00 2001 From: Integral <71180087+Integral-Tech@users.noreply.github.com> Date: Sat, 25 Feb 2023 14:25:35 +0800 Subject: [PATCH 013/382] Update cn.rs Some small fixes --- src/lang/cn.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 818e63203..fd2e04c53 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -38,7 +38,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop service", "停止服务"), ("Change ID", "更改 ID"), ("Your new ID", "你的新 ID"), - ("length %min% to %max%", "长度在 %min 与 %max 之间"), + ("length %min% to %max%", "长度在 %min% 与 %max% 之间"), ("starts with a letter", "以字母开头"), ("allowed characters", "使用允许的字符"), ("id_change_tip", "只可以使用字母 a-z, A-Z, 0-9, _ (下划线)。首字母必须是 a-z, A-Z。长度在 6 与 16 之间。"), @@ -137,7 +137,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Failed to connect to rendezvous server", "连接注册服务器失败"), ("Please try later", "请稍后再试"), ("Remote desktop is offline", "远程电脑处于离线状态"), - ("Key mismatch", "密钥不匹配"), + ("Key mismatch", "Key 不匹配"), ("Timeout", "连接超时"), ("Failed to connect to relay server", "无法连接到中继服务器"), ("Failed to connect via rendezvous server", "无法通过注册服务器建立连接"), From abeb2058eeb3e05691721c421913116f369b5197 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Sat, 25 Feb 2023 09:44:23 +0100 Subject: [PATCH 014/382] implemented shrinking transfers --- .../lib/desktop/pages/file_manager_page.dart | 291 +++++++++--------- 1 file changed, 144 insertions(+), 147 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 39d66f568..a709ccba5 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -153,9 +153,17 @@ class _FileManagerPageState extends State backgroundColor: Theme.of(context).scaffoldBackgroundColor, body: Row( children: [ - Flexible(flex: 3, child: body(isLocal: true)), - Flexible(flex: 3, child: body(isLocal: false)), - Flexible(flex: 2, child: statusList()) + Flexible( + flex: 3, + child: body(isLocal: true), + ), + Flexible( + flex: 3, + child: body(isLocal: false), + ), + model.jobTable.isEmpty + ? SizedBox() + : Flexible(flex: 2, child: statusList()) ], ), ); @@ -546,157 +554,146 @@ class _FileManagerPageState extends State /// watch transfer status Widget statusList() { return PreferredSize( - preferredSize: const Size(200, double.infinity), - child: model.jobTable.isEmpty - ? Center(child: Text(translate("Empty"))) - : Container( - margin: - const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0), - padding: const EdgeInsets.all(8.0), - child: Obx( - () => ListView.builder( - controller: ScrollController(), - itemBuilder: (BuildContext context, int index) { - final item = model.jobTable[index]; - return Padding( - padding: const EdgeInsets.only(bottom: 5), - child: Container( - decoration: BoxDecoration( - color: Theme.of(context).cardColor, - borderRadius: BorderRadius.all( - Radius.circular(15.0), + preferredSize: const Size(200, double.infinity), + child: Container( + margin: const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0), + padding: const EdgeInsets.all(8.0), + child: Obx( + () => ListView.builder( + controller: ScrollController(), + itemBuilder: (BuildContext context, int index) { + final item = model.jobTable[index]; + return Padding( + padding: const EdgeInsets.only(bottom: 5), + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.all( + Radius.circular(15.0), + ), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Transform.rotate( + angle: item.isRemote ? pi : 0, + child: SvgPicture.asset( + "assets/arrow.svg", + color: Theme.of(context).tabBarTheme.labelColor, + ), + ).paddingOnly(left: 15), + const SizedBox( + width: 16.0, + ), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Tooltip( + waitDuration: Duration(milliseconds: 500), + message: item.jobName, + child: Text( + item.jobName, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ).paddingSymmetric(vertical: 10), + ), + Text( + '${translate("Total")} ${readableFileSize(item.totalSize.toDouble())}', + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + Offstage( + offstage: item.state != JobState.inProgress, + child: Text( + '${translate("Speed")} ${readableFileSize(item.speed)}/s', + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + ), + Offstage( + offstage: item.state == JobState.inProgress, + child: Text( + translate( + item.display(), + ), + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + ), + Offstage( + offstage: item.state != JobState.inProgress, + child: LinearPercentIndicator( + padding: EdgeInsets.only(right: 15), + animateFromLastPercent: true, + center: Text( + '${(item.finishedSize / item.totalSize * 100).toStringAsFixed(0)}%', + ), + barRadius: Radius.circular(15), + percent: item.finishedSize / item.totalSize, + progressColor: MyTheme.accent, + backgroundColor: + Theme.of(context).hoverColor, + lineHeight: kDesktopFileTransferRowHeight, + ).paddingSymmetric(vertical: 15), + ), + ], ), ), - child: Column( - mainAxisSize: MainAxisSize.min, + Row( + mainAxisAlignment: MainAxisAlignment.end, children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Transform.rotate( - angle: item.isRemote ? pi : 0, - child: SvgPicture.asset( - "assets/arrow.svg", - color: Theme.of(context) - .tabBarTheme - .labelColor, - ), - ).paddingOnly(left: 15), - const SizedBox( - width: 16.0, + Offstage( + offstage: item.state != JobState.paused, + child: MenuButton( + onPressed: () { + model.resumeJob(item.id); + }, + child: SvgPicture.asset( + "assets/refresh.svg", + color: Colors.white, ), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Tooltip( - waitDuration: - Duration(milliseconds: 500), - message: item.jobName, - child: Text( - item.jobName, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ).paddingSymmetric(vertical: 10), - ), - Text( - '${translate("Total")} ${readableFileSize(item.totalSize.toDouble())}', - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, - ), - ), - Offstage( - offstage: - item.state != JobState.inProgress, - child: Text( - '${translate("Speed")} ${readableFileSize(item.speed)}/s', - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, - ), - ), - ), - Offstage( - offstage: - item.state == JobState.inProgress, - child: Text( - translate( - item.display(), - ), - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, - ), - ), - ), - Offstage( - offstage: - item.state != JobState.inProgress, - child: LinearPercentIndicator( - padding: EdgeInsets.only(right: 15), - animateFromLastPercent: true, - center: Text( - '${(item.finishedSize / item.totalSize * 100).toStringAsFixed(0)}%', - ), - barRadius: Radius.circular(15), - percent: item.finishedSize / - item.totalSize, - progressColor: MyTheme.accent, - backgroundColor: - Theme.of(context).hoverColor, - lineHeight: - kDesktopFileTransferRowHeight, - ).paddingSymmetric(vertical: 15), - ), - ], - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Offstage( - offstage: item.state != JobState.paused, - child: MenuButton( - onPressed: () { - model.resumeJob(item.id); - }, - child: SvgPicture.asset( - "assets/refresh.svg", - color: Colors.white, - ), - color: MyTheme.accent, - hoverColor: MyTheme.accent80, - ), - ), - MenuButton( - padding: EdgeInsets.only(right: 15), - child: SvgPicture.asset( - "assets/close.svg", - color: Colors.white, - ), - onPressed: () { - model.jobTable.removeAt(index); - model.cancelJob(item.id); - }, - color: MyTheme.accent, - hoverColor: MyTheme.accent80, - ), - ], - ), - ], + color: MyTheme.accent, + hoverColor: MyTheme.accent80, + ), + ), + MenuButton( + padding: EdgeInsets.only(right: 15), + child: SvgPicture.asset( + "assets/close.svg", + color: Colors.white, + ), + onPressed: () { + model.jobTable.removeAt(index); + model.cancelJob(item.id); + }, + color: MyTheme.accent, + hoverColor: MyTheme.accent80, ), ], - ).paddingSymmetric(vertical: 10), - ), - ); - }, - itemCount: model.jobTable.length, - ), + ), + ], + ), + ], + ).paddingSymmetric(vertical: 10), ), - )); + ); + }, + itemCount: model.jobTable.length, + ), + ), + ), + ); } Widget headTools(bool isLocal) { From 75ecb66576226292b9d4845c6e91b5e9d8fb323b Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Sat, 25 Feb 2023 09:50:40 +0100 Subject: [PATCH 015/382] improved light mode send/receive button readability --- flutter/lib/desktop/pages/file_manager_page.dart | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index a709ccba5..96ab4044f 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -1000,7 +1000,9 @@ class _FileManagerPageState extends State textAlign: TextAlign.right, style: TextStyle( color: selectedItems.length == 0 - ? MyTheme.darkGray + ? Theme.of(context).brightness == Brightness.light + ? MyTheme.grayBg + : MyTheme.darkGray : Colors.white, ), ) @@ -1009,7 +1011,9 @@ class _FileManagerPageState extends State child: SvgPicture.asset( "assets/arrow.svg", color: selectedItems.length == 0 - ? MyTheme.darkGray + ? Theme.of(context).brightness == Brightness.light + ? MyTheme.grayBg + : MyTheme.darkGray : Colors.white, alignment: Alignment.bottomRight, ), @@ -1018,14 +1022,18 @@ class _FileManagerPageState extends State ? SvgPicture.asset( "assets/arrow.svg", color: selectedItems.length == 0 - ? MyTheme.darkGray + ? Theme.of(context).brightness == Brightness.light + ? MyTheme.grayBg + : MyTheme.darkGray : Colors.white, ) : Text( translate('Receive'), style: TextStyle( color: selectedItems.length == 0 - ? MyTheme.darkGray + ? Theme.of(context).brightness == Brightness.light + ? MyTheme.grayBg + : MyTheme.darkGray : Colors.white, ), ), From eb39cc5da189e3c67c5b270dc38f1c18c9248ce4 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Sat, 25 Feb 2023 10:08:34 +0100 Subject: [PATCH 016/382] fix button flicker --- flutter/lib/desktop/pages/file_manager_page.dart | 2 +- flutter/lib/desktop/widgets/menu_button.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 96ab4044f..5df9c9a80 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -678,7 +678,7 @@ class _FileManagerPageState extends State model.cancelJob(item.id); }, color: MyTheme.accent, - hoverColor: MyTheme.accent80, + hoverColor: MyTheme.button, ), ], ), diff --git a/flutter/lib/desktop/widgets/menu_button.dart b/flutter/lib/desktop/widgets/menu_button.dart index df2c48ab4..17b160fed 100644 --- a/flutter/lib/desktop/widgets/menu_button.dart +++ b/flutter/lib/desktop/widgets/menu_button.dart @@ -37,7 +37,7 @@ class _MenuButtonState extends State { message: widget.tooltip, child: Material( type: MaterialType.transparency, - child: Ink( + child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(_borderRadius), color: _isHover ? widget.hoverColor : widget.color, From f71d4e9e815edf2486f01158250ef50873f5f1b4 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sat, 25 Feb 2023 18:39:27 +0800 Subject: [PATCH 017/382] initialize vdi with .devcontainer --- vdi/README.md | 1 + vdi/host/.devcontainer/Dockerfile | 16 + vdi/host/.devcontainer/devcontainer.json | 27 + vdi/host/.gitignore | 1 + vdi/host/Cargo.lock | 1185 ++++++++++++++++++++++ vdi/host/Cargo.toml | 9 + vdi/host/README.md | 1 + vdi/host/src/main.rs | 2 + 8 files changed, 1242 insertions(+) create mode 100644 vdi/README.md create mode 100644 vdi/host/.devcontainer/Dockerfile create mode 100644 vdi/host/.devcontainer/devcontainer.json create mode 100644 vdi/host/.gitignore create mode 100644 vdi/host/Cargo.lock create mode 100644 vdi/host/Cargo.toml create mode 100644 vdi/host/README.md create mode 100644 vdi/host/src/main.rs diff --git a/vdi/README.md b/vdi/README.md new file mode 100644 index 000000000..85e6ff194 --- /dev/null +++ b/vdi/README.md @@ -0,0 +1 @@ +# WIP diff --git a/vdi/host/.devcontainer/Dockerfile b/vdi/host/.devcontainer/Dockerfile new file mode 100644 index 000000000..f02042771 --- /dev/null +++ b/vdi/host/.devcontainer/Dockerfile @@ -0,0 +1,16 @@ +FROM rockylinux:9.1 +ENV HOME=/home/vscode +ENV WORKDIR=$HOME/rustdesk/vdi/host + +# https://ciq.co/blog/top-10-things-to-do-after-rocky-linux-9-install/ also gpu driver install +WORKDIR $HOME +RUN dnf -y install epel-release +RUN dnf config-manager --set-enabled crb +RUN dnf -y install cargo libvpx-devel opus-devel usbredir-devel git cmake gcc-c++ pkg-config nasm yasm ninja-build automake libtool libva-devel libvdpau-devel llvm-devel +WORKDIR / + +RUN git clone https://chromium.googlesource.com/libyuv/libyuv +WORKDIR /libyuv +RUN cmake . -DCMAKE_INSTALL_PREFIX=/user +RUN make -j4 && make install +WORKDIR / \ No newline at end of file diff --git a/vdi/host/.devcontainer/devcontainer.json b/vdi/host/.devcontainer/devcontainer.json new file mode 100644 index 000000000..02c6e589b --- /dev/null +++ b/vdi/host/.devcontainer/devcontainer.json @@ -0,0 +1,27 @@ +{ + "name": "rustdesk", + "build": { + "dockerfile": "./Dockerfile", + "context": "." + }, + "workspaceMount": "source=${localWorkspaceFolder},target=/home/vscode/rustdesk,type=bind,consistency=cache", + "workspaceFolder": "/home/vscode/rustdesk", + "customizations": { + "vscode": { + "extensions": [ + "vadimcn.vscode-lldb", + "mutantdino.resourcemonitor", + "rust-lang.rust-analyzer", + "tamasfe.even-better-toml", + "serayuzgur.crates", + "mhutchie.git-graph", + "eamodio.gitlens" + ], + "settings": { + "files.watcherExclude": { + "**/target/**": true + } + } + } + } +} \ No newline at end of file diff --git a/vdi/host/.gitignore b/vdi/host/.gitignore new file mode 100644 index 000000000..ea8c4bf7f --- /dev/null +++ b/vdi/host/.gitignore @@ -0,0 +1 @@ +/target diff --git a/vdi/host/Cargo.lock b/vdi/host/Cargo.lock new file mode 100644 index 000000000..d4254717e --- /dev/null +++ b/vdi/host/Cargo.lock @@ -0,0 +1,1185 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "async-broadcast" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90622698a1218e0b2fb846c97b5f19a0831f6baddee73d9454156365ccfa473b" +dependencies = [ + "easy-parallel", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-broadcast" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d26004fe83b2d1cd3a97609b21e39f9a31535822210fe83205d2ce48866ea61" +dependencies = [ + "event-listener", + "futures-core", + "parking_lot", +] + +[[package]] +name = "async-channel" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-io" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" +dependencies = [ + "async-lock", + "autocfg", + "concurrent-queue", + "futures-lite", + "libc", + "log", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "windows-sys 0.42.0", +] + +[[package]] +name = "async-lock" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" +dependencies = [ + "event-listener", + "futures-lite", +] + +[[package]] +name = "async-recursion" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-task" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" + +[[package]] +name = "async-trait" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "concurrent-queue" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "easy-parallel" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6907e25393cdcc1f4f3f513d9aac1e840eb1cc341a0fccb01171f7d14d10b946" + +[[package]] +name = "enumflags2" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "futures" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" + +[[package]] +name = "futures-executor" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" + +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" + +[[package]] +name = "futures-task" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" + +[[package]] +name = "futures-util" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "libusb1-sys" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d0e2afce4245f2c9a418511e5af8718bcaf2fa408aefb259504d1a9cb25f27" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "nix" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +dependencies = [ + "bitflags", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "ordered-stream" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44630c059eacfd6e08bdaa51b1db2ce33119caa4ddc1235e923109aa5f25ccb1" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "parking" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys 0.45.0", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + +[[package]] +name = "polling" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" +dependencies = [ + "autocfg", + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "windows-sys 0.42.0", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-crate" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "qemu-display" +version = "0.1.0" +source = "git+https://gitlab.com/marcandre.lureau/qemu-display#544a4075615702abf414cd2d63bbb6a9ca10d0ea" +dependencies = [ + "async-broadcast 0.3.4", + "async-lock", + "async-trait", + "cfg-if", + "derivative", + "enumflags2", + "futures", + "futures-util", + "libc", + "log", + "once_cell", + "serde", + "serde_bytes", + "serde_repr", + "uds_windows", + "usbredirhost", + "windows", + "zbus", + "zvariant", +] + +[[package]] +name = "qemu-rustdesk" +version = "0.1.0" +dependencies = [ + "qemu-display", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rusb" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703aa035c21c589b34fb5136b12e68fc8dcf7ea46486861381361dd8ebf5cee0" +dependencies = [ + "libc", + "libusb1-sys", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-xml-rs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0bf1ba0696ccf0872866277143ff1fd14d22eec235d2b23702f95e6660f7dfa" +dependencies = [ + "log", + "serde", + "thiserror", + "xml-rs", +] + +[[package]] +name = "serde_bytes" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_repr" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha1" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "thiserror" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml_datetime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" + +[[package]] +name = "toml_edit" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" +dependencies = [ + "indexmap", + "nom8", + "toml_datetime", +] + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "uds_windows" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" +dependencies = [ + "tempfile", + "winapi", +] + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "usbredirhost" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87485e4dfeb0176203afd1086f11ed2ead837053143b12b6eed55c598e9393d5" +dependencies = [ + "libc", + "rusb", + "usbredirhost-sys", + "usbredirparser", +] + +[[package]] +name = "usbredirhost-sys" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b27c305da1f7601b665d68948bcfaf9909d443bec94510ab776118ab8afc2c7d" +dependencies = [ + "libusb1-sys", + "pkg-config", + "usbredirparser-sys", +] + +[[package]] +name = "usbredirparser" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f8b5241d7cbb3e08b4677212a9ac001f116f50731c2737d16129a84ecf6a56" +dependencies = [ + "libc", + "usbredirparser-sys", +] + +[[package]] +name = "usbredirparser-sys" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8b0e834e187916fc762bccdc9d64e454a0ee58b134f8f7adab321141e8e0d91" +dependencies = [ + "pkg-config", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + +[[package]] +name = "xml-rs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" + +[[package]] +name = "zbus" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ce2de393c874ba871292e881bf3c13a0d5eb38170ebab2e50b4c410eaa222b" +dependencies = [ + "async-broadcast 0.4.1", + "async-channel", + "async-executor", + "async-io", + "async-lock", + "async-recursion", + "async-task", + "async-trait", + "byteorder", + "derivative", + "dirs", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix", + "once_cell", + "ordered-stream", + "rand", + "serde", + "serde-xml-rs", + "serde_repr", + "sha1", + "static_assertions", + "tracing", + "uds_windows", + "winapi", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13d08f5dc6cf725b693cb6ceacd43cd430ec0664a879188f29e7d7dcd98f96d" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "syn", +] + +[[package]] +name = "zbus_names" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f34f314916bd89bdb9934154627fab152f4f28acdda03e7c4c68181b214fe7e3" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + +[[package]] +name = "zvariant" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "903169c05b9ab948ee93fefc9127d08930df4ce031d46c980784274439803e51" +dependencies = [ + "byteorder", + "enumflags2", + "libc", + "serde", + "serde_bytes", + "static_assertions", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cce76636e8fab7911be67211cf378c252b115ee7f2bae14b18b84821b39260b5" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] diff --git a/vdi/host/Cargo.toml b/vdi/host/Cargo.toml new file mode 100644 index 000000000..62c964122 --- /dev/null +++ b/vdi/host/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "qemu-rustdesk" +version = "0.1.0" +authors = ["rustdesk "] +edition = "2021" + + +[dependencies] +qemu-display = { git = "https://gitlab.com/marcandre.lureau/qemu-display" } \ No newline at end of file diff --git a/vdi/host/README.md b/vdi/host/README.md new file mode 100644 index 000000000..3b29a10e3 --- /dev/null +++ b/vdi/host/README.md @@ -0,0 +1 @@ +# RustDesk protocol on QEMU D-Bus display diff --git a/vdi/host/src/main.rs b/vdi/host/src/main.rs new file mode 100644 index 000000000..f79c691f0 --- /dev/null +++ b/vdi/host/src/main.rs @@ -0,0 +1,2 @@ +fn main() { +} From b8b3e996026fa47352feb9bcb30c45cc5b4a1442 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 25 Feb 2023 22:39:12 +0800 Subject: [PATCH 018/382] macos, periodically check if current display is changed Signed-off-by: fufesou --- src/platform/macos.mm | 3 +-- src/platform/macos.rs | 8 ++++---- src/server/video_service.rs | 8 ++++++++ src/ui.rs | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/platform/macos.mm b/src/platform/macos.mm index 443351469..8be0c6db5 100644 --- a/src/platform/macos.mm +++ b/src/platform/macos.mm @@ -60,7 +60,7 @@ extern "C" bool MacGetModes(CGDirectDisplayID display, uint32_t *widths, uint32_ return false; } *numModes = CFArrayGetCount(allModes); - for (int i = 0; i < *numModes && i < max; i++) { + for (uint32_t i = 0; i < *numModes && i < max; i++) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); widths[i] = (uint32_t)CGDisplayModeGetWidth(mode); heights[i] = (uint32_t)CGDisplayModeGetHeight(mode); @@ -136,7 +136,6 @@ extern "C" bool MacSetMode(CGDirectDisplayID display, uint32_t width, uint32_t h return ret; } int numModes = CFArrayGetCount(allModes); - CGDisplayModeRef bestMode = NULL; for (int i = 0; i < numModes; i++) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); if (width == CGDisplayModeGetWidth(mode) && diff --git a/src/platform/macos.rs b/src/platform/macos.rs index 025274840..b663b0f41 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -612,18 +612,18 @@ pub fn resolutions(name: &str) -> Vec { unsafe { if YES == MacGetModeNum(display, &mut num) { let (mut widths, mut heights) = (vec![0; num as _], vec![0; num as _]); - let mut realNum = 0; + let mut real_num = 0; if YES == MacGetModes( display, widths.as_mut_ptr(), heights.as_mut_ptr(), num, - &mut realNum, + &mut real_num, ) { - if realNum <= num { - for i in 0..realNum { + if real_num <= num { + for i in 0..real_num { let resolution = Resolution { width: widths[i as usize] as _, height: heights[i as usize] as _, diff --git a/src/server/video_service.rs b/src/server/video_service.rs index a9a9fd9ab..affb5eb17 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -577,6 +577,14 @@ fn run(sp: GenericService) -> ResultType<()> { if last_check_displays.elapsed().as_millis() > 1000 { last_check_displays = now; + // Capturer on macos does not return Err event the solution is changed. + #[cfg(target_os = "macos")] + if check_display_changed(c.ndisplay, c.current, c.width, c.height) { + log::info!("Displays changed"); + *SWITCH.lock().unwrap() = true; + bail!("SWITCH"); + } + if let Some(msg_out) = check_displays_changed() { sp.send(msg_out); } diff --git a/src/ui.rs b/src/ui.rs index a197cb257..e0449fd95 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -9,7 +9,7 @@ use sciter::Value; use hbb_common::{ allow_err, - config::{self, LocalConfig, PeerConfig}, + config::{LocalConfig, PeerConfig}, log, }; From 59cd775d5fe7606891ebbcff80f329510b52bff8 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 25 Feb 2023 22:47:22 +0800 Subject: [PATCH 019/382] fix notify peer resolution change Signed-off-by: fufesou --- flutter/lib/models/model.dart | 79 +++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index eae41679f..e48d74dac 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -156,7 +156,7 @@ class FfiModel with ChangeNotifier { } else if (name == 'clipboard') { Clipboard.setData(ClipboardData(text: evt['content'])); } else if (name == 'permission') { - parent.target?.ffiModel.updatePermission(evt, peerId); + updatePermission(evt, peerId); } else if (name == 'chat_client_mode') { parent.target?.chatModel .receive(ChatModel.clientModeID, evt['text'] ?? ''); @@ -241,36 +241,33 @@ class FfiModel with ChangeNotifier { } } - handleSwitchDisplay(Map evt, String peerId) { - final oldOrientation = _display.width > _display.height; - var old = _pi.currentDisplay; - _pi.currentDisplay = int.parse(evt['display']); - _display.x = double.parse(evt['x']); - _display.y = double.parse(evt['y']); - _display.width = int.parse(evt['width']); - _display.height = int.parse(evt['height']); - _display.cursorEmbedded = int.parse(evt['cursor_embedded']) == 1; - if (old != _pi.currentDisplay) { - parent.target?.cursorModel.updateDisplayOrigin(_display.x, _display.y); + _updateCurDisplay(String peerId, Display newDisplay) { + if (newDisplay != _display) { + if (newDisplay.x != _display.x || newDisplay.y != _display.y) { + parent.target?.cursorModel + .updateDisplayOrigin(newDisplay.x, newDisplay.y); + } + _display = newDisplay; + _updateSessionWidthHeight(peerId); } + } - _updateSessionWidthHeight(peerId, display.width, display.height); + handleSwitchDisplay(Map evt, String peerId) { + _pi.currentDisplay = int.parse(evt['display']); + var newDisplay = Display(); + newDisplay.x = double.parse(evt['x']); + newDisplay.y = double.parse(evt['y']); + newDisplay.width = int.parse(evt['width']); + newDisplay.height = int.parse(evt['height']); + newDisplay.cursorEmbedded = int.parse(evt['cursor_embedded']) == 1; + + _updateCurDisplay(peerId, newDisplay); try { CurrentDisplayState.find(peerId).value = _pi.currentDisplay; } catch (e) { // } - - // remote is mobile, and orientation changed - if ((_display.width > _display.height) != oldOrientation) { - gFFI.canvasModel.updateViewStyle(); - } - if (_pi.platform == kPeerPlatformLinux || - _pi.platform == kPeerPlatformWindows || - _pi.platform == kPeerPlatformMacOS) { - parent.target?.canvasModel.updateViewStyle(); - } parent.target?.recordingModel.onSwitchDisplay(); handleResolutions(peerId, evt["resolutions"]); notifyListeners(); @@ -372,7 +369,8 @@ class FfiModel with ChangeNotifier { }); } - _updateSessionWidthHeight(String id, int width, int height) { + _updateSessionWidthHeight(String id) { + parent.target?.canvasModel.updateViewStyle(); bind.sessionSetSize(id: id, width: display.width, height: display.height); } @@ -429,7 +427,7 @@ class FfiModel with ChangeNotifier { stateGlobal.displaysCount.value = _pi.displays.length; if (_pi.currentDisplay < _pi.displays.length) { _display = _pi.displays[_pi.currentDisplay]; - _updateSessionWidthHeight(peerId, display.width, display.height); + _updateSessionWidthHeight(peerId); } if (displays.isNotEmpty) { parent.target?.dialogManager.showLoading( @@ -488,7 +486,7 @@ class FfiModel with ChangeNotifier { _pi.displays = newDisplays; stateGlobal.displaysCount.value = _pi.displays.length; if (_pi.currentDisplay >= 0 && _pi.currentDisplay < _pi.displays.length) { - _display = _pi.displays[_pi.currentDisplay]; + _updateCurDisplay(peerId, _pi.displays[_pi.currentDisplay]); } } notifyListeners(); @@ -797,12 +795,18 @@ class CanvasModel with ChangeNotifier { final dh = getDisplayHeight() * _scale; var dxOffset = 0; var dyOffset = 0; - if (dw > size.width) { - dxOffset = (x - dw * (x / size.width) - _x).toInt(); - } - if (dh > size.height) { - dyOffset = (y - dh * (y / size.height) - _y).toInt(); + try { + if (dw > size.width) { + dxOffset = (x - dw * (x / size.width) - _x).toInt(); + } + if (dh > size.height) { + dyOffset = (y - dh * (y / size.height) - _y).toInt(); + } + } catch (e) { + // Unhandled Exception: Unsupported operation: Infinity or NaN toInt + return; } + _x += dxOffset; _y += dyOffset; if (dxOffset != 0 || dyOffset != 0) { @@ -1579,6 +1583,19 @@ class Display { ? kDesktopDefaultDisplayHeight : kMobileDefaultDisplayHeight; } + + @override + bool operator ==(Object other) => + other is Display && + other.runtimeType == runtimeType && + _innerEqual(other); + + bool _innerEqual(Display other) => + other.x == x && + other.y == y && + other.width == width && + other.height == height && + other.cursorEmbedded == cursorEmbedded; } class Resolution { From e876adaec58ed45761a0aae250425d49b75faebd Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 25 Feb 2023 22:59:59 +0800 Subject: [PATCH 020/382] fix, flutter keyboard grab, connecting peers of older version Signed-off-by: fufesou --- .../lib/desktop/widgets/remote_menubar.dart | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 37bbbd66a..8500bec03 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -23,6 +23,10 @@ import '../../common/shared_state.dart'; import './popup_menu.dart'; import './kb_layout_type_chooser.dart'; +const _kKeyLegacyMode = 'legacy'; +const _kKeyMapMode = 'map'; +const _kKeyTranslateMode = 'translate'; + class MenubarState { final kStoreKey = 'remoteMenubarState'; late RxBool show; @@ -1540,9 +1544,10 @@ class _KeyboardMenu extends StatelessWidget { Widget build(BuildContext context) { var ffiModel = Provider.of(context); if (ffiModel.permissions['keyboard'] == false) return Offstage(); - // Do not support peer 1.1.9. if (stateGlobal.grabKeyboard) { - bind.sessionSetKeyboardMode(id: id, value: 'map'); + if (bind.sessionIsKeyboardModeSupported(id: id, mode: _kKeyMapMode)) { + bind.sessionSetKeyboardMode(id: id, value: _kKeyMapMode); + } return Offstage(); } return _IconSubmenuButton( @@ -1555,13 +1560,13 @@ class _KeyboardMenu extends StatelessWidget { mode() { return futureBuilder(future: () async { - return await bind.sessionGetKeyboardMode(id: id) ?? 'legacy'; + return await bind.sessionGetKeyboardMode(id: id) ?? _kKeyLegacyMode; }(), hasData: (data) { final groupValue = data as String; List modes = [ - KeyboardModeMenu(key: 'legacy', menu: 'Legacy mode'), - KeyboardModeMenu(key: 'map', menu: 'Map mode'), - KeyboardModeMenu(key: 'translate', menu: 'Translate mode'), + KeyboardModeMenu(key: _kKeyLegacyMode, menu: 'Legacy mode'), + KeyboardModeMenu(key: _kKeyMapMode, menu: 'Map mode'), + KeyboardModeMenu(key: _kKeyTranslateMode, menu: 'Translate mode'), ]; List<_RadioMenuButton> list = []; onChanged(String? value) async { @@ -1571,13 +1576,13 @@ class _KeyboardMenu extends StatelessWidget { for (KeyboardModeMenu mode in modes) { if (bind.sessionIsKeyboardModeSupported(id: id, mode: mode.key)) { - if (mode.key == 'translate') { + if (mode.key == _kKeyTranslateMode) { if (Platform.isLinux || pi.platform == kPeerPlatformLinux) { continue; } } var text = translate(mode.menu); - if (mode.key == 'translate') { + if (mode.key == _kKeyTranslateMode) { text = '$text beta'; } list.add(_RadioMenuButton( From 6740587d8adf6a8cc62c6d09ead26a1a878400c2 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 25 Feb 2023 23:11:28 +0800 Subject: [PATCH 021/382] do not check keyboard permission on menu build Signed-off-by: fufesou --- flutter/lib/desktop/widgets/remote_menubar.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 8500bec03..c27546d9f 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -1542,11 +1542,15 @@ class _KeyboardMenu extends StatelessWidget { @override Widget build(BuildContext context) { - var ffiModel = Provider.of(context); - if (ffiModel.permissions['keyboard'] == false) return Offstage(); + // Do not check permission here? + // var ffiModel = Provider.of(context); + // if (ffiModel.permissions['keyboard'] == false) return Offstage(); if (stateGlobal.grabKeyboard) { if (bind.sessionIsKeyboardModeSupported(id: id, mode: _kKeyMapMode)) { bind.sessionSetKeyboardMode(id: id, value: _kKeyMapMode); + } else if (bind.sessionIsKeyboardModeSupported( + id: id, mode: _kKeyLegacyMode)) { + bind.sessionSetKeyboardMode(id: id, value: _kKeyLegacyMode); } return Offstage(); } From 037641624c82aa5cd0cf6ae8475bb9ef82b4172a Mon Sep 17 00:00:00 2001 From: "Miguel F. G" <116861809+flusheDData@users.noreply.github.com> Date: Sat, 25 Feb 2023 21:39:21 +0100 Subject: [PATCH 022/382] Update es.rs New terms added --- src/lang/es.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/es.rs b/src/lang/es.rs index d7e43b6bf..5ae368581 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -454,7 +454,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Detener llamada de voz"), ("relay_hint_tip", "Puede que no sea posible conectar directamente. Puedes tratar de conectar a través de relay. \nAdicionalmente, si quieres usar relay en el primer intento, puedes añadir el sufijo \"/r\" a la ID o seleccionar la opción \"Conectar siempre a través de relay\" en la tarjeta del par."), ("Reconnect", "Reconectar"), - ("Codec", ""), - ("Resolution", ""), + ("Codec", "Códec"), + ("Resolution", "Resolución"), ].iter().cloned().collect(); } From 8092f3ad94f11112d8c37b60d45dfd928be1eeb1 Mon Sep 17 00:00:00 2001 From: PCKUO Date: Sun, 26 Feb 2023 12:51:16 +0800 Subject: [PATCH 023/382] Make up for the missing --- src/lang/tw.rs | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/lang/tw.rs b/src/lang/tw.rs index ca1193eaa..e20c7f254 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -37,19 +37,19 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Clipboard is empty", "剪貼簿是空的"), ("Stop service", "停止服務"), ("Change ID", "更改 ID"), - ("Your new ID", ""), - ("length %min% to %max%", ""), - ("starts with a letter", ""), - ("allowed characters", ""), + ("Your new ID", "你的新 ID"), + ("length %min% to %max%", "長度在 %min% 與 %max% 之間"), + ("starts with a letter", "以字母開頭"), + ("allowed characters", "使用允許的字元"), ("id_change_tip", "僅能使用以下字元:a-z、A-Z、0-9、_ (底線)。首字元必須為 a-z 或 A-Z。長度介於 6 到 16 之間。"), ("Website", "網站"), ("About", "關於"), ("Slogan_tip", ""), - ("Privacy Statement", ""), + ("Privacy Statement", "隱私聲明"), ("Mute", "靜音"), - ("Build Date", ""), - ("Version", ""), - ("Home", ""), + ("Build Date", "建構日期"), + ("Version", "版本"), + ("Home", "主頁"), ("Audio Input", "音訊輸入"), ("Enhancements", "增強功能"), ("Hardware Codec", "硬件編解碼"), @@ -213,15 +213,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the peer", "由對方手動關閉"), ("Enable remote configuration modification", "啟用遠端更改設定"), ("Run without install", "跳過安裝直接執行"), - ("Connect via relay", ""), + ("Connect via relay", "中繼連線"), ("Always connect via relay", "一律透過轉送連線"), ("whitelist_tip", "只有白名單中的 IP 可以存取"), ("Login", "登入"), - ("Verify", ""), - ("Remember me", ""), - ("Trust this device", ""), - ("Verification code", ""), - ("verification_tip", ""), + ("Verify", "驗證"), + ("Remember me", "記住我"), + ("Trust this device", "信任此設備"), + ("Verification code", "驗證碼"), + ("verification_tip", "檢測到新設備登錄,已向註冊郵箱發送了登入驗證碼,請輸入驗證碼繼續登錄"), ("Logout", "登出"), ("Tags", "標籤"), ("Search ID", "搜尋 ID"), @@ -391,12 +391,12 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland 需要更高版本的 linux 發行版。 請嘗試 X11 桌面或更改您的操作系統。"), ("JumpLink", "查看"), ("Please Select the screen to be shared(Operate on the peer side).", "請選擇要分享的畫面(在對端操作)。"), - ("Show RustDesk", ""), - ("This PC", ""), - ("or", ""), - ("Continue with", ""), + ("Show RustDesk", "顯示 RustDesk"), + ("This PC", "此電腦"), + ("or", "或"), + ("Continue with", "使用"), ("Elevate", "提權"), - ("Zoom cursor", ""), + ("Zoom cursor", "縮放游標"), ("Accept sessions via password", "只允許密碼訪問"), ("Accept sessions via click", "只允許點擊訪問"), ("Accept sessions via both", "允許密碼或點擊訪問"), @@ -407,9 +407,9 @@ 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_experiment_tip", "Wayland 支持處於實驗階段,如果你需要使用無人值守訪問,請使用 X11。"), ("Right click to select tabs", "右鍵選擇選項卡"), - ("Skipped", ""), + ("Skipped", "已略過"), ("Add to Address Book", "添加到地址簿"), ("Group", "小組"), ("Search", "搜索"), @@ -418,8 +418,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Select local keyboard type", "請選擇本地鍵盤類型"), ("software_render_tip", "如果你使用英偉達顯卡, 並且遠程窗口在會話建立後會立刻關閉, 那麼安裝nouveau驅動並且選擇使用軟件渲染可能會有幫助。重啟軟件後生效。"), ("Always use software rendering", "使用軟件渲染"), - ("config_input", ""), - ("config_microphone", ""), + ("config_input", "為了能夠通過鍵盤控制遠程桌面, 請給予 RustDesk \"輸入監控\" 權限。"), + ("config_microphone", "為了支持通過麥克風進行音訊傳輸,請給予 RustDesk \"錄音\"權限。"), ("request_elevation_tip", "如果對面有人, 也可以請求提升權限。"), ("Wait", "等待"), ("Elevation Error", "提權失敗"), @@ -438,8 +438,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Weak", "弱"), ("Medium", "中"), ("Strong", "強"), - ("Switch Sides", ""), - ("Please confirm if you want to share your desktop?", ""), + ("Switch Sides", "反轉訪問方向"), + ("Please confirm if you want to share your desktop?", "請確認是否要讓對方訪問你的桌面?"), ("Display", "顯示"), ("Default View Style", "默認顯示方式"), ("Default Scroll Style", "默認滾動方式"), From 4b2529125567207721489caaf2085532d998705c Mon Sep 17 00:00:00 2001 From: 21pages Date: Sun, 26 Feb 2023 11:23:43 +0800 Subject: [PATCH 024/382] sciter/mobile id suffix "\r" or "/r" for relay Signed-off-by: 21pages --- flutter/lib/common.dart | 6 ++++-- .../lib/desktop/pages/connection_page.dart | 5 +---- src/flutter_ffi.rs | 4 ++++ src/ui.rs | 19 ++++++++++++++----- src/ui/index.tis | 5 ++++- src/ui/remote.rs | 3 ++- src/ui_interface.rs | 9 +++++++++ 7 files changed, 38 insertions(+), 13 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index ff373cc9c..e89671711 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -1453,10 +1453,12 @@ connectMainDesktop(String id, connect(BuildContext context, String id, {bool isFileTransfer = false, bool isTcpTunneling = false, - bool isRDP = false, - bool forceRelay = false}) async { + bool isRDP = false}) async { if (id == '') return; id = id.replaceAll(' ', ''); + final oldId = id; + id = await bind.mainHandleRelayId(id: id); + final forceRelay = id != oldId; assert(!(isFileTransfer && isTcpTunneling && isRDP), "more than one connect type"); diff --git a/flutter/lib/desktop/pages/connection_page.dart b/flutter/lib/desktop/pages/connection_page.dart index 4aad66eee..edbd5b7c6 100644 --- a/flutter/lib/desktop/pages/connection_page.dart +++ b/flutter/lib/desktop/pages/connection_page.dart @@ -151,10 +151,7 @@ class _ConnectionPageState extends State /// Connects to the selected peer. void onConnect({bool isFileTransfer = false}) { var id = _idController.id; - var forceRelay = id.endsWith(r'/r'); - if (forceRelay) id = id.substring(0, id.length - 2); - connect(context, id, - isFileTransfer: isFileTransfer, forceRelay: forceRelay); + connect(context, id, isFileTransfer: isFileTransfer); } /// UI for the remote ID TextField. diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 0866ff739..e49ba65f7 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -840,6 +840,10 @@ pub fn main_get_user_default_option(key: String) -> SyncReturn { SyncReturn(get_user_default_option(key)) } +pub fn main_handle_relay_id(id: String) -> String { + handle_relay_id(id) +} + pub fn session_add_port_forward( id: String, local_port: i32, diff --git a/src/ui.rs b/src/ui.rs index e0449fd95..22c44ec5f 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -420,8 +420,8 @@ impl UI { crate::lan::send_wol(id) } - fn new_remote(&mut self, id: String, remote_type: String) { - new_remote(id, remote_type) + fn new_remote(&mut self, id: String, remote_type: String, force_relay: bool) { + new_remote(id, remote_type, force_relay) } fn is_process_trusted(&mut self, _prompt: bool) -> bool { @@ -571,6 +571,10 @@ impl UI { fn default_video_save_directory(&self) -> String { default_video_save_directory() } + + fn handle_relay_id(&self, id: String) -> String { + handle_relay_id(id) + } } impl sciter::EventHandler for UI { @@ -588,7 +592,7 @@ impl sciter::EventHandler for UI { fn set_remote_id(String); fn closing(i32, i32, i32, i32); fn get_size(); - fn new_remote(String, bool); + fn new_remote(String, String, bool); fn send_wol(String); fn remove_peer(String); fn remove_discovered(String); @@ -653,6 +657,7 @@ impl sciter::EventHandler for UI { fn has_hwcodec(); fn get_langs(); fn default_video_save_directory(); + fn handle_relay_id(String); } } @@ -718,9 +723,13 @@ pub fn value_crash_workaround(values: &[Value]) -> Arc> { } #[inline] -pub fn new_remote(id: String, remote_type: String) { +pub fn new_remote(id: String, remote_type: String, force_relay: bool) { let mut lock = CHILDREN.lock().unwrap(); - let args = vec![format!("--{}", remote_type), id.clone()]; + let mut args = vec![format!("--{}", remote_type), id.clone()]; + if force_relay { + args.push("".to_string()); // password + args.push("--relay".to_string()); + } let key = (id.clone(), remote_type.clone()); if let Some(c) = lock.1.get_mut(&key) { if let Ok(Some(_)) = c.try_wait() { diff --git a/src/ui/index.tis b/src/ui/index.tis index ec2e0a748..0e2247070 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -62,12 +62,15 @@ function createNewConnect(id, type) { id = id.replace(/\s/g, ""); app.remote_id.value = formatId(id); if (!id) return; + var old_id = id; + id = handler.handle_relay_id(id); + var force_relay = old_id != id; if (id == my_id) { msgbox("custom-error", "Error", "You cannot connect to your own computer"); return; } handler.set_remote_id(id); - handler.new_remote(id, type); + handler.new_remote(id, type, force_relay); } class ShareRdp: Reactor.Component { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index c6e0229b2..ed16f1e0e 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -462,6 +462,7 @@ impl sciter::EventHandler for SciterSession { impl SciterSession { pub fn new(cmd: String, id: String, password: String, args: Vec) -> Self { + let force_relay = args.contains(&"--relay".to_string()); let session: Session = Session { id: id.clone(), password: password.clone(), @@ -486,7 +487,7 @@ impl SciterSession { .lc .write() .unwrap() - .initialize(id, conn_type, None, false); + .initialize(id, conn_type, None, force_relay); Self(session) } diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 3b2ba0897..62eba25c1 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -970,3 +970,12 @@ async fn check_id( } "" } + +// if it's relay id, return id processed, otherwise return original id +pub fn handle_relay_id(id: String) -> String { + if id.ends_with(r"\r") || id.ends_with(r"/r") { + id[0..id.len() - 2].to_string() + } else { + id + } +} From 8fa487e5b07f1c53b6cfd79fbda952e22e2bbcea Mon Sep 17 00:00:00 2001 From: Michal Witek Date: Sun, 26 Feb 2023 09:07:00 +0100 Subject: [PATCH 025/382] Added missing translation --- src/lang/pl.rs | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/lang/pl.rs b/src/lang/pl.rs index eea46accb..fe6454fad 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -284,13 +284,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Do you accept?", "Akceptujesz?"), ("Open System Setting", "Otwórz ustawienia systemowe"), ("How to get Android input permission?", "Jak uzyskać uprawnienia do wprowadzania danych w systemie Android?"), - ("android_input_permission_tip1", "android_input_permission_tip1"), - ("android_input_permission_tip2", "android_input_permission_tip2"), - ("android_new_connection_tip", "android_new_connection_tip"), - ("android_service_will_start_tip", "android_service_will_start_tip"), - ("android_stop_service_tip", "android_stop_service_tip"), - ("android_version_audio_tip", "android_version_audio_tip"), - ("android_start_service_tip", "android_start_service_tip"), + ("android_input_permission_tip1", "Aby można było sterować Twoim urządzeniem za pomocą myszy lub dotyku, musisz zezwolić RustDesk na korzystanie z usługi \"Ułatwienia dostępu\"."), + ("android_input_permission_tip2", "Przejdź do następnej strony ustawień systemowych, znajdź i wejdź w [Zainstalowane usługi], włącz usługę [RustDesk Input]."), + ("android_new_connection_tip", "Otrzymano nowe żądanie zdalnego dostępu, które chce przejąć kontrolę nad Twoim urządzeniem."), + ("android_service_will_start_tip", "Włączenie opcji „Przechwytywanie ekranu” spowoduje automatyczne uruchomienie usługi, umożliwiając innym urządzeniom żądanie połączenia z Twoim urządzeniem."), + ("android_stop_service_tip", "Zamknięcie usługi spowoduje automatyczne zamknięcie wszystkich nawiązanych połączeń."), + ("android_version_audio_tip", "Bieżąca wersja systemu Android nie obsługuje przechwytywania dźwięku, zaktualizuj system do wersji Android 10 lub nowszej."), + ("android_start_service_tip", "Kliknij [Uruchom usługę] lub Otwórz [Przechwytywanie ekranu], aby uruchomić usługę udostępniania ekranu."), ("Account", "Konto"), ("Overwrite", "Nadpisz"), ("This file exists, skip or overwrite this file?", "Ten plik istnieje, pominąć czy nadpisać ten plik?"), @@ -311,7 +311,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Language", "Język"), ("Keep RustDesk background service", "Zachowaj usługę RustDesk w tle"), ("Ignore Battery Optimizations", "Ignoruj optymalizację baterii"), - ("android_open_battery_optimizations_tip", "android_open_battery_optimizations_tip"), + ("android_open_battery_optimizations_tip", "Jeśli chcesz wyłączyć tę funkcję, przejdź do następnej strony ustawień aplikacji RustDesk, znajdź i wprowadź [Bateria], odznacz [Bez ograniczeń]"), ("Connection not allowed", "Połączenie niedozwolone"), ("Legacy mode", "Tryb kompatybilności wstecznej (legacy)"), ("Map mode", "Tryb mapowania"), @@ -449,12 +449,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("FPS", "FPS"), ("Auto", "Auto"), ("Other Default Options", "Inne opcje domyślne"), - ("Voice call", ""), - ("Text chat", ""), - ("Stop voice call", ""), - ("relay_hint_tip", ""), - ("Reconnect", ""), - ("Codec", ""), - ("Resolution", ""), + ("Voice call", "Rozmowa głosowa"), + ("Text chat", "Chat tekstowy"), + ("Stop voice call", "Rozłącz"), + ("relay_hint_tip", "Bezpośrednie połączenie może nie być możliwe, możesz spróbować połączyć się przez serwer przekazujący. \nDodatkowo, jeśli chcesz użyć serwera przekazującego przy pierwszej próbie, możesz dodać sufiks \"/r\" do identyfikatora lub wybrać opcję \"Zawsze łącz przez serwer przekazujący\" na karcie peer-ów."), + ("Reconnect", "Połącz ponownie"), + ("Codec", "Kodek"), + ("Resolution", "Rozdzielczość"), + ("Use temporary password", "Użyj hasła tymczasowego"), + ("Set temporary password length", "Ustaw długość hasła tymczasowego"), + ("Key", "Klucz") ].iter().cloned().collect(); } From ee893ce744dd2d06020a80849f707c9902fa495e Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Sun, 26 Feb 2023 09:13:42 +0100 Subject: [PATCH 026/382] changed empty job list logic --- flutter/assets/transfer.svg | 2 + .../lib/desktop/pages/file_manager_page.dart | 293 ++++++++++-------- 2 files changed, 163 insertions(+), 132 deletions(-) create mode 100644 flutter/assets/transfer.svg diff --git a/flutter/assets/transfer.svg b/flutter/assets/transfer.svg new file mode 100644 index 000000000..24149bf58 --- /dev/null +++ b/flutter/assets/transfer.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 5df9c9a80..c3322fef7 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -153,17 +153,9 @@ class _FileManagerPageState extends State backgroundColor: Theme.of(context).scaffoldBackgroundColor, body: Row( children: [ - Flexible( - flex: 3, - child: body(isLocal: true), - ), - Flexible( - flex: 3, - child: body(isLocal: false), - ), - model.jobTable.isEmpty - ? SizedBox() - : Flexible(flex: 2, child: statusList()) + Flexible(flex: 3, child: body(isLocal: true)), + Flexible(flex: 3, child: body(isLocal: false)), + Flexible(flex: 2, child: statusList()) ], ), ); @@ -550,6 +542,18 @@ class _FileManagerPageState extends State return false; } + Widget generateCard(Widget child) { + return Container( + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.all( + Radius.circular(15.0), + ), + ), + child: child, + ); + } + /// transfer status list /// watch transfer status Widget statusList() { @@ -558,140 +562,165 @@ class _FileManagerPageState extends State child: Container( margin: const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0), padding: const EdgeInsets.all(8.0), - child: Obx( - () => ListView.builder( - controller: ScrollController(), - itemBuilder: (BuildContext context, int index) { - final item = model.jobTable[index]; - return Padding( - padding: const EdgeInsets.only(bottom: 5), - child: Container( - decoration: BoxDecoration( - color: Theme.of(context).cardColor, - borderRadius: BorderRadius.all( - Radius.circular(15.0), - ), - ), + child: model.jobTable.isEmpty + ? generateCard( + Center( child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Transform.rotate( - angle: item.isRemote ? pi : 0, - child: SvgPicture.asset( - "assets/arrow.svg", - color: Theme.of(context).tabBarTheme.labelColor, - ), - ).paddingOnly(left: 15), - const SizedBox( - width: 16.0, - ), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + SvgPicture.asset( + "assets/transfer.svg", + color: Theme.of(context).tabBarTheme.labelColor, + height: 40, + ).paddingOnly(bottom: 10), + Text( + translate("No transfers in progress"), + textAlign: TextAlign.center, + textScaleFactor: 1.20, + style: TextStyle( + color: Theme.of(context).tabBarTheme.labelColor), + ), + ], + ), + ), + ) + : Obx( + () => ListView.builder( + controller: ScrollController(), + itemBuilder: (BuildContext context, int index) { + final item = model.jobTable[index]; + return Padding( + padding: const EdgeInsets.only(bottom: 5), + child: generateCard( + Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Tooltip( - waitDuration: Duration(milliseconds: 500), - message: item.jobName, - child: Text( - item.jobName, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ).paddingSymmetric(vertical: 10), + Transform.rotate( + angle: item.isRemote ? pi : 0, + child: SvgPicture.asset( + "assets/arrow.svg", + color: Theme.of(context) + .tabBarTheme + .labelColor, + ), + ).paddingOnly(left: 15), + const SizedBox( + width: 16.0, ), - Text( - '${translate("Total")} ${readableFileSize(item.totalSize.toDouble())}', - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Tooltip( + waitDuration: + Duration(milliseconds: 500), + message: item.jobName, + child: Text( + item.jobName, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ).paddingSymmetric(vertical: 10), + ), + Text( + '${translate("Total")} ${readableFileSize(item.totalSize.toDouble())}', + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + Offstage( + offstage: + item.state != JobState.inProgress, + child: Text( + '${translate("Speed")} ${readableFileSize(item.speed)}/s', + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + ), + Offstage( + offstage: + item.state == JobState.inProgress, + child: Text( + translate( + item.display(), + ), + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + ), + Offstage( + offstage: + item.state != JobState.inProgress, + child: LinearPercentIndicator( + padding: EdgeInsets.only(right: 15), + animateFromLastPercent: true, + center: Text( + '${(item.finishedSize / item.totalSize * 100).toStringAsFixed(0)}%', + ), + barRadius: Radius.circular(15), + percent: item.finishedSize / + item.totalSize, + progressColor: MyTheme.accent, + backgroundColor: + Theme.of(context).hoverColor, + lineHeight: + kDesktopFileTransferRowHeight, + ).paddingSymmetric(vertical: 15), + ), + ], ), ), - Offstage( - offstage: item.state != JobState.inProgress, - child: Text( - '${translate("Speed")} ${readableFileSize(item.speed)}/s', - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Offstage( + offstage: item.state != JobState.paused, + child: MenuButton( + onPressed: () { + model.resumeJob(item.id); + }, + child: SvgPicture.asset( + "assets/refresh.svg", + color: Colors.white, + ), + color: MyTheme.accent, + hoverColor: MyTheme.accent80, + ), ), - ), - ), - Offstage( - offstage: item.state == JobState.inProgress, - child: Text( - translate( - item.display(), + MenuButton( + padding: EdgeInsets.only(right: 15), + child: SvgPicture.asset( + "assets/close.svg", + color: Colors.white, + ), + onPressed: () { + model.jobTable.removeAt(index); + model.cancelJob(item.id); + }, + color: MyTheme.accent, + hoverColor: MyTheme.accent80, ), - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, - ), - ), - ), - Offstage( - offstage: item.state != JobState.inProgress, - child: LinearPercentIndicator( - padding: EdgeInsets.only(right: 15), - animateFromLastPercent: true, - center: Text( - '${(item.finishedSize / item.totalSize * 100).toStringAsFixed(0)}%', - ), - barRadius: Radius.circular(15), - percent: item.finishedSize / item.totalSize, - progressColor: MyTheme.accent, - backgroundColor: - Theme.of(context).hoverColor, - lineHeight: kDesktopFileTransferRowHeight, - ).paddingSymmetric(vertical: 15), + ], ), ], ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Offstage( - offstage: item.state != JobState.paused, - child: MenuButton( - onPressed: () { - model.resumeJob(item.id); - }, - child: SvgPicture.asset( - "assets/refresh.svg", - color: Colors.white, - ), - color: MyTheme.accent, - hoverColor: MyTheme.accent80, - ), - ), - MenuButton( - padding: EdgeInsets.only(right: 15), - child: SvgPicture.asset( - "assets/close.svg", - color: Colors.white, - ), - onPressed: () { - model.jobTable.removeAt(index); - model.cancelJob(item.id); - }, - color: MyTheme.accent, - hoverColor: MyTheme.button, - ), - ], - ), - ], + ], + ).paddingSymmetric(vertical: 10), ), - ], - ).paddingSymmetric(vertical: 10), + ); + }, + itemCount: model.jobTable.length, ), - ); - }, - itemCount: model.jobTable.length, - ), - ), + ), ), ); } From d8af4f2acb9b157b037203770ea445993425e71f Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Sun, 26 Feb 2023 09:14:22 +0100 Subject: [PATCH 027/382] added new string "No transfers in progress" --- 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/en.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/nl.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 + 34 files changed, 34 insertions(+) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 45c552848..4a6536afa 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 4824ac5e9..593e023d2 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "停止语音通话"), ("relay_hint_tip", "可能无法直连,可以尝试中继连接。\n另外,如果想直接使用中继连接,可以在 ID 后面添加/r,或者在卡片选项里选择强制走中继连接。"), ("Reconnect", "重连"), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index e2761e45e..d09bba096 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 2020a2b6f..428150eff 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 7cf563fc3..8bfa973c4 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Sprachanruf beenden"), ("relay_hint_tip", "Wenn eine direkte Verbindung nicht möglich ist, können Sie versuchen, eine Verbindung über einen Relay-Server herzustellen. \nWenn Sie eine Relay-Verbindung beim ersten Versuch herstellen möchten, können Sie das Suffix \"/r\" an die ID anhängen oder die Option \"Immer über Relay-Server verbinden\" auf der Gegenstelle auswählen."), ("Reconnect", "Erneut verbinden"), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index 4bfa86349..3e87cd661 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -44,5 +44,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("still_click_uac_tip", "Still requires the remote user to click OK on the UAC window of running RustDesk."), ("config_microphone", "In order to speak remotely, you need to grant RustDesk \"Record Audio\" permissions."), ("relay_hint_tip", "It may not be possible to connect directly, you can try to connect via relay. \nIn addition, if you want to use relay on your first try, you can add the \"/r\" suffix to the ID, or select the option \"Always connect via relay\" in the peer card."), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index c22532440..1ea05d5ab 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 3ce2860f0..494dd4cb7 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Detener llamada de voz"), ("relay_hint_tip", "Puede que no sea posible conectar directamente. Puedes tratar de conectar a través de relay. \nAdicionalmente, si quieres usar relay en el primer intento, puedes añadir el sufijo \"/r\" a la ID o seleccionar la opción \"Conectar siempre a través de relay\" en la tarjeta del par."), ("Reconnect", "Reconectar"), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 70051f3e8..72dd93a10 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "توقف تماس صوتی"), ("relay_hint_tip", " را به شناسه اضافه کنید یا گزینه \"همیشه از طریق رله متصل شوید\" را در کارت همتا انتخاب کنید. همچنین، اگر می‌خواهید فوراً از سرور رله استفاده کنید، می‌توانید پسوند \"/r\".\n اتصال مستقیم ممکن است امکان پذیر نباشد. در این صورت می توانید سعی کنید از طریق سرور رله متصل شوید"), ("Reconnect", "اتصال مجدد"), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 1f6e9f55b..a600c92eb 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/gr.rs b/src/lang/gr.rs index b7ebf4577..26e5a649c 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 21ab28214..125d982dc 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index f48de17f6..17a9589a8 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 4c63106da..0749603b0 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Interrompi la chiamata vocale"), ("relay_hint_tip", "Se non è possibile connettersi direttamente, si può provare a farlo tramite relay.\nInoltre, se si desidera utilizzare il relay al primo tentativo, è possibile aggiungere il suffisso \"/r\" all'ID o selezionare l'opzione \"Collegati sempre tramite relay\" nella scheda peer."), ("Reconnect", "Riconnetti"), + ("No transfers in progress", "Nessun trasferimento in corso"), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index b291a6e7a..7c810cbac 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index d63e83187..87425b402 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index b8b9eb1df..49017f4ff 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 1a806c803..615c3601b 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Stop spraakoproep"), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 2b29c7cb2..ae1743ee2 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index e91cd3909..4e619a6e4 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index b0fe9175d..8f4b2b13d 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index d0232ba37..ebefd1a80 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index fe5d708ad..d652904cc 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Завершить голосовой вызов"), ("relay_hint_tip", "Прямое подключение может оказаться невозможным. В этом случае можно попытаться подключиться через сервер ретрансляции. \nКроме того, если вы хотите сразу использовать сервер ретрансляции, можно добавить к ID суффикс \"/r\" или включить \"Всегда подключаться через ретранслятор\" в настройках удалённого узла."), ("Reconnect", "Переподключить"), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 458002f4c..47843fd55 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 2abd1870f..95d65a453 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 6b739e8ab..3ec67d77a 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 90a435fd7..31f408748 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index a98ea6346..3afcf1a9a 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 61c2b5d28..53df7b4f7 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 236ee5e8d..a5db9708c 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index f2a34e212..96e35e2b1 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 84e74716f..f49e81a7b 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "停止語音聊天"), ("relay_hint_tip", "可能無法直連,可以嘗試中繼連接。 \n另外,如果想直接使用中繼連接,可以在ID後面添加/r,或者在卡片選項裡選擇強制走中繼連接。"), ("Reconnect", "重連"), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 0c4caf4db..1729d42a7 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 19e1184d9..5521022b7 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } From ab792f798e0581084de7bb965fe88b979b11925b Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Sun, 26 Feb 2023 10:19:13 +0100 Subject: [PATCH 028/382] fix missing comma --- src/lang/pl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 5269c4ee8..13027a682 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -458,7 +458,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Rozdzielczość"), ("Use temporary password", "Użyj hasła tymczasowego"), ("Set temporary password length", "Ustaw długość hasła tymczasowego"), - ("Key", "Klucz") + ("Key", "Klucz"), ("No transfers in progress", ""), ].iter().cloned().collect(); } From b83583769b51a01071ea241704607647e5130872 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sun, 26 Feb 2023 18:49:07 +0800 Subject: [PATCH 029/382] mount rustdesk rather than vdi/host --- Cargo.toml | 1 + vdi/host/.devcontainer/devcontainer.json | 5 +- vdi/host/Cargo.lock | 970 ++++++++++++++++++++++- vdi/host/Cargo.toml | 4 +- 4 files changed, 972 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f93f776a0..b53615c4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -132,6 +132,7 @@ flutter_rust_bridge = "1.61.1" [workspace] members = ["libs/scrap", "libs/hbb_common", "libs/enigo", "libs/clipboard", "libs/virtual_display", "libs/virtual_display/dylib", "libs/simple_rc", "libs/portable"] +exclude = ["vdi/host"] [package.metadata.winres] LegalCopyright = "Copyright © 2022 Purslane, Inc." diff --git a/vdi/host/.devcontainer/devcontainer.json b/vdi/host/.devcontainer/devcontainer.json index 02c6e589b..f0016b5b1 100644 --- a/vdi/host/.devcontainer/devcontainer.json +++ b/vdi/host/.devcontainer/devcontainer.json @@ -4,8 +4,8 @@ "dockerfile": "./Dockerfile", "context": "." }, - "workspaceMount": "source=${localWorkspaceFolder},target=/home/vscode/rustdesk,type=bind,consistency=cache", - "workspaceFolder": "/home/vscode/rustdesk", + "workspaceMount": "source=${localWorkspaceFolder}/../..,target=/home/vscode/rustdesk,type=bind,consistency=cache", + "workspaceFolder": "/home/vscode/rustdesk/vdi/host", "customizations": { "vscode": { "extensions": [ @@ -15,6 +15,7 @@ "tamasfe.even-better-toml", "serayuzgur.crates", "mhutchie.git-graph", + "formulahendry.terminal", "eamodio.gitlens" ], "settings": { diff --git a/vdi/host/Cargo.lock b/vdi/host/Cargo.lock index d4254717e..7b7cf26bd 100644 --- a/vdi/host/Cargo.lock +++ b/vdi/host/Cargo.lock @@ -2,6 +2,32 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.20" @@ -11,6 +37,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" + [[package]] name = "async-broadcast" version = "0.3.4" @@ -73,7 +114,7 @@ dependencies = [ "parking", "polling", "slab", - "socket2", + "socket2 0.4.7", "waker-fn", "windows-sys 0.42.0", ] @@ -116,29 +157,73 @@ dependencies = [ "syn", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +dependencies = [ + "serde", +] + [[package]] name = "cc" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] [[package]] name = "cfg-if" @@ -146,6 +231,31 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "time", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "concurrent-queue" version = "2.1.0" @@ -155,6 +265,57 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "confy" +version = "0.4.0" +source = "git+https://github.com/open-trade/confy#630cc28a396cb7d01eefdd9f3824486fe4d8554b" +dependencies = [ + "directories-next", + "serde", + "thiserror", + "toml", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset 0.7.1", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.8.14" @@ -164,6 +325,50 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "cxx" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "derivative" version = "2.2.0" @@ -175,6 +380,16 @@ dependencies = [ "syn", ] +[[package]] +name = "directories-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + [[package]] name = "dirs" version = "4.0.0" @@ -184,6 +399,16 @@ dependencies = [ "dirs-sys", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + [[package]] name = "dirs-sys" version = "0.3.7" @@ -195,12 +420,38 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "easy-parallel" version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6907e25393cdcc1f4f3f513d9aac1e840eb1cc341a0fccb01171f7d14d10b946" +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "signature", +] + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + [[package]] name = "enumflags2" version = "0.7.5" @@ -222,6 +473,19 @@ dependencies = [ "syn", ] +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -237,6 +501,18 @@ dependencies = [ "instant", ] +[[package]] +name = "filetime" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "windows-sys 0.45.0", +] + [[package]] name = "futures" version = "0.3.26" @@ -349,14 +625,78 @@ checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "gimli" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hbb_common" +version = "0.1.0" +dependencies = [ + "anyhow", + "backtrace", + "bytes", + "chrono", + "confy", + "directories-next", + "dirs-next", + "env_logger", + "filetime", + "futures", + "futures-util", + "lazy_static", + "libc", + "log", + "mac_address", + "machine-uid", + "osascript", + "protobuf", + "protobuf-codegen", + "rand", + "regex", + "serde", + "serde_derive", + "socket2 0.3.19", + "sodiumoxide", + "sysinfo", + "tokio", + "tokio-socks", + "tokio-util", + "winapi", + "zstd", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] [[package]] name = "hex" @@ -364,6 +704,36 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "indexmap" version = "1.9.2" @@ -383,12 +753,54 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "jobserver" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +[[package]] +name = "libsodium-sys" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b779387cd56adfbc02ea4a668e704f729be8d6a6abd2c27ca5ee537849a92fd" +dependencies = [ + "cc", + "libc", + "pkg-config", + "walkdir", +] + [[package]] name = "libusb1-sys" version = "0.6.4" @@ -401,6 +813,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + [[package]] name = "lock_api" version = "0.4.9" @@ -420,6 +841,25 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "mac_address" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b238e3235c8382b7653c6408ed1b08dd379bdb9fdf990fb0bbae3db2cc0ae963" +dependencies = [ + "nix 0.23.2", + "winapi", +] + +[[package]] +name = "machine-uid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f1595709b0a7386bcd56ba34d250d626e5503917d05d32cdccddcd68603e212" +dependencies = [ + "winreg", +] + [[package]] name = "memchr" version = "2.5.0" @@ -435,6 +875,49 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.45.0", +] + +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset 0.6.5", +] + [[package]] name = "nix" version = "0.24.3" @@ -444,7 +927,7 @@ dependencies = [ "bitflags", "cfg-if", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] @@ -456,6 +939,53 @@ dependencies = [ "memchr", ] +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "object" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.17.1" @@ -472,6 +1002,17 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "osascript" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38731fa859ef679f1aec66ca9562165926b442f298467f76f5990f431efe87dc" +dependencies = [ + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "parking" version = "2.0.0" @@ -501,6 +1042,26 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "pin-project" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -558,6 +1119,58 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "protobuf" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55bad9126f378a853655831eb7363b7b01b81d19f8cb1218861086ca4a1a61e" +dependencies = [ + "bytes", + "once_cell", + "protobuf-support", + "thiserror", +] + +[[package]] +name = "protobuf-codegen" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd418ac3c91caa4032d37cb80ff0d44e2ebe637b2fb243b6234bf89cdac4901" +dependencies = [ + "anyhow", + "once_cell", + "protobuf", + "protobuf-parse", + "regex", + "tempfile", + "thiserror", +] + +[[package]] +name = "protobuf-parse" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d39b14605eaa1f6a340aec7f320b34064feb26c93aec35d6a9a2272a8ddfa49" +dependencies = [ + "anyhow", + "indexmap", + "log", + "protobuf", + "protobuf-support", + "tempfile", + "thiserror", + "which", +] + +[[package]] +name = "protobuf-support" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d4d7b8601c814cfb36bcebb79f0e61e45e1e93640cf778837833bbed05c372" +dependencies = [ + "thiserror", +] + [[package]] name = "qemu-display" version = "0.1.0" @@ -588,6 +1201,7 @@ dependencies = [ name = "qemu-rustdesk" version = "0.1.0" dependencies = [ + "hbb_common", "qemu-display", ] @@ -630,6 +1244,28 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -686,12 +1322,39 @@ dependencies = [ "libusb1-sys", ] +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + [[package]] name = "serde" version = "1.0.152" @@ -733,6 +1396,17 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_repr" version = "0.1.10" @@ -759,6 +1433,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" + [[package]] name = "slab" version = "0.4.8" @@ -774,6 +1463,17 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "socket2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +dependencies = [ + "cfg-if", + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.4.7" @@ -784,6 +1484,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "sodiumoxide" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e26be3acb6c2d9a7aac28482586a7856436af4cfe7100031d219de2d2ecb0028" +dependencies = [ + "ed25519", + "libc", + "libsodium-sys", + "serde", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -801,6 +1513,21 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sysinfo" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54cb4ebf3d49308b99e6e9dc95e989e2fdbdc210e4f67c39db0bb89ba927001c" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "winapi", +] + [[package]] name = "tempfile" version = "3.3.0" @@ -815,6 +1542,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.38" @@ -835,6 +1571,91 @@ dependencies = [ "syn", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "tokio" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.4.7", + "tokio-macros", + "windows-sys 0.42.0", +] + +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-socks" +version = "0.5.1-1" +source = "git+https://github.com/open-trade/tokio-socks#7034e79263ce25c348be072808d7601d82cd892d" +dependencies = [ + "bytes", + "either", + "futures-core", + "futures-sink", + "futures-util", + "pin-project", + "thiserror", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "futures-util", + "hashbrown", + "pin-project-lite", + "slab", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml_datetime" version = "0.5.1" @@ -900,6 +1721,12 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + [[package]] name = "usbredirhost" version = "0.0.1" @@ -948,18 +1775,95 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "waker-fn" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + [[package]] name = "wepoll-ffi" version = "0.1.2" @@ -969,6 +1873,17 @@ dependencies = [ "cc", ] +[[package]] +name = "which" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +dependencies = [ + "either", + "libc", + "once_cell", +] + [[package]] name = "winapi" version = "0.3.9" @@ -985,6 +1900,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -1087,6 +2011,15 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +[[package]] +name = "winreg" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +dependencies = [ + "winapi", +] + [[package]] name = "xml-rs" version = "0.8.4" @@ -1116,7 +2049,7 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix", + "nix 0.24.3", "once_cell", "ordered-stream", "rand", @@ -1157,6 +2090,35 @@ dependencies = [ "zvariant", ] +[[package]] +name = "zstd" +version = "0.9.2+zstd.1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2390ea1bf6c038c39674f22d95f0564725fc06034a47129179810b2fc58caa54" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "4.1.3+zstd.1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e99d81b99fb3c2c2c794e3fe56c305c63d5173a16a46b5850b07c935ffc7db79" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "1.6.2+zstd.1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2daf2f248d9ea44454bfcb2516534e8b8ad2fc91bf818a1885495fc42bc8ac9f" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "zvariant" version = "3.11.0" diff --git a/vdi/host/Cargo.toml b/vdi/host/Cargo.toml index 62c964122..6a67813a2 100644 --- a/vdi/host/Cargo.toml +++ b/vdi/host/Cargo.toml @@ -4,6 +4,6 @@ version = "0.1.0" authors = ["rustdesk "] edition = "2021" - [dependencies] -qemu-display = { git = "https://gitlab.com/marcandre.lureau/qemu-display" } \ No newline at end of file +qemu-display = { git = "https://gitlab.com/marcandre.lureau/qemu-display" } +hbb_common = { path = "../../libs/hbb_common" } From 459bed1a68cac7d1634e0101dd4fb05601be373b Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Sun, 26 Feb 2023 11:49:22 +0100 Subject: [PATCH 030/382] dark theme fix --- flutter/lib/common.dart | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index e89671711..53a401230 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -189,7 +189,9 @@ class MyTheme { style: ButtonStyle(splashFactory: NoSplash.splashFactory), ) : null, - colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.blue).copyWith( + colorScheme: ColorScheme.fromSwatch( + primarySwatch: Colors.blue, + ).copyWith( brightness: Brightness.light, background: Color(0xFFEEEEEE), ), @@ -229,9 +231,11 @@ class MyTheme { checkboxTheme: const CheckboxThemeData(checkColor: MaterialStatePropertyAll(dark)), colorScheme: ColorScheme.fromSwatch( - brightness: Brightness.dark, primarySwatch: Colors.blue, - ).copyWith(background: Color(0xFF24252B)), + ).copyWith( + brightness: Brightness.dark, + background: Color(0xFF24252B), + ), ).copyWith( extensions: >[ ColorThemeExtension.dark, From 0a52d64900a8f1f182073eb79affdee4cf6a596c Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 26 Feb 2023 23:29:36 +0800 Subject: [PATCH 031/382] print stack Signed-off-by: fufesou --- flutter/lib/models/input_model.dart | 23 ++++++++++++++++++----- flutter/lib/models/model.dart | 4 +++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index fca73eac7..37c4a39dc 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -503,8 +503,21 @@ class InputModel { } x += d.x; y += d.y; + var evtX = 0; + var evtY = 0; + try { + x.round(); + y.round(); + } catch (e) { + debugPrintStack( + label: 'canvasModel.scale value ${canvasModel.scale}, $e'); + return; + } - if (x < d.x || y < d.y || x > (d.x + d.width) || y > (d.y + d.height)) { + if (evtX < d.x || + evtY < d.y || + evtX > (d.x + d.width) || + evtY > (d.y + d.height)) { // If left mouse up, no early return. if (evt['buttons'] != kPrimaryMouseButton || type != 'up') { return; @@ -512,12 +525,12 @@ class InputModel { } if (type != '') { - x = 0; - y = 0; + evtX = 0; + evtY = 0; } - evt['x'] = '${x.round()}'; - evt['y'] = '${y.round()}'; + evt['x'] = '$evtX'; + evt['y'] = '$evtY'; var buttons = ''; switch (evt['buttons']) { case kPrimaryMouseButton: diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index e48d74dac..74cc7f14f 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -803,7 +803,9 @@ class CanvasModel with ChangeNotifier { dyOffset = (y - dh * (y / size.height) - _y).toInt(); } } catch (e) { - // Unhandled Exception: Unsupported operation: Infinity or NaN toInt + debugPrintStack( + label: + '(x,y) ($x,$y), (_x,_y) ($_x,$_y), _scale $_scale, display size (${getDisplayWidth()},${getDisplayHeight()}), size $size, , $e'); return; } From 544e39e11cf5127944bd8d112a453f74cfa7f801 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 26 Feb 2023 23:31:11 +0800 Subject: [PATCH 032/382] fix assign Signed-off-by: fufesou --- flutter/lib/models/input_model.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index 37c4a39dc..b91453138 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -506,8 +506,8 @@ class InputModel { var evtX = 0; var evtY = 0; try { - x.round(); - y.round(); + evtX = x.round(); + evtY = y.round(); } catch (e) { debugPrintStack( label: 'canvasModel.scale value ${canvasModel.scale}, $e'); From 8073fa2386bb4a407203e4a383c2cd14b48b21f9 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sun, 26 Feb 2023 19:43:24 +0100 Subject: [PATCH 033/382] Update de.rs --- src/lang/de.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lang/de.rs b/src/lang/de.rs index ee28fe0e7..3d95832ec 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -454,8 +454,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Sprachanruf beenden"), ("relay_hint_tip", "Wenn eine direkte Verbindung nicht möglich ist, können Sie versuchen, eine Verbindung über einen Relay-Server herzustellen. \nWenn Sie eine Relay-Verbindung beim ersten Versuch herstellen möchten, können Sie das Suffix \"/r\" an die ID anhängen oder die Option \"Immer über Relay-Server verbinden\" auf der Gegenstelle auswählen."), ("Reconnect", "Erneut verbinden"), - ("Codec", ""), - ("Resolution", ""), - ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Codec", "Codec"), + ("Resolution", "Auflösung"), + ("No transfers in progress", "Keine Übertragungen im Gange"), + ].iter().cloned().collect(); } From 5793c730c8f1f9c5c96786a656db6546435fceeb Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sun, 26 Feb 2023 19:48:20 +0100 Subject: [PATCH 034/382] Update README-DE.md --- docs/README-DE.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/README-DE.md b/docs/README-DE.md index 8ee4a51fa..dd2aa8609 100644 --- a/docs/README-DE.md +++ b/docs/README-DE.md @@ -17,9 +17,9 @@ RustDesk ist eine in Rust geschriebene Remote-Desktop-Software, die out of the b ![image](https://user-images.githubusercontent.com/71636191/171661982-430285f0-2e12-4b1d-9957-4a58e375304d.png) -RustDesk heißt jegliche Mitarbeit willkommen. Schau dir [`docs/CONTRIBUTING.md`](CONTRIBUTING.md) an, wenn du Unterstützung beim Start brauchst. +RustDesk heißt jegliche Mitarbeit willkommen. Schau dir [CONTRIBUTING-DE.md](CONTRIBUTING-DE.md) an, wenn du Unterstützung beim Start brauchst. -[**Wie arbeitet RustDesk?**](https://github.com/rustdesk/rustdesk/wiki/How-does-RustDesk-work%3F) +[**FAQ**](https://github.com/rustdesk/rustdesk/wiki/FAQ) [**Programm herunterladen**](https://github.com/rustdesk/rustdesk/releases) @@ -41,6 +41,14 @@ Nachfolgend sind die Server gelistet, die du kostenlos nutzen kannst. Es kann se | USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8 GB RAM | | Ukraine (Kiew) | dc.volia (2VM) | 2 vCPU / 4 GB RAM | +## Dev-Container + +[![In Dev-Containern öffnen](https://img.shields.io/static/v1?label=Dev%20Container&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/rustdesk/rustdesk) + +Wenn du VS Code und Docker bereits installiert hast, kannst du auf das Abzeichen oben klicken, um loszulegen. Wenn du darauf klickst, wird VS Code automatisch die Dev-Container-Erweiterung installieren, den Quellcode in ein Container-Volume klonen und einen Dev-Container für die Verwendung aufsetzen. + +Weitere Informationen findest du in [DEVCONTAINER-DE.md](DEVCONTAINER-DE.md). + ## Abhängigkeiten Desktop-Versionen verwenden [Sciter](https://sciter.com/) oder Flutter für die GUI, dieses Tutorial ist nur für Sciter. From c580bc16cc86919157d0e327ca97bc26db27cea5 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sun, 26 Feb 2023 19:48:55 +0100 Subject: [PATCH 035/382] Add files via upload --- docs/CONTRIBUTING-DE.md | 50 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 docs/CONTRIBUTING-DE.md diff --git a/docs/CONTRIBUTING-DE.md b/docs/CONTRIBUTING-DE.md new file mode 100644 index 000000000..6258a9a7a --- /dev/null +++ b/docs/CONTRIBUTING-DE.md @@ -0,0 +1,50 @@ +# Beitrge zu RustDesk + +RustDesk begrt Beitrge von jedem. Hier sind die Richtlinien, wenn Sie uns +helfen mchten: + +## Beitrge + +Beitrge zu RustDesk oder seinen Abhngigkeiten sollten in Form von Pull +Requests auf GitHub erfolgen. Jeder Pull Request wird von einem Hauptakteur +(jemand mit der Erlaubnis, Korrekturen einzubringen) geprft und entweder in den +Hauptbaum eingefgt oder Feedback fr notwendige nderungen gegeben. Alle +Beitrge sollten diesem Format folgen, auch die von Hauptakteuren. + +Wenn Sie an einem Problem arbeiten mchten, melden Sie es bitte zuerst an, indem +Sie auf GitHub erklren, dass Sie daran arbeiten mchten. Damit soll verhindert +werden, dass Beitrge zum gleichen Thema doppelt bearbeitet werden. + +## Checkliste fr Pull Requests + +- Verzweigen Sie sich vom Master-Branch und, falls ntig, wechseln Sie zum + aktuellen Master-Branch, bevor Sie Ihren Pull Request einreichen. Wenn das + Zusammenfhren mit dem Master nicht reibungslos funktioniert, werden Sie + mglicherweise aufgefordert, Ihre nderungen zu berarbeiten. + +- Commits sollten so klein wie mglich sein und gleichzeitig sicherstellen, dass + jeder Commit unabhngig voneinander korrekt ist (d. h., jeder Commit sollte + sich bersetzen lassen und Tests bestehen). + +- Commits sollten von einem "Herkunftszertifikat fr Entwickler" + (https://developercertificate.org) begleitet werden, das besagt, dass Sie (und + ggf. Ihr Arbeitgeber) mit den Bedingungen der [Projektlizenz](../LICENCE) + einverstanden sind. In Git ist dies die Option `-s` fr `git commit`. + +- Wenn Ihr Patch nicht begutachtet wird oder Sie eine bestimmte Person zur + Begutachtung bentigen, knnen Sie einem Gutachter mit @ antworten und um eine + Begutachtung des Pull Requests oder einen Kommentar bitten. Sie knnen auch + per [E-Mail](mailto:info@rustdesk.com) um eine Begutachtung bitten. + +- Fgen Sie Tests hinzu, die sich auf den behobenen Fehler oder die neue + Funktion beziehen. + +Spezifische Git-Anweisungen finden Sie im [GitHub-Workflow](https://github.com/servo/servo/wiki/GitHub-workflow). + +## Verhalten + +https://github.com/rustdesk/rustdesk/blob/master/docs/CODE_OF_CONDUCT.md + +## Kommunikation + +RustDesk-Mitarbeiter arbeiten hufig im [Discord](https://discord.gg/nDceKgxnkV). From d25c8df0501cf60ee2dd5e0699475f220fa9fea1 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sun, 26 Feb 2023 19:49:36 +0100 Subject: [PATCH 036/382] Add files via upload --- docs/DEVCONTAINER-DE.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/DEVCONTAINER-DE.md diff --git a/docs/DEVCONTAINER-DE.md b/docs/DEVCONTAINER-DE.md new file mode 100644 index 000000000..2a0d73f17 --- /dev/null +++ b/docs/DEVCONTAINER-DE.md @@ -0,0 +1,14 @@ + +Nach dem Start von Dev-Container im Docker-Container wird ein Linux-Binrprogramm im Debug-Modus erstellt. + +Derzeit bietet Dev-Container Linux- und Android-Builds sowohl im Debug- als auch im Release-Modus an. + +Nachfolgend finden Sie eine Tabelle mit Befehlen, die im Stammverzeichnis des Projekts ausgefhrt werden mssen, um bestimmte Builds zu erstellen. + +Kommando|Build-Typ|Modus +-|-|-| +`.devcontainer/build.sh --debug linux`|Linux|debug +`.devcontainer/build.sh --release linux`|Linux|release +`.devcontainer/build.sh --debug android`|android-arm64|debug +`.devcontainer/build.sh --release android`|android-arm64|release + From b9b4913ca0d5f402db9a7cb2422f7167603f08ce Mon Sep 17 00:00:00 2001 From: 21pages Date: Sat, 25 Feb 2023 04:55:37 -0800 Subject: [PATCH 037/382] mac admin auth check --- src/platform/macos.mm | 30 ++++++++++++++++++++++++++++++ src/platform/macos.rs | 8 ++++++++ src/ui_interface.rs | 6 +++--- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/platform/macos.mm b/src/platform/macos.mm index 8be0c6db5..ac9a69d04 100644 --- a/src/platform/macos.mm +++ b/src/platform/macos.mm @@ -1,6 +1,9 @@ #import #import #import +#include +#include + // https://github.com/codebytere/node-mac-permissions/blob/main/permissions.mm @@ -35,6 +38,33 @@ extern "C" bool InputMonitoringAuthStatus(bool prompt) { return false; } +extern "C" bool MacCheckAdminAuthorization() { + AuthorizationRef authRef; + OSStatus status; + + status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, + kAuthorizationFlagDefaults, &authRef); + if (status != errAuthorizationSuccess) { + printf("Failed to create AuthorizationRef\n"); + return false; + } + + AuthorizationItem authItem = {kAuthorizationRightExecute, 0, NULL, 0}; + AuthorizationRights authRights = {1, &authItem}; + AuthorizationFlags flags = kAuthorizationFlagDefaults | + kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagPreAuthorize | + kAuthorizationFlagExtendRights; + status = AuthorizationCopyRights(authRef, &authRights, kAuthorizationEmptyEnvironment, flags, NULL); + if (status != errAuthorizationSuccess) { + printf("Failed to authorize\n"); + return false; + } + + AuthorizationFree(authRef, kAuthorizationFlagDefaults); + return true; +} + extern "C" float BackingScaleFactor() { NSScreen* s = [NSScreen mainScreen]; if (s) return [s backingScaleFactor]; diff --git a/src/platform/macos.rs b/src/platform/macos.rs index b663b0f41..5c4c68e2c 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -34,6 +34,7 @@ extern "C" { static kAXTrustedCheckOptionPrompt: CFStringRef; fn AXIsProcessTrustedWithOptions(options: CFDictionaryRef) -> BOOL; fn InputMonitoringAuthStatus(_: BOOL) -> BOOL; + fn MacCheckAdminAuthorization() -> BOOL; fn MacGetModeNum(display: u32, numModes: *mut u32) -> BOOL; fn MacGetModes( display: u32, @@ -665,3 +666,10 @@ pub fn change_resolution(name: &str, width: usize, height: usize) -> ResultType< } Ok(()) } + + +pub fn check_super_user_permission() -> ResultType { + unsafe { + Ok(MacCheckAdminAuthorization() == YES) + } +} diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 62eba25c1..471150f60 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -707,10 +707,10 @@ pub fn is_root() -> bool { pub fn check_super_user_permission() -> bool { #[cfg(feature = "flatpak")] return true; - #[cfg(any(windows, target_os = "linux"))] + #[cfg(any(windows, target_os = "linux", target_os = "macos"))] return crate::platform::check_super_user_permission().unwrap_or(false); - #[cfg(not(any(windows, target_os = "linux")))] - true + #[cfg(not(any(windows, target_os = "linux", target_os = "macos")))] + return true; } #[allow(dead_code)] From e3d704dfdee6712eca17964a74ac3bb1ebe97526 Mon Sep 17 00:00:00 2001 From: 21pages Date: Sat, 25 Feb 2023 21:26:09 +0800 Subject: [PATCH 038/382] ensure same bpp and framerate when get and set for mac --- src/platform/macos.mm | 83 +++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/src/platform/macos.mm b/src/platform/macos.mm index ac9a69d04..3c90981c4 100644 --- a/src/platform/macos.mm +++ b/src/platform/macos.mm @@ -74,6 +74,33 @@ extern "C" float BackingScaleFactor() { // https://github.com/jhford/screenresolution/blob/master/cg_utils.c // https://github.com/jdoupe/screenres/blob/master/setgetscreen.m +size_t bitDepth(CGDisplayModeRef mode) { + size_t depth = 0; + // Deprecated, same display same bpp? + // https://stackoverflow.com/questions/8210824/how-to-avoid-cgdisplaymodecopypixelencoding-to-get-bpp + // https://github.com/libsdl-org/SDL/pull/6628 + CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); + // my numerical representation for kIO16BitFloatPixels and kIO32bitFloatPixels + // are made up and possibly non-sensical + if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO32BitFloatPixels), kCFCompareCaseInsensitive)) { + depth = 96; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO64BitDirectPixels), kCFCompareCaseInsensitive)) { + depth = 64; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO16BitFloatPixels), kCFCompareCaseInsensitive)) { + depth = 48; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive)) { + depth = 32; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO30BitDirectPixels), kCFCompareCaseInsensitive)) { + depth = 30; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive)) { + depth = 16; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive)) { + depth = 8; + } + CFRelease(pixelEncoding); + return depth; +} + extern "C" bool MacGetModeNum(CGDirectDisplayID display, uint32_t *numModes) { CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); if (allModes == NULL) { @@ -85,16 +112,28 @@ extern "C" bool MacGetModeNum(CGDirectDisplayID display, uint32_t *numModes) { } extern "C" bool MacGetModes(CGDirectDisplayID display, uint32_t *widths, uint32_t *heights, uint32_t max, uint32_t *numModes) { - CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); - if (allModes == NULL) { + CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(display); + if (currentMode == NULL) { return false; } - *numModes = CFArrayGetCount(allModes); - for (uint32_t i = 0; i < *numModes && i < max; i++) { - CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); - widths[i] = (uint32_t)CGDisplayModeGetWidth(mode); - heights[i] = (uint32_t)CGDisplayModeGetHeight(mode); + CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); + if (allModes == NULL) { + CGDisplayModeRelease(currentMode); + return false; } + uint32_t allModeCount = CFArrayGetCount(allModes); + uint32_t realNum = 0; + for (uint32_t i = 0; i < allModeCount && realNum < max; i++) { + CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); + if (CGDisplayModeGetRefreshRate(currentMode) == CGDisplayModeGetRefreshRate(mode) && + bitDepth(currentMode) == bitDepth(mode)) { + widths[realNum] = (uint32_t)CGDisplayModeGetWidth(mode); + heights[realNum] = (uint32_t)CGDisplayModeGetHeight(mode); + realNum++; + } + } + *numModes = realNum; + CGDisplayModeRelease(currentMode); CFRelease(allModes); return true; } @@ -110,31 +149,8 @@ extern "C" bool MacGetMode(CGDirectDisplayID display, uint32_t *width, uint32_t return true; } -size_t bitDepth(CGDisplayModeRef mode) { - size_t depth = 0; - CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); - // my numerical representation for kIO16BitFloatPixels and kIO32bitFloatPixels - // are made up and possibly non-sensical - if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO32BitFloatPixels), kCFCompareCaseInsensitive)) { - depth = 96; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO64BitDirectPixels), kCFCompareCaseInsensitive)) { - depth = 64; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO16BitFloatPixels), kCFCompareCaseInsensitive)) { - depth = 48; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive)) { - depth = 32; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO30BitDirectPixels), kCFCompareCaseInsensitive)) { - depth = 30; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive)) { - depth = 16; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive)) { - depth = 8; - } - CFRelease(pixelEncoding); - return depth; -} -bool setDisplayToMode(CGDirectDisplayID display, CGDisplayModeRef mode) { +static bool setDisplayToMode(CGDirectDisplayID display, CGDisplayModeRef mode) { CGError rc; CGDisplayConfigRef config; rc = CGBeginDisplayConfiguration(&config); @@ -152,7 +168,6 @@ bool setDisplayToMode(CGDirectDisplayID display, CGDisplayModeRef mode) { return true; } - extern "C" bool MacSetMode(CGDirectDisplayID display, uint32_t width, uint32_t height) { bool ret = false; @@ -170,8 +185,8 @@ extern "C" bool MacSetMode(CGDirectDisplayID display, uint32_t width, uint32_t h CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); if (width == CGDisplayModeGetWidth(mode) && height == CGDisplayModeGetHeight(mode) && - bitDepth(currentMode) == bitDepth(mode) && - CGDisplayModeGetRefreshRate(currentMode) == CGDisplayModeGetRefreshRate(mode)) { + CGDisplayModeGetRefreshRate(currentMode) == CGDisplayModeGetRefreshRate(mode) && + bitDepth(currentMode) == bitDepth(mode)) { ret = setDisplayToMode(display, mode); break; } From b6c3c74286e74b79e1eb688d4f44035f70dbf6a1 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Mon, 27 Feb 2023 12:01:22 +0800 Subject: [PATCH 039/382] opt: move the resize area out of the flutter view --- flutter/lib/consts.dart | 7 +++++++ flutter/lib/desktop/pages/port_forward_tab_page.dart | 12 +++++++----- flutter/lib/desktop/pages/remote_tab_page.dart | 2 ++ .../lib/desktop/screen/desktop_remote_screen.dart | 5 +++++ flutter/lib/desktop/widgets/tabbar_widget.dart | 7 +++++++ flutter/lib/models/state_model.dart | 11 +++++++++++ flutter/pubspec.yaml | 4 ++-- 7 files changed, 41 insertions(+), 7 deletions(-) diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 537784918..789517bf7 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; +import 'package:flutter_hbb/models/state_model.dart'; const double kDesktopRemoteTabBarHeight = 28.0; const int kMainWindowId = 0; @@ -58,6 +59,11 @@ const double kDesktopFileTransferMaximumWidth = 300; const double kDesktopFileTransferRowHeight = 30.0; const double kDesktopFileTransferHeaderHeight = 25.0; +EdgeInsets get kDragToResizeAreaPadding => Platform.isLinux + ? stateGlobal.fullscreen || stateGlobal.maximize + ? EdgeInsets.zero + : EdgeInsets.all(4.0) + : EdgeInsets.zero; // https://en.wikipedia.org/wiki/Non-breaking_space const int $nbsp = 0x00A0; @@ -79,6 +85,7 @@ const kDefaultScrollAmountMultiplier = 5.0; const kDefaultScrollDuration = Duration(milliseconds: 50); const kDefaultMouseWheelThrottleDuration = Duration(milliseconds: 50); const kFullScreenEdgeSize = 0.0; +const kMaximizeEdgeSize = 0.0; var kWindowEdgeSize = Platform.isWindows ? 1.0 : 5.0; const kWindowBorderWidth = 1.0; const kDesktopMenuPadding = EdgeInsets.only(left: 12.0, right: 3.0); diff --git a/flutter/lib/desktop/pages/port_forward_tab_page.dart b/flutter/lib/desktop/pages/port_forward_tab_page.dart index f2d75d00f..394d89e38 100644 --- a/flutter/lib/desktop/pages/port_forward_tab_page.dart +++ b/flutter/lib/desktop/pages/port_forward_tab_page.dart @@ -109,11 +109,13 @@ class _PortForwardTabPageState extends State { ); return Platform.isMacOS ? tabWidget - : SubWindowDragToResizeArea( - child: tabWidget, - resizeEdgeSize: stateGlobal.resizeEdgeSize.value, - windowId: stateGlobal.windowId, - ); + : Obx( + () => SubWindowDragToResizeArea( + child: tabWidget, + resizeEdgeSize: stateGlobal.resizeEdgeSize.value, + windowId: stateGlobal.windowId, + ), + ); } void onRemoveId(String id) { diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index 0deb646c0..e7aed0358 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -210,6 +210,8 @@ class _ConnectionTabPageState extends State { : Obx(() => SubWindowDragToResizeArea( key: contentKey, child: tabWidget, + // Specially configured for a better resize area and remote control. + childPadding: kDragToResizeAreaPadding, resizeEdgeSize: stateGlobal.resizeEdgeSize.value, windowId: stateGlobal.windowId, )); diff --git a/flutter/lib/desktop/screen/desktop_remote_screen.dart b/flutter/lib/desktop/screen/desktop_remote_screen.dart index bb6bc431b..64af41401 100644 --- a/flutter/lib/desktop/screen/desktop_remote_screen.dart +++ b/flutter/lib/desktop/screen/desktop_remote_screen.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/desktop/pages/remote_tab_page.dart'; @@ -26,6 +28,9 @@ class DesktopRemoteScreen extends StatelessWidget { ChangeNotifierProvider.value(value: gFFI.canvasModel), ], child: Scaffold( + // Set transparent background for padding the resize area out of the flutter view. + // This allows the wallpaper goes through our resize area. (Linux only now). + backgroundColor: Platform.isLinux ? Colors.transparent : null, body: ConnectionTabPage( params: params, ), diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index ee3aaaf2c..958c4c035 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -523,12 +523,18 @@ class WindowActionPanelState extends State super.dispose(); } + void _setMaximize(bool maximize) { + stateGlobal.setMaximize(maximize); + setState(() {}); + } + @override void onWindowMaximize() { // catch maximize from system if (!widget.isMaximized.value) { widget.isMaximized.value = true; } + _setMaximize(true); super.onWindowMaximize(); } @@ -538,6 +544,7 @@ class WindowActionPanelState extends State if (widget.isMaximized.value) { widget.isMaximized.value = false; } + _setMaximize(false); super.onWindowUnmaximize(); } diff --git a/flutter/lib/models/state_model.dart b/flutter/lib/models/state_model.dart index 761c95ded..7de258a39 100644 --- a/flutter/lib/models/state_model.dart +++ b/flutter/lib/models/state_model.dart @@ -9,8 +9,10 @@ import '../consts.dart'; class StateGlobal { int _windowId = -1; bool _fullscreen = false; + bool _maximize = false; bool grabKeyboard = false; final RxBool _showTabBar = true.obs; + final RxBool _showResizeEdge = true.obs; final RxDouble _resizeEdgeSize = RxDouble(kWindowEdgeSize); final RxDouble _windowBorderWidth = RxDouble(kWindowBorderWidth); final RxBool showRemoteMenuBar = false.obs; @@ -18,12 +20,21 @@ class StateGlobal { int get windowId => _windowId; bool get fullscreen => _fullscreen; + bool get maximize => _maximize; double get tabBarHeight => fullscreen ? 0 : kDesktopRemoteTabBarHeight; RxBool get showTabBar => _showTabBar; RxDouble get resizeEdgeSize => _resizeEdgeSize; RxDouble get windowBorderWidth => _windowBorderWidth; setWindowId(int id) => _windowId = id; + setMaximize(bool v) { + if (_maximize != v) { + print("set maximize"); + _maximize = v; + _resizeEdgeSize.value = + _maximize ? kMaximizeEdgeSize : kWindowEdgeSize; + } + } setFullscreen(bool v) { if (_fullscreen != v) { _fullscreen = v; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 572b3e20a..b10dd1ec0 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: f37357ed98a10717576eb9ed8413e92b2ec5d13a + ref: c717159ea8fc0b9c6b4ac50110efc1dfd3c1ba7a freezed_annotation: ^2.0.3 flutter_custom_cursor: ^0.0.4 window_size: @@ -76,7 +76,7 @@ dependencies: file_picker: ^5.1.0 flutter_svg: ^1.1.5 flutter_improved_scrolling: - # currently, we use flutter 3.0.5 for windows build, latest for other builds. + # currently, we use flutter 3.7.0+. # # for flutter 3.0.5, please use official version(just comment code below). # if build rustdesk by flutter >=3.3, please use our custom pub below (uncomment code below). From cb4b658e483c50c0028f0675eedff5bf40703a81 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 27 Feb 2023 14:24:15 +0800 Subject: [PATCH 040/382] Avoid dividing by 0 and setting scale to 0 Signed-off-by: fufesou --- flutter/lib/models/model.dart | 38 ++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 74cc7f14f..21949705f 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -617,13 +617,28 @@ class ViewStyle { final int displayWidth; final int displayHeight; ViewStyle({ - this.style = '', - this.width = 0.0, - this.height = 0.0, - this.displayWidth = 0, - this.displayHeight = 0, + required this.style, + required this.width, + required this.height, + required this.displayWidth, + required this.displayHeight, }); + static defaultViewStyle() { + final desktop = (isDesktop || isWebDesktop); + final w = + desktop ? kDesktopDefaultDisplayWidth : kMobileDefaultDisplayWidth; + final h = + desktop ? kDesktopDefaultDisplayHeight : kMobileDefaultDisplayHeight; + return ViewStyle( + style: '', + width: w.toDouble(), + height: h.toDouble(), + displayWidth: w, + displayHeight: h, + ); + } + static int _double2Int(double v) => (v * 100).round().toInt(); @override @@ -652,9 +667,14 @@ class ViewStyle { double get scale { double s = 1.0; if (style == kRemoteViewStyleAdaptive) { - final s1 = width / displayWidth; - final s2 = height / displayHeight; - s = s1 < s2 ? s1 : s2; + if (width != 0 && + height != 0 && + displayWidth != 0 && + displayHeight != 0) { + final s1 = width / displayWidth; + final s2 = height / displayHeight; + s = s1 < s2 ? s1 : s2; + } } return s; } @@ -680,7 +700,7 @@ class CanvasModel with ChangeNotifier { // scroll offset y percent double _scrollY = 0.0; ScrollStyle _scrollStyle = ScrollStyle.scrollauto; - ViewStyle _lastViewStyle = ViewStyle(); + ViewStyle _lastViewStyle = ViewStyle.defaultViewStyle(); final _imageOverflow = false.obs; From c18c6d72bd6e5a914c7acea91154d48c69bc3b3b Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Mon, 27 Feb 2023 09:44:52 +0100 Subject: [PATCH 041/382] create folder modern dialog --- flutter/lib/common.dart | 47 ++++++- .../lib/desktop/pages/file_manager_page.dart | 120 ++++++++++++------ 2 files changed, 119 insertions(+), 48 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 53a401230..a73ab8bd3 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -168,6 +168,22 @@ class MyTheme { brightness: Brightness.light, hoverColor: Color.fromARGB(255, 224, 224, 224), scaffoldBackgroundColor: Color(0xFFFFFFFF), + dialogBackgroundColor: Color(0xFFFFFFFF), + dialogTheme: DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18.0), + ), + ), + inputDecorationTheme: InputDecorationTheme( + fillColor: Color(0xFFEEEEEE), + filled: true, + isDense: true, + contentPadding: EdgeInsets.all(15), + border: UnderlineInputBorder( + borderRadius: BorderRadius.circular(18), + borderSide: BorderSide.none, + ), + ), textTheme: const TextTheme( titleLarge: TextStyle(fontSize: 19, color: Colors.black87), titleSmall: TextStyle(fontSize: 14, color: Colors.black87), @@ -205,6 +221,22 @@ class MyTheme { brightness: Brightness.dark, hoverColor: Color.fromARGB(255, 45, 46, 53), scaffoldBackgroundColor: Color(0xFF18191E), + dialogBackgroundColor: Color(0xFF18191E), + dialogTheme: DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18.0), + ), + ), + inputDecorationTheme: InputDecorationTheme( + fillColor: Color(0xFF24252B), + filled: true, + isDense: true, + contentPadding: EdgeInsets.all(15), + border: UnderlineInputBorder( + borderRadius: BorderRadius.circular(18), + borderSide: BorderSide.none, + ), + ), textTheme: const TextTheme( titleLarge: TextStyle(fontSize: 19), titleSmall: TextStyle(fontSize: 14), @@ -681,18 +713,19 @@ class CustomAlertDialog extends StatelessWidget { scrollable: true, title: title, titlePadding: EdgeInsets.fromLTRB(padding, 24, padding, 0), - contentPadding: EdgeInsets.fromLTRB(contentPadding ?? padding, 25, - contentPadding ?? padding, actions is List ? 10 : padding), + contentPadding: EdgeInsets.fromLTRB( + contentPadding ?? padding, + 25, + contentPadding ?? padding, + actions is List ? 10 : padding, + ), content: ConstrainedBox( constraints: contentBoxConstraints, - child: Theme( - data: Theme.of(context).copyWith( - inputDecorationTheme: InputDecorationTheme( - isDense: true, contentPadding: EdgeInsets.all(15))), - child: content), + child: content, ), actions: actions, actionsPadding: EdgeInsets.fromLTRB(padding, 0, padding, padding), + actionsAlignment: MainAxisAlignment.center, ), ); } diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index badb68a84..31f9e154b 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -49,6 +49,11 @@ enum MouseFocusScope { none } +final buttonShape = + MaterialStateProperty.all(RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18.0), +)); + class FileManagerPage extends StatefulWidget { const FileManagerPage({Key? key, required this.id, this.forceRelay}) : super(key: key); @@ -300,14 +305,13 @@ class _FileManagerPageState extends State } skipCount = index + 1; } - var searchResult = entries - .skip(skipCount) - .where((element) => element.name.toLowerCase().startsWith(buffer)); + var searchResult = entries.skip(skipCount).where( + (element) => element.name.toLowerCase().startsWith(buffer)); if (searchResult.isEmpty) { // cannot find next, lets restart search from head debugPrint("restart search from head"); - searchResult = - entries.where((element) => element.name.toLowerCase().startsWith(buffer)); + searchResult = entries.where( + (element) => element.name.toLowerCase().startsWith(buffer)); } if (searchResult.isEmpty) { setState(() { @@ -321,8 +325,8 @@ class _FileManagerPageState extends State onSearch: (buffer) { debugPrint("searching for $buffer"); final selectedEntries = getSelectedItems(isLocal); - final searchResult = - entries.where((element) => element.name.toLowerCase().startsWith(buffer)); + final searchResult = entries.where( + (element) => element.name.toLowerCase().startsWith(buffer)); selectedEntries.clear(); if (searchResult.isEmpty) { setState(() { @@ -504,8 +508,7 @@ class _FileManagerPageState extends State debugPrint("entry is not valid: ${entry.path}"); } final selectedEntries = getSelectedItems(isLocal); - final searchResult = - entries.where((element) => element == entry); + final searchResult = entries.where((element) => element == entry); selectedEntries.clear(); if (searchResult.isEmpty) { return; @@ -976,25 +979,66 @@ class _FileManagerPageState extends State cancel() => close(false); return CustomAlertDialog( - title: Text(translate("Create Folder")), - content: Column( - mainAxisSize: MainAxisSize.min, + title: Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - TextFormField( - decoration: InputDecoration( - labelText: translate( - "Please enter the folder name"), - ), - controller: name, - autofocus: true, + SvgPicture.asset("assets/folder_new.svg", + color: MyTheme.accent), + Text( + translate("Create Folder"), + ).paddingOnly( + left: 10, + ), + ], + ), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Column( + children: [ + TextFormField( + decoration: InputDecoration( + labelText: translate( + "Please enter the folder name", + ), + ), + controller: name, + autofocus: true, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + ElevatedButton.icon( + style: ButtonStyle( + backgroundColor: + MaterialStateProperty.all( + MyTheme.accent, + ), + shape: buttonShape, + ), + icon: Icon(Icons.close_rounded), + label: Text(translate("Cancel")), + onPressed: cancel, + ), + ElevatedButton.icon( + style: ButtonStyle( + backgroundColor: + MaterialStateProperty.all( + MyTheme.accent, + ), + shape: buttonShape, + ), + icon: Icon(Icons.done_rounded), + label: Text(translate("Ok")), + onPressed: submit, + ), + ], + ).paddingOnly(top: 20) + ], ), ], ), - actions: [ - dialogButton("Cancel", - onPressed: cancel, isOutline: true), - dialogButton("OK", onPressed: submit) - ], onSubmit: submit, onCancel: cancel, ); @@ -1036,11 +1080,7 @@ class _FileManagerPageState extends State ? MyTheme.accent80 : MyTheme.accent, ), - shape: MaterialStateProperty.all( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18.0), - ), - ), + shape: buttonShape, ), onPressed: validItems(selectedItems) ? () { @@ -1430,14 +1470,14 @@ class _FileManagerPageState extends State ).marginSymmetric(horizontal: 4), ), Flexible( - flex: 1, - child: ascending.value != null - ? Icon( - ascending.value! - ? Icons.keyboard_arrow_up_rounded - : Icons.keyboard_arrow_down_rounded, - ) - : const Offstage()) + flex: 1, + child: ascending.value != null + ? Icon( + ascending.value! + ? Icons.keyboard_arrow_up_rounded + : Icons.keyboard_arrow_down_rounded, + ) + : const Offstage()) ], ), ), @@ -1467,10 +1507,8 @@ class _FileManagerPageState extends State axis: Axis.vertical, onPointerMove: (dx) { nameColWidth.value += dx; - nameColWidth.value = min( - kDesktopFileTransferMaximumWidth, - max(kDesktopFileTransferMinimumWidth, - nameColWidth.value)); + nameColWidth.value = min(kDesktopFileTransferMaximumWidth, + max(kDesktopFileTransferMinimumWidth, nameColWidth.value)); }, padding: padding, ), From 6e6fc64f629c6b1a9067a7f16645451cd11f1073 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Mon, 27 Feb 2023 15:56:09 +0800 Subject: [PATCH 042/382] opt: add resize area into the compatible ui mode --- flutter/lib/consts.dart | 2 +- flutter/lib/desktop/pages/desktop_tab_page.dart | 2 +- flutter/lib/desktop/pages/file_manager_tab_page.dart | 2 +- flutter/lib/desktop/pages/port_forward_tab_page.dart | 2 +- flutter/lib/desktop/pages/remote_tab_page.dart | 2 +- flutter/lib/models/state_model.dart | 1 - flutter/pubspec.yaml | 2 +- 7 files changed, 6 insertions(+), 7 deletions(-) diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 789517bf7..b43f3e7da 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -59,7 +59,7 @@ const double kDesktopFileTransferMaximumWidth = 300; const double kDesktopFileTransferRowHeight = 30.0; const double kDesktopFileTransferHeaderHeight = 25.0; -EdgeInsets get kDragToResizeAreaPadding => Platform.isLinux +EdgeInsets get kDragToResizeAreaPadding => !kUseCompatibleUiMode && Platform.isLinux ? stateGlobal.fullscreen || stateGlobal.maximize ? EdgeInsets.zero : EdgeInsets.all(4.0) diff --git a/flutter/lib/desktop/pages/desktop_tab_page.dart b/flutter/lib/desktop/pages/desktop_tab_page.dart index 053a2d8a2..4a1a40242 100644 --- a/flutter/lib/desktop/pages/desktop_tab_page.dart +++ b/flutter/lib/desktop/pages/desktop_tab_page.dart @@ -75,7 +75,7 @@ class _DesktopTabPageState extends State { isClose: false, ), ))); - return Platform.isMacOS + return Platform.isMacOS || kUseCompatibleUiMode ? tabWidget : Obx( () => DragToResizeArea( diff --git a/flutter/lib/desktop/pages/file_manager_tab_page.dart b/flutter/lib/desktop/pages/file_manager_tab_page.dart index 148d928d9..39958e88e 100644 --- a/flutter/lib/desktop/pages/file_manager_tab_page.dart +++ b/flutter/lib/desktop/pages/file_manager_tab_page.dart @@ -98,7 +98,7 @@ class _FileManagerTabPageState extends State { labelGetter: DesktopTab.labelGetterAlias, )), ); - return Platform.isMacOS + return Platform.isMacOS || kUseCompatibleUiMode ? tabWidget : SubWindowDragToResizeArea( child: tabWidget, diff --git a/flutter/lib/desktop/pages/port_forward_tab_page.dart b/flutter/lib/desktop/pages/port_forward_tab_page.dart index 394d89e38..32f02c9b7 100644 --- a/flutter/lib/desktop/pages/port_forward_tab_page.dart +++ b/flutter/lib/desktop/pages/port_forward_tab_page.dart @@ -107,7 +107,7 @@ class _PortForwardTabPageState extends State { labelGetter: DesktopTab.labelGetterAlias, )), ); - return Platform.isMacOS + return Platform.isMacOS || kUseCompatibleUiMode ? tabWidget : Obx( () => SubWindowDragToResizeArea( diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index e7aed0358..d810650fd 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -205,7 +205,7 @@ class _ConnectionTabPageState extends State { ), ), ); - return Platform.isMacOS + return Platform.isMacOS || kUseCompatibleUiMode ? tabWidget : Obx(() => SubWindowDragToResizeArea( key: contentKey, diff --git a/flutter/lib/models/state_model.dart b/flutter/lib/models/state_model.dart index 7de258a39..aa4fab86e 100644 --- a/flutter/lib/models/state_model.dart +++ b/flutter/lib/models/state_model.dart @@ -29,7 +29,6 @@ class StateGlobal { setWindowId(int id) => _windowId = id; setMaximize(bool v) { if (_maximize != v) { - print("set maximize"); _maximize = v; _resizeEdgeSize.value = _maximize ? kMaximizeEdgeSize : kWindowEdgeSize; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index b10dd1ec0..8d390d370 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: c717159ea8fc0b9c6b4ac50110efc1dfd3c1ba7a + ref: e383fffb5c4529c9e0a710f1025a0c590b99ee08 freezed_annotation: ^2.0.3 flutter_custom_cursor: ^0.0.4 window_size: From 920fa6dac7c2d9aa6b709398a3f7cb10c65fcd7f Mon Sep 17 00:00:00 2001 From: Kingtous Date: Mon, 27 Feb 2023 16:53:13 +0800 Subject: [PATCH 043/382] opt: resize padding set to 5.0 --- flutter/lib/consts.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index b43f3e7da..3c414cd85 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -62,7 +62,7 @@ const double kDesktopFileTransferHeaderHeight = 25.0; EdgeInsets get kDragToResizeAreaPadding => !kUseCompatibleUiMode && Platform.isLinux ? stateGlobal.fullscreen || stateGlobal.maximize ? EdgeInsets.zero - : EdgeInsets.all(4.0) + : EdgeInsets.all(5.0) : EdgeInsets.zero; // https://en.wikipedia.org/wiki/Non-breaking_space const int $nbsp = 0x00A0; From 2f7e758c751538e3caf025081b230ed2b49ee60a Mon Sep 17 00:00:00 2001 From: FastAct <93490087+FastAct@users.noreply.github.com> Date: Mon, 27 Feb 2023 09:56:56 +0100 Subject: [PATCH 044/382] Update nl.rs corrected error --- src/lang/nl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/nl.rs b/src/lang/nl.rs index eb7c214ab..f38c14791 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -444,7 +444,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Default View Style", "Standaard Weergave Stijl"), ("Default Scroll Style", "Standaard Scroll Stijl"), ("Default Image Quality", "Standaard Beeldkwaliteit"), - ("Default Codec", "tandaard Codec"), + ("Default Codec", "Standaard Codec"), ("Bitrate", "Bitrate"), ("FPS", "FPS"), ("Auto", "Auto"), From 6971f45fd0734b4e56d416d9ee0bba49eabb5334 Mon Sep 17 00:00:00 2001 From: 21pages Date: Mon, 27 Feb 2023 17:54:18 +0800 Subject: [PATCH 045/382] dark theme install page Signed-off-by: 21pages --- flutter/lib/desktop/pages/install_page.dart | 20 ++++++++++---------- flutter/lib/main.dart | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/flutter/lib/desktop/pages/install_page.dart b/flutter/lib/desktop/pages/install_page.dart index e7bb28813..d7202e300 100644 --- a/flutter/lib/desktop/pages/install_page.dart +++ b/flutter/lib/desktop/pages/install_page.dart @@ -46,15 +46,19 @@ class _InstallPageState extends State with WindowListener { final double em = 13; final btnFontSize = 0.9 * em; final double button_radius = 6; + final isDarkTheme = MyTheme.currentThemeMode() == ThemeMode.dark; final buttonStyle = OutlinedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(button_radius)), )); final inputBorder = OutlineInputBorder( borderRadius: BorderRadius.zero, - borderSide: BorderSide(color: Colors.black12)); + borderSide: + BorderSide(color: isDarkTheme ? Colors.white70 : Colors.black12)); + final textColor = isDarkTheme ? null : Colors.black87; + final dividerColor = isDarkTheme ? Colors.white70 : Colors.black87; return Scaffold( - backgroundColor: Colors.white, + backgroundColor: null, body: SingleChildScrollView( child: Column( children: [ @@ -91,8 +95,7 @@ class _InstallPageState extends State with WindowListener { style: buttonStyle, child: Text(translate('Change Path'), style: TextStyle( - color: Colors.black87, - fontSize: btnFontSize))) + color: textColor, fontSize: btnFontSize))) .marginOnly(left: em)) ], ).marginSymmetric(vertical: 2 * em), @@ -127,8 +130,7 @@ class _InstallPageState extends State with WindowListener { )).marginOnly(top: 2 * em), Row(children: [Text(translate('agreement_tip'))]) .marginOnly(top: em), - Divider(color: Colors.black87) - .marginSymmetric(vertical: 0.5 * em), + Divider(color: dividerColor).marginSymmetric(vertical: 0.5 * em), Row( children: [ Expanded( @@ -143,8 +145,7 @@ class _InstallPageState extends State with WindowListener { style: buttonStyle, child: Text(translate('Cancel'), style: TextStyle( - color: Colors.black87, - fontSize: btnFontSize))) + color: textColor, fontSize: btnFontSize))) .marginOnly(right: 2 * em)), Obx(() => ElevatedButton( onPressed: btnEnabled.value ? install : null, @@ -167,8 +168,7 @@ class _InstallPageState extends State with WindowListener { style: buttonStyle, child: Text(translate('Run without install'), style: TextStyle( - color: Colors.black87, - fontSize: btnFontSize))) + color: textColor, fontSize: btnFontSize))) .marginOnly(left: 2 * em)), ), ], diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index c61287d4f..baf7193b3 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -291,7 +291,7 @@ void _runApp( void runInstallPage() async { await windowManager.ensureInitialized(); await initEnv(kAppTypeMain); - _runApp('', const InstallPage(), ThemeMode.light); + _runApp('', const InstallPage(), MyTheme.currentThemeMode()); windowManager.waitUntilReadyToShow( WindowOptions(size: Size(800, 600), center: true), () async { windowManager.show(); From 2678c503a01aaac28936a6128019c72e77e578ca Mon Sep 17 00:00:00 2001 From: rustdesk Date: Mon, 27 Feb 2023 20:28:55 +0800 Subject: [PATCH 046/382] chore: fix recursive os.system on my m1 in build.py, and modify windows subsystem macro --- build.py | 184 ++++++++++++++++++++++++---------------------------- src/main.rs | 7 +- 2 files changed, 90 insertions(+), 101 deletions(-) diff --git a/build.py b/build.py index 727b53fe0..b30f76f95 100755 --- a/build.py +++ b/build.py @@ -18,14 +18,11 @@ exe_path = 'target/release/' + hbb_name flutter_win_target_dir = 'flutter/build/windows/runner/Release/' skip_cargo = False -def custom_os_system(cmd): - err = os._system(cmd) +def system2(cmd): + err = os.system(cmd) if err != 0: print(f"Error occurred when executing: {cmd}. Exiting.") sys.exit(-1) -# replace prebuilt os.system -os._system = os.system -os.system = custom_os_system def get_version(): with open("Cargo.toml", encoding="utf-8") as fh: @@ -144,8 +141,8 @@ def generate_build_script_for_docker(): # build rustdesk ./build.py --flutter --hwcodec ''') - os.system("chmod +x /tmp/build.sh") - os.system("bash /tmp/build.sh") + system2("chmod +x /tmp/build.sh") + system2("bash /tmp/build.sh") def download_extract_features(features, res_dir): @@ -250,7 +247,7 @@ def get_features(args): def generate_control_file(version): control_file_path = "../res/DEBIAN/control" - os.system('/bin/rm -rf %s' % control_file_path) + system2('/bin/rm -rf %s' % control_file_path) content = """Package: rustdesk Version: %s @@ -268,45 +265,45 @@ Description: A remote control software. def ffi_bindgen_function_refactor(): # workaround ffigen - os.system( + system2( 'sed -i "s/ffi.NativeFunction> tmpdeb/usr/share/rustdesk/files/polkit && chmod a+x tmpdeb/usr/share/rustdesk/files/polkit") - os.system('mkdir -p tmpdeb/DEBIAN') + system2('mkdir -p tmpdeb/DEBIAN') generate_control_file(version) - os.system('cp -a ../res/DEBIAN/* tmpdeb/DEBIAN/') + system2('cp -a ../res/DEBIAN/* tmpdeb/DEBIAN/') md5_file('usr/share/rustdesk/files/systemd/rustdesk.service') - os.system('dpkg-deb -b tmpdeb rustdesk.deb;') + system2('dpkg-deb -b tmpdeb rustdesk.deb;') - os.system('/bin/rm -rf tmpdeb/') - os.system('/bin/rm -rf ../res/DEBIAN/control') + system2('/bin/rm -rf tmpdeb/') + system2('/bin/rm -rf ../res/DEBIAN/control') os.rename('rustdesk.deb', '../rustdesk-%s.deb' % version) os.chdir("..") @@ -314,16 +311,16 @@ def build_flutter_deb(version, features): def build_flutter_dmg(version, features): if not skip_cargo: # set minimum osx build target, now is 10.14, which is the same as the flutter xcode project - os.system(f'MACOSX_DEPLOYMENT_TARGET=10.14 cargo build --features {features} --lib --release') + system2(f'MACOSX_DEPLOYMENT_TARGET=10.14 cargo build --features {features} --lib --release') # copy dylib - os.system( + system2( "cp target/release/liblibrustdesk.dylib target/release/librustdesk.dylib") # ffi_bindgen_function_refactor() # limitations from flutter rust bridge - os.system('sed -i "" "s/char \*\*rustdesk_core_main(int \*args_len);//" flutter/macos/Runner/bridge_generated.h') + system2('sed -i "" "s/char \*\*rustdesk_core_main(int \*args_len);//" flutter/macos/Runner/bridge_generated.h') os.chdir('flutter') - os.system('flutter build macos --release') - os.system( + system2('flutter build macos --release') + system2( "create-dmg rustdesk.dmg ./build/macos/Build/Products/Release/RustDesk.app") os.rename("rustdesk.dmg", f"../rustdesk-{version}.dmg") os.chdir("..") @@ -331,29 +328,29 @@ def build_flutter_dmg(version, features): def build_flutter_arch_manjaro(version, features): if not skip_cargo: - os.system(f'cargo build --features {features} --lib --release') + system2(f'cargo build --features {features} --lib --release') ffi_bindgen_function_refactor() os.chdir('flutter') - os.system('flutter build linux --release') - os.system('strip build/linux/x64/release/bundle/lib/librustdesk.so') + system2('flutter build linux --release') + system2('strip build/linux/x64/release/bundle/lib/librustdesk.so') os.chdir('../res') - os.system('HBB=`pwd`/.. FLUTTER=1 makepkg -f') + system2('HBB=`pwd`/.. FLUTTER=1 makepkg -f') def build_flutter_windows(version, features): if not skip_cargo: - os.system(f'cargo build --features {features} --lib --release') + system2(f'cargo build --features {features} --lib --release') if not os.path.exists("target/release/librustdesk.dll"): print("cargo build failed, please check rust source code.") exit(-1) os.chdir('flutter') - os.system('flutter build windows --release') + system2('flutter build windows --release') os.chdir('..') shutil.copy2('target/release/deps/dylib_virtual_display.dll', flutter_win_target_dir) os.chdir('libs/portable') - os.system('pip3 install -r requirements.txt') - os.system( + system2('pip3 install -r requirements.txt') + system2( f'python3 ./generate.py -f ../../{flutter_win_target_dir} -o . -e ../../{flutter_win_target_dir}/rustdesk.exe') os.chdir('../..') if os.path.exists('./rustdesk_portable.exe'): @@ -374,22 +371,15 @@ def main(): parser = make_parser() args = parser.parse_args() - shutil.copy2('Cargo.toml', 'Cargo.toml.bk') - shutil.copy2('src/main.rs', 'src/main.rs.bk') - if windows: - txt = open('src/main.rs', encoding='utf8').read() - with open('src/main.rs', 'wt', encoding='utf8') as fh: - fh.write(txt.replace( - '//#![windows_subsystem', '#![windows_subsystem')) if os.path.exists(exe_path): os.unlink(exe_path) if os.path.isfile('/usr/bin/pacman'): - os.system('git checkout src/ui/common.tis') + system2('git checkout src/ui/common.tis') version = get_version() features = ','.join(get_features(args)) flutter = args.flutter if not flutter: - os.system('python3 res/inline-sciter.py') + system2('python3 res/inline-sciter.py') print(args.skip_cargo) if args.skip_cargo: skip_cargo = True @@ -397,55 +387,55 @@ def main(): if windows: # build virtual display dynamic library os.chdir('libs/virtual_display/dylib') - os.system('cargo build --release') + system2('cargo build --release') os.chdir('../../..') if flutter: build_flutter_windows(version, features) return - os.system('cargo build --release --features ' + features) - # os.system('upx.exe target/release/rustdesk.exe') - os.system('mv target/release/rustdesk.exe target/release/RustDesk.exe') + system2('cargo build --release --features ' + features) + # system2('upx.exe target/release/rustdesk.exe') + system2('mv target/release/rustdesk.exe target/release/RustDesk.exe') pa = os.environ.get('P') if pa: - os.system( + system2( f'signtool sign /a /v /p {pa} /debug /f .\\cert.pfx /t http://timestamp.digicert.com ' 'target\\release\\rustdesk.exe') else: print('Not signed') - os.system( + system2( f'cp -rf target/release/RustDesk.exe rustdesk-{version}-win7-install.exe') elif os.path.isfile('/usr/bin/pacman'): # pacman -S -needed base-devel - os.system("sed -i 's/pkgver=.*/pkgver=%s/g' res/PKGBUILD" % version) + system2("sed -i 's/pkgver=.*/pkgver=%s/g' res/PKGBUILD" % version) if flutter: build_flutter_arch_manjaro(version, features) else: - os.system('cargo build --release --features ' + features) - os.system('git checkout src/ui/common.tis') - os.system('strip target/release/rustdesk') - os.system('ln -s res/pacman_install && ln -s res/PKGBUILD') - os.system('HBB=`pwd` makepkg -f') - os.system('mv rustdesk-%s-0-x86_64.pkg.tar.zst rustdesk-%s-manjaro-arch.pkg.tar.zst' % ( + system2('cargo build --release --features ' + features) + system2('git checkout src/ui/common.tis') + system2('strip target/release/rustdesk') + system2('ln -s res/pacman_install && ln -s res/PKGBUILD') + system2('HBB=`pwd` makepkg -f') + system2('mv rustdesk-%s-0-x86_64.pkg.tar.zst rustdesk-%s-manjaro-arch.pkg.tar.zst' % ( version, version)) # pacman -U ./rustdesk.pkg.tar.zst elif os.path.isfile('/usr/bin/yum'): - os.system('cargo build --release --features ' + features) - os.system('strip target/release/rustdesk') - os.system( + system2('cargo build --release --features ' + features) + system2('strip target/release/rustdesk') + system2( "sed -i 's/Version: .*/Version: %s/g' res/rpm.spec" % version) - os.system('HBB=`pwd` rpmbuild -ba res/rpm.spec') - os.system( + system2('HBB=`pwd` rpmbuild -ba res/rpm.spec') + system2( 'mv $HOME/rpmbuild/RPMS/x86_64/rustdesk-%s-0.x86_64.rpm ./rustdesk-%s-fedora28-centos8.rpm' % ( version, version)) # yum localinstall rustdesk.rpm elif os.path.isfile('/usr/bin/zypper'): - os.system('cargo build --release --features ' + features) - os.system('strip target/release/rustdesk') - os.system( + system2('cargo build --release --features ' + features) + system2('strip target/release/rustdesk') + system2( "sed -i 's/Version: .*/Version: %s/g' res/rpm-suse.spec" % version) - os.system('HBB=`pwd` rpmbuild -ba res/rpm-suse.spec') - os.system( + system2('HBB=`pwd` rpmbuild -ba res/rpm-suse.spec') + system2( 'mv $HOME/rpmbuild/RPMS/x86_64/rustdesk-%s-0.x86_64.rpm ./rustdesk-%s-suse.rpm' % ( version, version)) # yum localinstall rustdesk.rpm @@ -455,18 +445,18 @@ def main(): build_flutter_dmg(version, features) pass else: - # os.system( + # system2( # 'mv target/release/bundle/deb/rustdesk*.deb ./flutter/rustdesk.deb') build_flutter_deb(version, features) else: - os.system('cargo bundle --release --features ' + features) + system2('cargo bundle --release --features ' + features) if osx: - os.system( + system2( 'strip target/release/bundle/osx/RustDesk.app/Contents/MacOS/rustdesk') - os.system( + system2( 'cp libsciter.dylib target/release/bundle/osx/RustDesk.app/Contents/MacOS/') # https://github.com/sindresorhus/create-dmg - os.system('/bin/rm -rf *.dmg') + system2('/bin/rm -rf *.dmg') plist = "target/release/bundle/osx/RustDesk.app/Contents/Info.plist" txt = open(plist).read() with open(plist, "wt") as fh: @@ -476,7 +466,7 @@ def main(): """)) pa = os.environ.get('P') if pa: - os.system(''' + system2(''' # buggy: rcodesign sign ... path/*, have to sign one by one # install rcodesign via cargo install apple-codesign #rcodesign sign --p12-file ~/.p12/rustdesk-developer-id.p12 --p12-password-file ~/.p12/.cert-pass --code-signature-flags runtime ./target/release/bundle/osx/RustDesk.app/Contents/MacOS/rustdesk @@ -486,11 +476,11 @@ def main(): codesign -s "Developer ID Application: {0}" --force --options runtime ./target/release/bundle/osx/RustDesk.app/Contents/MacOS/* codesign -s "Developer ID Application: {0}" --force --options runtime ./target/release/bundle/osx/RustDesk.app '''.format(pa)) - os.system('create-dmg target/release/bundle/osx/RustDesk.app') + system2('create-dmg target/release/bundle/osx/RustDesk.app') os.rename('RustDesk %s.dmg' % version, 'rustdesk-%s.dmg' % version) if pa: - os.system(''' + system2(''' # https://pyoxidizer.readthedocs.io/en/apple-codesign-0.14.0/apple_codesign.html # https://pyoxidizer.readthedocs.io/en/stable/tugger_code_signing.html # https://developer.apple.com/developer-id/ @@ -507,34 +497,32 @@ def main(): print('Not signed') else: # buid deb package - os.system( + system2( 'mv target/release/bundle/deb/rustdesk*.deb ./rustdesk.deb') - os.system('dpkg-deb -R rustdesk.deb tmpdeb') - os.system('mkdir -p tmpdeb/usr/share/rustdesk/files/systemd/') - os.system( + system2('dpkg-deb -R rustdesk.deb tmpdeb') + system2('mkdir -p tmpdeb/usr/share/rustdesk/files/systemd/') + system2( 'cp res/rustdesk.service tmpdeb/usr/share/rustdesk/files/systemd/') - os.system( + system2( 'cp res/128x128@2x.png tmpdeb/usr/share/rustdesk/files/rustdesk.png') - os.system( + system2( 'cp res/rustdesk.desktop tmpdeb/usr/share/applications/rustdesk.desktop') - os.system( + system2( 'cp res/rustdesk-link.desktop tmpdeb/usr/share/applications/rustdesk-link.desktop') - os.system('cp -a res/DEBIAN/* tmpdeb/DEBIAN/') - os.system('strip tmpdeb/usr/bin/rustdesk') - os.system('mkdir -p tmpdeb/usr/lib/rustdesk') - os.system('mv tmpdeb/usr/bin/rustdesk tmpdeb/usr/lib/rustdesk/') - os.system('cp libsciter-gtk.so tmpdeb/usr/lib/rustdesk/') + system2('cp -a res/DEBIAN/* tmpdeb/DEBIAN/') + system2('strip tmpdeb/usr/bin/rustdesk') + system2('mkdir -p tmpdeb/usr/lib/rustdesk') + system2('mv tmpdeb/usr/bin/rustdesk tmpdeb/usr/lib/rustdesk/') + system2('cp libsciter-gtk.so tmpdeb/usr/lib/rustdesk/') md5_file('usr/share/rustdesk/files/systemd/rustdesk.service') md5_file('usr/lib/rustdesk/libsciter-gtk.so') - os.system('dpkg-deb -b tmpdeb rustdesk.deb; /bin/rm -rf tmpdeb/') + system2('dpkg-deb -b tmpdeb rustdesk.deb; /bin/rm -rf tmpdeb/') os.rename('rustdesk.deb', 'rustdesk-%s.deb' % version) - os.system("mv Cargo.toml.bk Cargo.toml") - os.system("mv src/main.rs.bk src/main.rs") def md5_file(fn): md5 = hashlib.md5(open('tmpdeb/' + fn, 'rb').read()).hexdigest() - os.system('echo "%s %s" >> tmpdeb/DEBIAN/md5sums' % (md5, fn)) + system2('echo "%s %s" >> tmpdeb/DEBIAN/md5sums' % (md5, fn)) if __name__ == "__main__": diff --git a/src/main.rs b/src/main.rs index 169515425..3759f6056 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ -// Specify the Windows subsystem to eliminate console window. -// Requires Rust 1.18. -//#![windows_subsystem = "windows"] + #![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" + )] use librustdesk::*; From f94791793bdec5d83b011709261857a6d6a8f653 Mon Sep 17 00:00:00 2001 From: 21pages Date: Mon, 27 Feb 2023 19:22:52 +0800 Subject: [PATCH 047/382] fix can't install when username contains &, @, ^ Signed-off-by: 21pages --- src/platform/windows.rs | 25 +++++++++++++++++++++++++ src/server/portable_service.rs | 12 +----------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 6b3f8013c..0bba649f4 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1236,6 +1236,15 @@ pub fn uninstall_me() -> ResultType<()> { fn write_cmds(cmds: String, ext: &str, tip: &str) -> ResultType { let mut tmp = std::env::temp_dir(); + // When dir contains these characters, the bat file will not execute in elevated mode. + if vec!["&", "@", "^"] + .drain(..) + .any(|s| tmp.to_string_lossy().to_string().contains(s)) + { + if let Ok(dir) = user_accessible_folder() { + tmp = dir; + } + } tmp.push(format!("{}_{}.{}", crate::get_app_name(), tip, ext)); let mut file = std::fs::File::create(&tmp)?; // in case cmds mixed with \r\n and \n, make sure all ending with \r\n @@ -1872,3 +1881,19 @@ pub fn change_resolution(name: &str, width: usize, height: usize) -> ResultType< Ok(()) } } + +pub fn user_accessible_folder() -> ResultType { + let disk = std::env::var("SystemDrive").unwrap_or("C:".to_string()); + let dir1 = PathBuf::from(format!("{}\\ProgramData", disk)); + // NOTICE: "C:\Windows\Temp" requires permanent authorization. + let dir2 = PathBuf::from(format!("{}\\Windows\\Temp", disk)); + let dir; + if dir1.exists() { + dir = dir1; + } else if dir2.exists() { + dir = dir2; + } else { + bail!("no vaild user accessible folder"); + } + Ok(dir) +} diff --git a/src/server/portable_service.rs b/src/server/portable_service.rs index 7514ead38..c49f974a7 100644 --- a/src/server/portable_service.rs +++ b/src/server/portable_service.rs @@ -117,17 +117,7 @@ impl SharedMemory { } fn flink(name: String) -> ResultType { - let disk = std::env::var("SystemDrive").unwrap_or("C:".to_string()); - let dir1 = PathBuf::from(format!("{}\\ProgramData", disk)); - let dir2 = PathBuf::from(format!("{}\\Windows\\Temp", disk)); - let mut dir; - if dir1.exists() { - dir = dir1; - } else if dir2.exists() { - dir = dir2; - } else { - bail!("no vaild flink directory"); - } + let mut dir = crate::platform::user_accessible_folder()?; dir = dir.join(hbb_common::config::APP_NAME.read().unwrap().clone()); if !dir.exists() { std::fs::create_dir(&dir)?; From c7e8037a79f3446591e585bbdfe52ed696c26873 Mon Sep 17 00:00:00 2001 From: solokot Date: Mon, 27 Feb 2023 15:57:46 +0300 Subject: [PATCH 048/382] Update ru.rs --- src/lang/ru.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 07b8af998..3bfb5357d 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -454,8 +454,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Завершить голосовой вызов"), ("relay_hint_tip", "Прямое подключение может оказаться невозможным. В этом случае можно попытаться подключиться через сервер ретрансляции. \nКроме того, если вы хотите сразу использовать сервер ретрансляции, можно добавить к ID суффикс \"/r\" или включить \"Всегда подключаться через ретранслятор\" в настройках удалённого узла."), ("Reconnect", "Переподключить"), - ("Codec", ""), - ("Resolution", ""), - ("No transfers in progress", ""), + ("Codec", "Кодек"), + ("Resolution", "Разрешение"), + ("No transfers in progress", "Передача не осуществляется"), ].iter().cloned().collect(); } From 63185a5bcb6272ad42b3f5abbaa54a9724fc03e7 Mon Sep 17 00:00:00 2001 From: csf Date: Mon, 27 Feb 2023 23:07:52 +0900 Subject: [PATCH 049/382] 1. enable BootReceiver. 2. add PermissionRequestTransparentActivity. 3. opt const. --- .../android/app/src/main/AndroidManifest.xml | 21 +++++--- .../com/carriez/flutter_hbb/BootReceiver.kt | 17 ++++-- .../com/carriez/flutter_hbb/MainActivity.kt | 51 ++++-------------- .../com/carriez/flutter_hbb/MainService.kt | 37 ++++++++----- .../PermissionRequestTransparentActivity.kt | 54 +++++++++++++++++++ .../kotlin/com/carriez/flutter_hbb/common.kt | 21 ++++++-- .../app/src/main/res/values/styles.xml | 8 +++ 7 files changed, 137 insertions(+), 72 deletions(-) create mode 100644 flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/PermissionRequestTransparentActivity.kt diff --git a/flutter/android/app/src/main/AndroidManifest.xml b/flutter/android/app/src/main/AndroidManifest.xml index ede6353ef..6f646b913 100644 --- a/flutter/android/app/src/main/AndroidManifest.xml +++ b/flutter/android/app/src/main/AndroidManifest.xml @@ -11,22 +11,24 @@ - + + android:supportsRtl="true"> + android:enabled="true" + android:exported="true"> + + @@ -53,8 +55,6 @@ android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:windowSoftInputMode="adjustResize"> - - @@ -62,6 +62,11 @@ + + - + \ No newline at end of file diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt index 328701567..a49dcc326 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt @@ -4,18 +4,25 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.os.Build +import android.util.Log import android.widget.Toast +const val DEBUG_BOOT_COMPLETED = "com.carriez.flutter_hbb.DEBUG_BOOT_COMPLETED" + class BootReceiver : BroadcastReceiver() { + private val logTag = "tagBootReceiver" + override fun onReceive(context: Context, intent: Intent) { - if ("android.intent.action.BOOT_COMPLETED" == intent.action){ - val it = Intent(context,MainService::class.java).apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + Log.d(logTag, "onReceive ${intent.action}") + + if (Intent.ACTION_BOOT_COMPLETED == intent.action || DEBUG_BOOT_COMPLETED == intent.action) { + val it = Intent(context, MainService::class.java).apply { + action = ACT_INIT_MEDIA_PROJECTION_AND_SERVICE } - Toast.makeText(context, "RustDesk is Open", Toast.LENGTH_LONG).show(); + Toast.makeText(context, "RustDesk is Open", Toast.LENGTH_LONG).show() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.startForegroundService(it) - }else{ + } else { context.startService(it) } } diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt index fd340f7ed..73dbd2dad 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt @@ -7,12 +7,10 @@ package com.carriez.flutter_hbb * Inspired by [droidVNC-NG] https://github.com/bk138/droidVNC-NG */ -import android.app.Activity import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.ServiceConnection -import android.media.projection.MediaProjectionManager import android.os.Build import android.os.IBinder import android.provider.Settings @@ -23,7 +21,6 @@ import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel -const val MEDIA_REQUEST_CODE = 42 class MainActivity : FlutterActivity() { companion object { @@ -32,7 +29,6 @@ class MainActivity : FlutterActivity() { private val channelTag = "mChannel" private val logTag = "mMainActivity" - private var mediaProjectionResultIntent: Intent? = null private var mainService: MainService? = null @RequiresApi(Build.VERSION_CODES.M) @@ -58,7 +54,7 @@ class MainActivity : FlutterActivity() { result.success(false) return@setMethodCallHandler } - getMediaProjection() + requestMediaProjection() result.success(true) } "start_capture" -> { @@ -153,35 +149,6 @@ class MainActivity : FlutterActivity() { } } - private fun getMediaProjection() { - val mMediaProjectionManager = - getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager - val mIntent = mMediaProjectionManager.createScreenCaptureIntent() - startActivityForResult(mIntent, MEDIA_REQUEST_CODE) - } - - private fun initService() { - if (mediaProjectionResultIntent == null) { - Log.w(logTag, "initService fail,mediaProjectionResultIntent is null") - return - } - Log.d(logTag, "Init service") - val serviceIntent = Intent(this, MainService::class.java) - serviceIntent.action = INIT_SERVICE - serviceIntent.putExtra(EXTRA_MP_DATA, mediaProjectionResultIntent) - - launchMainService(serviceIntent) - } - - private fun launchMainService(intent: Intent) { - // TEST api < O - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - startForegroundService(intent) - } else { - startService(intent) - } - } - private fun initInput() { val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS) if (intent.resolveActivity(packageManager) != null) { @@ -200,15 +167,17 @@ class MainActivity : FlutterActivity() { } } + private fun requestMediaProjection() { + val intent = Intent(this, PermissionRequestTransparentActivity::class.java).apply { + action = ACT_REQUEST_MEDIA_PROJECTION + } + startActivityForResult(intent, REQ_INVOKE_PERMISSION_ACTIVITY_MEDIA_PROJECTION) + } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - if (requestCode == MEDIA_REQUEST_CODE) { - if (resultCode == Activity.RESULT_OK && data != null) { - mediaProjectionResultIntent = data - initService() - } else { - flutterMethodChannel.invokeMethod("on_media_projection_canceled", null) - } + if (requestCode == REQ_INVOKE_PERMISSION_ACTIVITY_MEDIA_PROJECTION && resultCode == RES_FAILED) { + flutterMethodChannel.invokeMethod("on_media_projection_canceled", null) } } diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt index cf8e12e92..e28311964 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt @@ -43,10 +43,6 @@ import java.nio.ByteBuffer import kotlin.math.max import kotlin.math.min -const val EXTRA_MP_DATA = "mp_intent" -const val INIT_SERVICE = "init_service" -const val ACTION_LOGIN_REQ_NOTIFY = "ACTION_LOGIN_REQ_NOTIFY" -const val EXTRA_LOGIN_REQ_NOTIFY = "EXTRA_LOGIN_REQ_NOTIFY" const val DEFAULT_NOTIFY_TITLE = "RustDesk" const val DEFAULT_NOTIFY_TEXT = "Service is running" @@ -195,6 +191,7 @@ class MainService : Service() { override fun onCreate() { super.onCreate() + Log.d(logTag,"MainService onCreate") HandlerThread("Service", Process.THREAD_PRIORITY_BACKGROUND).apply { start() serviceLooper = looper @@ -203,6 +200,7 @@ class MainService : Service() { updateScreenInfo(resources.configuration.orientation) initNotification() startServer() + createForegroundNotification() } override fun onDestroy() { @@ -277,22 +275,25 @@ class MainService : Service() { } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - Log.d("whichService", "this service:${Thread.currentThread()}") + Log.d("whichService", "this service: ${Thread.currentThread()}") super.onStartCommand(intent, flags, startId) - if (intent?.action == INIT_SERVICE) { - Log.d(logTag, "service starting:${startId}:${Thread.currentThread()}") - createForegroundNotification() - val mMediaProjectionManager = + if (intent?.action == ACT_INIT_MEDIA_PROJECTION_AND_SERVICE) { + Log.d(logTag, "service starting: ${startId}:${Thread.currentThread()}") + val mediaProjectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager - intent.getParcelableExtra(EXTRA_MP_DATA)?.let { + + intent.getParcelableExtra(EXT_MEDIA_PROJECTION_RES_INTENT)?.let { mediaProjection = - mMediaProjectionManager.getMediaProjection(Activity.RESULT_OK, it) + mediaProjectionManager.getMediaProjection(Activity.RESULT_OK, it) checkMediaPermission() init(this) _isReady = true + } ?: let { + Log.d(logTag, "getParcelableExtra intent null, invoke requestMediaProjection") + requestMediaProjection() } } - return START_NOT_STICKY // don't use sticky (auto restart),the new service (from auto restart) will lose control + return START_NOT_STICKY // don't use sticky (auto restart), the new service (from auto restart) will lose control } override fun onConfigurationChanged(newConfig: Configuration) { @@ -300,6 +301,14 @@ class MainService : Service() { updateScreenInfo(newConfig.orientation) } + private fun requestMediaProjection() { + val intent = Intent(this, PermissionRequestTransparentActivity::class.java).apply { + action = ACT_REQUEST_MEDIA_PROJECTION + flags = Intent.FLAG_ACTIVITY_NEW_TASK + } + startActivity(intent) + } + @SuppressLint("WrongConstant") private fun createSurface(): Surface? { return if (useVP9) { @@ -653,8 +662,8 @@ class MainService : Service() { @SuppressLint("UnspecifiedImmutableFlag") private fun genLoginRequestPendingIntent(res: Boolean): PendingIntent { val intent = Intent(this, MainService::class.java).apply { - action = ACTION_LOGIN_REQ_NOTIFY - putExtra(EXTRA_LOGIN_REQ_NOTIFY, res) + action = ACT_LOGIN_REQ_NOTIFY + putExtra(EXT_LOGIN_REQ_NOTIFY, res) } return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { PendingIntent.getService(this, 111, intent, FLAG_IMMUTABLE) diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/PermissionRequestTransparentActivity.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/PermissionRequestTransparentActivity.kt new file mode 100644 index 000000000..3beb7ec6b --- /dev/null +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/PermissionRequestTransparentActivity.kt @@ -0,0 +1,54 @@ +package com.carriez.flutter_hbb + +import android.app.Activity +import android.content.Intent +import android.media.projection.MediaProjectionManager +import android.os.Build +import android.os.Bundle +import android.util.Log + +class PermissionRequestTransparentActivity: Activity() { + private val logTag = "permissionRequest" + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + Log.d(logTag, "onCreate PermissionRequestTransparentActivity: intent.action: ${intent.action}") + + when (intent.action) { + ACT_REQUEST_MEDIA_PROJECTION -> { + val mediaProjectionManager = + getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager + val intent = mediaProjectionManager.createScreenCaptureIntent() + startActivityForResult(intent, REQ_REQUEST_MEDIA_PROJECTION) + } + else -> finish() + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == REQ_REQUEST_MEDIA_PROJECTION) { + if (resultCode == RESULT_OK && data != null) { + launchService(data) + } else { + setResult(RES_FAILED) + } + } + + finish() + } + + private fun launchService(mediaProjectionResultIntent: Intent) { + Log.d(logTag, "Launch MainService") + val serviceIntent = Intent(this, MainService::class.java) + serviceIntent.action = ACT_INIT_MEDIA_PROJECTION_AND_SERVICE + serviceIntent.putExtra(EXT_MEDIA_PROJECTION_RES_INTENT, mediaProjectionResultIntent) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(serviceIntent) + } else { + startService(serviceIntent) + } + } + +} \ No newline at end of file diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt index 4bf244a06..a812686ec 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt @@ -12,8 +12,7 @@ import android.os.Build import android.os.Handler import android.os.Looper import android.os.PowerManager -import android.provider.Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS -import android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS +import android.provider.Settings.* import androidx.annotation.RequiresApi import androidx.core.content.ContextCompat.getSystemService import com.hjq.permissions.Permission @@ -22,6 +21,21 @@ import java.nio.ByteBuffer import java.util.* +// intent action, extra +const val ACT_REQUEST_MEDIA_PROJECTION = "REQUEST_MEDIA_PROJECTION" +const val ACT_INIT_MEDIA_PROJECTION_AND_SERVICE = "INIT_MEDIA_PROJECTION_AND_SERVICE" +const val ACT_LOGIN_REQ_NOTIFY = "LOGIN_REQ_NOTIFY" +const val EXT_MEDIA_PROJECTION_RES_INTENT = "MEDIA_PROJECTION_RES_INTENT" +const val EXT_LOGIN_REQ_NOTIFY = "LOGIN_REQ_NOTIFY" + +// Activity requestCode +const val REQ_INVOKE_PERMISSION_ACTIVITY_MEDIA_PROJECTION = 101 +const val REQ_REQUEST_MEDIA_PROJECTION = 201 + +// Activity responseCode +const val RES_FAILED = -100 + + @SuppressLint("ConstantLocale") val LOCAL_NAME = Locale.getDefault().toString() val SCREEN_INFO = Info(0, 0, 1, 200) @@ -59,9 +73,8 @@ fun requestPermission(context: Context, type: String) { } "application_details_settings" -> { try { - context.startActivity(Intent().apply { + context.startActivity(Intent(ACTION_APPLICATION_DETAILS_SETTINGS).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - action = "android.settings.APPLICATION_DETAILS_SETTINGS" data = Uri.parse("package:" + context.packageName) }) } catch (e:Exception) { diff --git a/flutter/android/app/src/main/res/values/styles.xml b/flutter/android/app/src/main/res/values/styles.xml index d74aa35c2..146267c91 100644 --- a/flutter/android/app/src/main/res/values/styles.xml +++ b/flutter/android/app/src/main/res/values/styles.xml @@ -15,4 +15,12 @@ + From 658c45d1c233a7be5997e38db701ea2af9c81c45 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 27 Feb 2023 21:46:26 +0800 Subject: [PATCH 050/382] Do not use flutter texture for render. Signed-off-by: fufesou --- .github/workflows/flutter-nightly.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/flutter-nightly.yml b/.github/workflows/flutter-nightly.yml index b08193971..ffcadd18b 100644 --- a/.github/workflows/flutter-nightly.yml +++ b/.github/workflows/flutter-nightly.yml @@ -732,7 +732,7 @@ jobs: x86_64) # no need mock on x86_64 export VCPKG_ROOT=/opt/artifacts/vcpkg - cargo build --lib --features hwcodec,flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features hwcodec,flutter,${{ matrix.job.extra-build-features }} --release ;; esac @@ -900,7 +900,7 @@ jobs: ln -s /usr/include /vcpkg/installed/arm64-linux/include export VCPKG_ROOT=/vcpkg # disable hwcodec for compilation - cargo build --lib --features flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features flutter,${{ matrix.job.extra-build-features }} --release ;; armv7) cp -r /opt/artifacts/vcpkg/installed/lib/* /usr/lib/arm-linux-gnueabihf/ @@ -910,7 +910,7 @@ jobs: ln -s /usr/include /vcpkg/installed/arm-linux/include export VCPKG_ROOT=/vcpkg # disable hwcodec for compilation - cargo build --lib --features flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features flutter,${{ matrix.job.extra-build-features }} --release ;; esac From fb21f9df440101739875eece1c45383272394cd1 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 27 Feb 2023 22:24:00 +0800 Subject: [PATCH 051/382] check divide by 0 Signed-off-by: fufesou --- flutter/lib/models/model.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 21949705f..fd97b1e5c 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -810,6 +810,10 @@ class CanvasModel with ChangeNotifier { double get tabBarHeight => stateGlobal.tabBarHeight; moveDesktopMouse(double x, double y) { + if (size.width == 0 || size.height == 0) { + return; + } + // On mobile platforms, move the canvas with the cursor. final dw = getDisplayWidth() * _scale; final dh = getDisplayHeight() * _scale; From 8cd9f8745d99686598347d1f0cd0d0192d1ec288 Mon Sep 17 00:00:00 2001 From: csf Date: Tue, 28 Feb 2023 00:41:09 +0900 Subject: [PATCH 052/382] opt AndroidPermissionManager --- .../com/carriez/flutter_hbb/MainActivity.kt | 8 ++ .../kotlin/com/carriez/flutter_hbb/common.kt | 84 +++++-------------- flutter/lib/common.dart | 27 ++---- flutter/lib/consts.dart | 26 ++++-- flutter/lib/mobile/pages/server_page.dart | 12 +-- flutter/lib/mobile/pages/settings_page.dart | 10 ++- flutter/lib/models/server_model.dart | 19 +++-- 7 files changed, 85 insertions(+), 101 deletions(-) diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt index 73dbd2dad..7050e7a46 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt @@ -88,6 +88,14 @@ class MainActivity : FlutterActivity() { result.success(false) } } + START_ACTION -> { + if (call.arguments is String) { + startAction(context, call.arguments as String) + result.success(true) + } else { + result.success(false) + } + } "check_video_permission" -> { mainService?.let { result.success(it.checkMediaPermission()) diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt index a812686ec..0bc6c1c28 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt @@ -1,5 +1,6 @@ package com.carriez.flutter_hbb +import android.Manifest.permission.* import android.annotation.SuppressLint import android.content.Context import android.content.Intent @@ -35,6 +36,10 @@ const val REQ_REQUEST_MEDIA_PROJECTION = 201 // Activity responseCode const val RES_FAILED = -100 +// Flutter channel +const val START_ACTION = "start_action"; +const val IGNORE_BATTERY_OPTIMIZATIONS = "ignore_battery_optimizations"; + @SuppressLint("ConstantLocale") val LOCAL_NAME = Locale.getDefault().toString() @@ -44,56 +49,10 @@ data class Info( var width: Int, var height: Int, var scale: Int, var dpi: Int ) -@RequiresApi(Build.VERSION_CODES.LOLLIPOP) -fun testVP9Support(): Boolean { - return true - val res = MediaCodecList(MediaCodecList.ALL_CODECS) - .findEncoderForFormat( - MediaFormat.createVideoFormat( - MediaFormat.MIMETYPE_VIDEO_VP9, - SCREEN_INFO.width, - SCREEN_INFO.width - ) - ) - return res != null -} - @RequiresApi(Build.VERSION_CODES.M) fun requestPermission(context: Context, type: String) { - val permission = when (type) { - "ignore_battery_optimizations" -> { - try { - context.startActivity(Intent(ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).apply { - data = Uri.parse("package:" + context.packageName) - }) - } catch (e:Exception) { - e.printStackTrace() - } - return - } - "application_details_settings" -> { - try { - context.startActivity(Intent(ACTION_APPLICATION_DETAILS_SETTINGS).apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - data = Uri.parse("package:" + context.packageName) - }) - } catch (e:Exception) { - e.printStackTrace() - } - return - } - "audio" -> { - Permission.RECORD_AUDIO - } - "file" -> { - Permission.MANAGE_EXTERNAL_STORAGE - } - else -> { - return - } - } XXPermissions.with(context) - .permission(permission) + .permission(type) .request { _, all -> if (all) { Handler(Looper.getMainLooper()).post { @@ -108,22 +67,23 @@ fun requestPermission(context: Context, type: String) { @RequiresApi(Build.VERSION_CODES.M) fun checkPermission(context: Context, type: String): Boolean { - val permission = when (type) { - "ignore_battery_optimizations" -> { - val pw = context.getSystemService(Context.POWER_SERVICE) as PowerManager - return pw.isIgnoringBatteryOptimizations(context.packageName) - } - "audio" -> { - Permission.RECORD_AUDIO - } - "file" -> { - Permission.MANAGE_EXTERNAL_STORAGE - } - else -> { - return false - } + if (IGNORE_BATTERY_OPTIMIZATIONS == type) { + val pw = context.getSystemService(Context.POWER_SERVICE) as PowerManager + return pw.isIgnoringBatteryOptimizations(context.packageName) + } + return XXPermissions.isGranted(context, type) +} + +@RequiresApi(Build.VERSION_CODES.M) +fun startAction(context: Context, action: String) { + try { + context.startActivity(Intent(action).apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + data = Uri.parse("package:" + context.packageName) + }) + } catch (e: Exception) { + e.printStackTrace() } - return XXPermissions.isGranted(context, permission) } class AudioReader(val bufSize: Int, private val maxFrames: Int) { diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 53a401230..41ac595f2 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -907,21 +907,14 @@ class AccessibilityListener extends StatelessWidget { } } -class PermissionManager { +class AndroidPermissionManager { static Completer? _completer; static Timer? _timer; static var _current = ""; - static final permissions = [ - "audio", - "file", - "ignore_battery_optimizations", - "application_details_settings" - ]; - static bool isWaitingFile() { if (_completer != null) { - return !_completer!.isCompleted && _current == "file"; + return !_completer!.isCompleted && _current == kManageExternalStorage; } return false; } @@ -930,9 +923,6 @@ class PermissionManager { if (isDesktop) { return Future.value(true); } - if (!permissions.contains(type)) { - return Future.error("Wrong permission!$type"); - } return gFFI.invokeMethod("check_permission", type); } @@ -940,17 +930,16 @@ class PermissionManager { if (isDesktop) { return Future.value(true); } - if (!permissions.contains(type)) { - return Future.error("Wrong permission!$type"); - } gFFI.invokeMethod("request_permission", type); - if (type == "ignore_battery_optimizations") { + + // kIgnoreBatteryOptimizations permission doesn't depend on callback result, the result will be checked and updated on page resume + if (type == kIgnoreBatteryOptimizations) { return Future.value(false); } + _current = type; _completer = Completer(); - gFFI.invokeMethod("request_permission", type); // timeout _timer?.cancel(); @@ -1484,8 +1473,8 @@ connect(BuildContext context, String id, } } else { if (isFileTransfer) { - if (!await PermissionManager.check("file")) { - if (!await PermissionManager.request("file")) { + if (!await AndroidPermissionManager.check(kManageExternalStorage)) { + if (!await AndroidPermissionManager.request(kManageExternalStorage)) { return; } } diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 3c414cd85..a0766a874 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -59,11 +59,12 @@ const double kDesktopFileTransferMaximumWidth = 300; const double kDesktopFileTransferRowHeight = 30.0; const double kDesktopFileTransferHeaderHeight = 25.0; -EdgeInsets get kDragToResizeAreaPadding => !kUseCompatibleUiMode && Platform.isLinux - ? stateGlobal.fullscreen || stateGlobal.maximize - ? EdgeInsets.zero - : EdgeInsets.all(5.0) - : EdgeInsets.zero; +EdgeInsets get kDragToResizeAreaPadding => + !kUseCompatibleUiMode && Platform.isLinux + ? stateGlobal.fullscreen || stateGlobal.maximize + ? EdgeInsets.zero + : EdgeInsets.all(5.0) + : EdgeInsets.zero; // https://en.wikipedia.org/wiki/Non-breaking_space const int $nbsp = 0x00A0; @@ -136,6 +137,21 @@ const kRemoteAudioDualWay = 'dual-way'; const kIgnoreDpi = true; +/// Android constants +const kActionApplicationDetailsSettings = + "android.settings.APPLICATION_DETAILS_SETTINGS"; +const kActionRequestIgnoreBatteryOptimizations = + "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; +const kRecordAudio = "android.permission.RECORD_AUDIO"; +const kManageExternalStorage = "android.permission.MANAGE_EXTERNAL_STORAGE"; +const kSystemAlertWindow = "android.permission.SYSTEM_ALERT_WINDOW"; + +/// [kIgnoreBatteryOptimizations] not a Android Permission, it is a custom key, used in `ignore battery optimizations` check +const kIgnoreBatteryOptimizations = "ignore_battery_optimizations"; + +/// Android channel invoke type key +const kStartAction = "start_action"; + /// flutter/packages/flutter/lib/src/services/keyboard_key.dart -> _keyLabels /// see [LogicalKeyboardKey.keyLabel] const Map logicalKeyMap = { diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index abccdf683..648448f41 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -6,6 +6,7 @@ import 'package:provider/provider.dart'; import '../../common.dart'; import '../../common/widgets/dialog.dart'; +import '../../consts.dart'; import '../../models/platform_model.dart'; import '../../models/server_model.dart'; import 'home_page.dart'; @@ -150,10 +151,11 @@ class _ServerPageState extends State { } void checkService() async { - gFFI.invokeMethod("check_service"); // jvm - // for Android 10/11,MANAGE_EXTERNAL_STORAGE permission from a system setting page - if (PermissionManager.isWaitingFile() && !gFFI.serverModel.fileOk) { - PermissionManager.complete("file", await PermissionManager.check("file")); + gFFI.invokeMethod("check_service"); + // for Android 10/11, request MANAGE_EXTERNAL_STORAGE permission from system setting page + if (AndroidPermissionManager.isWaitingFile() && !gFFI.serverModel.fileOk) { + AndroidPermissionManager.complete(kManageExternalStorage, + await AndroidPermissionManager.check(kManageExternalStorage)); debugPrint("file permission finished"); } } @@ -567,7 +569,7 @@ void androidChannelInit() { { var type = arguments["type"] as String; var result = arguments["result"] as bool; - PermissionManager.complete(type, result); + AndroidPermissionManager.complete(type, result); break; } case "on_media_projection_canceled": diff --git a/flutter/lib/mobile/pages/settings_page.dart b/flutter/lib/mobile/pages/settings_page.dart index c5f3b6935..6bdb7e813 100644 --- a/flutter/lib/mobile/pages/settings_page.dart +++ b/flutter/lib/mobile/pages/settings_page.dart @@ -10,6 +10,7 @@ import 'package:url_launcher/url_launcher.dart'; import '../../common.dart'; import '../../common/widgets/dialog.dart'; import '../../common/widgets/login.dart'; +import '../../consts.dart'; import '../../models/model.dart'; import '../../models/platform_model.dart'; import '../widgets/dialog.dart'; @@ -133,7 +134,8 @@ class _SettingsState extends State with WidgetsBindingObserver { } Future updateIgnoreBatteryStatus() async { - final res = await PermissionManager.check("ignore_battery_optimizations"); + final res = + await AndroidPermissionManager.check(kIgnoreBatteryOptimizations); if (_ignoreBatteryOpt != res) { _ignoreBatteryOpt = res; return true; @@ -265,7 +267,8 @@ class _SettingsState extends State with WidgetsBindingObserver { ]), onToggle: (v) async { if (v) { - PermissionManager.request("ignore_battery_optimizations"); + gFFI.invokeMethod( + kStartAction, kActionRequestIgnoreBatteryOptimizations); } else { final res = await gFFI.dialogManager .show((setState, close) => CustomAlertDialog( @@ -282,7 +285,8 @@ class _SettingsState extends State with WidgetsBindingObserver { ], )); if (res == true) { - PermissionManager.request("application_details_settings"); + gFFI.invokeMethod( + kStartAction, kActionApplicationDetailsSettings); } } })); diff --git a/flutter/lib/models/server_model.dart b/flutter/lib/models/server_model.dart index b2043f3c2..433990a2a 100644 --- a/flutter/lib/models/server_model.dart +++ b/flutter/lib/models/server_model.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter_hbb/consts.dart'; import 'package:flutter_hbb/main.dart'; import 'package:flutter_hbb/models/platform_model.dart'; import 'package:get/get.dart'; @@ -154,7 +155,8 @@ class ServerModel with ChangeNotifier { /// file true by default (if permission on) checkAndroidPermission() async { // audio - if (androidVersion < 30 || !await PermissionManager.check("audio")) { + if (androidVersion < 30 || + !await AndroidPermissionManager.check(kRecordAudio)) { _audioOk = false; bind.mainSetOption(key: "enable-audio", value: "N"); } else { @@ -163,7 +165,7 @@ class ServerModel with ChangeNotifier { } // file - if (!await PermissionManager.check("file")) { + if (!await AndroidPermissionManager.check(kManageExternalStorage)) { _fileOk = false; bind.mainSetOption(key: "enable-file-transfer", value: "N"); } else { @@ -229,8 +231,8 @@ class ServerModel with ChangeNotifier { } toggleAudio() async { - if (!_audioOk && !await PermissionManager.check("audio")) { - final res = await PermissionManager.request("audio"); + if (!_audioOk && !await AndroidPermissionManager.check(kRecordAudio)) { + final res = await AndroidPermissionManager.request(kRecordAudio); if (!res) { // TODO handle fail return; @@ -243,8 +245,10 @@ class ServerModel with ChangeNotifier { } toggleFile() async { - if (!_fileOk && !await PermissionManager.check("file")) { - final res = await PermissionManager.request("file"); + if (!_fileOk && + !await AndroidPermissionManager.check(kManageExternalStorage)) { + final res = + await AndroidPermissionManager.request(kManageExternalStorage); if (!res) { // TODO handle fail return; @@ -561,7 +565,8 @@ class ServerModel with ChangeNotifier { } Future closeAll() async { - await Future.wait(_clients.map((client) => bind.cmCloseConnection(connId: client.id))); + await Future.wait( + _clients.map((client) => bind.cmCloseConnection(connId: client.id))); _clients.clear(); tabController.state.value.tabs.clear(); } From 7bbeb351ce4eb6c582a7b162b4e415270b86b1be Mon Sep 17 00:00:00 2001 From: Michal Witek Date: Mon, 27 Feb 2023 20:40:39 +0100 Subject: [PATCH 053/382] Updated Flutter Version to `3.7.5` Updated agents OS to `Ubuntu 20.04` where possible --- .github/workflows/flutter-ci.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/flutter-ci.yml b/.github/workflows/flutter-ci.yml index 74e4efa99..cae5b82c7 100644 --- a/.github/workflows/flutter-ci.yml +++ b/.github/workflows/flutter-ci.yml @@ -18,7 +18,7 @@ on: env: LLVM_VERSION: "15.0.6" - FLUTTER_VERSION: "3.7.0" + FLUTTER_VERSION: "3.7.5" # vcpkg version: 2022.05.10 # for multiarch gcc compatibility VCPKG_COMMIT_ID: "14e7bb4ae24616ec54ff6b2f6ef4e8659434ea44" @@ -260,7 +260,7 @@ jobs: job: - { target: x86_64-unknown-linux-gnu, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-args: "", } steps: @@ -330,13 +330,13 @@ jobs: - { arch: x86_64, target: aarch64-linux-android, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-features: "", } # - { # arch: x86_64, # target: armv7-linux-androideabi, - # os: ubuntu-18.04, + # os: ubuntu-20.04, # extra-build-features: "", # } steps: @@ -907,19 +907,19 @@ jobs: - { arch: x86_64, target: x86_64-unknown-linux-gnu, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-features: "", } - { arch: x86_64, target: x86_64-unknown-linux-gnu, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-features: "flatpak", } - { arch: x86_64, target: x86_64-unknown-linux-gnu, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-features: "appimage", } # - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true } From 828c201fe092cc3ac33d61a70288f07b3345ed53 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Mon, 27 Feb 2023 20:56:45 +0100 Subject: [PATCH 054/382] modern file manager delete dialog --- flutter/lib/common.dart | 77 ++++++++++++++-- .../lib/desktop/pages/file_manager_page.dart | 14 --- flutter/lib/models/file_model.dart | 87 +++++++++++-------- 3 files changed, 125 insertions(+), 53 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index a73ab8bd3..3680b0a11 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -202,9 +202,43 @@ class MyTheme { splashFactory: isDesktop ? NoSplash.splashFactory : null, textButtonTheme: isDesktop ? TextButtonThemeData( - style: ButtonStyle(splashFactory: NoSplash.splashFactory), + style: ButtonStyle( + splashFactory: NoSplash.splashFactory, + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18.0), + ), + ), + ), ) : null, + elevatedButtonTheme: ElevatedButtonThemeData( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all( + MyTheme.accent, + ), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18.0), + ), + ), + ), + ), + checkboxTheme: const CheckboxThemeData( + splashRadius: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + ), + ), + listTileTheme: ListTileThemeData( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + ), + ), colorScheme: ColorScheme.fromSwatch( primarySwatch: Colors.blue, ).copyWith( @@ -257,11 +291,44 @@ class MyTheme { OutlinedButton.styleFrom(side: BorderSide(color: Colors.white38))), textButtonTheme: isDesktop ? TextButtonThemeData( - style: ButtonStyle(splashFactory: NoSplash.splashFactory), + style: ButtonStyle( + splashFactory: NoSplash.splashFactory, + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18.0), + ), + ), + ), ) : null, - checkboxTheme: - const CheckboxThemeData(checkColor: MaterialStatePropertyAll(dark)), + elevatedButtonTheme: ElevatedButtonThemeData( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all( + MyTheme.accent, + ), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18.0), + ), + ), + ), + ), + checkboxTheme: const CheckboxThemeData( + checkColor: MaterialStatePropertyAll(dark), + splashRadius: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + ), + ), + listTileTheme: ListTileThemeData( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + ), + ), colorScheme: ColorScheme.fromSwatch( primarySwatch: Colors.blue, ).copyWith( @@ -684,7 +751,7 @@ class CustomAlertDialog extends StatelessWidget { Future.delayed(Duration.zero, () { if (!scopeNode.hasFocus) scopeNode.requestFocus(); }); - const double padding = 16; + const double padding = 30; bool tabTapped = false; return FocusScope( node: scopeNode, diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 31f9e154b..f276961b0 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -1010,25 +1010,11 @@ class _FileManagerPageState extends State MainAxisAlignment.spaceBetween, children: [ ElevatedButton.icon( - style: ButtonStyle( - backgroundColor: - MaterialStateProperty.all( - MyTheme.accent, - ), - shape: buttonShape, - ), icon: Icon(Icons.close_rounded), label: Text(translate("Cancel")), onPressed: cancel, ), ElevatedButton.icon( - style: ButtonStyle( - backgroundColor: - MaterialStateProperty.all( - MyTheme.accent, - ), - shape: buttonShape, - ), icon: Icon(Icons.done_rounded), label: Text(translate("Ok")), onPressed: submit, diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index 5817e54fe..7e702f6f2 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -593,9 +593,11 @@ class FileModel extends ChangeNotifier { ? "${translate("Are you sure you want to delete the file of this directory?")}\n" : ""; final count = entries.length > 1 ? "${i + 1}/${entries.length}" : ""; - content = "$dirShow$count \n${entries[i].path}"; - final confirm = - await showRemoveDialog(title, content, item.isDirectory); + content = "$dirShow\n\n${entries[i].path}".trim(); + final confirm = await showRemoveDialog( + count.isEmpty ? title : "$title ($count)", + content, + item.isDirectory); try { if (confirm == true) { sendRemoveFile(entries[i].path, i, items.isLocal!); @@ -636,42 +638,59 @@ class FileModel extends ChangeNotifier { submit() => close(true); return CustomAlertDialog( title: Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon(Icons.warning, color: Colors.red), - const SizedBox(width: 20), - Text(title) + const Icon(Icons.warning_rounded, color: Colors.red), + Text(title).paddingOnly( + left: 10, + ), ], ), contentBoxConstraints: - BoxConstraints(minHeight: 100, minWidth: 400, maxWidth: 400), + BoxConstraints(minHeight: 80, minWidth: 400, maxWidth: 400), content: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text(content), - const SizedBox(height: 5), - Text(translate("This is irreversible!"), - style: const TextStyle(fontWeight: FontWeight.bold)), - showCheckbox - ? CheckboxListTile( - contentPadding: const EdgeInsets.all(0), - dense: true, - controlAffinity: ListTileControlAffinity.leading, - title: Text( - translate("Do this for all conflicts"), - ), - value: removeCheckboxRemember, - onChanged: (v) { - if (v == null) return; - setState(() => removeCheckboxRemember = v); - }, - ) - : const SizedBox.shrink() - ]), - actions: [ - dialogButton("Cancel", onPressed: cancel, isOutline: true), - dialogButton("OK", onPressed: submit), - ], + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(content), + Text( + translate("This is irreversible!"), + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.red, + ), + ).paddingOnly(top: 20), + showCheckbox + ? CheckboxListTile( + contentPadding: const EdgeInsets.all(0), + dense: true, + controlAffinity: ListTileControlAffinity.leading, + title: Text( + translate("Do this for all conflicts"), + ), + value: removeCheckboxRemember, + onChanged: (v) { + if (v == null) return; + setState(() => removeCheckboxRemember = v); + }, + ) + : const SizedBox.shrink(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ElevatedButton.icon( + icon: Icon(Icons.close_rounded), + label: Text(translate("Cancel")), + onPressed: cancel, + ), + ElevatedButton.icon( + icon: Icon(Icons.done_rounded), + label: Text(translate("Ok")), + onPressed: submit, + ), + ], + ).paddingOnly(top: 20) + ], + ), onSubmit: submit, onCancel: cancel, ); From 0380fc0c9e6235b86af42d99041a55401ea63e13 Mon Sep 17 00:00:00 2001 From: "Miguel F. G" <116861809+flusheDData@users.noreply.github.com> Date: Tue, 28 Feb 2023 00:50:07 +0100 Subject: [PATCH 055/382] 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 af0da0479..a95d39776 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -456,6 +456,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Reconnect", "Reconectar"), ("Codec", "Códec"), ("Resolution", "Resolución"), - ("No transfers in progress", ""), + ("No transfers in progress", "No hay transferencias en curso"), ].iter().cloned().collect(); } From 48100c9e91ed7ac725e8651f5fbc458c4a71613c Mon Sep 17 00:00:00 2001 From: csf Date: Tue, 28 Feb 2023 11:31:30 +0900 Subject: [PATCH 056/382] 1. add _systemAlertWindow and _enableStartOnBoot options. 2. opt settings_page.dart state variables --- .../android/app/src/main/AndroidManifest.xml | 1 + .../com/carriez/flutter_hbb/MainActivity.kt | 20 ++++ .../kotlin/com/carriez/flutter_hbb/common.kt | 9 +- flutter/lib/consts.dart | 6 +- flutter/lib/mobile/pages/settings_page.dart | 101 ++++++++++++++---- 5 files changed, 116 insertions(+), 21 deletions(-) diff --git a/flutter/android/app/src/main/AndroidManifest.xml b/flutter/android/app/src/main/AndroidManifest.xml index 6f646b913..b3c655917 100644 --- a/flutter/android/app/src/main/AndroidManifest.xml +++ b/flutter/android/app/src/main/AndroidManifest.xml @@ -12,6 +12,7 @@ + { + val prefs = getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE) + result.success(prefs.getBoolean(KEY_START_ON_BOOT_OPT, false)) + } + SET_START_ON_BOOT_OPT -> { + try { + if (call.arguments is Boolean) { + val prefs = getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE) + val edit = prefs.edit() + edit.putBoolean(KEY_START_ON_BOOT_OPT, call.arguments as Boolean) + edit.apply() + result.success(true) + } else { + result.success(false) + } + } finally { + result.success(false) + } + } else -> { result.error("-1", "No such method", null) } diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt index 0bc6c1c28..2d53ea010 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt @@ -37,9 +37,14 @@ const val REQ_REQUEST_MEDIA_PROJECTION = 201 const val RES_FAILED = -100 // Flutter channel -const val START_ACTION = "start_action"; -const val IGNORE_BATTERY_OPTIMIZATIONS = "ignore_battery_optimizations"; +const val START_ACTION = "start_action" +const val GET_START_ON_BOOT_OPT = "get_start_on_boot_opt" +const val SET_START_ON_BOOT_OPT = "set_start_on_boot_opt" +const val IGNORE_BATTERY_OPTIMIZATIONS = "ignore_battery_optimizations" + +const val KEY_SHARED_PREFERENCES = "KEY_SHARED_PREFERENCES" +const val KEY_START_ON_BOOT_OPT = "KEY_START_ON_BOOT_OPT" @SuppressLint("ConstantLocale") val LOCAL_NAME = Locale.getDefault().toString() diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index a0766a874..1dc1c0b5a 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -150,7 +150,11 @@ const kSystemAlertWindow = "android.permission.SYSTEM_ALERT_WINDOW"; const kIgnoreBatteryOptimizations = "ignore_battery_optimizations"; /// Android channel invoke type key -const kStartAction = "start_action"; +class AndroidChannel { + static final kStartAction = "start_action"; + static final kGetStartOnBootOpt = "get_start_on_boot_opt"; + static final kSetStartOnBootOpt = "set_start_on_boot_opt"; +} /// flutter/packages/flutter/lib/src/services/keyboard_key.dart -> _keyLabels /// see [LogicalKeyboardKey.keyLabel] diff --git a/flutter/lib/mobile/pages/settings_page.dart b/flutter/lib/mobile/pages/settings_page.dart index 6bdb7e813..0e160396b 100644 --- a/flutter/lib/mobile/pages/settings_page.dart +++ b/flutter/lib/mobile/pages/settings_page.dart @@ -32,18 +32,21 @@ class SettingsPage extends StatefulWidget implements PageShape { } const url = 'https://rustdesk.com/'; -final _hasIgnoreBattery = androidVersion >= 26; -var _ignoreBatteryOpt = false; -var _enableAbr = false; -var _denyLANDiscovery = false; -var _onlyWhiteList = false; -var _enableDirectIPAccess = false; -var _enableRecordSession = false; -var _autoRecordIncomingSession = false; -var _localIP = ""; -var _directAccessPort = ""; class _SettingsState extends State with WidgetsBindingObserver { + final _hasIgnoreBattery = androidVersion >= 26; + var _ignoreBatteryOpt = false; + var _systemAlertWindow = false; + var _enableStartOnBoot = false; + var _enableAbr = false; + var _denyLANDiscovery = false; + var _onlyWhiteList = false; + var _enableDirectIPAccess = false; + var _enableRecordSession = false; + var _autoRecordIncomingSession = false; + var _localIP = ""; + var _directAccessPort = ""; + @override void initState() { super.initState(); @@ -51,11 +54,35 @@ class _SettingsState extends State with WidgetsBindingObserver { () async { var update = false; + if (_hasIgnoreBattery) { - update = await updateIgnoreBatteryStatus(); + if (await checkAndUpdateIgnoreBatteryStatus()) { + update = true; + } } - final enableAbrRes = await bind.mainGetOption(key: "enable-abr") != "N"; + if (await checkAndUpdateSystemAlertWindow()) { + update = true; + } + + // TODO need input + // start on boot depends on ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS and SYSTEM_ALERT_WINDOW + var enableStartOnBoot = + await gFFI.invokeMethod(AndroidChannel.kGetStartOnBootOpt); + if (enableStartOnBoot) { + if (!canStartOnBoot()) { + enableStartOnBoot = false; + gFFI.invokeMethod(AndroidChannel.kSetStartOnBootOpt, false); + } + } + + if (enableStartOnBoot != _enableStartOnBoot) { + update = true; + _enableStartOnBoot = enableStartOnBoot; + } + + final enableAbrRes = option2bool( + "enable-abr", await bind.mainGetOption(key: "enable-abr")); if (enableAbrRes != _enableAbr) { update = true; _enableAbr = enableAbrRes; @@ -126,14 +153,15 @@ class _SettingsState extends State with WidgetsBindingObserver { void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { () async { - if (await updateIgnoreBatteryStatus()) { + if (await checkAndUpdateIgnoreBatteryStatus() || + await checkAndUpdateSystemAlertWindow()) { setState(() {}); } }(); } } - Future updateIgnoreBatteryStatus() async { + Future checkAndUpdateIgnoreBatteryStatus() async { final res = await AndroidPermissionManager.check(kIgnoreBatteryOptimizations); if (_ignoreBatteryOpt != res) { @@ -144,6 +172,16 @@ class _SettingsState extends State with WidgetsBindingObserver { } } + Future checkAndUpdateSystemAlertWindow() async { + final res = await AndroidPermissionManager.check(kSystemAlertWindow); + if (_systemAlertWindow != res) { + _systemAlertWindow = res; + return true; + } else { + return false; + } + } + @override Widget build(BuildContext context) { Provider.of(context); @@ -267,8 +305,8 @@ class _SettingsState extends State with WidgetsBindingObserver { ]), onToggle: (v) async { if (v) { - gFFI.invokeMethod( - kStartAction, kActionRequestIgnoreBatteryOptimizations); + gFFI.invokeMethod(AndroidChannel.kStartAction, + kActionRequestIgnoreBatteryOptimizations); } else { final res = await gFFI.dialogManager .show((setState, close) => CustomAlertDialog( @@ -285,12 +323,27 @@ class _SettingsState extends State with WidgetsBindingObserver { ], )); if (res == true) { - gFFI.invokeMethod( - kStartAction, kActionApplicationDetailsSettings); + gFFI.invokeMethod(AndroidChannel.kStartAction, + kActionApplicationDetailsSettings); } } })); } + enhancementsTiles.add(SettingsTile.switchTile( + initialValue: _enableStartOnBoot, + title: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text("$translate('Start on Boot') (beta)"), + Text( + '* ${translate('Start the screen recording service on boot, which requires special permissions')}', + style: Theme.of(context).textTheme.bodySmall), + ]), + onToggle: (v) async { + if (v) { + // TODO + } else { + gFFI.invokeMethod(AndroidChannel.kSetStartOnBootOpt, false); + } + })); return SettingsList( sections: [ @@ -391,6 +444,18 @@ class _SettingsState extends State with WidgetsBindingObserver { ], ); } + + bool canStartOnBoot() { + // TODO need input + // start on boot depends on ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS and SYSTEM_ALERT_WINDOW + if (_hasIgnoreBattery && !_ignoreBatteryOpt) { + return false; + } + if (!_systemAlertWindow) { + return false; + } + return true; + } } void showServerSettings(OverlayDialogManager dialogManager) async { From eebe3448786b1704d9be4c2b08e9d7de619511da Mon Sep 17 00:00:00 2001 From: Andi Ariffin Date: Tue, 28 Feb 2023 11:57:39 +0700 Subject: [PATCH 057/382] Fix typos causing gen_js_from_hbb.py to fail --- src/lang/en.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/en.rs b/src/lang/en.rs index 3e87cd661..250530013 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -39,8 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("verification_tip", "A new device has been detected, and a verification code has been sent to the registered email address, enter the verification code to continue logging in."), ("software_render_tip", "If you have an Nvidia graphics card and the remote window closes immediately after connecting, installing the nouveau driver and choosing to use software rendering may help. A software restart is required."), ("config_input", "In order to control remote desktop with keyboard, you need to grant RustDesk \"Input Monitoring\" permissions."), - ("request_elevation_tip","You can also request elevation if there is someone on the remote side."), - ("wait_accept_uac_tip","Please wait for the remote user to accept the UAC dialog."), + ("request_elevation_tip", "You can also request elevation if there is someone on the remote side."), + ("wait_accept_uac_tip", "Please wait for the remote user to accept the UAC dialog."), ("still_click_uac_tip", "Still requires the remote user to click OK on the UAC window of running RustDesk."), ("config_microphone", "In order to speak remotely, you need to grant RustDesk \"Record Audio\" permissions."), ("relay_hint_tip", "It may not be possible to connect directly, you can try to connect via relay. \nIn addition, if you want to use relay on your first try, you can add the \"/r\" suffix to the ID, or select the option \"Always connect via relay\" in the peer card."), From 6bd26ef3987db43cadfecb19267262c8d5cf50f1 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Tue, 28 Feb 2023 13:23:27 +0800 Subject: [PATCH 058/382] fix: linux canvas offset --- flutter/lib/models/model.dart | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index fd97b1e5c..cea6785fc 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -731,8 +731,15 @@ class CanvasModel with ChangeNotifier { Size getSize() { final size = MediaQueryData.fromWindow(ui.window).size; // If minimized, w or h may be negative here. - double w = size.width - windowBorderWidth * 2; - double h = size.height - tabBarHeight - windowBorderWidth * 2; + double w = size.width - + windowBorderWidth * 2 - + kDragToResizeAreaPadding.left - + kDragToResizeAreaPadding.right; + double h = size.height - + tabBarHeight - + windowBorderWidth * 2 - + kDragToResizeAreaPadding.top - + kDragToResizeAreaPadding.bottom; return Size(w < 0 ? 0 : w, h < 0 ? 0 : h); } From e26707e55277cfb82644e8b471466ab0fde65994 Mon Sep 17 00:00:00 2001 From: sjpark Date: Tue, 28 Feb 2023 15:47:44 +0900 Subject: [PATCH 059/382] delete unused patch --- Cargo.toml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d768005fe..f93f776a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -166,8 +166,3 @@ panic = 'abort' strip = true #opt-level = 'z' # only have smaller size after strip rpath = true - -[patch."https://github.com/fufesou/rdev"] -#rdev = { path = "../rdev" } -rdev = { git = "https://github.com/sj6219/rdev", branch = "sigma" } - From 8703d23277e66b970d52bb43d7e7d360051e47e4 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 28 Feb 2023 14:50:51 +0800 Subject: [PATCH 060/382] refact canvas position and size Signed-off-by: fufesou --- .../lib/desktop/widgets/remote_menubar.dart | 15 ++++++------ flutter/lib/models/input_model.dart | 4 ++-- flutter/lib/models/model.dart | 24 ++++++++++--------- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index c27546d9f..4b0215703 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -953,12 +953,13 @@ class _DisplayMenuState extends State<_DisplayMenu> { final canvasModel = widget.ffi.canvasModel; final width = (canvasModel.getDisplayWidth() * canvasModel.scale + - canvasModel.windowBorderWidth * 2) * + CanvasModel.leftToEdge + + CanvasModel.rightToEdge) * scale + magicWidth; final height = (canvasModel.getDisplayHeight() * canvasModel.scale + - canvasModel.tabBarHeight + - canvasModel.windowBorderWidth * 2) * + CanvasModel.topToEdge + + CanvasModel.bottomToEdge) * scale + magicHeight; double left = wndRect.left + (wndRect.width - width) / 2; @@ -1027,10 +1028,10 @@ class _DisplayMenuState extends State<_DisplayMenu> { final canvasModel = widget.ffi.canvasModel; final displayWidth = canvasModel.getDisplayWidth(); final displayHeight = canvasModel.getDisplayHeight(); - final requiredWidth = displayWidth + - (canvasModel.tabBarHeight + canvasModel.windowBorderWidth * 2); - final requiredHeight = displayHeight + - (canvasModel.tabBarHeight + canvasModel.windowBorderWidth * 2); + final requiredWidth = + CanvasModel.leftToEdge + displayWidth + CanvasModel.rightToEdge; + final requiredHeight = + CanvasModel.topToEdge + displayHeight + CanvasModel.bottomToEdge; return selfWidth > (requiredWidth * scale) && selfHeight > (requiredHeight * scale); } diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index b91453138..8c6a89377 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -459,8 +459,8 @@ class InputModel { } evt['type'] = type; if (isDesktop) { - y = y - stateGlobal.tabBarHeight - stateGlobal.windowBorderWidth.value; - x -= stateGlobal.windowBorderWidth.value; + y -= CanvasModel.topToEdge; + x -= CanvasModel.leftToEdge; } final canvasModel = parent.target!.canvasModel; final nearThr = 3; diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index cea6785fc..6def57462 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -727,19 +727,21 @@ class CanvasModel with ChangeNotifier { double get scrollX => _scrollX; double get scrollY => _scrollY; + static double get leftToEdge => + windowBorderWidth + kDragToResizeAreaPadding.left; + static double get rightToEdge => + windowBorderWidth + kDragToResizeAreaPadding.right; + static double get topToEdge => + tabBarHeight + windowBorderWidth + kDragToResizeAreaPadding.top; + static double get bottomToEdge => + windowBorderWidth + kDragToResizeAreaPadding.bottom; + updateViewStyle() async { Size getSize() { final size = MediaQueryData.fromWindow(ui.window).size; // If minimized, w or h may be negative here. - double w = size.width - - windowBorderWidth * 2 - - kDragToResizeAreaPadding.left - - kDragToResizeAreaPadding.right; - double h = size.height - - tabBarHeight - - windowBorderWidth * 2 - - kDragToResizeAreaPadding.top - - kDragToResizeAreaPadding.bottom; + double w = size.width - leftToEdge - rightToEdge; + double h = size.height - topToEdge - bottomToEdge; return Size(w < 0 ? 0 : w, h < 0 ? 0 : h); } @@ -813,8 +815,8 @@ class CanvasModel with ChangeNotifier { return parent.target?.ffiModel.display.height ?? defaultHeight; } - double get windowBorderWidth => stateGlobal.windowBorderWidth.value; - double get tabBarHeight => stateGlobal.tabBarHeight; + static double get windowBorderWidth => stateGlobal.windowBorderWidth.value; + static double get tabBarHeight => stateGlobal.tabBarHeight; moveDesktopMouse(double x, double y) { if (size.width == 0 || size.height == 0) { From 409da145c3138ff30c8372d9a88ac2842f467a4b Mon Sep 17 00:00:00 2001 From: rustdesk Date: Tue, 28 Feb 2023 15:23:25 +0800 Subject: [PATCH 061/382] add settings page left side to 200 to conform to main page --- flutter/lib/desktop/pages/desktop_setting_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index e041b591d..52f64c0e3 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -19,7 +19,7 @@ import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart'; import '../../common/widgets/dialog.dart'; import '../../common/widgets/login.dart'; -const double _kTabWidth = 235; +const double _kTabWidth = 200; const double _kTabHeight = 42; const double _kCardFixedWidth = 540; const double _kCardLeftMargin = 15; From 45de6e3f66a7930097f1914aa818eff4091f0db9 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Tue, 28 Feb 2023 15:28:11 +0800 Subject: [PATCH 062/382] update Cargo.lock for new merge --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index a2cdf91a4..8f8895bd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4656,7 +4656,7 @@ dependencies = [ [[package]] name = "rdev" version = "0.5.0-2" -source = "git+https://github.com/fufesou/rdev#5b9fb5e42117f44e0ce0fe7cf2bddf270c75f1dc" +source = "git+https://github.com/fufesou/rdev#25a99ce71ab42843ad253dd51e6a35e83e87a8a4" dependencies = [ "cocoa", "core-foundation 0.9.3", From f65a40f914225052184d1b1b039a7e1b80aff947 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Tue, 28 Feb 2023 16:21:14 +0800 Subject: [PATCH 063/382] chore: try to enable keyboard for scroll, but behavior is strange on mac, #3428 issue --- flutter/lib/desktop/widgets/scroll_wrapper.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/flutter/lib/desktop/widgets/scroll_wrapper.dart b/flutter/lib/desktop/widgets/scroll_wrapper.dart index 32ed149e5..c5bc3394b 100644 --- a/flutter/lib/desktop/widgets/scroll_wrapper.dart +++ b/flutter/lib/desktop/widgets/scroll_wrapper.dart @@ -14,6 +14,7 @@ class DesktopScrollWrapper extends StatelessWidget { return ImprovedScrolling( scrollController: scrollController, enableCustomMouseWheelScrolling: true, + // enableKeyboardScrolling: true, // strange behavior on mac customMouseWheelScrollConfig: CustomMouseWheelScrollConfig( scrollDuration: kDefaultScrollDuration, scrollCurve: Curves.linearToEaseOut, From 1b396d22879f1143f55080e5f19e5888fd355819 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Tue, 28 Feb 2023 17:25:59 +0800 Subject: [PATCH 064/382] opt: scrollbar in night mode --- flutter/lib/common.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 53a401230..023fe7511 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -217,6 +217,9 @@ class MyTheme { tabBarTheme: const TabBarTheme( labelColor: Colors.white70, ), + scrollbarTheme: ScrollbarThemeData( + thumbColor: MaterialStateProperty.all(Colors.grey[500]) + ), splashColor: Colors.transparent, highlightColor: Colors.transparent, splashFactory: isDesktop ? NoSplash.splashFactory : null, From a974fef1e50e456a592a7ea37a6271829d03567e Mon Sep 17 00:00:00 2001 From: mehdi-song Date: Tue, 28 Feb 2023 13:19:02 +0330 Subject: [PATCH 065/382] Update fa.rs --- src/lang/fa.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 0c31e1531..f76567ee5 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -454,8 +454,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "توقف تماس صوتی"), ("relay_hint_tip", " را به شناسه اضافه کنید یا گزینه \"همیشه از طریق رله متصل شوید\" را در کارت همتا انتخاب کنید. همچنین، اگر می‌خواهید فوراً از سرور رله استفاده کنید، می‌توانید پسوند \"/r\".\n اتصال مستقیم ممکن است امکان پذیر نباشد. در این صورت می توانید سعی کنید از طریق سرور رله متصل شوید"), ("Reconnect", "اتصال مجدد"), - ("No transfers in progress", ""), - ("Codec", ""), - ("Resolution", ""), + ("No transfers in progress", "هیچ انتقالی در حال انجام نیست"), + ("Codec", "کدک"), + ("Resolution", "وضوح"), ].iter().cloned().collect(); } From 73bc963311475f8433dfede2f292cd6d05d9e9fc Mon Sep 17 00:00:00 2001 From: csf Date: Tue, 28 Feb 2023 19:46:41 +0900 Subject: [PATCH 066/382] add kActionAccessibilitySettings to manage Input Permission --- flutter/lib/common.dart | 5 +++++ flutter/lib/consts.dart | 2 ++ flutter/lib/mobile/pages/settings_page.dart | 4 ++-- flutter/lib/models/server_model.dart | 10 +++------- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 41ac595f2..89b2c1b28 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -926,6 +926,11 @@ class AndroidPermissionManager { return gFFI.invokeMethod("check_permission", type); } + // startActivity goto Android Setting's page to request permission manually by user + static void startAction(String action) { + gFFI.invokeMethod(AndroidChannel.kStartAction, action); + } + static Future request(String type) { if (isDesktop) { return Future.value(true); diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 1dc1c0b5a..3edafbf62 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -142,6 +142,8 @@ const kActionApplicationDetailsSettings = "android.settings.APPLICATION_DETAILS_SETTINGS"; const kActionRequestIgnoreBatteryOptimizations = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; +const kActionAccessibilitySettings = "android.settings.ACCESSIBILITY_SETTINGS"; + const kRecordAudio = "android.permission.RECORD_AUDIO"; const kManageExternalStorage = "android.permission.MANAGE_EXTERNAL_STORAGE"; const kSystemAlertWindow = "android.permission.SYSTEM_ALERT_WINDOW"; diff --git a/flutter/lib/mobile/pages/settings_page.dart b/flutter/lib/mobile/pages/settings_page.dart index 0e160396b..397c117f7 100644 --- a/flutter/lib/mobile/pages/settings_page.dart +++ b/flutter/lib/mobile/pages/settings_page.dart @@ -305,7 +305,7 @@ class _SettingsState extends State with WidgetsBindingObserver { ]), onToggle: (v) async { if (v) { - gFFI.invokeMethod(AndroidChannel.kStartAction, + AndroidPermissionManager.startAction( kActionRequestIgnoreBatteryOptimizations); } else { final res = await gFFI.dialogManager @@ -323,7 +323,7 @@ class _SettingsState extends State with WidgetsBindingObserver { ], )); if (res == true) { - gFFI.invokeMethod(AndroidChannel.kStartAction, + AndroidPermissionManager.startAction( kActionApplicationDetailsSettings); } } diff --git a/flutter/lib/models/server_model.dart b/flutter/lib/models/server_model.dart index 433990a2a..7ee23ec40 100644 --- a/flutter/lib/models/server_model.dart +++ b/flutter/lib/models/server_model.dart @@ -234,7 +234,7 @@ class ServerModel with ChangeNotifier { if (!_audioOk && !await AndroidPermissionManager.check(kRecordAudio)) { final res = await AndroidPermissionManager.request(kRecordAudio); if (!res) { - // TODO handle fail + showToast(translate('Failed')); return; } } @@ -250,7 +250,7 @@ class ServerModel with ChangeNotifier { final res = await AndroidPermissionManager.request(kManageExternalStorage); if (!res) { - // TODO handle fail + showToast(translate('Failed')); return; } } @@ -348,10 +348,6 @@ class ServerModel with ChangeNotifier { } } - Future initInput() async { - await parent.target?.invokeMethod("init_input"); - } - Future setPermanentPassword(String newPW) async { await bind.mainSetPermanentPassword(password: newPW); await Future.delayed(Duration(milliseconds: 500)); @@ -689,7 +685,7 @@ String getLoginDialogTag(int id) { showInputWarnAlert(FFI ffi) { ffi.dialogManager.show((setState, close) { submit() { - ffi.serverModel.initInput(); + AndroidPermissionManager.startAction(kActionAccessibilitySettings); close(); } From a071700cc7c77e9fa50bf44341a4e8eb3796d6a9 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Tue, 28 Feb 2023 19:25:14 +0800 Subject: [PATCH 067/382] fix build.py for mac --- build.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.py b/build.py index b30f76f95..8d64553c2 100755 --- a/build.py +++ b/build.py @@ -317,11 +317,11 @@ def build_flutter_dmg(version, features): "cp target/release/liblibrustdesk.dylib target/release/librustdesk.dylib") # ffi_bindgen_function_refactor() # limitations from flutter rust bridge - system2('sed -i "" "s/char \*\*rustdesk_core_main(int \*args_len);//" flutter/macos/Runner/bridge_generated.h') + system2('sed -i "s/char \*\*rustdesk_core_main(int \*args_len);//" flutter/macos/Runner/bridge_generated.h') os.chdir('flutter') system2('flutter build macos --release') system2( - "create-dmg rustdesk.dmg ./build/macos/Build/Products/Release/RustDesk.app") + "create-dmg --volname \"RustDesk Installer\" --window-pos 200 120 --window-size 800 400 --icon-size 100 --app-drop-link 600 185 --icon RustDesk.app 200 190 --hide-extension RustDesk.app rustdesk.dmg ./build/macos/Build/Products/Release/RustDesk.app") os.rename("rustdesk.dmg", f"../rustdesk-{version}.dmg") os.chdir("..") From 60ab29ad6e9ec80b9ce50abb073ac6bc384f8230 Mon Sep 17 00:00:00 2001 From: csf Date: Tue, 28 Feb 2023 21:02:42 +0900 Subject: [PATCH 068/382] 1. use XXPermissions to manage REQUEST_IGNORE_BATTERY_OPTIMIZATIONS. 2. pre-request permission on Start on Boot enabled. --- .../com/carriez/flutter_hbb/MainActivity.kt | 14 +------ .../kotlin/com/carriez/flutter_hbb/common.kt | 17 +++----- flutter/lib/common.dart | 13 ++++--- flutter/lib/consts.dart | 7 +--- flutter/lib/mobile/pages/settings_page.dart | 39 +++++++++++++------ 5 files changed, 43 insertions(+), 47 deletions(-) diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt index 126e169da..e4b42cf08 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt @@ -18,6 +18,7 @@ import android.provider.Settings import android.util.Log import android.view.WindowManager import androidx.annotation.RequiresApi +import com.hjq.permissions.XXPermissions import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel @@ -76,7 +77,7 @@ class MainActivity : FlutterActivity() { } "check_permission" -> { if (call.arguments is String) { - result.success(checkPermission(context, call.arguments as String)) + result.success(XXPermissions.isGranted(context, call.arguments as String)) } else { result.success(false) } @@ -115,10 +116,6 @@ class MainActivity : FlutterActivity() { ) result.success(true) } - "init_input" -> { - initInput() - result.success(true) - } "stop_input" -> { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { InputService.ctx?.disableSelf() @@ -177,13 +174,6 @@ class MainActivity : FlutterActivity() { } } - private fun initInput() { - val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS) - if (intent.resolveActivity(packageManager) != null) { - startActivity(intent) - } - } - override fun onResume() { super.onResume() val inputPer = InputService.isOpen diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt index 2d53ea010..0c34c2223 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt @@ -13,6 +13,7 @@ import android.os.Build import android.os.Handler import android.os.Looper import android.os.PowerManager +import android.provider.Settings import android.provider.Settings.* import androidx.annotation.RequiresApi import androidx.core.content.ContextCompat.getSystemService @@ -41,8 +42,6 @@ const val START_ACTION = "start_action" const val GET_START_ON_BOOT_OPT = "get_start_on_boot_opt" const val SET_START_ON_BOOT_OPT = "set_start_on_boot_opt" -const val IGNORE_BATTERY_OPTIMIZATIONS = "ignore_battery_optimizations" - const val KEY_SHARED_PREFERENCES = "KEY_SHARED_PREFERENCES" const val KEY_START_ON_BOOT_OPT = "KEY_START_ON_BOOT_OPT" @@ -70,21 +69,15 @@ fun requestPermission(context: Context, type: String) { } } -@RequiresApi(Build.VERSION_CODES.M) -fun checkPermission(context: Context, type: String): Boolean { - if (IGNORE_BATTERY_OPTIMIZATIONS == type) { - val pw = context.getSystemService(Context.POWER_SERVICE) as PowerManager - return pw.isIgnoringBatteryOptimizations(context.packageName) - } - return XXPermissions.isGranted(context, type) -} - @RequiresApi(Build.VERSION_CODES.M) fun startAction(context: Context, action: String) { try { context.startActivity(Intent(action).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - data = Uri.parse("package:" + context.packageName) + // don't pass package name when launch ACTION_ACCESSIBILITY_SETTINGS + if (ACTION_ACCESSIBILITY_SETTINGS != action) { + data = Uri.parse("package:" + context.packageName) + } }) } catch (e: Exception) { e.printStackTrace() diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 89b2c1b28..155fcc743 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -931,6 +931,8 @@ class AndroidPermissionManager { gFFI.invokeMethod(AndroidChannel.kStartAction, action); } + /// We use XXPermissions to request permissions, + /// for supported types, see https://github.com/getActivity/XXPermissions/blob/e46caea32a64ad7819df62d448fb1c825481cd28/library/src/main/java/com/hjq/permissions/Permission.java static Future request(String type) { if (isDesktop) { return Future.value(true); @@ -938,17 +940,16 @@ class AndroidPermissionManager { gFFI.invokeMethod("request_permission", type); - // kIgnoreBatteryOptimizations permission doesn't depend on callback result, the result will be checked and updated on page resume - if (type == kIgnoreBatteryOptimizations) { - return Future.value(false); + // clear last task + if (_completer?.isCompleted == false) { + _completer?.complete(false); } + _timer?.cancel(); _current = type; _completer = Completer(); - // timeout - _timer?.cancel(); - _timer = Timer(Duration(seconds: 60), () { + _timer = Timer(Duration(seconds: 120), () { if (_completer == null) return; if (!_completer!.isCompleted) { _completer!.complete(false); diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 3edafbf62..b075ee76f 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -140,17 +140,14 @@ const kIgnoreDpi = true; /// Android constants const kActionApplicationDetailsSettings = "android.settings.APPLICATION_DETAILS_SETTINGS"; -const kActionRequestIgnoreBatteryOptimizations = - "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; const kActionAccessibilitySettings = "android.settings.ACCESSIBILITY_SETTINGS"; const kRecordAudio = "android.permission.RECORD_AUDIO"; const kManageExternalStorage = "android.permission.MANAGE_EXTERNAL_STORAGE"; +const kRequestIgnoreBatteryOptimizations = + "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; const kSystemAlertWindow = "android.permission.SYSTEM_ALERT_WINDOW"; -/// [kIgnoreBatteryOptimizations] not a Android Permission, it is a custom key, used in `ignore battery optimizations` check -const kIgnoreBatteryOptimizations = "ignore_battery_optimizations"; - /// Android channel invoke type key class AndroidChannel { static final kStartAction = "start_action"; diff --git a/flutter/lib/mobile/pages/settings_page.dart b/flutter/lib/mobile/pages/settings_page.dart index 397c117f7..d4887bb58 100644 --- a/flutter/lib/mobile/pages/settings_page.dart +++ b/flutter/lib/mobile/pages/settings_page.dart @@ -65,7 +65,6 @@ class _SettingsState extends State with WidgetsBindingObserver { update = true; } - // TODO need input // start on boot depends on ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS and SYSTEM_ALERT_WINDOW var enableStartOnBoot = await gFFI.invokeMethod(AndroidChannel.kGetStartOnBootOpt); @@ -162,8 +161,8 @@ class _SettingsState extends State with WidgetsBindingObserver { } Future checkAndUpdateIgnoreBatteryStatus() async { - final res = - await AndroidPermissionManager.check(kIgnoreBatteryOptimizations); + final res = await AndroidPermissionManager.check( + kRequestIgnoreBatteryOptimizations); if (_ignoreBatteryOpt != res) { _ignoreBatteryOpt = res; return true; @@ -305,8 +304,8 @@ class _SettingsState extends State with WidgetsBindingObserver { ]), onToggle: (v) async { if (v) { - AndroidPermissionManager.startAction( - kActionRequestIgnoreBatteryOptimizations); + await AndroidPermissionManager.request( + kRequestIgnoreBatteryOptimizations); } else { final res = await gFFI.dialogManager .show((setState, close) => CustomAlertDialog( @@ -332,17 +331,34 @@ class _SettingsState extends State with WidgetsBindingObserver { enhancementsTiles.add(SettingsTile.switchTile( initialValue: _enableStartOnBoot, title: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("$translate('Start on Boot') (beta)"), + Text("${translate('Start on Boot')} (beta)"), Text( '* ${translate('Start the screen recording service on boot, which requires special permissions')}', style: Theme.of(context).textTheme.bodySmall), ]), - onToggle: (v) async { - if (v) { - // TODO - } else { - gFFI.invokeMethod(AndroidChannel.kSetStartOnBootOpt, false); + onToggle: (toValue) async { + if (toValue) { + // 1. request kIgnoreBatteryOptimizations + if (!await AndroidPermissionManager.check( + kRequestIgnoreBatteryOptimizations)) { + if (!await AndroidPermissionManager.request( + kRequestIgnoreBatteryOptimizations)) { + return; + } + } + + // 2. request kSystemAlertWindow + if (!await AndroidPermissionManager.check(kSystemAlertWindow)) { + if (!await AndroidPermissionManager.request(kSystemAlertWindow)) { + return; + } + } + + // (Optional) 3. request input permission } + setState(() => _enableStartOnBoot = toValue); + + gFFI.invokeMethod(AndroidChannel.kSetStartOnBootOpt, toValue); })); return SettingsList( @@ -446,7 +462,6 @@ class _SettingsState extends State with WidgetsBindingObserver { } bool canStartOnBoot() { - // TODO need input // start on boot depends on ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS and SYSTEM_ALERT_WINDOW if (_hasIgnoreBattery && !_ignoreBatteryOpt) { return false; From fe262abc5d75f1bc92829680314190ca13a7052e Mon Sep 17 00:00:00 2001 From: rustdesk Date: Tue, 28 Feb 2023 20:15:14 +0800 Subject: [PATCH 069/382] remove useless code --- build.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/build.py b/build.py index 8d64553c2..45fe1b132 100755 --- a/build.py +++ b/build.py @@ -315,9 +315,6 @@ def build_flutter_dmg(version, features): # copy dylib system2( "cp target/release/liblibrustdesk.dylib target/release/librustdesk.dylib") - # ffi_bindgen_function_refactor() - # limitations from flutter rust bridge - system2('sed -i "s/char \*\*rustdesk_core_main(int \*args_len);//" flutter/macos/Runner/bridge_generated.h') os.chdir('flutter') system2('flutter build macos --release') system2( From 836249d34cd01277b3d851a62f104cca9c9a600b Mon Sep 17 00:00:00 2001 From: csf Date: Tue, 28 Feb 2023 21:48:40 +0900 Subject: [PATCH 070/382] refactor initFlutterChannel --- .../com/carriez/flutter_hbb/MainActivity.kt | 255 +++++++++--------- .../kotlin/com/carriez/flutter_hbb/common.kt | 2 - 2 files changed, 125 insertions(+), 132 deletions(-) diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt index e4b42cf08..be8c857ce 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt @@ -13,8 +13,6 @@ import android.content.Intent import android.content.ServiceConnection import android.os.Build import android.os.IBinder -import android.preference.PreferenceManager -import android.provider.Settings import android.util.Log import android.view.WindowManager import androidx.annotation.RequiresApi @@ -44,134 +42,8 @@ class MainActivity : FlutterActivity() { flutterMethodChannel = MethodChannel( flutterEngine.dartExecutor.binaryMessenger, channelTag - ).apply { - // make sure result is set, otherwise flutter will await forever - setMethodCallHandler { call, result -> - when (call.method) { - "init_service" -> { - Intent(activity, MainService::class.java).also { - bindService(it, serviceConnection, Context.BIND_AUTO_CREATE) - } - if (MainService.isReady) { - result.success(false) - return@setMethodCallHandler - } - requestMediaProjection() - result.success(true) - } - "start_capture" -> { - mainService?.let { - result.success(it.startCapture()) - } ?: let { - result.success(false) - } - } - "stop_service" -> { - Log.d(logTag, "Stop service") - mainService?.let { - it.destroy() - result.success(true) - } ?: let { - result.success(false) - } - } - "check_permission" -> { - if (call.arguments is String) { - result.success(XXPermissions.isGranted(context, call.arguments as String)) - } else { - result.success(false) - } - } - "request_permission" -> { - if (call.arguments is String) { - requestPermission(context, call.arguments as String) - result.success(true) - } else { - result.success(false) - } - } - START_ACTION -> { - if (call.arguments is String) { - startAction(context, call.arguments as String) - result.success(true) - } else { - result.success(false) - } - } - "check_video_permission" -> { - mainService?.let { - result.success(it.checkMediaPermission()) - } ?: let { - result.success(false) - } - } - "check_service" -> { - flutterMethodChannel.invokeMethod( - "on_state_changed", - mapOf("name" to "input", "value" to InputService.isOpen.toString()) - ) - flutterMethodChannel.invokeMethod( - "on_state_changed", - mapOf("name" to "media", "value" to MainService.isReady.toString()) - ) - result.success(true) - } - "stop_input" -> { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - InputService.ctx?.disableSelf() - } - InputService.ctx = null - flutterMethodChannel.invokeMethod( - "on_state_changed", - mapOf("name" to "input", "value" to InputService.isOpen.toString()) - ) - result.success(true) - } - "cancel_notification" -> { - try { - val id = call.arguments as Int - mainService?.cancelNotification(id) - } finally { - result.success(true) - } - } - "enable_soft_keyboard" -> { - // https://blog.csdn.net/hanye2020/article/details/105553780 - try { - if (call.arguments as Boolean) { - window.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) - } else { - window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) - } - } finally { - result.success(true) - } - } - GET_START_ON_BOOT_OPT -> { - val prefs = getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE) - result.success(prefs.getBoolean(KEY_START_ON_BOOT_OPT, false)) - } - SET_START_ON_BOOT_OPT -> { - try { - if (call.arguments is Boolean) { - val prefs = getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE) - val edit = prefs.edit() - edit.putBoolean(KEY_START_ON_BOOT_OPT, call.arguments as Boolean) - edit.apply() - result.success(true) - } else { - result.success(false) - } - } finally { - result.success(false) - } - } - else -> { - result.error("-1", "No such method", null) - } - } - } - } + ) + initFlutterChannel(flutterMethodChannel) } override fun onResume() { @@ -219,4 +91,127 @@ class MainActivity : FlutterActivity() { mainService = null } } + + private fun initFlutterChannel(flutterMethodChannel: MethodChannel) { + flutterMethodChannel.setMethodCallHandler { call, result -> + // make sure result will be invoked, otherwise flutter will await forever + when (call.method) { + "init_service" -> { + Intent(activity, MainService::class.java).also { + bindService(it, serviceConnection, Context.BIND_AUTO_CREATE) + } + if (MainService.isReady) { + result.success(false) + return@setMethodCallHandler + } + requestMediaProjection() + result.success(true) + } + "start_capture" -> { + mainService?.let { + result.success(it.startCapture()) + } ?: let { + result.success(false) + } + } + "stop_service" -> { + Log.d(logTag, "Stop service") + mainService?.let { + it.destroy() + result.success(true) + } ?: let { + result.success(false) + } + } + "check_permission" -> { + if (call.arguments is String) { + result.success(XXPermissions.isGranted(context, call.arguments as String)) + } else { + result.success(false) + } + } + "request_permission" -> { + if (call.arguments is String) { + requestPermission(context, call.arguments as String) + result.success(true) + } else { + result.success(false) + } + } + START_ACTION -> { + if (call.arguments is String) { + startAction(context, call.arguments as String) + result.success(true) + } else { + result.success(false) + } + } + "check_video_permission" -> { + mainService?.let { + result.success(it.checkMediaPermission()) + } ?: let { + result.success(false) + } + } + "check_service" -> { + Companion.flutterMethodChannel.invokeMethod( + "on_state_changed", + mapOf("name" to "input", "value" to InputService.isOpen.toString()) + ) + Companion.flutterMethodChannel.invokeMethod( + "on_state_changed", + mapOf("name" to "media", "value" to MainService.isReady.toString()) + ) + result.success(true) + } + "stop_input" -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + InputService.ctx?.disableSelf() + } + InputService.ctx = null + Companion.flutterMethodChannel.invokeMethod( + "on_state_changed", + mapOf("name" to "input", "value" to InputService.isOpen.toString()) + ) + result.success(true) + } + "cancel_notification" -> { + if (call.arguments is Int) { + val id = call.arguments as Int + mainService?.cancelNotification(id) + } else { + result.success(true) + } + } + "enable_soft_keyboard" -> { + // https://blog.csdn.net/hanye2020/article/details/105553780 + if (call.arguments as Boolean) { + window.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) + } else { + window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) + } + result.success(true) + + } + GET_START_ON_BOOT_OPT -> { + val prefs = getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE) + result.success(prefs.getBoolean(KEY_START_ON_BOOT_OPT, false)) + } + SET_START_ON_BOOT_OPT -> { + if (call.arguments is Boolean) { + val prefs = getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE) + val edit = prefs.edit() + edit.putBoolean(KEY_START_ON_BOOT_OPT, call.arguments as Boolean) + edit.apply() + result.success(true) + } else { + result.success(false) + } + } + else -> { + result.error("-1", "No such method", null) + } + } + } + } } diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt index 0c34c2223..6970fd137 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt @@ -53,7 +53,6 @@ data class Info( var width: Int, var height: Int, var scale: Int, var dpi: Int ) -@RequiresApi(Build.VERSION_CODES.M) fun requestPermission(context: Context, type: String) { XXPermissions.with(context) .permission(type) @@ -69,7 +68,6 @@ fun requestPermission(context: Context, type: String) { } } -@RequiresApi(Build.VERSION_CODES.M) fun startAction(context: Context, action: String) { try { context.startActivity(Intent(action).apply { From bf0e0d20c308246f266590a04dee14b8ffc45a9f Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Tue, 28 Feb 2023 14:08:55 +0100 Subject: [PATCH 071/382] improved readability --- flutter/lib/common.dart | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 3680b0a11..29d4a195d 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -170,8 +170,13 @@ class MyTheme { scaffoldBackgroundColor: Color(0xFFFFFFFF), dialogBackgroundColor: Color(0xFFFFFFFF), dialogTheme: DialogTheme( + elevation: 15, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(18.0), + side: BorderSide( + width: 1, + color: Color(0xFFEEEEEE), + ), ), ), inputDecorationTheme: InputDecorationTheme( @@ -257,8 +262,13 @@ class MyTheme { scaffoldBackgroundColor: Color(0xFF18191E), dialogBackgroundColor: Color(0xFF18191E), dialogTheme: DialogTheme( + elevation: 15, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(18.0), + side: BorderSide( + width: 1, + color: Color(0xFF24252B), + ), ), ), inputDecorationTheme: InputDecorationTheme( @@ -559,7 +569,7 @@ class OverlayDialogManager { BackButtonInterceptor.removeByName(dialogTag); } - dialog.entry = OverlayEntry(builder: (_) { + dialog.entry = OverlayEntry(builder: (context) { bool innerClicked = false; return Listener( onPointerUp: (_) { @@ -569,7 +579,9 @@ class OverlayDialogManager { innerClicked = false; }, child: Container( - color: Colors.black12, + color: Theme.of(context).brightness == Brightness.light + ? Colors.black12 + : Colors.black45, child: StatefulBuilder(builder: (context, setState) { return Listener( onPointerUp: (_) => innerClicked = true, From 561d2bfb1f870ee34c645148ff9f8a1dd8ead900 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Tue, 28 Feb 2023 14:10:36 +0100 Subject: [PATCH 072/382] removed useless buttonShape --- flutter/lib/desktop/pages/file_manager_page.dart | 6 ------ 1 file changed, 6 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index f276961b0..9210a30c1 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -49,11 +49,6 @@ enum MouseFocusScope { none } -final buttonShape = - MaterialStateProperty.all(RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18.0), -)); - class FileManagerPage extends StatefulWidget { const FileManagerPage({Key? key, required this.id, this.forceRelay}) : super(key: key); @@ -1066,7 +1061,6 @@ class _FileManagerPageState extends State ? MyTheme.accent80 : MyTheme.accent, ), - shape: buttonShape, ), onPressed: validItems(selectedItems) ? () { From baea9e529d5b32740014a55c6b4fb769f8614cf4 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Tue, 28 Feb 2023 14:21:27 +0100 Subject: [PATCH 073/382] modern rename peer dialog --- flutter/lib/common/widgets/peer_card.dart | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/flutter/lib/common/widgets/peer_card.dart b/flutter/lib/common/widgets/peer_card.dart index a69fc3bbe..1d3a18c7c 100644 --- a/flutter/lib/common/widgets/peer_card.dart +++ b/flutter/lib/common/widgets/peer_card.dart @@ -682,21 +682,30 @@ abstract class BasePeerCard extends StatelessWidget { child: TextFormField( controller: controller, autofocus: true, - decoration: InputDecoration( - border: OutlineInputBorder(), - labelText: translate('Name')), + decoration: InputDecoration(labelText: translate('Name')), ), ), ), Obx(() => Offstage( offstage: isInProgress.isFalse, child: const LinearProgressIndicator())), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ElevatedButton.icon( + icon: Icon(Icons.close_rounded), + label: Text(translate("Cancel")), + onPressed: close, + ), + ElevatedButton.icon( + icon: Icon(Icons.done_rounded), + label: Text(translate("Ok")), + onPressed: submit, + ), + ], + ).paddingOnly(top: 20) ], ), - actions: [ - dialogButton("Cancel", onPressed: close, isOutline: true), - dialogButton("OK", onPressed: submit), - ], onSubmit: submit, onCancel: close, ); From 660d6ff2302e4ad3a3a4091e267a066eef620693 Mon Sep 17 00:00:00 2001 From: csf Date: Tue, 28 Feb 2023 22:26:47 +0900 Subject: [PATCH 074/382] 1. fix check boot on start opt. 2. fix late var flutterMethodChannel --- .../com/carriez/flutter_hbb/BootReceiver.kt | 16 +++++++++++++ .../com/carriez/flutter_hbb/MainActivity.kt | 14 +++++------ .../com/carriez/flutter_hbb/MainService.kt | 4 ++-- .../kotlin/com/carriez/flutter_hbb/common.kt | 2 +- flutter/lib/mobile/pages/settings_page.dart | 24 ++++++++++--------- 5 files changed, 39 insertions(+), 21 deletions(-) diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt index a49dcc326..8f6767e58 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt @@ -1,11 +1,15 @@ package com.carriez.flutter_hbb +import android.Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS +import android.Manifest.permission.SYSTEM_ALERT_WINDOW import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.os.Build import android.util.Log import android.widget.Toast +import com.hjq.permissions.XXPermissions +import io.flutter.embedding.android.FlutterActivity const val DEBUG_BOOT_COMPLETED = "com.carriez.flutter_hbb.DEBUG_BOOT_COMPLETED" @@ -16,6 +20,18 @@ class BootReceiver : BroadcastReceiver() { Log.d(logTag, "onReceive ${intent.action}") if (Intent.ACTION_BOOT_COMPLETED == intent.action || DEBUG_BOOT_COMPLETED == intent.action) { + // check SharedPreferences config + val prefs = context.getSharedPreferences(KEY_SHARED_PREFERENCES, FlutterActivity.MODE_PRIVATE) + if (!prefs.getBoolean(KEY_START_ON_BOOT_OPT, false)) { + Log.d(logTag, "KEY_START_ON_BOOT_OPT is false") + return + } + // check pre-permission + if (!XXPermissions.isGranted(context, REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, SYSTEM_ALERT_WINDOW)){ + Log.d(logTag, "REQUEST_IGNORE_BATTERY_OPTIMIZATIONS or SYSTEM_ALERT_WINDOW is not granted") + return + } + val it = Intent(context, MainService::class.java).apply { action = ACT_INIT_MEDIA_PROJECTION_AND_SERVICE } diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt index be8c857ce..79fb60790 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt @@ -24,7 +24,7 @@ import io.flutter.plugin.common.MethodChannel class MainActivity : FlutterActivity() { companion object { - lateinit var flutterMethodChannel: MethodChannel + var flutterMethodChannel: MethodChannel? = null } private val channelTag = "mChannel" @@ -43,14 +43,14 @@ class MainActivity : FlutterActivity() { flutterEngine.dartExecutor.binaryMessenger, channelTag ) - initFlutterChannel(flutterMethodChannel) + initFlutterChannel(flutterMethodChannel!!) } override fun onResume() { super.onResume() val inputPer = InputService.isOpen activity.runOnUiThread { - flutterMethodChannel.invokeMethod( + flutterMethodChannel?.invokeMethod( "on_state_changed", mapOf("name" to "input", "value" to inputPer.toString()) ) @@ -67,7 +67,7 @@ class MainActivity : FlutterActivity() { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQ_INVOKE_PERMISSION_ACTIVITY_MEDIA_PROJECTION && resultCode == RES_FAILED) { - flutterMethodChannel.invokeMethod("on_media_projection_canceled", null) + flutterMethodChannel?.invokeMethod("on_media_projection_canceled", null) } } @@ -154,11 +154,11 @@ class MainActivity : FlutterActivity() { } } "check_service" -> { - Companion.flutterMethodChannel.invokeMethod( + Companion.flutterMethodChannel?.invokeMethod( "on_state_changed", mapOf("name" to "input", "value" to InputService.isOpen.toString()) ) - Companion.flutterMethodChannel.invokeMethod( + Companion.flutterMethodChannel?.invokeMethod( "on_state_changed", mapOf("name" to "media", "value" to MainService.isReady.toString()) ) @@ -169,7 +169,7 @@ class MainActivity : FlutterActivity() { InputService.ctx?.disableSelf() } InputService.ctx = null - Companion.flutterMethodChannel.invokeMethod( + Companion.flutterMethodChannel?.invokeMethod( "on_state_changed", mapOf("name" to "input", "value" to InputService.isOpen.toString()) ) diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt index e28311964..e323d2951 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt @@ -409,13 +409,13 @@ class MainService : Service() { fun checkMediaPermission(): Boolean { Handler(Looper.getMainLooper()).post { - MainActivity.flutterMethodChannel.invokeMethod( + MainActivity.flutterMethodChannel?.invokeMethod( "on_state_changed", mapOf("name" to "media", "value" to isReady.toString()) ) } Handler(Looper.getMainLooper()).post { - MainActivity.flutterMethodChannel.invokeMethod( + MainActivity.flutterMethodChannel?.invokeMethod( "on_state_changed", mapOf("name" to "input", "value" to InputService.isOpen.toString()) ) diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt index 6970fd137..bd91d582c 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt @@ -59,7 +59,7 @@ fun requestPermission(context: Context, type: String) { .request { _, all -> if (all) { Handler(Looper.getMainLooper()).post { - MainActivity.flutterMethodChannel.invokeMethod( + MainActivity.flutterMethodChannel?.invokeMethod( "on_android_permission_result", mapOf("type" to type, "result" to all) ) diff --git a/flutter/lib/mobile/pages/settings_page.dart b/flutter/lib/mobile/pages/settings_page.dart index d4887bb58..e54f66ffb 100644 --- a/flutter/lib/mobile/pages/settings_page.dart +++ b/flutter/lib/mobile/pages/settings_page.dart @@ -36,7 +36,6 @@ const url = 'https://rustdesk.com/'; class _SettingsState extends State with WidgetsBindingObserver { final _hasIgnoreBattery = androidVersion >= 26; var _ignoreBatteryOpt = false; - var _systemAlertWindow = false; var _enableStartOnBoot = false; var _enableAbr = false; var _denyLANDiscovery = false; @@ -61,7 +60,7 @@ class _SettingsState extends State with WidgetsBindingObserver { } } - if (await checkAndUpdateSystemAlertWindow()) { + if (await checkAndUpdateStartOnBoot()) { update = true; } @@ -69,7 +68,7 @@ class _SettingsState extends State with WidgetsBindingObserver { var enableStartOnBoot = await gFFI.invokeMethod(AndroidChannel.kGetStartOnBootOpt); if (enableStartOnBoot) { - if (!canStartOnBoot()) { + if (!await canStartOnBoot()) { enableStartOnBoot = false; gFFI.invokeMethod(AndroidChannel.kSetStartOnBootOpt, false); } @@ -152,8 +151,9 @@ class _SettingsState extends State with WidgetsBindingObserver { void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { () async { - if (await checkAndUpdateIgnoreBatteryStatus() || - await checkAndUpdateSystemAlertWindow()) { + final ibs = await checkAndUpdateIgnoreBatteryStatus(); + final sob = await checkAndUpdateStartOnBoot(); + if (ibs || sob) { setState(() {}); } }(); @@ -171,10 +171,12 @@ class _SettingsState extends State with WidgetsBindingObserver { } } - Future checkAndUpdateSystemAlertWindow() async { - final res = await AndroidPermissionManager.check(kSystemAlertWindow); - if (_systemAlertWindow != res) { - _systemAlertWindow = res; + Future checkAndUpdateStartOnBoot() async { + if (!await canStartOnBoot() && _enableStartOnBoot) { + _enableStartOnBoot = false; + debugPrint( + "checkAndUpdateStartOnBoot and set _enableStartOnBoot -> false"); + gFFI.invokeMethod(AndroidChannel.kSetStartOnBootOpt, false); return true; } else { return false; @@ -461,12 +463,12 @@ class _SettingsState extends State with WidgetsBindingObserver { ); } - bool canStartOnBoot() { + Future canStartOnBoot() async { // start on boot depends on ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS and SYSTEM_ALERT_WINDOW if (_hasIgnoreBattery && !_ignoreBatteryOpt) { return false; } - if (!_systemAlertWindow) { + if (!await AndroidPermissionManager.check(kSystemAlertWindow)) { return false; } return true; From be2fa3e4443c3a12af5bc3541757878ce1389232 Mon Sep 17 00:00:00 2001 From: csf Date: Tue, 28 Feb 2023 22:32:51 +0900 Subject: [PATCH 075/382] fix restart service crash --- .../app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt index e323d2951..6b6169c61 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt @@ -278,6 +278,7 @@ class MainService : Service() { Log.d("whichService", "this service: ${Thread.currentThread()}") super.onStartCommand(intent, flags, startId) if (intent?.action == ACT_INIT_MEDIA_PROJECTION_AND_SERVICE) { + createForegroundNotification() Log.d(logTag, "service starting: ${startId}:${Thread.currentThread()}") val mediaProjectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager From 20c7075ddb06c102b70e780017e144c24bf8779e Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 28 Feb 2023 15:30:46 +0800 Subject: [PATCH 076/382] mobile, canvas size Signed-off-by: fufesou --- flutter/lib/models/input_model.dart | 6 ++---- flutter/lib/models/model.dart | 20 ++++++++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index 8c6a89377..df9ad2585 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -458,10 +458,8 @@ class InputModel { return; } evt['type'] = type; - if (isDesktop) { - y -= CanvasModel.topToEdge; - x -= CanvasModel.leftToEdge; - } + y -= CanvasModel.topToEdge; + x -= CanvasModel.leftToEdge; final canvasModel = parent.target!.canvasModel; final nearThr = 3; var nearRight = (canvasModel.size.width - x) < nearThr; diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 6def57462..802a18a52 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -727,14 +727,18 @@ class CanvasModel with ChangeNotifier { double get scrollX => _scrollX; double get scrollY => _scrollY; - static double get leftToEdge => - windowBorderWidth + kDragToResizeAreaPadding.left; - static double get rightToEdge => - windowBorderWidth + kDragToResizeAreaPadding.right; - static double get topToEdge => - tabBarHeight + windowBorderWidth + kDragToResizeAreaPadding.top; - static double get bottomToEdge => - windowBorderWidth + kDragToResizeAreaPadding.bottom; + static double get leftToEdge => (isDesktop || isWebDesktop) + ? windowBorderWidth + kDragToResizeAreaPadding.left + : 0; + static double get rightToEdge => (isDesktop || isWebDesktop) + ? windowBorderWidth + kDragToResizeAreaPadding.right + : 0; + static double get topToEdge => (isDesktop || isWebDesktop) + ? tabBarHeight + windowBorderWidth + kDragToResizeAreaPadding.top + : 0; + static double get bottomToEdge => (isDesktop || isWebDesktop) + ? windowBorderWidth + kDragToResizeAreaPadding.bottom + : 0; updateViewStyle() async { Size getSize() { From 75e3f1c3639f8067590d3ae0864138241930a546 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Tue, 28 Feb 2023 15:40:44 +0100 Subject: [PATCH 077/382] Added delete confermation dialog --- flutter/lib/common/widgets/peer_card.dart | 61 ++++++++++++++++++----- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/flutter/lib/common/widgets/peer_card.dart b/flutter/lib/common/widgets/peer_card.dart index 1d3a18c7c..13321db57 100644 --- a/flutter/lib/common/widgets/peer_card.dart +++ b/flutter/lib/common/widgets/peer_card.dart @@ -532,19 +532,7 @@ abstract class BasePeerCard extends StatelessWidget { ], ), proc: () { - () async { - if (isLan) { - bind.mainRemoveDiscovered(id: id); - } else { - final favs = (await bind.mainGetFav()).toList(); - if (favs.remove(id)) { - await bind.mainStoreFav(favs: favs); - } - await bind.mainRemovePeer(id: id); - } - removePreference(id); - await reloadFunc(); - }(); + _delete(id, isLan, reloadFunc); }, padding: menuPadding, dismissOnClicked: true, @@ -714,6 +702,53 @@ abstract class BasePeerCard extends StatelessWidget { @protected void _update(); + + void _delete(String id, bool isLan, Function reloadFunc) async { + gFFI.dialogManager.show( + (setState, close) { + submit() async { + if (isLan) { + bind.mainRemoveDiscovered(id: id); + } else { + final favs = (await bind.mainGetFav()).toList(); + if (favs.remove(id)) { + await bind.mainStoreFav(favs: favs); + } + await bind.mainRemovePeer(id: id); + } + removePreference(id); + await reloadFunc(); + close(); + } + + return CustomAlertDialog( + title: Text(translate('Delete')), + content: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ElevatedButton.icon( + icon: Icon(Icons.close_rounded), + label: Text(translate("Cancel")), + onPressed: close, + ), + ElevatedButton.icon( + icon: Icon(Icons.done_rounded), + label: Text(translate("Ok")), + onPressed: submit, + ), + ], + ).paddingOnly(top: 20) + ], + ), + onSubmit: submit, + onCancel: close, + ); + }, + ); + } } class RecentPeerCard extends BasePeerCard { From 7bf728bdad47b10e43e9368c473c6a7effd909c3 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Tue, 28 Feb 2023 15:57:25 +0100 Subject: [PATCH 078/382] restart device dialog --- flutter/lib/common/widgets/peer_card.dart | 21 +++++++++++++-- flutter/lib/mobile/widgets/dialog.dart | 33 ++++++++++++++++------- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/flutter/lib/common/widgets/peer_card.dart b/flutter/lib/common/widgets/peer_card.dart index 13321db57..cc5568bca 100644 --- a/flutter/lib/common/widgets/peer_card.dart +++ b/flutter/lib/common/widgets/peer_card.dart @@ -661,7 +661,13 @@ abstract class BasePeerCard extends StatelessWidget { } return CustomAlertDialog( - title: Text(translate('Rename')), + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.edit_rounded, color: MyTheme.accent), + Text(translate('Rename')).paddingOnly(left: 10), + ], + ), content: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -722,7 +728,18 @@ abstract class BasePeerCard extends StatelessWidget { } return CustomAlertDialog( - title: Text(translate('Delete')), + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.delete_rounded, + color: Colors.red, + ), + Text(translate('Delete')).paddingOnly( + left: 10, + ), + ], + ), content: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index 931999382..fde9ac4ad 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -25,19 +25,32 @@ void showRestartRemoteDevice( final res = await dialogManager.show((setState, close) => CustomAlertDialog( title: Row(children: [ - Icon(Icons.warning_amber_sharp, - color: Colors.redAccent, size: 28), - SizedBox(width: 10), - Text(translate("Restart Remote Device")), + Icon(Icons.warning_rounded, color: Colors.redAccent, size: 28), + Text(translate("Restart Remote Device")).paddingOnly(left: 10), ]), - content: Text( - "${translate('Are you sure you want to restart')} \n${pi.username}@${pi.hostname}($id) ?"), + content: Column( + children: [ + Text( + "${translate('Are you sure you want to restart')} \n${pi.username}@${pi.hostname}($id) ?"), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ElevatedButton.icon( + icon: Icon(Icons.close_rounded), + label: Text(translate("Cancel")), + onPressed: close, + ), + ElevatedButton.icon( + icon: Icon(Icons.done_rounded), + label: Text(translate("Ok")), + onPressed: () => close(true), + ), + ], + ).paddingOnly(top: 20) + ], + ), onCancel: close, onSubmit: () => close(true), - actions: [ - dialogButton("Cancel", onPressed: close, isOutline: true), - dialogButton("OK", onPressed: () => close(true)), - ], )); if (res == true) bind.sessionRestartRemoteDevice(id: id); } From 5375c98e25bcd1d4a7c51d6fcdcb70482312fcda Mon Sep 17 00:00:00 2001 From: rustdesk Date: Tue, 28 Feb 2023 23:04:15 +0800 Subject: [PATCH 079/382] to make macos debug can be run directly without flutter run to skip "mapped file has no Team ID and is not a platform binary (signed with custom identity or adhoc" issue --- flutter/macos/Runner.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/macos/Runner.xcodeproj/project.pbxproj b/flutter/macos/Runner.xcodeproj/project.pbxproj index 0019335ef..c73e666c7 100644 --- a/flutter/macos/Runner.xcodeproj/project.pbxproj +++ b/flutter/macos/Runner.xcodeproj/project.pbxproj @@ -487,7 +487,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_IDENTITY = "Apple Development"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; From f26088765e31e7da255633ba717913e86a699978 Mon Sep 17 00:00:00 2001 From: csf Date: Wed, 1 Mar 2023 00:05:06 +0900 Subject: [PATCH 080/382] 1. sync from flutter and pass app_dir from MainService.kt to backend server when app start on boot. 2. add start_service when start on boot. --- .../com/carriez/flutter_hbb/BootReceiver.kt | 1 + .../com/carriez/flutter_hbb/MainActivity.kt | 13 +++++++++++-- .../com/carriez/flutter_hbb/MainService.kt | 18 ++++++++++++++++-- .../kotlin/com/carriez/flutter_hbb/common.kt | 3 +++ flutter/lib/consts.dart | 1 + flutter/lib/main.dart | 1 + flutter/lib/models/native_model.dart | 10 +++++++--- src/flutter_ffi.rs | 18 ++++++++++++++++-- 8 files changed, 56 insertions(+), 9 deletions(-) diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt index 8f6767e58..71bbba754 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt @@ -34,6 +34,7 @@ class BootReceiver : BroadcastReceiver() { val it = Intent(context, MainService::class.java).apply { action = ACT_INIT_MEDIA_PROJECTION_AND_SERVICE + putExtra(EXT_INIT_FROM_BOOT, true) } Toast.makeText(context, "RustDesk is Open", Toast.LENGTH_LONG).show() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt index 79fb60790..52a5ff75e 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt @@ -15,7 +15,6 @@ import android.os.Build import android.os.IBinder import android.util.Log import android.view.WindowManager -import androidx.annotation.RequiresApi import com.hjq.permissions.XXPermissions import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine @@ -31,7 +30,6 @@ class MainActivity : FlutterActivity() { private val logTag = "mMainActivity" private var mainService: MainService? = null - @RequiresApi(Build.VERSION_CODES.M) override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) if (MainService.isReady) { @@ -208,6 +206,17 @@ class MainActivity : FlutterActivity() { result.success(false) } } + SYNC_APP_DIR_CONFIG_PATH -> { + if (call.arguments is String) { + val prefs = getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE) + val edit = prefs.edit() + edit.putString(KEY_APP_DIR_CONFIG_PATH, call.arguments as String) + edit.apply() + result.success(true) + } else { + result.success(false) + } + } else -> { result.error("-1", "No such method", null) } diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt index 6b6169c61..fa7440c8d 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt @@ -35,6 +35,7 @@ import androidx.annotation.RequiresApi import androidx.core.app.ActivityCompat import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat +import io.flutter.embedding.android.FlutterActivity import java.util.concurrent.Executors import kotlin.concurrent.thread import org.json.JSONException @@ -143,7 +144,11 @@ class MainService : Service() { // jvm call rust private external fun init(ctx: Context) - private external fun startServer() + + /// When app start on boot, app_dir will not be passed from flutter + /// so pass a app_dir here to rust server + private external fun startServer(app_dir: String) + private external fun startService() private external fun onVideoFrameUpdate(buf: ByteBuffer) private external fun onAudioFrameUpdate(buf: ByteBuffer) private external fun translateLocale(localeName: String, input: String): String @@ -199,7 +204,12 @@ class MainService : Service() { } updateScreenInfo(resources.configuration.orientation) initNotification() - startServer() + + // keep the config dir same with flutter + val prefs = applicationContext.getSharedPreferences(KEY_SHARED_PREFERENCES, FlutterActivity.MODE_PRIVATE) + val configPath = prefs.getString(KEY_APP_DIR_CONFIG_PATH, "") ?: "" + startServer(configPath) + createForegroundNotification() } @@ -279,6 +289,10 @@ class MainService : Service() { super.onStartCommand(intent, flags, startId) if (intent?.action == ACT_INIT_MEDIA_PROJECTION_AND_SERVICE) { createForegroundNotification() + + if (intent.getBooleanExtra(EXT_INIT_FROM_BOOT, false)) { + startService() + } Log.d(logTag, "service starting: ${startId}:${Thread.currentThread()}") val mediaProjectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt index bd91d582c..f8ef07fd1 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt @@ -27,6 +27,7 @@ import java.util.* const val ACT_REQUEST_MEDIA_PROJECTION = "REQUEST_MEDIA_PROJECTION" const val ACT_INIT_MEDIA_PROJECTION_AND_SERVICE = "INIT_MEDIA_PROJECTION_AND_SERVICE" const val ACT_LOGIN_REQ_NOTIFY = "LOGIN_REQ_NOTIFY" +const val EXT_INIT_FROM_BOOT = "EXT_INIT_FROM_BOOT" const val EXT_MEDIA_PROJECTION_RES_INTENT = "MEDIA_PROJECTION_RES_INTENT" const val EXT_LOGIN_REQ_NOTIFY = "LOGIN_REQ_NOTIFY" @@ -41,9 +42,11 @@ const val RES_FAILED = -100 const val START_ACTION = "start_action" const val GET_START_ON_BOOT_OPT = "get_start_on_boot_opt" const val SET_START_ON_BOOT_OPT = "set_start_on_boot_opt" +const val SYNC_APP_DIR_CONFIG_PATH = "sync_app_dir" const val KEY_SHARED_PREFERENCES = "KEY_SHARED_PREFERENCES" const val KEY_START_ON_BOOT_OPT = "KEY_START_ON_BOOT_OPT" +const val KEY_APP_DIR_CONFIG_PATH = "KEY_APP_DIR_CONFIG_PATH" @SuppressLint("ConstantLocale") val LOCAL_NAME = Locale.getDefault().toString() diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index b075ee76f..95e4d17e7 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -153,6 +153,7 @@ class AndroidChannel { static final kStartAction = "start_action"; static final kGetStartOnBootOpt = "get_start_on_boot_opt"; static final kSetStartOnBootOpt = "set_start_on_boot_opt"; + static final kSyncAppDirConfigPath = "sync_app_dir"; } /// flutter/packages/flutter/lib/src/services/keyboard_key.dart -> _keyLabels diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index baf7193b3..6d3f863e7 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -153,6 +153,7 @@ void runMainApp(bool startService) async { void runMobileApp() async { await initEnv(kAppTypeMain); if (isAndroid) androidChannelInit(); + platformFFI.syncAndroidServiceAppDirConfigPath(); runApp(App()); } diff --git a/flutter/lib/models/native_model.dart b/flutter/lib/models/native_model.dart index 13f5b4587..28dc8085e 100644 --- a/flutter/lib/models/native_model.dart +++ b/flutter/lib/models/native_model.dart @@ -30,7 +30,7 @@ typedef F4Dart = int Function(Pointer); typedef F5 = Void Function(Pointer); typedef F5Dart = void Function(Pointer); typedef HandleEvent = Future Function(Map evt); -// pub fn session_register_texture(id: *const char, ptr: usize) +// pub fn session_register_texture(id: *const char, ptr: usize) typedef F6 = Void Function(Pointer, Uint64); typedef F6Dart = void Function(Pointer, int); @@ -56,7 +56,6 @@ class PlatformFFI { F4Dart? _session_get_rgba_size; F5Dart? _session_next_rgba; F6Dart? _session_register_texture; - static get localeName => Platform.localeName; @@ -162,7 +161,8 @@ class PlatformFFI { dylib.lookupFunction("session_get_rgba_size"); _session_next_rgba = dylib.lookupFunction("session_next_rgba"); - _session_register_texture = dylib.lookupFunction("session_register_texture"); + _session_register_texture = + dylib.lookupFunction("session_register_texture"); try { // SYSTEM user failed _dir = (await getApplicationDocumentsDirectory()).path; @@ -301,4 +301,8 @@ class PlatformFFI { if (!isAndroid) return Future(() => false); return await _toAndroidChannel.invokeMethod(method, arguments); } + + void syncAndroidServiceAppDirConfigPath() { + invokeMethod(AndroidChannel.kSyncAppDirConfigPath, _dir); + } } diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index e49ba65f7..e5b24fa53 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -1361,7 +1361,7 @@ pub fn send_url_scheme(_url: String) { #[cfg(target_os = "android")] pub mod server_side { - use hbb_common::log; + use hbb_common::{log, config}; use jni::{ objects::{JClass, JString}, sys::jstring, @@ -1374,11 +1374,25 @@ pub mod server_side { pub unsafe extern "system" fn Java_com_carriez_flutter_1hbb_MainService_startServer( env: JNIEnv, _class: JClass, + app_dir: JString, ) { - log::debug!("startServer from java"); + log::debug!("startServer from jvm"); + if let Ok(app_dir) = env.get_string(app_dir) { + *config::APP_DIR.write().unwrap() = app_dir.into(); + } std::thread::spawn(move || start_server(true)); } + #[no_mangle] + pub unsafe extern "system" fn Java_com_carriez_flutter_1hbb_MainService_startService( + env: JNIEnv, + _class: JClass, + ) { + log::debug!("startService from jvm"); + config::Config::set_option("stop-service".into(), "".into()); + crate::rendezvous_mediator::RendezvousMediator::restart(); + } + #[no_mangle] pub unsafe extern "system" fn Java_com_carriez_flutter_1hbb_MainService_translateLocale( env: JNIEnv, From 2cb3ca4ed00a22d4f512e70f0202a6f05bc1be13 Mon Sep 17 00:00:00 2001 From: csf Date: Wed, 1 Mar 2023 00:14:37 +0900 Subject: [PATCH 081/382] update lang, start on boot --- flutter/lib/mobile/pages/settings_page.dart | 2 +- src/lang/ca.rs | 2 ++ src/lang/cn.rs | 2 ++ src/lang/cs.rs | 4 +++- src/lang/da.rs | 2 ++ src/lang/de.rs | 4 +++- src/lang/eo.rs | 2 ++ src/lang/es.rs | 2 ++ src/lang/fa.rs | 4 +++- src/lang/fr.rs | 2 ++ src/lang/gr.rs | 2 ++ src/lang/hu.rs | 2 ++ src/lang/id.rs | 2 ++ src/lang/it.rs | 4 +++- src/lang/ja.rs | 2 ++ src/lang/ko.rs | 2 ++ src/lang/kz.rs | 2 ++ src/lang/nl.rs | 2 ++ src/lang/pl.rs | 5 ++--- src/lang/pt_PT.rs | 4 +++- src/lang/ptbr.rs | 2 ++ src/lang/ro.rs | 2 ++ src/lang/ru.rs | 2 ++ src/lang/sk.rs | 2 ++ src/lang/sl.rs | 2 ++ src/lang/sq.rs | 2 ++ src/lang/sr.rs | 2 ++ src/lang/sv.rs | 2 ++ src/lang/template.rs | 2 ++ src/lang/th.rs | 2 ++ src/lang/tr.rs | 2 ++ src/lang/tw.rs | 2 ++ src/lang/ua.rs | 2 ++ src/lang/vn.rs | 2 ++ 34 files changed, 72 insertions(+), 9 deletions(-) diff --git a/flutter/lib/mobile/pages/settings_page.dart b/flutter/lib/mobile/pages/settings_page.dart index e54f66ffb..e07f8f59f 100644 --- a/flutter/lib/mobile/pages/settings_page.dart +++ b/flutter/lib/mobile/pages/settings_page.dart @@ -335,7 +335,7 @@ class _SettingsState extends State with WidgetsBindingObserver { title: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("${translate('Start on Boot')} (beta)"), Text( - '* ${translate('Start the screen recording service on boot, which requires special permissions')}', + '* ${translate('Start the screen sharing service on boot, requires special permissions')}', style: Theme.of(context).textTheme.bodySmall), ]), onToggle: (toValue) async { diff --git a/src/lang/ca.rs b/src/lang/ca.rs index aa33ae6e5..53ec69b5f 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Mantenir RustDesk com a servei en segon pla"), ("Ignore Battery Optimizations", "Ignorar optimizacions de la bateria"), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Connexió no disponible"), ("Legacy mode", "Mode heretat"), ("Map mode", "Mode mapa"), diff --git a/src/lang/cn.rs b/src/lang/cn.rs index f975e343f..4c037234b 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "保持 RustDesk 后台服务"), ("Ignore Battery Optimizations", "忽略电池优化"), ("android_open_battery_optimizations_tip", "如需关闭此功能,请在接下来的 RustDesk 应用设置页面中,找到并进入 [电源] 页面,取消勾选 [不受限制]"), + ("Start on Boot", "开机自启动"), + ("Start the screen sharing service on boot, requires special permissions", "开机自动启动屏幕共享服务,此功能需要一些特殊权限。"), ("Connection not allowed", "对方不允许连接"), ("Legacy mode", "传统模式"), ("Map mode", "1:1 传输"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index cfe69924c..25a494eef 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), @@ -454,8 +456,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), - ("No transfers in progress", ""), ("Codec", ""), ("Resolution", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 19310357b..8fd6f9be1 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Behold RustDesk baggrundstjeneste"), ("Ignore Battery Optimizations", "Ignorer betteri optimeringer"), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Forbindelse ikke tilladt"), ("Legacy mode", "Bagudkompatibilitetstilstand"), ("Map mode", ""), diff --git a/src/lang/de.rs b/src/lang/de.rs index 3d95832ec..754d7b9ef 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk im Hintergrund ausführen"), ("Ignore Battery Optimizations", "Akkuoptimierung ignorieren"), ("android_open_battery_optimizations_tip", "Möchten Sie die Einstellungen zur Akkuoptimierung öffnen?"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Verbindung abgelehnt"), ("Legacy mode", "Kompatibilitätsmodus"), ("Map mode", "Kartenmodus"), @@ -457,5 +459,5 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Codec"), ("Resolution", "Auflösung"), ("No transfers in progress", "Keine Übertragungen im Gange"), - ].iter().cloned().collect(); + ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 9b7912cff..dfee4fb87 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/es.rs b/src/lang/es.rs index af0da0479..8477ba99b 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Dejar RustDesk como Servicio en 2do plano"), ("Ignore Battery Optimizations", "Ignorar optimizacioens de bateria"), ("android_open_battery_optimizations_tip", "Si deseas deshabilitar esta característica, por favor, ve a la página siguiente de ajustes, busca y entra en [Batería] y desmarca [Sin restricción]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Conexión no disponible"), ("Legacy mode", "Modo heredado"), ("Map mode", "Modo mapa"), diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 0c31e1531..2cefaa98f 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "را در پس زمینه نگه دارید RustDesk سرویس"), ("Ignore Battery Optimizations", "بهینه سازی باتری نادیده گرفته شود"), ("android_open_battery_optimizations_tip", "به صفحه تنظیمات بعدی بروید"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "اتصال مجاز نیست"), ("Legacy mode", "legacy حالت"), ("Map mode", "map حالت"), @@ -454,8 +456,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "توقف تماس صوتی"), ("relay_hint_tip", " را به شناسه اضافه کنید یا گزینه \"همیشه از طریق رله متصل شوید\" را در کارت همتا انتخاب کنید. همچنین، اگر می‌خواهید فوراً از سرور رله استفاده کنید، می‌توانید پسوند \"/r\".\n اتصال مستقیم ممکن است امکان پذیر نباشد. در این صورت می توانید سعی کنید از طریق سرور رله متصل شوید"), ("Reconnect", "اتصال مجدد"), - ("No transfers in progress", ""), ("Codec", ""), ("Resolution", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 0e45827f7..28f1dd9d1 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Gardez le service RustDesk en arrière plan"), ("Ignore Battery Optimizations", "Ignorer les optimisations batterie"), ("android_open_battery_optimizations_tip", "Conseil android d'optimisation de batterie"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Connexion non autorisée"), ("Legacy mode", "Mode hérité"), ("Map mode", ""), diff --git a/src/lang/gr.rs b/src/lang/gr.rs index fca98f228..55a3c9bb7 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Εκτέλεση του RustDesk στο παρασκήνιο"), ("Ignore Battery Optimizations", "Παράβλεψη βελτιστοποιήσεων μπαταρίας"), ("android_open_battery_optimizations_tip", "Θέλετε να ανοίξετε τις ρυθμίσεις βελτιστοποίησης μπαταρίας;"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Η σύνδεση απορρίφθηκε"), ("Legacy mode", "Λειτουργία συμβατότητας"), ("Map mode", "Map mode"), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 437cf445a..f47d522db 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk futtatása a háttérben"), ("Ignore Battery Optimizations", "Akkumulátorkímélő figyelmen kívűl hagyása"), ("android_open_battery_optimizations_tip", "Ha le szeretné tiltani ezt a funkciót, lépjen a RustDesk alkalmazás beállítási oldalára, keresse meg az [Akkumulátorkímélő] lehetőséget és válassza a nincs korlátozás lehetőséget."), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "A csatlakozás nem engedélyezett"), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/id.rs b/src/lang/id.rs index 84892a7f8..7d02e154d 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Pertahankan RustDesk berjalan pada background service"), ("Ignore Battery Optimizations", "Abaikan Pengoptimalan Baterai"), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Koneksi tidak dijinkan"), ("Legacy mode", "Mode lama"), ("Map mode", "Mode peta"), diff --git a/src/lang/it.rs b/src/lang/it.rs index 101685c4a..8aedc04f6 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Mantieni il servizio di RustDesk in background"), ("Ignore Battery Optimizations", "Ignora le ottimizzazioni della batteria"), ("android_open_battery_optimizations_tip", "Se si desidera disabilitare questa funzione, andare nelle impostazioni dell'applicazione RustDesk, aprire la sezione [Batteria] e deselezionare [Senza restrizioni]."), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Connessione non consentita"), ("Legacy mode", "Modalità legacy"), ("Map mode", "Modalità mappa"), @@ -454,8 +456,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Interrompi la chiamata vocale"), ("relay_hint_tip", "Se non è possibile connettersi direttamente, si può provare a farlo tramite relay.\nInoltre, se si desidera utilizzare il relay al primo tentativo, è possibile aggiungere il suffisso \"/r\" all'ID o selezionare l'opzione \"Collegati sempre tramite relay\" nella scheda peer."), ("Reconnect", "Riconnetti"), - ("No transfers in progress", "Nessun trasferimento in corso"), ("Codec", "Codec"), ("Resolution", "Risoluzione"), + ("No transfers in progress", "Nessun trasferimento in corso"), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index c19b607ca..d097a8b61 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk バックグラウンドサービスを維持"), ("Ignore Battery Optimizations", "バッテリーの最適化を無効にする"), ("android_open_battery_optimizations_tip", "この機能を使わない場合は、次のRestDeskアプリ設定ページから「バッテリー」に進み、「制限なし」の選択を外してください"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "接続が許可されていません"), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 97574e67d..8ca881f16 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk 백그라운드 서비스로 유지하기"), ("Ignore Battery Optimizations", "배터리 최적화 무시하기"), ("android_open_battery_optimizations_tip", "해당 기능을 비활성화하려면 RustDesk 응용 프로그램 설정 페이지로 이동하여 [배터리]에서 [제한 없음] 선택을 해제하십시오."), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "연결이 허용되지 않음"), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 54a51b439..a9acdce65 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Артжақтағы RustDesk сербесін сақтап тұру"), ("Ignore Battery Optimizations", "Бәтері Оңтайландыруларын Елемеу"), ("android_open_battery_optimizations_tip", "Егер де бұл ерекшелікті өшіруді қаласаңыз, келесі RustDesk апылқат орнатпалары бетіне барып, [Бәтері]'ні тауып кіріңіз де [Шектеусіз]'ден құсбелгіні алып тастауды өтінеміз"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Қосылу рұқсат етілмеген"), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/nl.rs b/src/lang/nl.rs index f38c14791..cf3eb430c 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk achtergronddienst behouden"), ("Ignore Battery Optimizations", "Negeer Batterij Optimalisaties"), ("android_open_battery_optimizations_tip", "Ga naar de volgende pagina met instellingen"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Verbinding niet toegestaan"), ("Legacy mode", "Verouderde modus"), ("Map mode", "Map mode"), diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 13027a682..a0808f5bf 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Zachowaj usługę RustDesk w tle"), ("Ignore Battery Optimizations", "Ignoruj optymalizację baterii"), ("android_open_battery_optimizations_tip", "Jeśli chcesz wyłączyć tę funkcję, przejdź do następnej strony ustawień aplikacji RustDesk, znajdź i wprowadź [Bateria], odznacz [Bez ograniczeń]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Połączenie niedozwolone"), ("Legacy mode", "Tryb kompatybilności wstecznej (legacy)"), ("Map mode", "Tryb mapowania"), @@ -456,9 +458,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Reconnect", "Połącz ponownie"), ("Codec", "Kodek"), ("Resolution", "Rozdzielczość"), - ("Use temporary password", "Użyj hasła tymczasowego"), - ("Set temporary password length", "Ustaw długość hasła tymczasowego"), - ("Key", "Klucz"), ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 923bbab05..b62bd5a31 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Manter o serviço RustDesk em funcionamento"), ("Ignore Battery Optimizations", "Ignorar optimizações de Bateria"), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Ligação não autorizada"), ("Legacy mode", ""), ("Map mode", ""), @@ -454,8 +456,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), - ("No transfers in progress", ""), ("Codec", ""), ("Resolution", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index aa491f951..546ef2a3c 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Manter o serviço do RustDesk executando em segundo plano"), ("Ignore Battery Optimizations", "Ignorar otimizações de bateria"), ("android_open_battery_optimizations_tip", "Abrir otimizações de bateria"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Conexão não permitida"), ("Legacy mode", "Modo legado"), ("Map mode", "Modo mapa"), diff --git a/src/lang/ro.rs b/src/lang/ro.rs index e992b19d8..af9389a29 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Rulează serviciul RustDesk în fundal"), ("Ignore Battery Optimizations", "Ignoră optimizările de baterie"), ("android_open_battery_optimizations_tip", "Pentru dezactivarea acestei funcții, accesează setările aplicației RustDesk, deschide secțiunea [Baterie] și deselectează [Fără restricții]."), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Conexiune neautoriztă"), ("Legacy mode", "Mod legacy"), ("Map mode", "Mod hartă"), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 3bfb5357d..b9af4ce98 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Держать в фоне службу RustDesk"), ("Ignore Battery Optimizations", "Игнорировать оптимизацию батареи"), ("android_open_battery_optimizations_tip", "Перейдите на следующую страницу настроек"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Подключение не разрешено"), ("Legacy mode", "Устаревший режим"), ("Map mode", "Режим сопоставления"), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 6468b7eef..8a6b765be 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/sl.rs b/src/lang/sl.rs index d128e7322..5721d01f4 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Ohrani RustDeskovo storitev v ozadju"), ("Ignore Battery Optimizations", "Prezri optimizacije baterije"), ("android_open_battery_optimizations_tip", "Če želite izklopiti to možnost, pojdite v nastavitve aplikacije RustDesk, poiščite »Baterija« in izklopite »Neomejeno«"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Povezava ni dovoljena"), ("Legacy mode", "Stari način"), ("Map mode", "Način preslikave"), diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 29c5cbbf8..1c488d470 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Mbaje shërbimin e sfondit të RustDesk"), ("Ignore Battery Optimizations", "Injoro optimizimet e baterisë"), ("android_open_battery_optimizations_tip", "Nëse dëshironi ta çaktivizoni këtë veçori, ju lutemi shkoni te faqja tjetër e cilësimeve të aplikacionit RustDesk, gjeni dhe shtypni [Batteri], hiqni zgjedhjen [Te pakufizuara]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Lidhja nuk lejohet"), ("Legacy mode", "Modaliteti i trashëgimisë"), ("Map mode", "Modaliteti i hartës"), diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 63173dc11..249c0b599 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Zadrži RustDesk kao pozadinski servis"), ("Ignore Battery Optimizations", "Zanemari optimizacije baterije"), ("android_open_battery_optimizations_tip", "Ako želite da onemogućite ovu funkciju, molimo idite na sledeću stranicu za podešavanje RustDesk aplikacije, pronađite i uđite u [Battery], isključite [Unrestricted]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Konekcija nije dozvoljena"), ("Legacy mode", "Zastareli mod"), ("Map mode", "Mod mapiranja"), diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 1a00ece43..90ec8c1cf 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Behåll RustDesk i bakgrunden"), ("Ignore Battery Optimizations", "Ignorera batterioptimering"), ("android_open_battery_optimizations_tip", "Om du vill stänga av denna funktion, gå till nästa RustDesk programs inställningar, hitta [Batteri], Checka ur [Obegränsad]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Anslutning ej tillåten"), ("Legacy mode", "Legacy mode"), ("Map mode", "Kartläge"), diff --git a/src/lang/template.rs b/src/lang/template.rs index 2c83f9474..6563d6056 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/th.rs b/src/lang/th.rs index 6fcf02ed2..316622395 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "คงสถานะการทำงานเบื้องหลังของเซอร์วิส RustDesk"), ("Ignore Battery Optimizations", "เพิกเฉยการตั้งค่าการใช้งาน Battery Optimization"), ("android_open_battery_optimizations_tip", "หากคุณต้องการปิดการใช้งานฟีเจอร์นี้ กรุณาไปยังหน้าตั้งค่าในแอปพลิเคชัน RustDesk ค้นหาหัวข้อ [Battery] และยกเลิกการเลือกรายการ [Unrestricted]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "การเชื่อมต่อไม่อนุญาต"), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index d35d288d6..7359bf064 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk arka plan hizmetini sürdürün"), ("Ignore Battery Optimizations", "Pil Optimizasyonlarını Yoksay"), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "bağlantıya izin verilmedi"), ("Legacy mode", "Eski mod"), ("Map mode", "Haritalama modu"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 20a2998ec..70533c482 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "保持RustDesk後台服務"), ("Ignore Battery Optimizations", "忽略電池優化"), ("android_open_battery_optimizations_tip", "如需關閉此功能,請在接下來的RustDesk應用設置頁面中,找到並進入 [電源] 頁面,取消勾選 [不受限制]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "對方不允許連接"), ("Legacy mode", "傳統模式"), ("Map mode", "1:1傳輸"), diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 4c4b5d4bc..6b54c83c3 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Зберегти фонову службу RustDesk"), ("Ignore Battery Optimizations", "Ігнорувати оптимізацію батареї"), ("android_open_battery_optimizations_tip", "Перейдіть на наступну сторінку налаштувань"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Підключення не дозволено"), ("Legacy mode", "Застарілий режим"), ("Map mode", "Режим карти"), diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 32cd084cb..a379b3185 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Giữ dịch vụ nền RustDesk"), ("Ignore Battery Optimizations", "Bỏ qua các tối ưu pin"), ("android_open_battery_optimizations_tip", "Nếu bạn muốn tắt tính năng này, vui lòng chuyển đến trang cài đặt ứng dụng RustDesk tiếp theo, tìm và nhập [Pin], Bỏ chọn [Không hạn chế]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Kết nối không đuợc phép"), ("Legacy mode", ""), ("Map mode", ""), From 18339cf34322c31a66d620253da894b3db7c5560 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Tue, 28 Feb 2023 16:36:44 +0100 Subject: [PATCH 082/382] password dialog --- .../lib/desktop/widgets/remote_menubar.dart | 27 ++- flutter/lib/mobile/widgets/dialog.dart | 156 +++++++++++------- 2 files changed, 118 insertions(+), 65 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index c27546d9f..90b48160b 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -655,7 +655,13 @@ class _ControlMenu extends StatelessWidget { } return CustomAlertDialog( - title: Text(translate('OS Password')), + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.password_rounded, color: MyTheme.accent), + Text(translate('OS Password')).paddingOnly(left: 10), + ], + ), content: Column(mainAxisSize: MainAxisSize.min, children: [ PasswordWidget(controller: controller), CheckboxListTile( @@ -671,11 +677,22 @@ class _ControlMenu extends StatelessWidget { setState(() => autoLogin = v); }, ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ElevatedButton.icon( + icon: Icon(Icons.close_rounded), + label: Text(translate("Cancel")), + onPressed: close, + ), + ElevatedButton.icon( + icon: Icon(Icons.done_rounded), + label: Text(translate("Ok")), + onPressed: submit, + ), + ], + ).paddingOnly(top: 20) ]), - actions: [ - dialogButton('Cancel', onPressed: close, isOutline: true), - dialogButton('OK', onPressed: submit), - ], onSubmit: submit, onCancel: close, ); diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index fde9ac4ad..6b87d62ba 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -75,64 +75,83 @@ void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async { } return CustomAlertDialog( - title: Text(translate('Set your own password')), - content: Form( - autovalidateMode: AutovalidateMode.onUserInteraction, - child: Column(mainAxisSize: MainAxisSize.min, children: [ - TextFormField( - autofocus: true, - obscureText: true, - keyboardType: TextInputType.visiblePassword, - decoration: InputDecoration( - labelText: translate('Password'), - ), - controller: p0, - validator: (v) { - if (v == null) return null; - final val = v.trim().length > 5; - if (validateLength != val) { - // use delay to make setState success - Future.delayed(Duration(microseconds: 1), - () => setState(() => validateLength = val)); - } - return val - ? null - : translate('Too short, at least 6 characters.'); - }, + title: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.password_rounded, color: MyTheme.accent), + Text(translate('Set your own password')).paddingOnly(left: 10), + ], + ), + content: Column( + children: [ + Form( + autovalidateMode: AutovalidateMode.onUserInteraction, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextFormField( + autofocus: true, + obscureText: true, + keyboardType: TextInputType.visiblePassword, + decoration: InputDecoration( + labelText: translate('Password'), + ), + controller: p0, + validator: (v) { + if (v == null) return null; + final val = v.trim().length > 5; + if (validateLength != val) { + // use delay to make setState success + Future.delayed(Duration(microseconds: 1), + () => setState(() => validateLength = val)); + } + return val + ? null + : translate('Too short, at least 6 characters.'); + }, + ), + TextFormField( + obscureText: true, + keyboardType: TextInputType.visiblePassword, + decoration: InputDecoration( + labelText: translate('Confirmation'), + ), + controller: p1, + validator: (v) { + if (v == null) return null; + final val = p0.text == v; + if (validateSame != val) { + Future.delayed(Duration(microseconds: 1), + () => setState(() => validateSame = val)); + } + return val + ? null + : translate('The confirmation is not identical.'); + }, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ElevatedButton.icon( + icon: Icon(Icons.close_rounded), + label: Text(translate("Cancel")), + onPressed: close, + ), + ElevatedButton.icon( + icon: Icon(Icons.done_rounded), + label: Text(translate("Ok")), + onPressed: + (validateLength && validateSame) ? submit : null, + ), + ], + ).paddingOnly(top: 20) + ], ), - TextFormField( - obscureText: true, - keyboardType: TextInputType.visiblePassword, - decoration: InputDecoration( - labelText: translate('Confirmation'), - ), - controller: p1, - validator: (v) { - if (v == null) return null; - final val = p0.text == v; - if (validateSame != val) { - Future.delayed(Duration(microseconds: 1), - () => setState(() => validateSame = val)); - } - return val - ? null - : translate('The confirmation is not identical.'); - }, - ), - ])), + ), + ], + ), onCancel: close, onSubmit: (validateLength && validateSame) ? submit : null, - actions: [ - dialogButton( - 'Cancel', - onPressed: close, - isOutline: true, - ), - dialogButton( - 'OK', - onPressed: (validateLength && validateSame) ? submit : null, - ), - ], ); }); } @@ -191,7 +210,13 @@ void enterPasswordDialog(String id, OverlayDialogManager dialogManager) async { } return CustomAlertDialog( - title: Text(translate('Password Required')), + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.password_rounded, color: MyTheme.accent), + Text(translate('Password Required')).paddingOnly(left: 10), + ], + ), content: Column(mainAxisSize: MainAxisSize.min, children: [ PasswordWidget(controller: controller), CheckboxListTile( @@ -208,11 +233,22 @@ void enterPasswordDialog(String id, OverlayDialogManager dialogManager) async { } }, ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ElevatedButton.icon( + icon: Icon(Icons.close_rounded), + label: Text(translate("Cancel")), + onPressed: close, + ), + ElevatedButton.icon( + icon: Icon(Icons.done_rounded), + label: Text(translate("Ok")), + onPressed: submit, + ), + ], + ).paddingOnly(top: 20) ]), - actions: [ - dialogButton('Cancel', onPressed: cancel, isOutline: true), - dialogButton('OK', onPressed: submit), - ], onSubmit: submit, onCancel: cancel, ); From e28317a8dd26a358abc4f2fe1f4035f09185b320 Mon Sep 17 00:00:00 2001 From: csf Date: Wed, 1 Mar 2023 10:12:10 +0900 Subject: [PATCH 083/382] fix lang.py --- res/lang.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/lang.py b/res/lang.py index 481d65553..aa5f99f83 100644 --- a/res/lang.py +++ b/res/lang.py @@ -36,11 +36,11 @@ def main(): def expand(): for fn in glob.glob('./src/lang/*'): lang = os.path.basename(fn)[:-3] - if lang in ['en','cn']: continue + if lang in ['en','template']: continue print(lang) dict = get_lang(lang) fw = open("./src/lang/%s.rs"%lang, "wt", encoding='utf8') - for line in open('./src/lang/cn.rs', encoding='utf8'): + for line in open('./src/lang/template.rs', encoding='utf8'): line_strip = line.strip() if line_strip.startswith('("'): k, v = line_split(line_strip) From cff2ca9df8d4d7c64731b1d27c3cd4b274b56987 Mon Sep 17 00:00:00 2001 From: csf Date: Wed, 1 Mar 2023 10:22:51 +0900 Subject: [PATCH 084/382] fix UI translate (One-time password) --- flutter/lib/mobile/pages/server_page.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index 648448f41..bab2911f1 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -41,14 +41,14 @@ class ServerPage extends StatefulWidget implements PageShape { value: "setTemporaryPasswordLength", enabled: gFFI.serverModel.verificationMethod != kUsePermanentPassword, - child: Text(translate("Set temporary password length")), + child: Text(translate("One-time password length")), ), const PopupMenuDivider(), PopupMenuItem( padding: const EdgeInsets.symmetric(horizontal: 0.0), value: kUseTemporaryPassword, child: ListTile( - title: Text(translate("Use temporary password")), + title: Text(translate("Use one-time password")), trailing: Icon( Icons.check, color: gFFI.serverModel.verificationMethod == From 138f6fe36b3530a72fa619026dcf627308a75d26 Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 1 Mar 2023 09:54:40 +0800 Subject: [PATCH 085/382] fix keyboard options, revert change Signed-off-by: fufesou --- flutter/lib/desktop/widgets/remote_menubar.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index f236a7828..47d58ce5e 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -1561,9 +1561,8 @@ class _KeyboardMenu extends StatelessWidget { @override Widget build(BuildContext context) { - // Do not check permission here? - // var ffiModel = Provider.of(context); - // if (ffiModel.permissions['keyboard'] == false) return Offstage(); + var ffiModel = Provider.of(context); + if (ffiModel.permissions['keyboard'] == false) return Offstage(); if (stateGlobal.grabKeyboard) { if (bind.sessionIsKeyboardModeSupported(id: id, mode: _kKeyMapMode)) { bind.sessionSetKeyboardMode(id: id, value: _kKeyMapMode); From 69e95bc245ab928455d6d7ab166796def6027a4d Mon Sep 17 00:00:00 2001 From: 21pages Date: Wed, 1 Mar 2023 11:17:46 +0800 Subject: [PATCH 086/382] fix windows uninstall can not delete the installation directory Signed-off-by: 21pages --- src/platform/windows.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 0bba649f4..561bb4570 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -976,7 +976,7 @@ fn get_after_install(exe: &str) -> String { } pub fn install_me(options: &str, path: String, silent: bool, debug: bool) -> ResultType<()> { - let uninstall_str = get_uninstall(); + let uninstall_str = get_uninstall(false); let mut path = path.trim_end_matches('\\').to_owned(); let (subkey, _path, start_menu, exe) = get_default_install_info(); let mut exe = exe; @@ -1188,30 +1188,35 @@ pub fn run_after_install() -> ResultType<()> { } pub fn run_before_uninstall() -> ResultType<()> { - run_cmds(get_before_uninstall(), true, "before_install") + run_cmds(get_before_uninstall(true), true, "before_install") } -fn get_before_uninstall() -> String { +fn get_before_uninstall(kill_self: bool) -> String { let app_name = crate::get_app_name(); let ext = app_name.to_lowercase(); + let filter = if kill_self { + "".to_string() + } else { + format!(" /FI \"PID ne {}\"", get_current_pid()) + }; format!( " chcp 65001 sc stop {app_name} sc delete {app_name} taskkill /F /IM {broker_exe} - taskkill /F /IM {app_name}.exe /FI \"PID ne {cur_pid}\" + taskkill /F /IM {app_name}.exe{filter} reg delete HKEY_CLASSES_ROOT\\.{ext} /f netsh advfirewall firewall delete rule name=\"{app_name} Service\" ", app_name = app_name, broker_exe = crate::win_privacy::INJECTED_PROCESS_EXE, ext = ext, - cur_pid = get_current_pid(), + filter = filter, ) } -fn get_uninstall() -> String { +fn get_uninstall(kill_self: bool) -> String { let (subkey, path, start_menu, _) = get_install_info(); format!( " @@ -1222,7 +1227,7 @@ fn get_uninstall() -> String { if exist \"%PUBLIC%\\Desktop\\{app_name}.lnk\" del /f /q \"%PUBLIC%\\Desktop\\{app_name}.lnk\" if exist \"%PROGRAMDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\{app_name} Tray.lnk\" del /f /q \"%PROGRAMDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\{app_name} Tray.lnk\" ", - before_uninstall=get_before_uninstall(), + before_uninstall=get_before_uninstall(kill_self), subkey=subkey, app_name = crate::get_app_name(), path = path, @@ -1231,7 +1236,7 @@ fn get_uninstall() -> String { } pub fn uninstall_me() -> ResultType<()> { - run_cmds(get_uninstall(), true, "uninstall") + run_cmds(get_uninstall(true), true, "uninstall") } fn write_cmds(cmds: String, ext: &str, tip: &str) -> ResultType { From 303462a87ca9261fd69429f28d0bf130dd9841f5 Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 1 Mar 2023 11:55:56 +0800 Subject: [PATCH 087/382] default config filed Signed-off-by: fufesou --- libs/hbb_common/examples/config.rs | 5 +++++ libs/hbb_common/src/config.rs | 26 ++++++++++++++++---------- 2 files changed, 21 insertions(+), 10 deletions(-) create mode 100644 libs/hbb_common/examples/config.rs diff --git a/libs/hbb_common/examples/config.rs b/libs/hbb_common/examples/config.rs new file mode 100644 index 000000000..95169df8e --- /dev/null +++ b/libs/hbb_common/examples/config.rs @@ -0,0 +1,5 @@ +extern crate hbb_common; + +fn main() { + println!("{:?}", hbb_common::config::PeerConfig::load("455058072")); +} diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 7bc82ed95..6fb2c895e 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -110,10 +110,10 @@ macro_rules! serde_field_string { } macro_rules! serde_field_bool { - ($struct_name: ident, $field_name: literal, $func: ident) => { + ($struct_name: ident, $field_name: literal, $func: ident, $default: literal) => { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct $struct_name { - #[serde(rename = $field_name)] + #[serde(default = $default, rename = $field_name)] pub v: bool, } impl Default for $struct_name { @@ -963,6 +963,7 @@ impl PeerConfig { }; let c = PeerConfig::load(&id_decoded_string); + log::info!("REMOVE ME ============================== peer config {:?}", &c); if c.info.platform.is_empty() { fs::remove_file(p).ok(); } @@ -1037,32 +1038,37 @@ impl PeerConfig { serde_field_bool!( ShowRemoteCursor, "show_remote_cursor", - default_show_remote_cursor + default_show_remote_cursor, + "ShowRemoteCursor::default_show_remote_cursor" ); serde_field_bool!( ShowQualityMonitor, "show_quality_monitor", - default_show_quality_monitor + default_show_quality_monitor, + "ShowQualityMonitor::default_show_quality_monitor" ); -serde_field_bool!(DisableAudio, "disable_audio", default_disable_audio); +serde_field_bool!(DisableAudio, "disable_audio", default_disable_audio, "DisableAudio::default_disable_audio"); serde_field_bool!( EnableFileTransfer, "enable_file_transfer", - default_enable_file_transfer + default_enable_file_transfer, + "EnableFileTransfer::default_enable_file_transfer" ); serde_field_bool!( DisableClipboard, "disable_clipboard", - default_disable_clipboard + default_disable_clipboard, + "DisableClipboard::default_disable_clipboard" ); serde_field_bool!( LockAfterSessionEnd, "lock_after_session_end", - default_lock_after_session_end + default_lock_after_session_end, + "LockAfterSessionEnd::default_lock_after_session_end" ); -serde_field_bool!(PrivacyMode, "privacy_mode", default_privacy_mode); +serde_field_bool!(PrivacyMode, "privacy_mode", default_privacy_mode, "PrivacyMode::default_privacy_mode"); -serde_field_bool!(AllowSwapKey, "allow_swap_key", default_swap_key); +serde_field_bool!(AllowSwapKey, "allow_swap_key", default_allow_swap_key, "AllowSwapKey::default_allow_swap_key"); #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct LocalConfig { From 0d64ee39de95f90c915a51937b408645c728b55b Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 1 Mar 2023 12:20:54 +0800 Subject: [PATCH 088/382] remove print Signed-off-by: fufesou --- libs/hbb_common/src/config.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 6fb2c895e..ed7270a85 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -963,7 +963,6 @@ impl PeerConfig { }; let c = PeerConfig::load(&id_decoded_string); - log::info!("REMOVE ME ============================== peer config {:?}", &c); if c.info.platform.is_empty() { fs::remove_file(p).ok(); } From 874d22168b171e12829b1808cfc564d4a620aefe Mon Sep 17 00:00:00 2001 From: FastAct <93490087+FastAct@users.noreply.github.com> Date: Wed, 1 Mar 2023 07:49:45 +0100 Subject: [PATCH 089/382] Update nl.rs --- src/lang/nl.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lang/nl.rs b/src/lang/nl.rs index cf3eb430c..c0e627c68 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -454,10 +454,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Voice call", "Spraakoproep"), ("Text chat", "Tekst chat"), ("Stop voice call", "Stop spraakoproep"), - ("relay_hint_tip", ""), - ("Reconnect", ""), - ("Codec", ""), - ("Resolution", ""), - ("No transfers in progress", ""), + ("relay_hint_tip", "Indien een directe verbinding niet mogelijk is, kunt u proberen verbinding te maken via een Relay Server. \nAls u bij de eerste poging een relaisverbinding tot stand wilt brengen, kunt u het achtervoegsel \"/r\" toevoegen aan het ID of de optie \"Altijd verbinden via relaisserver\" selecteren op de externe terminal."), + ("Reconnect", "Herverbinden"), + ("Codec", "odec"), + ("Resolution", "Resolutie"), + ("No transfers in progress", "Geen overdrachten in uitvoering"), ].iter().cloned().collect(); } From 80c39574f8c57d0e4e3bcc84a7eb2ea40fd9767a Mon Sep 17 00:00:00 2001 From: FastAct <93490087+FastAct@users.noreply.github.com> Date: Wed, 1 Mar 2023 08:09:11 +0100 Subject: [PATCH 090/382] Update nl.rs --- src/lang/nl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/nl.rs b/src/lang/nl.rs index c0e627c68..d1c154546 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -456,7 +456,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Stop spraakoproep"), ("relay_hint_tip", "Indien een directe verbinding niet mogelijk is, kunt u proberen verbinding te maken via een Relay Server. \nAls u bij de eerste poging een relaisverbinding tot stand wilt brengen, kunt u het achtervoegsel \"/r\" toevoegen aan het ID of de optie \"Altijd verbinden via relaisserver\" selecteren op de externe terminal."), ("Reconnect", "Herverbinden"), - ("Codec", "odec"), + ("Codec", "Codec"), ("Resolution", "Resolutie"), ("No transfers in progress", "Geen overdrachten in uitvoering"), ].iter().cloned().collect(); From 2417a079aab290f07d782c90c769185d594b995f Mon Sep 17 00:00:00 2001 From: Michal Witek Date: Wed, 1 Mar 2023 09:52:26 +0100 Subject: [PATCH 091/382] Additional translation for `pl.rs` --- src/lang/pl.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lang/pl.rs b/src/lang/pl.rs index a0808f5bf..494715527 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -312,8 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Zachowaj usługę RustDesk w tle"), ("Ignore Battery Optimizations", "Ignoruj optymalizację baterii"), ("android_open_battery_optimizations_tip", "Jeśli chcesz wyłączyć tę funkcję, przejdź do następnej strony ustawień aplikacji RustDesk, znajdź i wprowadź [Bateria], odznacz [Bez ograniczeń]"), - ("Start on Boot", ""), - ("Start the screen sharing service on boot, requires special permissions", ""), + ("Start on Boot", "Autostart"), + ("Start the screen sharing service on boot, requires special permissions", "Uruchom usługę udostępniania ekranu podczas startu, wymaga specjalnych uprawnień"), ("Connection not allowed", "Połączenie niedozwolone"), ("Legacy mode", "Tryb kompatybilności wstecznej (legacy)"), ("Map mode", "Tryb mapowania"), @@ -458,6 +458,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Reconnect", "Połącz ponownie"), ("Codec", "Kodek"), ("Resolution", "Rozdzielczość"), - ("No transfers in progress", ""), + ("Key", "Klucz"), + ("No transfers in progress", "Brak transferów w toku"), ].iter().cloned().collect(); } From 7b80269dabcc23a57c529bed7c0e0127dfb2eb17 Mon Sep 17 00:00:00 2001 From: 21pages Date: Wed, 1 Mar 2023 14:18:46 +0800 Subject: [PATCH 092/382] install page use custom titlebar Signed-off-by: 21pages --- flutter/lib/desktop/pages/install_page.dart | 48 ++++++++++++++++++- .../lib/desktop/widgets/tabbar_widget.dart | 16 ++++--- flutter/lib/main.dart | 11 +++-- 3 files changed, 64 insertions(+), 11 deletions(-) diff --git a/flutter/lib/desktop/pages/install_page.dart b/flutter/lib/desktop/pages/install_page.dart index d7202e300..00ca2bb23 100644 --- a/flutter/lib/desktop/pages/install_page.dart +++ b/flutter/lib/desktop/pages/install_page.dart @@ -1,7 +1,9 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; +import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; import 'package:flutter_hbb/models/platform_model.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'; @@ -13,7 +15,51 @@ class InstallPage extends StatefulWidget { State createState() => _InstallPageState(); } -class _InstallPageState extends State with WindowListener { +class _InstallPageState extends State { + final tabController = DesktopTabController(tabType: DesktopTabType.main); + + @override + void initState() { + super.initState(); + Get.put(tabController); + const lable = "install"; + tabController.add(TabInfo( + key: lable, + label: lable, + closable: false, + page: _InstallPageBody( + key: const ValueKey(lable), + ))); + } + + @override + void dispose() { + super.dispose(); + Get.delete(); + } + + @override + Widget build(BuildContext context) { + return DragToResizeArea( + resizeEdgeSize: stateGlobal.resizeEdgeSize.value, + child: Container( + child: Scaffold( + backgroundColor: Theme.of(context).colorScheme.background, + body: DesktopTab(controller: tabController)), + ), + ); + } +} + +class _InstallPageBody extends StatefulWidget { + const _InstallPageBody({Key? key}) : super(key: key); + + @override + State<_InstallPageBody> createState() => _InstallPageBodyState(); +} + +class _InstallPageBodyState extends State<_InstallPageBody> + with WindowListener { late final TextEditingController controller; final RxBool startmenu = true.obs; final RxBool desktopicon = true.obs; diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index 958c4c035..edc779fba 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -53,6 +53,7 @@ enum DesktopTabType { remoteScreen, fileTransfer, portForward, + install, } class DesktopTabState { @@ -249,8 +250,9 @@ class DesktopTab extends StatelessWidget { this.unSelectedTabBackgroundColor, }) : super(key: key) { tabType = controller.tabType; - isMainWindow = - tabType == DesktopTabType.main || tabType == DesktopTabType.cm; + isMainWindow = tabType == DesktopTabType.main || + tabType == DesktopTabType.cm || + tabType == DesktopTabType.install; } static RxString labelGetterAlias(String peerId) { @@ -361,7 +363,8 @@ class DesktopTab extends StatelessWidget { /// - hide single item when only has one item (home) on [DesktopTabPage]. bool isHideSingleItem() { return state.value.tabs.length == 1 && - controller.tabType == DesktopTabType.main; + (controller.tabType == DesktopTabType.main || + controller.tabType == DesktopTabType.install); } Widget _buildBar() { @@ -524,8 +527,8 @@ class WindowActionPanelState extends State } void _setMaximize(bool maximize) { - stateGlobal.setMaximize(maximize); - setState(() {}); + stateGlobal.setMaximize(maximize); + setState(() {}); } @override @@ -759,7 +762,8 @@ class _ListView extends StatelessWidget { /// - hide single item when only has one item (home) on [DesktopTabPage]. bool isHideSingleItem() { return state.value.tabs.length == 1 && - controller.tabType == DesktopTabType.main; + controller.tabType == DesktopTabType.main || + controller.tabType == DesktopTabType.install; } @override diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index 6d3f863e7..bb1b4f552 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -293,16 +293,19 @@ void runInstallPage() async { await windowManager.ensureInitialized(); await initEnv(kAppTypeMain); _runApp('', const InstallPage(), MyTheme.currentThemeMode()); - windowManager.waitUntilReadyToShow( - WindowOptions(size: Size(800, 600), center: true), () async { + WindowOptions windowOptions = + getHiddenTitleBarWindowOptions(size: Size(800, 600), center: true); + windowManager.waitUntilReadyToShow(windowOptions, () async { windowManager.show(); windowManager.focus(); windowManager.setOpacity(1); windowManager.setAlignment(Alignment.center); // ensure + windowManager.setTitle(getWindowName()); }); } -WindowOptions getHiddenTitleBarWindowOptions({Size? size}) { +WindowOptions getHiddenTitleBarWindowOptions( + {Size? size, bool center = false}) { var defaultTitleBarStyle = TitleBarStyle.hidden; // we do not hide titlebar on win7 because of the frame overflow. if (kUseCompatibleUiMode) { @@ -310,7 +313,7 @@ WindowOptions getHiddenTitleBarWindowOptions({Size? size}) { } return WindowOptions( size: size, - center: false, + center: center, backgroundColor: Colors.transparent, skipTaskbar: false, titleBarStyle: defaultTitleBarStyle, From d1f58a444d0bf143e9658cb0b2a43f363347530f Mon Sep 17 00:00:00 2001 From: 21pages Date: Wed, 1 Mar 2023 16:30:39 +0800 Subject: [PATCH 093/382] dark theme disabled button color, disabled combox color Signed-off-by: 21pages --- flutter/lib/common.dart | 21 ++++++++++++++----- .../desktop/pages/desktop_setting_page.dart | 8 +++++-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index e0306a3a7..e049c0fe1 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -218,19 +218,30 @@ class MyTheme { labelColor: Colors.white70, ), scrollbarTheme: ScrollbarThemeData( - thumbColor: MaterialStateProperty.all(Colors.grey[500]) + thumbColor: MaterialStateProperty.all(Colors.grey[500]), ), splashColor: Colors.transparent, highlightColor: Colors.transparent, splashFactory: isDesktop ? NoSplash.splashFactory : null, outlinedButtonTheme: OutlinedButtonThemeData( - style: - OutlinedButton.styleFrom(side: BorderSide(color: Colors.white38))), + style: OutlinedButton.styleFrom( + side: BorderSide(color: Colors.white38), + disabledForegroundColor: Colors.white70, + ), + ), textButtonTheme: isDesktop ? TextButtonThemeData( - style: ButtonStyle(splashFactory: NoSplash.splashFactory), - ) + style: TextButton.styleFrom( + splashFactory: NoSplash.splashFactory, + disabledForegroundColor: Colors.white70, + )) : null, + elevatedButtonTheme: ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + disabledForegroundColor: Colors.white70, + disabledBackgroundColor: Colors.white10, + ), + ), checkboxTheme: const CheckboxThemeData(checkColor: MaterialStatePropertyAll(dark)), colorScheme: ColorScheme.fromSwatch( diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 52f64c0e3..7d907d727 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -538,6 +538,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin { translate('Screen Share'), translate('Deny remote access'), ], + enabled: enabled, initialKey: initialKey, onChanged: (mode) async { String modeValue; @@ -667,6 +668,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin { return _Card(title: 'Password', children: [ _ComboBox( + enabled: !locked, keys: modeKeys, values: modeValues, initialKey: modeInitialKey, @@ -1722,7 +1724,6 @@ class _ComboBox extends StatelessWidget { required this.values, required this.initialKey, required this.onChanged, - // ignore: unused_element this.enabled = true, }) : super(key: key); @@ -1735,7 +1736,9 @@ class _ComboBox extends StatelessWidget { var ref = values[index].obs; current = keys[index]; return Container( - decoration: BoxDecoration(border: Border.all(color: MyTheme.border)), + decoration: BoxDecoration( + border: Border.all( + color: _disabledTextColor(context, enabled) ?? MyTheme.border)), height: 30, child: Obx(() => DropdownButton( isExpanded: true, @@ -1744,6 +1747,7 @@ class _ComboBox extends StatelessWidget { underline: Container( height: 25, ), + style: TextStyle(color: _disabledTextColor(context, enabled)), icon: const Icon( Icons.expand_more_sharp, size: 20, From 279fd7de67e5482c01a19f67057189d28edc7bae Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 1 Mar 2023 17:38:01 +0800 Subject: [PATCH 094/382] win, fix fullscreen with 3 pixels offset Signed-off-by: fufesou --- flutter/pubspec.lock | 4 ++-- flutter/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index 5ffe805b8..76fe929e5 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -325,8 +325,8 @@ packages: dependency: "direct main" description: path: "." - ref: f37357ed98a10717576eb9ed8413e92b2ec5d13a - resolved-ref: f37357ed98a10717576eb9ed8413e92b2ec5d13a + ref: "3e2655677c54f421f9e378680d8171b95a211e0f" + resolved-ref: "3e2655677c54f421f9e378680d8171b95a211e0f" url: "https://github.com/Kingtous/rustdesk_desktop_multi_window" source: git version: "0.1.0" diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 8d390d370..71a840c9c 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: e383fffb5c4529c9e0a710f1025a0c590b99ee08 + ref: 3e2655677c54f421f9e378680d8171b95a211e0f freezed_annotation: ^2.0.3 flutter_custom_cursor: ^0.0.4 window_size: From 6267d56b45e64e6b119489566274156425ee7723 Mon Sep 17 00:00:00 2001 From: 21pages Date: Wed, 1 Mar 2023 19:31:52 +0800 Subject: [PATCH 095/382] fix combox theme Signed-off-by: 21pages --- flutter/lib/common.dart | 8 +++++++- flutter/lib/desktop/pages/desktop_setting_page.dart | 10 ++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index e049c0fe1..c438a3c7b 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -109,27 +109,32 @@ class IconFont { class ColorThemeExtension extends ThemeExtension { const ColorThemeExtension({ required this.border, + required this.border2, required this.highlight, }); final Color? border; + final Color? border2; final Color? highlight; static const light = ColorThemeExtension( border: Color(0xFFCCCCCC), + border2: Color(0xFFBBBBBB), highlight: Color(0xFFE5E5E5), ); static const dark = ColorThemeExtension( border: Color(0xFF555555), + border2: Color(0xFFE5E5E5), highlight: Color(0xFF3F3F3F), ); @override ThemeExtension copyWith( - {Color? border, Color? highlight}) { + {Color? border, Color? border2, Color? highlight}) { return ColorThemeExtension( border: border ?? this.border, + border2: border2 ?? this.border2, highlight: highlight ?? this.highlight, ); } @@ -142,6 +147,7 @@ class ColorThemeExtension extends ThemeExtension { } return ColorThemeExtension( border: Color.lerp(border, other.border, t), + border2: Color.lerp(border2, other.border2, t), highlight: Color.lerp(highlight, other.highlight, t), ); } diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 7d907d727..0aafd48bb 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -1738,7 +1738,10 @@ class _ComboBox extends StatelessWidget { return Container( decoration: BoxDecoration( border: Border.all( - color: _disabledTextColor(context, enabled) ?? MyTheme.border)), + color: enabled + ? MyTheme.color(context).border2 ?? MyTheme.border + : MyTheme.border, + )), height: 30, child: Obx(() => DropdownButton( isExpanded: true, @@ -1747,7 +1750,10 @@ class _ComboBox extends StatelessWidget { underline: Container( height: 25, ), - style: TextStyle(color: _disabledTextColor(context, enabled)), + style: TextStyle( + color: enabled + ? Theme.of(context).textTheme.titleMedium?.color + : _disabledTextColor(context, enabled)), icon: const Icon( Icons.expand_more_sharp, size: 20, From fd8829f08e43cd2eb41c9ac9d638a9c4e7dbc4cc Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Wed, 1 Mar 2023 14:50:50 +0100 Subject: [PATCH 096/382] added icon to dialogButton, reverted some design changes. The outline buttons now rely on theme data --- flutter/lib/common.dart | 79 ++++++-- flutter/lib/common/widgets/peer_card.dart | 62 +++--- .../lib/desktop/pages/file_manager_page.dart | 47 ++--- flutter/lib/mobile/widgets/dialog.dart | 187 ++++++++---------- flutter/lib/models/file_model.dart | 39 ++-- 5 files changed, 210 insertions(+), 204 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 29d4a195d..47850fdb1 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -224,7 +224,20 @@ class MyTheme { ), shape: MaterialStateProperty.all( RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18.0), + borderRadius: BorderRadius.circular(8.0), + ), + ), + ), + ), + outlinedButtonTheme: OutlinedButtonThemeData( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all( + Color(0xFFEEEEEE), + ), + foregroundColor: MaterialStateProperty.all(Colors.black87), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), ), ), ), @@ -296,9 +309,6 @@ 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( @@ -318,7 +328,23 @@ class MyTheme { ), shape: MaterialStateProperty.all( RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18.0), + borderRadius: BorderRadius.circular(8.0), + ), + ), + ), + ), + outlinedButtonTheme: OutlinedButtonThemeData( + style: ButtonStyle( + backgroundColor: MaterialStatePropertyAll( + Color(0xFF24252B), + ), + side: MaterialStatePropertyAll( + BorderSide(color: Colors.white12, width: 0.5), + ), + foregroundColor: MaterialStateProperty.all(Colors.white70), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), ), ), ), @@ -1824,28 +1850,43 @@ class ServerConfig { Widget dialogButton(String text, {required VoidCallback? onPressed, bool isOutline = false, + Widget? icon, TextStyle? style, ButtonStyle? buttonStyle}) { if (isDesktop) { if (isOutline) { - return OutlinedButton( - onPressed: onPressed, - child: Text(translate(text), style: style), - ); + return icon == null + ? OutlinedButton( + onPressed: onPressed, + child: Text(translate(text), style: style), + ) + : OutlinedButton.icon( + icon: icon, + onPressed: onPressed, + label: Text(translate(text), style: style), + ); } else { - return ElevatedButton( - style: ElevatedButton.styleFrom(elevation: 0).merge(buttonStyle), - onPressed: onPressed, - child: Text(translate(text), style: style), - ); + return icon == null + ? ElevatedButton( + style: ElevatedButton.styleFrom(elevation: 0).merge(buttonStyle), + onPressed: onPressed, + child: Text(translate(text), style: style), + ) + : ElevatedButton.icon( + icon: icon, + style: ElevatedButton.styleFrom(elevation: 0).merge(buttonStyle), + onPressed: onPressed, + label: Text(translate(text), style: style), + ); } } else { return TextButton( - onPressed: onPressed, - child: Text( - translate(text), - style: style, - )); + onPressed: onPressed, + child: Text( + translate(text), + style: style, + ), + ); } } diff --git a/flutter/lib/common/widgets/peer_card.dart b/flutter/lib/common/widgets/peer_card.dart index cc5568bca..5a7f2bfa7 100644 --- a/flutter/lib/common/widgets/peer_card.dart +++ b/flutter/lib/common/widgets/peer_card.dart @@ -683,23 +683,21 @@ abstract class BasePeerCard extends StatelessWidget { Obx(() => Offstage( offstage: isInProgress.isFalse, child: const LinearProgressIndicator())), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ElevatedButton.icon( - icon: Icon(Icons.close_rounded), - label: Text(translate("Cancel")), - onPressed: close, - ), - ElevatedButton.icon( - icon: Icon(Icons.done_rounded), - label: Text(translate("Ok")), - onPressed: submit, - ), - ], - ).paddingOnly(top: 20) ], ), + actions: [ + dialogButton( + "Cancel", + icon: Icon(Icons.close_rounded), + onPressed: close, + isOutline: true, + ), + dialogButton( + "OK", + icon: Icon(Icons.done_rounded), + onPressed: submit, + ), + ], onSubmit: submit, onCancel: close, ); @@ -740,26 +738,20 @@ abstract class BasePeerCard extends StatelessWidget { ), ], ), - content: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ElevatedButton.icon( - icon: Icon(Icons.close_rounded), - label: Text(translate("Cancel")), - onPressed: close, - ), - ElevatedButton.icon( - icon: Icon(Icons.done_rounded), - label: Text(translate("Ok")), - onPressed: submit, - ), - ], - ).paddingOnly(top: 20) - ], - ), + content: SizedBox.shrink(), + actions: [ + dialogButton( + "Cancel", + icon: Icon(Icons.close_rounded), + onPressed: close, + isOutline: true, + ), + dialogButton( + "OK", + icon: Icon(Icons.done_rounded), + onPressed: submit, + ), + ], onSubmit: submit, onCancel: close, ); diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 9210a30c1..9c72caa5f 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -989,37 +989,30 @@ class _FileManagerPageState extends State content: Column( mainAxisSize: MainAxisSize.min, children: [ - Column( - children: [ - TextFormField( - decoration: InputDecoration( - labelText: translate( - "Please enter the folder name", - ), - ), - controller: name, - autofocus: true, + TextFormField( + decoration: InputDecoration( + labelText: translate( + "Please enter the folder name", ), - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - ElevatedButton.icon( - icon: Icon(Icons.close_rounded), - label: Text(translate("Cancel")), - onPressed: cancel, - ), - ElevatedButton.icon( - icon: Icon(Icons.done_rounded), - label: Text(translate("Ok")), - onPressed: submit, - ), - ], - ).paddingOnly(top: 20) - ], + ), + controller: name, + autofocus: true, ), ], ), + actions: [ + dialogButton( + "Cancel", + icon: Icon(Icons.close_rounded), + onPressed: cancel, + isOutline: true, + ), + dialogButton( + "Ok", + icon: Icon(Icons.done_rounded), + onPressed: submit, + ), + ], onSubmit: submit, onCancel: cancel, ); diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index 6b87d62ba..3832ca7b1 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -28,27 +28,21 @@ void showRestartRemoteDevice( Icon(Icons.warning_rounded, color: Colors.redAccent, size: 28), Text(translate("Restart Remote Device")).paddingOnly(left: 10), ]), - content: Column( - children: [ - Text( - "${translate('Are you sure you want to restart')} \n${pi.username}@${pi.hostname}($id) ?"), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ElevatedButton.icon( - icon: Icon(Icons.close_rounded), - label: Text(translate("Cancel")), - onPressed: close, - ), - ElevatedButton.icon( - icon: Icon(Icons.done_rounded), - label: Text(translate("Ok")), - onPressed: () => close(true), - ), - ], - ).paddingOnly(top: 20) - ], - ), + content: Text( + "${translate('Are you sure you want to restart')} \n${pi.username}@${pi.hostname}($id) ?"), + actions: [ + dialogButton( + "Cancel", + icon: Icon(Icons.close_rounded), + onPressed: close, + isOutline: true, + ), + dialogButton( + "OK", + icon: Icon(Icons.done_rounded), + onPressed: () => close(true), + ), + ], onCancel: close, onSubmit: () => close(true), )); @@ -82,76 +76,65 @@ void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async { Text(translate('Set your own password')).paddingOnly(left: 10), ], ), - content: Column( - children: [ - Form( - autovalidateMode: AutovalidateMode.onUserInteraction, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - TextFormField( - autofocus: true, - obscureText: true, - keyboardType: TextInputType.visiblePassword, - decoration: InputDecoration( - labelText: translate('Password'), - ), - controller: p0, - validator: (v) { - if (v == null) return null; - final val = v.trim().length > 5; - if (validateLength != val) { - // use delay to make setState success - Future.delayed(Duration(microseconds: 1), - () => setState(() => validateLength = val)); - } - return val - ? null - : translate('Too short, at least 6 characters.'); - }, - ), - TextFormField( - obscureText: true, - keyboardType: TextInputType.visiblePassword, - decoration: InputDecoration( - labelText: translate('Confirmation'), - ), - controller: p1, - validator: (v) { - if (v == null) return null; - final val = p0.text == v; - if (validateSame != val) { - Future.delayed(Duration(microseconds: 1), - () => setState(() => validateSame = val)); - } - return val - ? null - : translate('The confirmation is not identical.'); - }, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ElevatedButton.icon( - icon: Icon(Icons.close_rounded), - label: Text(translate("Cancel")), - onPressed: close, - ), - ElevatedButton.icon( - icon: Icon(Icons.done_rounded), - label: Text(translate("Ok")), - onPressed: - (validateLength && validateSame) ? submit : null, - ), - ], - ).paddingOnly(top: 20) - ], + content: Form( + autovalidateMode: AutovalidateMode.onUserInteraction, + child: Column(mainAxisSize: MainAxisSize.min, children: [ + TextFormField( + autofocus: true, + obscureText: true, + keyboardType: TextInputType.visiblePassword, + decoration: InputDecoration( + labelText: translate('Password'), + ), + controller: p0, + validator: (v) { + if (v == null) return null; + final val = v.trim().length > 5; + if (validateLength != val) { + // use delay to make setState success + Future.delayed(Duration(microseconds: 1), + () => setState(() => validateLength = val)); + } + return val + ? null + : translate('Too short, at least 6 characters.'); + }, ), - ), - ], - ), + TextFormField( + obscureText: true, + keyboardType: TextInputType.visiblePassword, + decoration: InputDecoration( + labelText: translate('Confirmation'), + ), + controller: p1, + validator: (v) { + if (v == null) return null; + final val = p0.text == v; + if (validateSame != val) { + Future.delayed(Duration(microseconds: 1), + () => setState(() => validateSame = val)); + } + return val + ? null + : translate('The confirmation is not identical.'); + }, + ), + ])), onCancel: close, onSubmit: (validateLength && validateSame) ? submit : null, + actions: [ + dialogButton( + 'Cancel', + icon: Icon(Icons.close_rounded), + onPressed: close, + isOutline: true, + ), + dialogButton( + 'OK', + icon: Icon(Icons.done_rounded), + onPressed: (validateLength && validateSame) ? submit : null, + ), + ], ); }); } @@ -233,22 +216,20 @@ void enterPasswordDialog(String id, OverlayDialogManager dialogManager) async { } }, ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ElevatedButton.icon( - icon: Icon(Icons.close_rounded), - label: Text(translate("Cancel")), - onPressed: close, - ), - ElevatedButton.icon( - icon: Icon(Icons.done_rounded), - label: Text(translate("Ok")), - onPressed: submit, - ), - ], - ).paddingOnly(top: 20) ]), + actions: [ + dialogButton( + 'Cancel', + icon: Icon(Icons.close_rounded), + onPressed: cancel, + isOutline: true, + ), + dialogButton( + 'OK', + icon: Icon(Icons.done_rounded), + onPressed: submit, + ), + ], onSubmit: submit, onCancel: cancel, ); diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index 7e702f6f2..a899f4106 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -595,9 +595,10 @@ class FileModel extends ChangeNotifier { final count = entries.length > 1 ? "${i + 1}/${entries.length}" : ""; content = "$dirShow\n\n${entries[i].path}".trim(); final confirm = await showRemoveDialog( - count.isEmpty ? title : "$title ($count)", - content, - item.isDirectory); + count.isEmpty ? title : "$title ($count)", + content, + item.isDirectory, + ); try { if (confirm == true) { sendRemoveFile(entries[i].path, i, items.isLocal!); @@ -647,7 +648,7 @@ class FileModel extends ChangeNotifier { ], ), contentBoxConstraints: - BoxConstraints(minHeight: 80, minWidth: 400, maxWidth: 400), + BoxConstraints(minHeight: 100, minWidth: 400, maxWidth: 400), content: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -673,24 +674,22 @@ class FileModel extends ChangeNotifier { setState(() => removeCheckboxRemember = v); }, ) - : const SizedBox.shrink(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ElevatedButton.icon( - icon: Icon(Icons.close_rounded), - label: Text(translate("Cancel")), - onPressed: cancel, - ), - ElevatedButton.icon( - icon: Icon(Icons.done_rounded), - label: Text(translate("Ok")), - onPressed: submit, - ), - ], - ).paddingOnly(top: 20) + : const SizedBox.shrink() ], ), + actions: [ + dialogButton( + "Cancel", + icon: Icon(Icons.close_rounded), + onPressed: cancel, + isOutline: true, + ), + dialogButton( + "OK", + icon: Icon(Icons.done_rounded), + onPressed: submit, + ), + ], onSubmit: submit, onCancel: cancel, ); From 55831948f8361742eb0473adfd0c9b1d805437f0 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Wed, 1 Mar 2023 16:35:51 +0100 Subject: [PATCH 097/382] prefere MaterialStatePropertyAll to MaterialStateProperty.all and other fixes --- flutter/lib/common.dart | 22 ++--- .../lib/desktop/widgets/remote_menubar.dart | 93 ++++++++++--------- flutter/lib/mobile/pages/server_page.dart | 2 +- flutter/lib/models/file_model.dart | 27 ++++-- 4 files changed, 82 insertions(+), 62 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 47850fdb1..eeae0972b 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -209,7 +209,7 @@ class MyTheme { ? TextButtonThemeData( style: ButtonStyle( splashFactory: NoSplash.splashFactory, - shape: MaterialStateProperty.all( + shape: MaterialStatePropertyAll( RoundedRectangleBorder( borderRadius: BorderRadius.circular(18.0), ), @@ -219,10 +219,10 @@ class MyTheme { : null, elevatedButtonTheme: ElevatedButtonThemeData( style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( + backgroundColor: MaterialStatePropertyAll( MyTheme.accent, ), - shape: MaterialStateProperty.all( + shape: MaterialStatePropertyAll( RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), @@ -231,11 +231,11 @@ class MyTheme { ), outlinedButtonTheme: OutlinedButtonThemeData( style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( + backgroundColor: MaterialStatePropertyAll( Color(0xFFEEEEEE), ), - foregroundColor: MaterialStateProperty.all(Colors.black87), - shape: MaterialStateProperty.all( + foregroundColor: MaterialStatePropertyAll(Colors.black87), + shape: MaterialStatePropertyAll( RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), @@ -313,7 +313,7 @@ class MyTheme { ? TextButtonThemeData( style: ButtonStyle( splashFactory: NoSplash.splashFactory, - shape: MaterialStateProperty.all( + shape: MaterialStatePropertyAll( RoundedRectangleBorder( borderRadius: BorderRadius.circular(18.0), ), @@ -323,10 +323,10 @@ class MyTheme { : null, elevatedButtonTheme: ElevatedButtonThemeData( style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( + backgroundColor: MaterialStatePropertyAll( MyTheme.accent, ), - shape: MaterialStateProperty.all( + shape: MaterialStatePropertyAll( RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), @@ -341,8 +341,8 @@ class MyTheme { side: MaterialStatePropertyAll( BorderSide(color: Colors.white12, width: 0.5), ), - foregroundColor: MaterialStateProperty.all(Colors.white70), - shape: MaterialStateProperty.all( + foregroundColor: MaterialStatePropertyAll(Colors.white70), + shape: MaterialStatePropertyAll( RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 90b48160b..49c56466c 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -411,17 +411,18 @@ class _RemoteMenubarState extends State { borderRadius: BorderRadius.all(Radius.circular(10)), ), child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Theme( - data: themeData(), - child: MenuBar( - children: [ - SizedBox(width: _MenubarTheme.buttonHMargin), - ...menubarItems, - SizedBox(width: _MenubarTheme.buttonHMargin) - ], - ), - )), + scrollDirection: Axis.horizontal, + child: Theme( + data: themeData(), + child: MenuBar( + children: [ + SizedBox(width: _MenubarTheme.buttonHMargin), + ...menubarItems, + SizedBox(width: _MenubarTheme.buttonHMargin) + ], + ), + ), + ), ), _buildDraggableShowHide(context), ], @@ -431,10 +432,13 @@ class _RemoteMenubarState extends State { ThemeData themeData() { return Theme.of(context).copyWith( menuButtonTheme: MenuButtonThemeData( - style: ButtonStyle( - minimumSize: MaterialStatePropertyAll(Size(64, 36)), - textStyle: MaterialStatePropertyAll( - TextStyle(fontWeight: FontWeight.normal)))), + style: ButtonStyle( + minimumSize: MaterialStatePropertyAll(Size(64, 36)), + textStyle: MaterialStatePropertyAll( + TextStyle(fontWeight: FontWeight.normal), + ), + ), + ), dividerTheme: DividerThemeData(space: 4), ); } @@ -662,37 +666,38 @@ class _ControlMenu extends StatelessWidget { Text(translate('OS Password')).paddingOnly(left: 10), ], ), - content: Column(mainAxisSize: MainAxisSize.min, children: [ - PasswordWidget(controller: controller), - CheckboxListTile( - contentPadding: const EdgeInsets.all(0), - dense: true, - controlAffinity: ListTileControlAffinity.leading, - title: Text( - translate('Auto Login'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + PasswordWidget(controller: controller), + CheckboxListTile( + contentPadding: const EdgeInsets.all(0), + dense: true, + controlAffinity: ListTileControlAffinity.leading, + title: Text( + translate('Auto Login'), + ), + value: autoLogin, + onChanged: (v) { + if (v == null) return; + setState(() => autoLogin = v); + }, ), - value: autoLogin, - onChanged: (v) { - if (v == null) return; - setState(() => autoLogin = v); - }, + ], + ), + actions: [ + dialogButton( + "Cancel", + icon: Icon(Icons.close_rounded), + onPressed: close, + isOutline: true, ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ElevatedButton.icon( - icon: Icon(Icons.close_rounded), - label: Text(translate("Cancel")), - onPressed: close, - ), - ElevatedButton.icon( - icon: Icon(Icons.done_rounded), - label: Text(translate("Ok")), - onPressed: submit, - ), - ], - ).paddingOnly(top: 20) - ]), + dialogButton( + "OK", + icon: Icon(Icons.done_rounded), + onPressed: submit, + ), + ], onSubmit: submit, onCancel: close, ); diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index abccdf683..1a77b8983 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -427,7 +427,7 @@ class ConnectionManager extends StatelessWidget { ? ElevatedButton.icon( style: ButtonStyle( backgroundColor: - MaterialStateProperty.all(Colors.red)), + MaterialStatePropertyAll(Colors.red)), icon: const Icon(Icons.close), onPressed: () { bind.cmCloseConnection(connId: client.id); diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index a899f4106..56c9339f3 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -708,9 +708,10 @@ class FileModel extends ChangeNotifier { return CustomAlertDialog( title: Row( children: [ - const Icon(Icons.warning, color: Colors.red), - const SizedBox(width: 20), - Text(title) + const Icon(Icons.warning_rounded, color: Colors.red), + Text(title).paddingOnly( + left: 10, + ), ], ), contentBoxConstraints: @@ -740,9 +741,23 @@ class FileModel extends ChangeNotifier { : const SizedBox.shrink() ]), actions: [ - dialogButton("Cancel", onPressed: cancel, isOutline: true), - dialogButton("Skip", onPressed: () => close(null), isOutline: true), - dialogButton("OK", onPressed: submit), + dialogButton( + "Cancel", + icon: Icon(Icons.close_rounded), + onPressed: cancel, + isOutline: true, + ), + dialogButton( + "Skip", + icon: Icon(Icons.navigate_next_rounded), + onPressed: () => close(null), + isOutline: true, + ), + dialogButton( + "OK", + icon: Icon(Icons.done_rounded), + onPressed: submit, + ), ], onSubmit: submit, onCancel: cancel, From ab4ef977f411075f564bb9c5bab4885cbdd5d01c Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Wed, 1 Mar 2023 18:00:56 +0100 Subject: [PATCH 098/382] Merge branch 'master' into modern-dialog --- .github/workflows/flutter-ci.yml | 14 +- .github/workflows/flutter-nightly.yml | 6 +- Cargo.lock | 2 +- Cargo.toml | 1 + build.py | 187 ++-- docs/CONTRIBUTING-DE.md | 50 + docs/DEVCONTAINER-DE.md | 14 + docs/README-DE.md | 12 +- .../android/app/src/main/AndroidManifest.xml | 22 +- .../com/carriez/flutter_hbb/BootReceiver.kt | 34 +- .../com/carriez/flutter_hbb/MainActivity.kt | 305 +++--- .../com/carriez/flutter_hbb/MainService.kt | 58 +- .../PermissionRequestTransparentActivity.kt | 54 + .../kotlin/com/carriez/flutter_hbb/common.kt | 110 +- .../app/src/main/res/values/styles.xml | 8 + flutter/lib/common.dart | 129 ++- flutter/lib/consts.dart | 27 + .../desktop/pages/desktop_setting_page.dart | 16 +- .../lib/desktop/pages/desktop_tab_page.dart | 2 +- .../desktop/pages/file_manager_tab_page.dart | 2 +- flutter/lib/desktop/pages/install_page.dart | 68 +- .../desktop/pages/port_forward_tab_page.dart | 14 +- .../lib/desktop/pages/remote_tab_page.dart | 4 +- .../desktop/screen/desktop_remote_screen.dart | 5 + .../lib/desktop/widgets/remote_menubar.dart | 38 +- .../lib/desktop/widgets/scroll_wrapper.dart | 1 + .../lib/desktop/widgets/tabbar_widget.dart | 19 +- flutter/lib/main.dart | 14 +- flutter/lib/mobile/pages/server_page.dart | 16 +- flutter/lib/mobile/pages/settings_page.dart | 120 ++- flutter/lib/models/input_model.dart | 29 +- flutter/lib/models/model.dart | 67 +- flutter/lib/models/native_model.dart | 10 +- flutter/lib/models/server_model.dart | 29 +- flutter/lib/models/state_model.dart | 10 + .../macos/Runner.xcodeproj/project.pbxproj | 2 +- flutter/pubspec.lock | 6 +- flutter/pubspec.yaml | 4 +- libs/hbb_common/examples/config.rs | 5 + libs/hbb_common/src/config.rs | 27 +- res/lang.py | 4 +- src/client.rs | 6 + src/flutter_ffi.rs | 18 +- src/lang/ca.rs | 2 + src/lang/cn.rs | 2 + src/lang/cs.rs | 4 +- src/lang/da.rs | 2 + src/lang/de.rs | 8 +- src/lang/en.rs | 4 +- src/lang/eo.rs | 2 + src/lang/es.rs | 4 +- src/lang/fa.rs | 8 +- src/lang/fr.rs | 2 + src/lang/gr.rs | 2 + src/lang/hu.rs | 2 + src/lang/id.rs | 2 + src/lang/it.rs | 4 +- src/lang/ja.rs | 2 + src/lang/ko.rs | 2 + src/lang/kz.rs | 2 + src/lang/nl.rs | 14 +- src/lang/pl.rs | 6 +- src/lang/pt_PT.rs | 4 +- src/lang/ptbr.rs | 2 + src/lang/ro.rs | 2 + src/lang/ru.rs | 8 +- src/lang/sk.rs | 2 + src/lang/sl.rs | 2 + src/lang/sq.rs | 2 + src/lang/sr.rs | 2 + src/lang/sv.rs | 2 + src/lang/template.rs | 2 + src/lang/th.rs | 2 + src/lang/tr.rs | 2 + src/lang/tw.rs | 2 + src/lang/ua.rs | 2 + src/lang/vn.rs | 2 + src/main.rs | 7 +- src/platform/macos.mm | 113 +- src/platform/macos.rs | 8 + src/platform/windows.rs | 46 +- src/server/portable_service.rs | 12 +- src/ui/header.tis | 3 +- src/ui_interface.rs | 6 +- src/ui_session_interface.rs | 96 +- vdi/host/.devcontainer/devcontainer.json | 5 +- vdi/host/Cargo.lock | 970 +++++++++++++++++- vdi/host/Cargo.toml | 4 +- 88 files changed, 2293 insertions(+), 658 deletions(-) create mode 100644 docs/CONTRIBUTING-DE.md create mode 100644 docs/DEVCONTAINER-DE.md create mode 100644 flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/PermissionRequestTransparentActivity.kt create mode 100644 libs/hbb_common/examples/config.rs diff --git a/.github/workflows/flutter-ci.yml b/.github/workflows/flutter-ci.yml index 74e4efa99..cae5b82c7 100644 --- a/.github/workflows/flutter-ci.yml +++ b/.github/workflows/flutter-ci.yml @@ -18,7 +18,7 @@ on: env: LLVM_VERSION: "15.0.6" - FLUTTER_VERSION: "3.7.0" + FLUTTER_VERSION: "3.7.5" # vcpkg version: 2022.05.10 # for multiarch gcc compatibility VCPKG_COMMIT_ID: "14e7bb4ae24616ec54ff6b2f6ef4e8659434ea44" @@ -260,7 +260,7 @@ jobs: job: - { target: x86_64-unknown-linux-gnu, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-args: "", } steps: @@ -330,13 +330,13 @@ jobs: - { arch: x86_64, target: aarch64-linux-android, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-features: "", } # - { # arch: x86_64, # target: armv7-linux-androideabi, - # os: ubuntu-18.04, + # os: ubuntu-20.04, # extra-build-features: "", # } steps: @@ -907,19 +907,19 @@ jobs: - { arch: x86_64, target: x86_64-unknown-linux-gnu, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-features: "", } - { arch: x86_64, target: x86_64-unknown-linux-gnu, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-features: "flatpak", } - { arch: x86_64, target: x86_64-unknown-linux-gnu, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-features: "appimage", } # - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true } diff --git a/.github/workflows/flutter-nightly.yml b/.github/workflows/flutter-nightly.yml index b08193971..ffcadd18b 100644 --- a/.github/workflows/flutter-nightly.yml +++ b/.github/workflows/flutter-nightly.yml @@ -732,7 +732,7 @@ jobs: x86_64) # no need mock on x86_64 export VCPKG_ROOT=/opt/artifacts/vcpkg - cargo build --lib --features hwcodec,flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features hwcodec,flutter,${{ matrix.job.extra-build-features }} --release ;; esac @@ -900,7 +900,7 @@ jobs: ln -s /usr/include /vcpkg/installed/arm64-linux/include export VCPKG_ROOT=/vcpkg # disable hwcodec for compilation - cargo build --lib --features flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features flutter,${{ matrix.job.extra-build-features }} --release ;; armv7) cp -r /opt/artifacts/vcpkg/installed/lib/* /usr/lib/arm-linux-gnueabihf/ @@ -910,7 +910,7 @@ jobs: ln -s /usr/include /vcpkg/installed/arm-linux/include export VCPKG_ROOT=/vcpkg # disable hwcodec for compilation - cargo build --lib --features flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features flutter,${{ matrix.job.extra-build-features }} --release ;; esac diff --git a/Cargo.lock b/Cargo.lock index a2cdf91a4..8f8895bd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4656,7 +4656,7 @@ dependencies = [ [[package]] name = "rdev" version = "0.5.0-2" -source = "git+https://github.com/fufesou/rdev#5b9fb5e42117f44e0ce0fe7cf2bddf270c75f1dc" +source = "git+https://github.com/fufesou/rdev#25a99ce71ab42843ad253dd51e6a35e83e87a8a4" dependencies = [ "cocoa", "core-foundation 0.9.3", diff --git a/Cargo.toml b/Cargo.toml index f93f776a0..b53615c4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -132,6 +132,7 @@ flutter_rust_bridge = "1.61.1" [workspace] members = ["libs/scrap", "libs/hbb_common", "libs/enigo", "libs/clipboard", "libs/virtual_display", "libs/virtual_display/dylib", "libs/simple_rc", "libs/portable"] +exclude = ["vdi/host"] [package.metadata.winres] LegalCopyright = "Copyright © 2022 Purslane, Inc." diff --git a/build.py b/build.py index 727b53fe0..45fe1b132 100755 --- a/build.py +++ b/build.py @@ -18,14 +18,11 @@ exe_path = 'target/release/' + hbb_name flutter_win_target_dir = 'flutter/build/windows/runner/Release/' skip_cargo = False -def custom_os_system(cmd): - err = os._system(cmd) +def system2(cmd): + err = os.system(cmd) if err != 0: print(f"Error occurred when executing: {cmd}. Exiting.") sys.exit(-1) -# replace prebuilt os.system -os._system = os.system -os.system = custom_os_system def get_version(): with open("Cargo.toml", encoding="utf-8") as fh: @@ -144,8 +141,8 @@ def generate_build_script_for_docker(): # build rustdesk ./build.py --flutter --hwcodec ''') - os.system("chmod +x /tmp/build.sh") - os.system("bash /tmp/build.sh") + system2("chmod +x /tmp/build.sh") + system2("bash /tmp/build.sh") def download_extract_features(features, res_dir): @@ -250,7 +247,7 @@ def get_features(args): def generate_control_file(version): control_file_path = "../res/DEBIAN/control" - os.system('/bin/rm -rf %s' % control_file_path) + system2('/bin/rm -rf %s' % control_file_path) content = """Package: rustdesk Version: %s @@ -268,45 +265,45 @@ Description: A remote control software. def ffi_bindgen_function_refactor(): # workaround ffigen - os.system( + system2( 'sed -i "s/ffi.NativeFunction> tmpdeb/usr/share/rustdesk/files/polkit && chmod a+x tmpdeb/usr/share/rustdesk/files/polkit") - os.system('mkdir -p tmpdeb/DEBIAN') + system2('mkdir -p tmpdeb/DEBIAN') generate_control_file(version) - os.system('cp -a ../res/DEBIAN/* tmpdeb/DEBIAN/') + system2('cp -a ../res/DEBIAN/* tmpdeb/DEBIAN/') md5_file('usr/share/rustdesk/files/systemd/rustdesk.service') - os.system('dpkg-deb -b tmpdeb rustdesk.deb;') + system2('dpkg-deb -b tmpdeb rustdesk.deb;') - os.system('/bin/rm -rf tmpdeb/') - os.system('/bin/rm -rf ../res/DEBIAN/control') + system2('/bin/rm -rf tmpdeb/') + system2('/bin/rm -rf ../res/DEBIAN/control') os.rename('rustdesk.deb', '../rustdesk-%s.deb' % version) os.chdir("..") @@ -314,46 +311,43 @@ def build_flutter_deb(version, features): def build_flutter_dmg(version, features): if not skip_cargo: # set minimum osx build target, now is 10.14, which is the same as the flutter xcode project - os.system(f'MACOSX_DEPLOYMENT_TARGET=10.14 cargo build --features {features} --lib --release') + system2(f'MACOSX_DEPLOYMENT_TARGET=10.14 cargo build --features {features} --lib --release') # copy dylib - os.system( + system2( "cp target/release/liblibrustdesk.dylib target/release/librustdesk.dylib") - # ffi_bindgen_function_refactor() - # limitations from flutter rust bridge - os.system('sed -i "" "s/char \*\*rustdesk_core_main(int \*args_len);//" flutter/macos/Runner/bridge_generated.h') os.chdir('flutter') - os.system('flutter build macos --release') - os.system( - "create-dmg rustdesk.dmg ./build/macos/Build/Products/Release/RustDesk.app") + system2('flutter build macos --release') + system2( + "create-dmg --volname \"RustDesk Installer\" --window-pos 200 120 --window-size 800 400 --icon-size 100 --app-drop-link 600 185 --icon RustDesk.app 200 190 --hide-extension RustDesk.app rustdesk.dmg ./build/macos/Build/Products/Release/RustDesk.app") os.rename("rustdesk.dmg", f"../rustdesk-{version}.dmg") os.chdir("..") def build_flutter_arch_manjaro(version, features): if not skip_cargo: - os.system(f'cargo build --features {features} --lib --release') + system2(f'cargo build --features {features} --lib --release') ffi_bindgen_function_refactor() os.chdir('flutter') - os.system('flutter build linux --release') - os.system('strip build/linux/x64/release/bundle/lib/librustdesk.so') + system2('flutter build linux --release') + system2('strip build/linux/x64/release/bundle/lib/librustdesk.so') os.chdir('../res') - os.system('HBB=`pwd`/.. FLUTTER=1 makepkg -f') + system2('HBB=`pwd`/.. FLUTTER=1 makepkg -f') def build_flutter_windows(version, features): if not skip_cargo: - os.system(f'cargo build --features {features} --lib --release') + system2(f'cargo build --features {features} --lib --release') if not os.path.exists("target/release/librustdesk.dll"): print("cargo build failed, please check rust source code.") exit(-1) os.chdir('flutter') - os.system('flutter build windows --release') + system2('flutter build windows --release') os.chdir('..') shutil.copy2('target/release/deps/dylib_virtual_display.dll', flutter_win_target_dir) os.chdir('libs/portable') - os.system('pip3 install -r requirements.txt') - os.system( + system2('pip3 install -r requirements.txt') + system2( f'python3 ./generate.py -f ../../{flutter_win_target_dir} -o . -e ../../{flutter_win_target_dir}/rustdesk.exe') os.chdir('../..') if os.path.exists('./rustdesk_portable.exe'): @@ -374,22 +368,15 @@ def main(): parser = make_parser() args = parser.parse_args() - shutil.copy2('Cargo.toml', 'Cargo.toml.bk') - shutil.copy2('src/main.rs', 'src/main.rs.bk') - if windows: - txt = open('src/main.rs', encoding='utf8').read() - with open('src/main.rs', 'wt', encoding='utf8') as fh: - fh.write(txt.replace( - '//#![windows_subsystem', '#![windows_subsystem')) if os.path.exists(exe_path): os.unlink(exe_path) if os.path.isfile('/usr/bin/pacman'): - os.system('git checkout src/ui/common.tis') + system2('git checkout src/ui/common.tis') version = get_version() features = ','.join(get_features(args)) flutter = args.flutter if not flutter: - os.system('python3 res/inline-sciter.py') + system2('python3 res/inline-sciter.py') print(args.skip_cargo) if args.skip_cargo: skip_cargo = True @@ -397,55 +384,55 @@ def main(): if windows: # build virtual display dynamic library os.chdir('libs/virtual_display/dylib') - os.system('cargo build --release') + system2('cargo build --release') os.chdir('../../..') if flutter: build_flutter_windows(version, features) return - os.system('cargo build --release --features ' + features) - # os.system('upx.exe target/release/rustdesk.exe') - os.system('mv target/release/rustdesk.exe target/release/RustDesk.exe') + system2('cargo build --release --features ' + features) + # system2('upx.exe target/release/rustdesk.exe') + system2('mv target/release/rustdesk.exe target/release/RustDesk.exe') pa = os.environ.get('P') if pa: - os.system( + system2( f'signtool sign /a /v /p {pa} /debug /f .\\cert.pfx /t http://timestamp.digicert.com ' 'target\\release\\rustdesk.exe') else: print('Not signed') - os.system( + system2( f'cp -rf target/release/RustDesk.exe rustdesk-{version}-win7-install.exe') elif os.path.isfile('/usr/bin/pacman'): # pacman -S -needed base-devel - os.system("sed -i 's/pkgver=.*/pkgver=%s/g' res/PKGBUILD" % version) + system2("sed -i 's/pkgver=.*/pkgver=%s/g' res/PKGBUILD" % version) if flutter: build_flutter_arch_manjaro(version, features) else: - os.system('cargo build --release --features ' + features) - os.system('git checkout src/ui/common.tis') - os.system('strip target/release/rustdesk') - os.system('ln -s res/pacman_install && ln -s res/PKGBUILD') - os.system('HBB=`pwd` makepkg -f') - os.system('mv rustdesk-%s-0-x86_64.pkg.tar.zst rustdesk-%s-manjaro-arch.pkg.tar.zst' % ( + system2('cargo build --release --features ' + features) + system2('git checkout src/ui/common.tis') + system2('strip target/release/rustdesk') + system2('ln -s res/pacman_install && ln -s res/PKGBUILD') + system2('HBB=`pwd` makepkg -f') + system2('mv rustdesk-%s-0-x86_64.pkg.tar.zst rustdesk-%s-manjaro-arch.pkg.tar.zst' % ( version, version)) # pacman -U ./rustdesk.pkg.tar.zst elif os.path.isfile('/usr/bin/yum'): - os.system('cargo build --release --features ' + features) - os.system('strip target/release/rustdesk') - os.system( + system2('cargo build --release --features ' + features) + system2('strip target/release/rustdesk') + system2( "sed -i 's/Version: .*/Version: %s/g' res/rpm.spec" % version) - os.system('HBB=`pwd` rpmbuild -ba res/rpm.spec') - os.system( + system2('HBB=`pwd` rpmbuild -ba res/rpm.spec') + system2( 'mv $HOME/rpmbuild/RPMS/x86_64/rustdesk-%s-0.x86_64.rpm ./rustdesk-%s-fedora28-centos8.rpm' % ( version, version)) # yum localinstall rustdesk.rpm elif os.path.isfile('/usr/bin/zypper'): - os.system('cargo build --release --features ' + features) - os.system('strip target/release/rustdesk') - os.system( + system2('cargo build --release --features ' + features) + system2('strip target/release/rustdesk') + system2( "sed -i 's/Version: .*/Version: %s/g' res/rpm-suse.spec" % version) - os.system('HBB=`pwd` rpmbuild -ba res/rpm-suse.spec') - os.system( + system2('HBB=`pwd` rpmbuild -ba res/rpm-suse.spec') + system2( 'mv $HOME/rpmbuild/RPMS/x86_64/rustdesk-%s-0.x86_64.rpm ./rustdesk-%s-suse.rpm' % ( version, version)) # yum localinstall rustdesk.rpm @@ -455,18 +442,18 @@ def main(): build_flutter_dmg(version, features) pass else: - # os.system( + # system2( # 'mv target/release/bundle/deb/rustdesk*.deb ./flutter/rustdesk.deb') build_flutter_deb(version, features) else: - os.system('cargo bundle --release --features ' + features) + system2('cargo bundle --release --features ' + features) if osx: - os.system( + system2( 'strip target/release/bundle/osx/RustDesk.app/Contents/MacOS/rustdesk') - os.system( + system2( 'cp libsciter.dylib target/release/bundle/osx/RustDesk.app/Contents/MacOS/') # https://github.com/sindresorhus/create-dmg - os.system('/bin/rm -rf *.dmg') + system2('/bin/rm -rf *.dmg') plist = "target/release/bundle/osx/RustDesk.app/Contents/Info.plist" txt = open(plist).read() with open(plist, "wt") as fh: @@ -476,7 +463,7 @@ def main(): """)) pa = os.environ.get('P') if pa: - os.system(''' + system2(''' # buggy: rcodesign sign ... path/*, have to sign one by one # install rcodesign via cargo install apple-codesign #rcodesign sign --p12-file ~/.p12/rustdesk-developer-id.p12 --p12-password-file ~/.p12/.cert-pass --code-signature-flags runtime ./target/release/bundle/osx/RustDesk.app/Contents/MacOS/rustdesk @@ -486,11 +473,11 @@ def main(): codesign -s "Developer ID Application: {0}" --force --options runtime ./target/release/bundle/osx/RustDesk.app/Contents/MacOS/* codesign -s "Developer ID Application: {0}" --force --options runtime ./target/release/bundle/osx/RustDesk.app '''.format(pa)) - os.system('create-dmg target/release/bundle/osx/RustDesk.app') + system2('create-dmg target/release/bundle/osx/RustDesk.app') os.rename('RustDesk %s.dmg' % version, 'rustdesk-%s.dmg' % version) if pa: - os.system(''' + system2(''' # https://pyoxidizer.readthedocs.io/en/apple-codesign-0.14.0/apple_codesign.html # https://pyoxidizer.readthedocs.io/en/stable/tugger_code_signing.html # https://developer.apple.com/developer-id/ @@ -507,34 +494,32 @@ def main(): print('Not signed') else: # buid deb package - os.system( + system2( 'mv target/release/bundle/deb/rustdesk*.deb ./rustdesk.deb') - os.system('dpkg-deb -R rustdesk.deb tmpdeb') - os.system('mkdir -p tmpdeb/usr/share/rustdesk/files/systemd/') - os.system( + system2('dpkg-deb -R rustdesk.deb tmpdeb') + system2('mkdir -p tmpdeb/usr/share/rustdesk/files/systemd/') + system2( 'cp res/rustdesk.service tmpdeb/usr/share/rustdesk/files/systemd/') - os.system( + system2( 'cp res/128x128@2x.png tmpdeb/usr/share/rustdesk/files/rustdesk.png') - os.system( + system2( 'cp res/rustdesk.desktop tmpdeb/usr/share/applications/rustdesk.desktop') - os.system( + system2( 'cp res/rustdesk-link.desktop tmpdeb/usr/share/applications/rustdesk-link.desktop') - os.system('cp -a res/DEBIAN/* tmpdeb/DEBIAN/') - os.system('strip tmpdeb/usr/bin/rustdesk') - os.system('mkdir -p tmpdeb/usr/lib/rustdesk') - os.system('mv tmpdeb/usr/bin/rustdesk tmpdeb/usr/lib/rustdesk/') - os.system('cp libsciter-gtk.so tmpdeb/usr/lib/rustdesk/') + system2('cp -a res/DEBIAN/* tmpdeb/DEBIAN/') + system2('strip tmpdeb/usr/bin/rustdesk') + system2('mkdir -p tmpdeb/usr/lib/rustdesk') + system2('mv tmpdeb/usr/bin/rustdesk tmpdeb/usr/lib/rustdesk/') + system2('cp libsciter-gtk.so tmpdeb/usr/lib/rustdesk/') md5_file('usr/share/rustdesk/files/systemd/rustdesk.service') md5_file('usr/lib/rustdesk/libsciter-gtk.so') - os.system('dpkg-deb -b tmpdeb rustdesk.deb; /bin/rm -rf tmpdeb/') + system2('dpkg-deb -b tmpdeb rustdesk.deb; /bin/rm -rf tmpdeb/') os.rename('rustdesk.deb', 'rustdesk-%s.deb' % version) - os.system("mv Cargo.toml.bk Cargo.toml") - os.system("mv src/main.rs.bk src/main.rs") def md5_file(fn): md5 = hashlib.md5(open('tmpdeb/' + fn, 'rb').read()).hexdigest() - os.system('echo "%s %s" >> tmpdeb/DEBIAN/md5sums' % (md5, fn)) + system2('echo "%s %s" >> tmpdeb/DEBIAN/md5sums' % (md5, fn)) if __name__ == "__main__": diff --git a/docs/CONTRIBUTING-DE.md b/docs/CONTRIBUTING-DE.md new file mode 100644 index 000000000..6258a9a7a --- /dev/null +++ b/docs/CONTRIBUTING-DE.md @@ -0,0 +1,50 @@ +# Beitrge zu RustDesk + +RustDesk begrt Beitrge von jedem. Hier sind die Richtlinien, wenn Sie uns +helfen mchten: + +## Beitrge + +Beitrge zu RustDesk oder seinen Abhngigkeiten sollten in Form von Pull +Requests auf GitHub erfolgen. Jeder Pull Request wird von einem Hauptakteur +(jemand mit der Erlaubnis, Korrekturen einzubringen) geprft und entweder in den +Hauptbaum eingefgt oder Feedback fr notwendige nderungen gegeben. Alle +Beitrge sollten diesem Format folgen, auch die von Hauptakteuren. + +Wenn Sie an einem Problem arbeiten mchten, melden Sie es bitte zuerst an, indem +Sie auf GitHub erklren, dass Sie daran arbeiten mchten. Damit soll verhindert +werden, dass Beitrge zum gleichen Thema doppelt bearbeitet werden. + +## Checkliste fr Pull Requests + +- Verzweigen Sie sich vom Master-Branch und, falls ntig, wechseln Sie zum + aktuellen Master-Branch, bevor Sie Ihren Pull Request einreichen. Wenn das + Zusammenfhren mit dem Master nicht reibungslos funktioniert, werden Sie + mglicherweise aufgefordert, Ihre nderungen zu berarbeiten. + +- Commits sollten so klein wie mglich sein und gleichzeitig sicherstellen, dass + jeder Commit unabhngig voneinander korrekt ist (d. h., jeder Commit sollte + sich bersetzen lassen und Tests bestehen). + +- Commits sollten von einem "Herkunftszertifikat fr Entwickler" + (https://developercertificate.org) begleitet werden, das besagt, dass Sie (und + ggf. Ihr Arbeitgeber) mit den Bedingungen der [Projektlizenz](../LICENCE) + einverstanden sind. In Git ist dies die Option `-s` fr `git commit`. + +- Wenn Ihr Patch nicht begutachtet wird oder Sie eine bestimmte Person zur + Begutachtung bentigen, knnen Sie einem Gutachter mit @ antworten und um eine + Begutachtung des Pull Requests oder einen Kommentar bitten. Sie knnen auch + per [E-Mail](mailto:info@rustdesk.com) um eine Begutachtung bitten. + +- Fgen Sie Tests hinzu, die sich auf den behobenen Fehler oder die neue + Funktion beziehen. + +Spezifische Git-Anweisungen finden Sie im [GitHub-Workflow](https://github.com/servo/servo/wiki/GitHub-workflow). + +## Verhalten + +https://github.com/rustdesk/rustdesk/blob/master/docs/CODE_OF_CONDUCT.md + +## Kommunikation + +RustDesk-Mitarbeiter arbeiten hufig im [Discord](https://discord.gg/nDceKgxnkV). diff --git a/docs/DEVCONTAINER-DE.md b/docs/DEVCONTAINER-DE.md new file mode 100644 index 000000000..2a0d73f17 --- /dev/null +++ b/docs/DEVCONTAINER-DE.md @@ -0,0 +1,14 @@ + +Nach dem Start von Dev-Container im Docker-Container wird ein Linux-Binrprogramm im Debug-Modus erstellt. + +Derzeit bietet Dev-Container Linux- und Android-Builds sowohl im Debug- als auch im Release-Modus an. + +Nachfolgend finden Sie eine Tabelle mit Befehlen, die im Stammverzeichnis des Projekts ausgefhrt werden mssen, um bestimmte Builds zu erstellen. + +Kommando|Build-Typ|Modus +-|-|-| +`.devcontainer/build.sh --debug linux`|Linux|debug +`.devcontainer/build.sh --release linux`|Linux|release +`.devcontainer/build.sh --debug android`|android-arm64|debug +`.devcontainer/build.sh --release android`|android-arm64|release + diff --git a/docs/README-DE.md b/docs/README-DE.md index 8ee4a51fa..dd2aa8609 100644 --- a/docs/README-DE.md +++ b/docs/README-DE.md @@ -17,9 +17,9 @@ RustDesk ist eine in Rust geschriebene Remote-Desktop-Software, die out of the b ![image](https://user-images.githubusercontent.com/71636191/171661982-430285f0-2e12-4b1d-9957-4a58e375304d.png) -RustDesk heißt jegliche Mitarbeit willkommen. Schau dir [`docs/CONTRIBUTING.md`](CONTRIBUTING.md) an, wenn du Unterstützung beim Start brauchst. +RustDesk heißt jegliche Mitarbeit willkommen. Schau dir [CONTRIBUTING-DE.md](CONTRIBUTING-DE.md) an, wenn du Unterstützung beim Start brauchst. -[**Wie arbeitet RustDesk?**](https://github.com/rustdesk/rustdesk/wiki/How-does-RustDesk-work%3F) +[**FAQ**](https://github.com/rustdesk/rustdesk/wiki/FAQ) [**Programm herunterladen**](https://github.com/rustdesk/rustdesk/releases) @@ -41,6 +41,14 @@ Nachfolgend sind die Server gelistet, die du kostenlos nutzen kannst. Es kann se | USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8 GB RAM | | Ukraine (Kiew) | dc.volia (2VM) | 2 vCPU / 4 GB RAM | +## Dev-Container + +[![In Dev-Containern öffnen](https://img.shields.io/static/v1?label=Dev%20Container&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/rustdesk/rustdesk) + +Wenn du VS Code und Docker bereits installiert hast, kannst du auf das Abzeichen oben klicken, um loszulegen. Wenn du darauf klickst, wird VS Code automatisch die Dev-Container-Erweiterung installieren, den Quellcode in ein Container-Volume klonen und einen Dev-Container für die Verwendung aufsetzen. + +Weitere Informationen findest du in [DEVCONTAINER-DE.md](DEVCONTAINER-DE.md). + ## Abhängigkeiten Desktop-Versionen verwenden [Sciter](https://sciter.com/) oder Flutter für die GUI, dieses Tutorial ist nur für Sciter. diff --git a/flutter/android/app/src/main/AndroidManifest.xml b/flutter/android/app/src/main/AndroidManifest.xml index ede6353ef..b3c655917 100644 --- a/flutter/android/app/src/main/AndroidManifest.xml +++ b/flutter/android/app/src/main/AndroidManifest.xml @@ -11,22 +11,25 @@ - + + + android:supportsRtl="true"> + android:enabled="true" + android:exported="true"> + + @@ -53,8 +56,6 @@ android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:windowSoftInputMode="adjustResize"> - - @@ -62,6 +63,11 @@ + + - + \ No newline at end of file diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt index 328701567..71bbba754 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt @@ -1,21 +1,45 @@ package com.carriez.flutter_hbb +import android.Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS +import android.Manifest.permission.SYSTEM_ALERT_WINDOW import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.os.Build +import android.util.Log import android.widget.Toast +import com.hjq.permissions.XXPermissions +import io.flutter.embedding.android.FlutterActivity + +const val DEBUG_BOOT_COMPLETED = "com.carriez.flutter_hbb.DEBUG_BOOT_COMPLETED" class BootReceiver : BroadcastReceiver() { + private val logTag = "tagBootReceiver" + override fun onReceive(context: Context, intent: Intent) { - if ("android.intent.action.BOOT_COMPLETED" == intent.action){ - val it = Intent(context,MainService::class.java).apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + Log.d(logTag, "onReceive ${intent.action}") + + if (Intent.ACTION_BOOT_COMPLETED == intent.action || DEBUG_BOOT_COMPLETED == intent.action) { + // check SharedPreferences config + val prefs = context.getSharedPreferences(KEY_SHARED_PREFERENCES, FlutterActivity.MODE_PRIVATE) + if (!prefs.getBoolean(KEY_START_ON_BOOT_OPT, false)) { + Log.d(logTag, "KEY_START_ON_BOOT_OPT is false") + return } - Toast.makeText(context, "RustDesk is Open", Toast.LENGTH_LONG).show(); + // check pre-permission + if (!XXPermissions.isGranted(context, REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, SYSTEM_ALERT_WINDOW)){ + Log.d(logTag, "REQUEST_IGNORE_BATTERY_OPTIMIZATIONS or SYSTEM_ALERT_WINDOW is not granted") + return + } + + val it = Intent(context, MainService::class.java).apply { + action = ACT_INIT_MEDIA_PROJECTION_AND_SERVICE + putExtra(EXT_INIT_FROM_BOOT, true) + } + Toast.makeText(context, "RustDesk is Open", Toast.LENGTH_LONG).show() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.startForegroundService(it) - }else{ + } else { context.startService(it) } } diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt index fd340f7ed..52a5ff75e 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt @@ -7,35 +7,29 @@ package com.carriez.flutter_hbb * Inspired by [droidVNC-NG] https://github.com/bk138/droidVNC-NG */ -import android.app.Activity import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.ServiceConnection -import android.media.projection.MediaProjectionManager import android.os.Build import android.os.IBinder -import android.provider.Settings import android.util.Log import android.view.WindowManager -import androidx.annotation.RequiresApi +import com.hjq.permissions.XXPermissions import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel -const val MEDIA_REQUEST_CODE = 42 class MainActivity : FlutterActivity() { companion object { - lateinit var flutterMethodChannel: MethodChannel + var flutterMethodChannel: MethodChannel? = null } private val channelTag = "mChannel" private val logTag = "mMainActivity" - private var mediaProjectionResultIntent: Intent? = null private var mainService: MainService? = null - @RequiresApi(Build.VERSION_CODES.M) override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) if (MainService.isReady) { @@ -46,169 +40,32 @@ class MainActivity : FlutterActivity() { flutterMethodChannel = MethodChannel( flutterEngine.dartExecutor.binaryMessenger, channelTag - ).apply { - // make sure result is set, otherwise flutter will await forever - setMethodCallHandler { call, result -> - when (call.method) { - "init_service" -> { - Intent(activity, MainService::class.java).also { - bindService(it, serviceConnection, Context.BIND_AUTO_CREATE) - } - if (MainService.isReady) { - result.success(false) - return@setMethodCallHandler - } - getMediaProjection() - result.success(true) - } - "start_capture" -> { - mainService?.let { - result.success(it.startCapture()) - } ?: let { - result.success(false) - } - } - "stop_service" -> { - Log.d(logTag, "Stop service") - mainService?.let { - it.destroy() - result.success(true) - } ?: let { - result.success(false) - } - } - "check_permission" -> { - if (call.arguments is String) { - result.success(checkPermission(context, call.arguments as String)) - } else { - result.success(false) - } - } - "request_permission" -> { - if (call.arguments is String) { - requestPermission(context, call.arguments as String) - result.success(true) - } else { - result.success(false) - } - } - "check_video_permission" -> { - mainService?.let { - result.success(it.checkMediaPermission()) - } ?: let { - result.success(false) - } - } - "check_service" -> { - flutterMethodChannel.invokeMethod( - "on_state_changed", - mapOf("name" to "input", "value" to InputService.isOpen.toString()) - ) - flutterMethodChannel.invokeMethod( - "on_state_changed", - mapOf("name" to "media", "value" to MainService.isReady.toString()) - ) - result.success(true) - } - "init_input" -> { - initInput() - result.success(true) - } - "stop_input" -> { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - InputService.ctx?.disableSelf() - } - InputService.ctx = null - flutterMethodChannel.invokeMethod( - "on_state_changed", - mapOf("name" to "input", "value" to InputService.isOpen.toString()) - ) - result.success(true) - } - "cancel_notification" -> { - try { - val id = call.arguments as Int - mainService?.cancelNotification(id) - } finally { - result.success(true) - } - } - "enable_soft_keyboard" -> { - // https://blog.csdn.net/hanye2020/article/details/105553780 - try { - if (call.arguments as Boolean) { - window.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) - } else { - window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) - } - } finally { - result.success(true) - } - } - else -> { - result.error("-1", "No such method", null) - } - } - } - } - } - - private fun getMediaProjection() { - val mMediaProjectionManager = - getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager - val mIntent = mMediaProjectionManager.createScreenCaptureIntent() - startActivityForResult(mIntent, MEDIA_REQUEST_CODE) - } - - private fun initService() { - if (mediaProjectionResultIntent == null) { - Log.w(logTag, "initService fail,mediaProjectionResultIntent is null") - return - } - Log.d(logTag, "Init service") - val serviceIntent = Intent(this, MainService::class.java) - serviceIntent.action = INIT_SERVICE - serviceIntent.putExtra(EXTRA_MP_DATA, mediaProjectionResultIntent) - - launchMainService(serviceIntent) - } - - private fun launchMainService(intent: Intent) { - // TEST api < O - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - startForegroundService(intent) - } else { - startService(intent) - } - } - - private fun initInput() { - val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS) - if (intent.resolveActivity(packageManager) != null) { - startActivity(intent) - } + ) + initFlutterChannel(flutterMethodChannel!!) } override fun onResume() { super.onResume() val inputPer = InputService.isOpen activity.runOnUiThread { - flutterMethodChannel.invokeMethod( + flutterMethodChannel?.invokeMethod( "on_state_changed", mapOf("name" to "input", "value" to inputPer.toString()) ) } } + private fun requestMediaProjection() { + val intent = Intent(this, PermissionRequestTransparentActivity::class.java).apply { + action = ACT_REQUEST_MEDIA_PROJECTION + } + startActivityForResult(intent, REQ_INVOKE_PERMISSION_ACTIVITY_MEDIA_PROJECTION) + } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - if (requestCode == MEDIA_REQUEST_CODE) { - if (resultCode == Activity.RESULT_OK && data != null) { - mediaProjectionResultIntent = data - initService() - } else { - flutterMethodChannel.invokeMethod("on_media_projection_canceled", null) - } + if (requestCode == REQ_INVOKE_PERMISSION_ACTIVITY_MEDIA_PROJECTION && resultCode == RES_FAILED) { + flutterMethodChannel?.invokeMethod("on_media_projection_canceled", null) } } @@ -232,4 +89,138 @@ class MainActivity : FlutterActivity() { mainService = null } } + + private fun initFlutterChannel(flutterMethodChannel: MethodChannel) { + flutterMethodChannel.setMethodCallHandler { call, result -> + // make sure result will be invoked, otherwise flutter will await forever + when (call.method) { + "init_service" -> { + Intent(activity, MainService::class.java).also { + bindService(it, serviceConnection, Context.BIND_AUTO_CREATE) + } + if (MainService.isReady) { + result.success(false) + return@setMethodCallHandler + } + requestMediaProjection() + result.success(true) + } + "start_capture" -> { + mainService?.let { + result.success(it.startCapture()) + } ?: let { + result.success(false) + } + } + "stop_service" -> { + Log.d(logTag, "Stop service") + mainService?.let { + it.destroy() + result.success(true) + } ?: let { + result.success(false) + } + } + "check_permission" -> { + if (call.arguments is String) { + result.success(XXPermissions.isGranted(context, call.arguments as String)) + } else { + result.success(false) + } + } + "request_permission" -> { + if (call.arguments is String) { + requestPermission(context, call.arguments as String) + result.success(true) + } else { + result.success(false) + } + } + START_ACTION -> { + if (call.arguments is String) { + startAction(context, call.arguments as String) + result.success(true) + } else { + result.success(false) + } + } + "check_video_permission" -> { + mainService?.let { + result.success(it.checkMediaPermission()) + } ?: let { + result.success(false) + } + } + "check_service" -> { + Companion.flutterMethodChannel?.invokeMethod( + "on_state_changed", + mapOf("name" to "input", "value" to InputService.isOpen.toString()) + ) + Companion.flutterMethodChannel?.invokeMethod( + "on_state_changed", + mapOf("name" to "media", "value" to MainService.isReady.toString()) + ) + result.success(true) + } + "stop_input" -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + InputService.ctx?.disableSelf() + } + InputService.ctx = null + Companion.flutterMethodChannel?.invokeMethod( + "on_state_changed", + mapOf("name" to "input", "value" to InputService.isOpen.toString()) + ) + result.success(true) + } + "cancel_notification" -> { + if (call.arguments is Int) { + val id = call.arguments as Int + mainService?.cancelNotification(id) + } else { + result.success(true) + } + } + "enable_soft_keyboard" -> { + // https://blog.csdn.net/hanye2020/article/details/105553780 + if (call.arguments as Boolean) { + window.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) + } else { + window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) + } + result.success(true) + + } + GET_START_ON_BOOT_OPT -> { + val prefs = getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE) + result.success(prefs.getBoolean(KEY_START_ON_BOOT_OPT, false)) + } + SET_START_ON_BOOT_OPT -> { + if (call.arguments is Boolean) { + val prefs = getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE) + val edit = prefs.edit() + edit.putBoolean(KEY_START_ON_BOOT_OPT, call.arguments as Boolean) + edit.apply() + result.success(true) + } else { + result.success(false) + } + } + SYNC_APP_DIR_CONFIG_PATH -> { + if (call.arguments is String) { + val prefs = getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE) + val edit = prefs.edit() + edit.putString(KEY_APP_DIR_CONFIG_PATH, call.arguments as String) + edit.apply() + result.success(true) + } else { + result.success(false) + } + } + else -> { + result.error("-1", "No such method", null) + } + } + } + } } diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt index cf8e12e92..fa7440c8d 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt @@ -35,6 +35,7 @@ import androidx.annotation.RequiresApi import androidx.core.app.ActivityCompat import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat +import io.flutter.embedding.android.FlutterActivity import java.util.concurrent.Executors import kotlin.concurrent.thread import org.json.JSONException @@ -43,10 +44,6 @@ import java.nio.ByteBuffer import kotlin.math.max import kotlin.math.min -const val EXTRA_MP_DATA = "mp_intent" -const val INIT_SERVICE = "init_service" -const val ACTION_LOGIN_REQ_NOTIFY = "ACTION_LOGIN_REQ_NOTIFY" -const val EXTRA_LOGIN_REQ_NOTIFY = "EXTRA_LOGIN_REQ_NOTIFY" const val DEFAULT_NOTIFY_TITLE = "RustDesk" const val DEFAULT_NOTIFY_TEXT = "Service is running" @@ -147,7 +144,11 @@ class MainService : Service() { // jvm call rust private external fun init(ctx: Context) - private external fun startServer() + + /// When app start on boot, app_dir will not be passed from flutter + /// so pass a app_dir here to rust server + private external fun startServer(app_dir: String) + private external fun startService() private external fun onVideoFrameUpdate(buf: ByteBuffer) private external fun onAudioFrameUpdate(buf: ByteBuffer) private external fun translateLocale(localeName: String, input: String): String @@ -195,6 +196,7 @@ class MainService : Service() { override fun onCreate() { super.onCreate() + Log.d(logTag,"MainService onCreate") HandlerThread("Service", Process.THREAD_PRIORITY_BACKGROUND).apply { start() serviceLooper = looper @@ -202,7 +204,13 @@ class MainService : Service() { } updateScreenInfo(resources.configuration.orientation) initNotification() - startServer() + + // keep the config dir same with flutter + val prefs = applicationContext.getSharedPreferences(KEY_SHARED_PREFERENCES, FlutterActivity.MODE_PRIVATE) + val configPath = prefs.getString(KEY_APP_DIR_CONFIG_PATH, "") ?: "" + startServer(configPath) + + createForegroundNotification() } override fun onDestroy() { @@ -277,22 +285,30 @@ class MainService : Service() { } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - Log.d("whichService", "this service:${Thread.currentThread()}") + Log.d("whichService", "this service: ${Thread.currentThread()}") super.onStartCommand(intent, flags, startId) - if (intent?.action == INIT_SERVICE) { - Log.d(logTag, "service starting:${startId}:${Thread.currentThread()}") + if (intent?.action == ACT_INIT_MEDIA_PROJECTION_AND_SERVICE) { createForegroundNotification() - val mMediaProjectionManager = + + if (intent.getBooleanExtra(EXT_INIT_FROM_BOOT, false)) { + startService() + } + Log.d(logTag, "service starting: ${startId}:${Thread.currentThread()}") + val mediaProjectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager - intent.getParcelableExtra(EXTRA_MP_DATA)?.let { + + intent.getParcelableExtra(EXT_MEDIA_PROJECTION_RES_INTENT)?.let { mediaProjection = - mMediaProjectionManager.getMediaProjection(Activity.RESULT_OK, it) + mediaProjectionManager.getMediaProjection(Activity.RESULT_OK, it) checkMediaPermission() init(this) _isReady = true + } ?: let { + Log.d(logTag, "getParcelableExtra intent null, invoke requestMediaProjection") + requestMediaProjection() } } - return START_NOT_STICKY // don't use sticky (auto restart),the new service (from auto restart) will lose control + return START_NOT_STICKY // don't use sticky (auto restart), the new service (from auto restart) will lose control } override fun onConfigurationChanged(newConfig: Configuration) { @@ -300,6 +316,14 @@ class MainService : Service() { updateScreenInfo(newConfig.orientation) } + private fun requestMediaProjection() { + val intent = Intent(this, PermissionRequestTransparentActivity::class.java).apply { + action = ACT_REQUEST_MEDIA_PROJECTION + flags = Intent.FLAG_ACTIVITY_NEW_TASK + } + startActivity(intent) + } + @SuppressLint("WrongConstant") private fun createSurface(): Surface? { return if (useVP9) { @@ -400,13 +424,13 @@ class MainService : Service() { fun checkMediaPermission(): Boolean { Handler(Looper.getMainLooper()).post { - MainActivity.flutterMethodChannel.invokeMethod( + MainActivity.flutterMethodChannel?.invokeMethod( "on_state_changed", mapOf("name" to "media", "value" to isReady.toString()) ) } Handler(Looper.getMainLooper()).post { - MainActivity.flutterMethodChannel.invokeMethod( + MainActivity.flutterMethodChannel?.invokeMethod( "on_state_changed", mapOf("name" to "input", "value" to InputService.isOpen.toString()) ) @@ -653,8 +677,8 @@ class MainService : Service() { @SuppressLint("UnspecifiedImmutableFlag") private fun genLoginRequestPendingIntent(res: Boolean): PendingIntent { val intent = Intent(this, MainService::class.java).apply { - action = ACTION_LOGIN_REQ_NOTIFY - putExtra(EXTRA_LOGIN_REQ_NOTIFY, res) + action = ACT_LOGIN_REQ_NOTIFY + putExtra(EXT_LOGIN_REQ_NOTIFY, res) } return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { PendingIntent.getService(this, 111, intent, FLAG_IMMUTABLE) diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/PermissionRequestTransparentActivity.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/PermissionRequestTransparentActivity.kt new file mode 100644 index 000000000..3beb7ec6b --- /dev/null +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/PermissionRequestTransparentActivity.kt @@ -0,0 +1,54 @@ +package com.carriez.flutter_hbb + +import android.app.Activity +import android.content.Intent +import android.media.projection.MediaProjectionManager +import android.os.Build +import android.os.Bundle +import android.util.Log + +class PermissionRequestTransparentActivity: Activity() { + private val logTag = "permissionRequest" + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + Log.d(logTag, "onCreate PermissionRequestTransparentActivity: intent.action: ${intent.action}") + + when (intent.action) { + ACT_REQUEST_MEDIA_PROJECTION -> { + val mediaProjectionManager = + getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager + val intent = mediaProjectionManager.createScreenCaptureIntent() + startActivityForResult(intent, REQ_REQUEST_MEDIA_PROJECTION) + } + else -> finish() + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == REQ_REQUEST_MEDIA_PROJECTION) { + if (resultCode == RESULT_OK && data != null) { + launchService(data) + } else { + setResult(RES_FAILED) + } + } + + finish() + } + + private fun launchService(mediaProjectionResultIntent: Intent) { + Log.d(logTag, "Launch MainService") + val serviceIntent = Intent(this, MainService::class.java) + serviceIntent.action = ACT_INIT_MEDIA_PROJECTION_AND_SERVICE + serviceIntent.putExtra(EXT_MEDIA_PROJECTION_RES_INTENT, mediaProjectionResultIntent) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(serviceIntent) + } else { + startService(serviceIntent) + } + } + +} \ No newline at end of file diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt index 4bf244a06..f8ef07fd1 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/common.kt @@ -1,5 +1,6 @@ package com.carriez.flutter_hbb +import android.Manifest.permission.* import android.annotation.SuppressLint import android.content.Context import android.content.Intent @@ -12,8 +13,8 @@ import android.os.Build import android.os.Handler import android.os.Looper import android.os.PowerManager -import android.provider.Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS -import android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS +import android.provider.Settings +import android.provider.Settings.* import androidx.annotation.RequiresApi import androidx.core.content.ContextCompat.getSystemService import com.hjq.permissions.Permission @@ -22,6 +23,31 @@ import java.nio.ByteBuffer import java.util.* +// intent action, extra +const val ACT_REQUEST_MEDIA_PROJECTION = "REQUEST_MEDIA_PROJECTION" +const val ACT_INIT_MEDIA_PROJECTION_AND_SERVICE = "INIT_MEDIA_PROJECTION_AND_SERVICE" +const val ACT_LOGIN_REQ_NOTIFY = "LOGIN_REQ_NOTIFY" +const val EXT_INIT_FROM_BOOT = "EXT_INIT_FROM_BOOT" +const val EXT_MEDIA_PROJECTION_RES_INTENT = "MEDIA_PROJECTION_RES_INTENT" +const val EXT_LOGIN_REQ_NOTIFY = "LOGIN_REQ_NOTIFY" + +// Activity requestCode +const val REQ_INVOKE_PERMISSION_ACTIVITY_MEDIA_PROJECTION = 101 +const val REQ_REQUEST_MEDIA_PROJECTION = 201 + +// Activity responseCode +const val RES_FAILED = -100 + +// Flutter channel +const val START_ACTION = "start_action" +const val GET_START_ON_BOOT_OPT = "get_start_on_boot_opt" +const val SET_START_ON_BOOT_OPT = "set_start_on_boot_opt" +const val SYNC_APP_DIR_CONFIG_PATH = "sync_app_dir" + +const val KEY_SHARED_PREFERENCES = "KEY_SHARED_PREFERENCES" +const val KEY_START_ON_BOOT_OPT = "KEY_START_ON_BOOT_OPT" +const val KEY_APP_DIR_CONFIG_PATH = "KEY_APP_DIR_CONFIG_PATH" + @SuppressLint("ConstantLocale") val LOCAL_NAME = Locale.getDefault().toString() val SCREEN_INFO = Info(0, 0, 1, 200) @@ -30,61 +56,13 @@ data class Info( var width: Int, var height: Int, var scale: Int, var dpi: Int ) -@RequiresApi(Build.VERSION_CODES.LOLLIPOP) -fun testVP9Support(): Boolean { - return true - val res = MediaCodecList(MediaCodecList.ALL_CODECS) - .findEncoderForFormat( - MediaFormat.createVideoFormat( - MediaFormat.MIMETYPE_VIDEO_VP9, - SCREEN_INFO.width, - SCREEN_INFO.width - ) - ) - return res != null -} - -@RequiresApi(Build.VERSION_CODES.M) fun requestPermission(context: Context, type: String) { - val permission = when (type) { - "ignore_battery_optimizations" -> { - try { - context.startActivity(Intent(ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).apply { - data = Uri.parse("package:" + context.packageName) - }) - } catch (e:Exception) { - e.printStackTrace() - } - return - } - "application_details_settings" -> { - try { - context.startActivity(Intent().apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - action = "android.settings.APPLICATION_DETAILS_SETTINGS" - data = Uri.parse("package:" + context.packageName) - }) - } catch (e:Exception) { - e.printStackTrace() - } - return - } - "audio" -> { - Permission.RECORD_AUDIO - } - "file" -> { - Permission.MANAGE_EXTERNAL_STORAGE - } - else -> { - return - } - } XXPermissions.with(context) - .permission(permission) + .permission(type) .request { _, all -> if (all) { Handler(Looper.getMainLooper()).post { - MainActivity.flutterMethodChannel.invokeMethod( + MainActivity.flutterMethodChannel?.invokeMethod( "on_android_permission_result", mapOf("type" to type, "result" to all) ) @@ -93,24 +71,18 @@ fun requestPermission(context: Context, type: String) { } } -@RequiresApi(Build.VERSION_CODES.M) -fun checkPermission(context: Context, type: String): Boolean { - val permission = when (type) { - "ignore_battery_optimizations" -> { - val pw = context.getSystemService(Context.POWER_SERVICE) as PowerManager - return pw.isIgnoringBatteryOptimizations(context.packageName) - } - "audio" -> { - Permission.RECORD_AUDIO - } - "file" -> { - Permission.MANAGE_EXTERNAL_STORAGE - } - else -> { - return false - } +fun startAction(context: Context, action: String) { + try { + context.startActivity(Intent(action).apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + // don't pass package name when launch ACTION_ACCESSIBILITY_SETTINGS + if (ACTION_ACCESSIBILITY_SETTINGS != action) { + data = Uri.parse("package:" + context.packageName) + } + }) + } catch (e: Exception) { + e.printStackTrace() } - return XXPermissions.isGranted(context, permission) } class AudioReader(val bufSize: Int, private val maxFrames: Int) { diff --git a/flutter/android/app/src/main/res/values/styles.xml b/flutter/android/app/src/main/res/values/styles.xml index d74aa35c2..146267c91 100644 --- a/flutter/android/app/src/main/res/values/styles.xml +++ b/flutter/android/app/src/main/res/values/styles.xml @@ -15,4 +15,12 @@ + diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index eeae0972b..ceff7480e 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -109,27 +109,32 @@ class IconFont { class ColorThemeExtension extends ThemeExtension { const ColorThemeExtension({ required this.border, + required this.border2, required this.highlight, }); final Color? border; + final Color? border2; final Color? highlight; static const light = ColorThemeExtension( border: Color(0xFFCCCCCC), + border2: Color(0xFFBBBBBB), highlight: Color(0xFFE5E5E5), ); static const dark = ColorThemeExtension( border: Color(0xFF555555), + border2: Color(0xFFE5E5E5), highlight: Color(0xFF3F3F3F), ); @override ThemeExtension copyWith( - {Color? border, Color? highlight}) { + {Color? border, Color? border2, Color? highlight}) { return ColorThemeExtension( border: border ?? this.border, + border2: border2 ?? this.border2, highlight: highlight ?? this.highlight, ); } @@ -142,6 +147,7 @@ class ColorThemeExtension extends ThemeExtension { } return ColorThemeExtension( border: Color.lerp(border, other.border, t), + border2: Color.lerp(border2, other.border2, t), highlight: Color.lerp(highlight, other.highlight, t), ); } @@ -207,38 +213,30 @@ class MyTheme { splashFactory: isDesktop ? NoSplash.splashFactory : null, textButtonTheme: isDesktop ? TextButtonThemeData( - style: ButtonStyle( + style: TextButton.styleFrom( splashFactory: NoSplash.splashFactory, - shape: MaterialStatePropertyAll( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18.0), - ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18.0), ), ), ) : null, elevatedButtonTheme: ElevatedButtonThemeData( - style: ButtonStyle( - backgroundColor: MaterialStatePropertyAll( - MyTheme.accent, - ), - shape: MaterialStatePropertyAll( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), + style: ElevatedButton.styleFrom( + backgroundColor: MyTheme.accent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), ), ), ), outlinedButtonTheme: OutlinedButtonThemeData( - style: ButtonStyle( - backgroundColor: MaterialStatePropertyAll( - Color(0xFFEEEEEE), + style: OutlinedButton.styleFrom( + backgroundColor: Color( + 0xFFEEEEEE, ), - foregroundColor: MaterialStatePropertyAll(Colors.black87), - shape: MaterialStatePropertyAll( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), + foregroundColor: Colors.black87, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), ), ), ), @@ -306,46 +304,42 @@ class MyTheme { tabBarTheme: const TabBarTheme( labelColor: Colors.white70, ), + scrollbarTheme: ScrollbarThemeData( + thumbColor: MaterialStateProperty.all(Colors.grey[500]), + ), splashColor: Colors.transparent, highlightColor: Colors.transparent, splashFactory: isDesktop ? NoSplash.splashFactory : null, textButtonTheme: isDesktop ? TextButtonThemeData( - style: ButtonStyle( + style: TextButton.styleFrom( splashFactory: NoSplash.splashFactory, - shape: MaterialStatePropertyAll( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18.0), - ), + disabledForegroundColor: Colors.white70, + foregroundColor: Colors.white70, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18.0), ), ), ) : null, elevatedButtonTheme: ElevatedButtonThemeData( - style: ButtonStyle( - backgroundColor: MaterialStatePropertyAll( - MyTheme.accent, - ), - shape: MaterialStatePropertyAll( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), + style: ElevatedButton.styleFrom( + backgroundColor: MyTheme.accent, + disabledForegroundColor: Colors.white70, + disabledBackgroundColor: Colors.white10, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), ), ), ), outlinedButtonTheme: OutlinedButtonThemeData( - style: ButtonStyle( - backgroundColor: MaterialStatePropertyAll( - Color(0xFF24252B), - ), - side: MaterialStatePropertyAll( - BorderSide(color: Colors.white12, width: 0.5), - ), - foregroundColor: MaterialStatePropertyAll(Colors.white70), - shape: MaterialStatePropertyAll( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), + style: OutlinedButton.styleFrom( + backgroundColor: Color(0xFF24252B), + side: BorderSide(color: Colors.white12, width: 0.5), + disabledForegroundColor: Colors.white70, + foregroundColor: Colors.white70, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), ), ), ), @@ -1045,21 +1039,14 @@ class AccessibilityListener extends StatelessWidget { } } -class PermissionManager { +class AndroidPermissionManager { static Completer? _completer; static Timer? _timer; static var _current = ""; - static final permissions = [ - "audio", - "file", - "ignore_battery_optimizations", - "application_details_settings" - ]; - static bool isWaitingFile() { if (_completer != null) { - return !_completer!.isCompleted && _current == "file"; + return !_completer!.isCompleted && _current == kManageExternalStorage; } return false; } @@ -1068,31 +1055,33 @@ class PermissionManager { if (isDesktop) { return Future.value(true); } - if (!permissions.contains(type)) { - return Future.error("Wrong permission!$type"); - } return gFFI.invokeMethod("check_permission", type); } + // startActivity goto Android Setting's page to request permission manually by user + static void startAction(String action) { + gFFI.invokeMethod(AndroidChannel.kStartAction, action); + } + + /// We use XXPermissions to request permissions, + /// for supported types, see https://github.com/getActivity/XXPermissions/blob/e46caea32a64ad7819df62d448fb1c825481cd28/library/src/main/java/com/hjq/permissions/Permission.java static Future request(String type) { if (isDesktop) { return Future.value(true); } - if (!permissions.contains(type)) { - return Future.error("Wrong permission!$type"); - } gFFI.invokeMethod("request_permission", type); - if (type == "ignore_battery_optimizations") { - return Future.value(false); + + // clear last task + if (_completer?.isCompleted == false) { + _completer?.complete(false); } + _timer?.cancel(); + _current = type; _completer = Completer(); - gFFI.invokeMethod("request_permission", type); - // timeout - _timer?.cancel(); - _timer = Timer(Duration(seconds: 60), () { + _timer = Timer(Duration(seconds: 120), () { if (_completer == null) return; if (!_completer!.isCompleted) { _completer!.complete(false); @@ -1622,8 +1611,8 @@ connect(BuildContext context, String id, } } else { if (isFileTransfer) { - if (!await PermissionManager.check("file")) { - if (!await PermissionManager.request("file")) { + if (!await AndroidPermissionManager.check(kManageExternalStorage)) { + if (!await AndroidPermissionManager.request(kManageExternalStorage)) { return; } } diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 537784918..95e4d17e7 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; +import 'package:flutter_hbb/models/state_model.dart'; const double kDesktopRemoteTabBarHeight = 28.0; const int kMainWindowId = 0; @@ -58,6 +59,12 @@ const double kDesktopFileTransferMaximumWidth = 300; const double kDesktopFileTransferRowHeight = 30.0; const double kDesktopFileTransferHeaderHeight = 25.0; +EdgeInsets get kDragToResizeAreaPadding => + !kUseCompatibleUiMode && Platform.isLinux + ? stateGlobal.fullscreen || stateGlobal.maximize + ? EdgeInsets.zero + : EdgeInsets.all(5.0) + : EdgeInsets.zero; // https://en.wikipedia.org/wiki/Non-breaking_space const int $nbsp = 0x00A0; @@ -79,6 +86,7 @@ const kDefaultScrollAmountMultiplier = 5.0; const kDefaultScrollDuration = Duration(milliseconds: 50); const kDefaultMouseWheelThrottleDuration = Duration(milliseconds: 50); const kFullScreenEdgeSize = 0.0; +const kMaximizeEdgeSize = 0.0; var kWindowEdgeSize = Platform.isWindows ? 1.0 : 5.0; const kWindowBorderWidth = 1.0; const kDesktopMenuPadding = EdgeInsets.only(left: 12.0, right: 3.0); @@ -129,6 +137,25 @@ const kRemoteAudioDualWay = 'dual-way'; const kIgnoreDpi = true; +/// Android constants +const kActionApplicationDetailsSettings = + "android.settings.APPLICATION_DETAILS_SETTINGS"; +const kActionAccessibilitySettings = "android.settings.ACCESSIBILITY_SETTINGS"; + +const kRecordAudio = "android.permission.RECORD_AUDIO"; +const kManageExternalStorage = "android.permission.MANAGE_EXTERNAL_STORAGE"; +const kRequestIgnoreBatteryOptimizations = + "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; +const kSystemAlertWindow = "android.permission.SYSTEM_ALERT_WINDOW"; + +/// Android channel invoke type key +class AndroidChannel { + static final kStartAction = "start_action"; + static final kGetStartOnBootOpt = "get_start_on_boot_opt"; + static final kSetStartOnBootOpt = "set_start_on_boot_opt"; + static final kSyncAppDirConfigPath = "sync_app_dir"; +} + /// flutter/packages/flutter/lib/src/services/keyboard_key.dart -> _keyLabels /// see [LogicalKeyboardKey.keyLabel] const Map logicalKeyMap = { diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index e041b591d..0aafd48bb 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -19,7 +19,7 @@ import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart'; import '../../common/widgets/dialog.dart'; import '../../common/widgets/login.dart'; -const double _kTabWidth = 235; +const double _kTabWidth = 200; const double _kTabHeight = 42; const double _kCardFixedWidth = 540; const double _kCardLeftMargin = 15; @@ -538,6 +538,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin { translate('Screen Share'), translate('Deny remote access'), ], + enabled: enabled, initialKey: initialKey, onChanged: (mode) async { String modeValue; @@ -667,6 +668,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin { return _Card(title: 'Password', children: [ _ComboBox( + enabled: !locked, keys: modeKeys, values: modeValues, initialKey: modeInitialKey, @@ -1722,7 +1724,6 @@ class _ComboBox extends StatelessWidget { required this.values, required this.initialKey, required this.onChanged, - // ignore: unused_element this.enabled = true, }) : super(key: key); @@ -1735,7 +1736,12 @@ class _ComboBox extends StatelessWidget { var ref = values[index].obs; current = keys[index]; return Container( - decoration: BoxDecoration(border: Border.all(color: MyTheme.border)), + decoration: BoxDecoration( + border: Border.all( + color: enabled + ? MyTheme.color(context).border2 ?? MyTheme.border + : MyTheme.border, + )), height: 30, child: Obx(() => DropdownButton( isExpanded: true, @@ -1744,6 +1750,10 @@ class _ComboBox extends StatelessWidget { underline: Container( height: 25, ), + style: TextStyle( + color: enabled + ? Theme.of(context).textTheme.titleMedium?.color + : _disabledTextColor(context, enabled)), icon: const Icon( Icons.expand_more_sharp, size: 20, diff --git a/flutter/lib/desktop/pages/desktop_tab_page.dart b/flutter/lib/desktop/pages/desktop_tab_page.dart index 053a2d8a2..4a1a40242 100644 --- a/flutter/lib/desktop/pages/desktop_tab_page.dart +++ b/flutter/lib/desktop/pages/desktop_tab_page.dart @@ -75,7 +75,7 @@ class _DesktopTabPageState extends State { isClose: false, ), ))); - return Platform.isMacOS + return Platform.isMacOS || kUseCompatibleUiMode ? tabWidget : Obx( () => DragToResizeArea( diff --git a/flutter/lib/desktop/pages/file_manager_tab_page.dart b/flutter/lib/desktop/pages/file_manager_tab_page.dart index 148d928d9..39958e88e 100644 --- a/flutter/lib/desktop/pages/file_manager_tab_page.dart +++ b/flutter/lib/desktop/pages/file_manager_tab_page.dart @@ -98,7 +98,7 @@ class _FileManagerTabPageState extends State { labelGetter: DesktopTab.labelGetterAlias, )), ); - return Platform.isMacOS + return Platform.isMacOS || kUseCompatibleUiMode ? tabWidget : SubWindowDragToResizeArea( child: tabWidget, diff --git a/flutter/lib/desktop/pages/install_page.dart b/flutter/lib/desktop/pages/install_page.dart index e7bb28813..00ca2bb23 100644 --- a/flutter/lib/desktop/pages/install_page.dart +++ b/flutter/lib/desktop/pages/install_page.dart @@ -1,7 +1,9 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; +import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; import 'package:flutter_hbb/models/platform_model.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'; @@ -13,7 +15,51 @@ class InstallPage extends StatefulWidget { State createState() => _InstallPageState(); } -class _InstallPageState extends State with WindowListener { +class _InstallPageState extends State { + final tabController = DesktopTabController(tabType: DesktopTabType.main); + + @override + void initState() { + super.initState(); + Get.put(tabController); + const lable = "install"; + tabController.add(TabInfo( + key: lable, + label: lable, + closable: false, + page: _InstallPageBody( + key: const ValueKey(lable), + ))); + } + + @override + void dispose() { + super.dispose(); + Get.delete(); + } + + @override + Widget build(BuildContext context) { + return DragToResizeArea( + resizeEdgeSize: stateGlobal.resizeEdgeSize.value, + child: Container( + child: Scaffold( + backgroundColor: Theme.of(context).colorScheme.background, + body: DesktopTab(controller: tabController)), + ), + ); + } +} + +class _InstallPageBody extends StatefulWidget { + const _InstallPageBody({Key? key}) : super(key: key); + + @override + State<_InstallPageBody> createState() => _InstallPageBodyState(); +} + +class _InstallPageBodyState extends State<_InstallPageBody> + with WindowListener { late final TextEditingController controller; final RxBool startmenu = true.obs; final RxBool desktopicon = true.obs; @@ -46,15 +92,19 @@ class _InstallPageState extends State with WindowListener { final double em = 13; final btnFontSize = 0.9 * em; final double button_radius = 6; + final isDarkTheme = MyTheme.currentThemeMode() == ThemeMode.dark; final buttonStyle = OutlinedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(button_radius)), )); final inputBorder = OutlineInputBorder( borderRadius: BorderRadius.zero, - borderSide: BorderSide(color: Colors.black12)); + borderSide: + BorderSide(color: isDarkTheme ? Colors.white70 : Colors.black12)); + final textColor = isDarkTheme ? null : Colors.black87; + final dividerColor = isDarkTheme ? Colors.white70 : Colors.black87; return Scaffold( - backgroundColor: Colors.white, + backgroundColor: null, body: SingleChildScrollView( child: Column( children: [ @@ -91,8 +141,7 @@ class _InstallPageState extends State with WindowListener { style: buttonStyle, child: Text(translate('Change Path'), style: TextStyle( - color: Colors.black87, - fontSize: btnFontSize))) + color: textColor, fontSize: btnFontSize))) .marginOnly(left: em)) ], ).marginSymmetric(vertical: 2 * em), @@ -127,8 +176,7 @@ class _InstallPageState extends State with WindowListener { )).marginOnly(top: 2 * em), Row(children: [Text(translate('agreement_tip'))]) .marginOnly(top: em), - Divider(color: Colors.black87) - .marginSymmetric(vertical: 0.5 * em), + Divider(color: dividerColor).marginSymmetric(vertical: 0.5 * em), Row( children: [ Expanded( @@ -143,8 +191,7 @@ class _InstallPageState extends State with WindowListener { style: buttonStyle, child: Text(translate('Cancel'), style: TextStyle( - color: Colors.black87, - fontSize: btnFontSize))) + color: textColor, fontSize: btnFontSize))) .marginOnly(right: 2 * em)), Obx(() => ElevatedButton( onPressed: btnEnabled.value ? install : null, @@ -167,8 +214,7 @@ class _InstallPageState extends State with WindowListener { style: buttonStyle, child: Text(translate('Run without install'), style: TextStyle( - color: Colors.black87, - fontSize: btnFontSize))) + color: textColor, fontSize: btnFontSize))) .marginOnly(left: 2 * em)), ), ], diff --git a/flutter/lib/desktop/pages/port_forward_tab_page.dart b/flutter/lib/desktop/pages/port_forward_tab_page.dart index f2d75d00f..32f02c9b7 100644 --- a/flutter/lib/desktop/pages/port_forward_tab_page.dart +++ b/flutter/lib/desktop/pages/port_forward_tab_page.dart @@ -107,13 +107,15 @@ class _PortForwardTabPageState extends State { labelGetter: DesktopTab.labelGetterAlias, )), ); - return Platform.isMacOS + return Platform.isMacOS || kUseCompatibleUiMode ? tabWidget - : SubWindowDragToResizeArea( - child: tabWidget, - resizeEdgeSize: stateGlobal.resizeEdgeSize.value, - windowId: stateGlobal.windowId, - ); + : Obx( + () => SubWindowDragToResizeArea( + child: tabWidget, + resizeEdgeSize: stateGlobal.resizeEdgeSize.value, + windowId: stateGlobal.windowId, + ), + ); } void onRemoveId(String id) { diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index 0deb646c0..d810650fd 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -205,11 +205,13 @@ class _ConnectionTabPageState extends State { ), ), ); - return Platform.isMacOS + return Platform.isMacOS || kUseCompatibleUiMode ? tabWidget : Obx(() => SubWindowDragToResizeArea( key: contentKey, child: tabWidget, + // Specially configured for a better resize area and remote control. + childPadding: kDragToResizeAreaPadding, resizeEdgeSize: stateGlobal.resizeEdgeSize.value, windowId: stateGlobal.windowId, )); diff --git a/flutter/lib/desktop/screen/desktop_remote_screen.dart b/flutter/lib/desktop/screen/desktop_remote_screen.dart index bb6bc431b..64af41401 100644 --- a/flutter/lib/desktop/screen/desktop_remote_screen.dart +++ b/flutter/lib/desktop/screen/desktop_remote_screen.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/desktop/pages/remote_tab_page.dart'; @@ -26,6 +28,9 @@ class DesktopRemoteScreen extends StatelessWidget { ChangeNotifierProvider.value(value: gFFI.canvasModel), ], child: Scaffold( + // Set transparent background for padding the resize area out of the flutter view. + // This allows the wallpaper goes through our resize area. (Linux only now). + backgroundColor: Platform.isLinux ? Colors.transparent : null, body: ConnectionTabPage( params: params, ), diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 49c56466c..081cd1649 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -942,6 +942,7 @@ class _DisplayMenuState extends State<_DisplayMenu> { disableClipboard(), lockAfterSessionEnd(), privacyMode(), + swapKey(), ]); } @@ -975,12 +976,13 @@ class _DisplayMenuState extends State<_DisplayMenu> { final canvasModel = widget.ffi.canvasModel; final width = (canvasModel.getDisplayWidth() * canvasModel.scale + - canvasModel.windowBorderWidth * 2) * + CanvasModel.leftToEdge + + CanvasModel.rightToEdge) * scale + magicWidth; final height = (canvasModel.getDisplayHeight() * canvasModel.scale + - canvasModel.tabBarHeight + - canvasModel.windowBorderWidth * 2) * + CanvasModel.topToEdge + + CanvasModel.bottomToEdge) * scale + magicHeight; double left = wndRect.left + (wndRect.width - width) / 2; @@ -1049,10 +1051,10 @@ class _DisplayMenuState extends State<_DisplayMenu> { final canvasModel = widget.ffi.canvasModel; final displayWidth = canvasModel.getDisplayWidth(); final displayHeight = canvasModel.getDisplayHeight(); - final requiredWidth = displayWidth + - (canvasModel.tabBarHeight + canvasModel.windowBorderWidth * 2); - final requiredHeight = displayHeight + - (canvasModel.tabBarHeight + canvasModel.windowBorderWidth * 2); + final requiredWidth = + CanvasModel.leftToEdge + displayWidth + CanvasModel.rightToEdge; + final requiredHeight = + CanvasModel.topToEdge + displayHeight + CanvasModel.bottomToEdge; return selfWidth > (requiredWidth * scale) && selfHeight > (requiredHeight * scale); } @@ -1549,6 +1551,23 @@ class _DisplayMenuState extends State<_DisplayMenu> { ffi: widget.ffi, child: Text(translate('Privacy mode'))); } + + swapKey() { + final visible = perms['keyboard'] != false && + ((Platform.isMacOS && pi.platform != kPeerPlatformMacOS) || + (!Platform.isMacOS && pi.platform == kPeerPlatformMacOS)); + if (!visible) return Offstage(); + final option = 'allow_swap_key'; + final value = bind.sessionGetToggleOptionSync(id: widget.id, arg: option); + return _CheckboxMenuButton( + value: value, + onChanged: (value) { + if (value == null) return; + bind.sessionToggleOption(id: widget.id, value: option); + }, + ffi: widget.ffi, + child: Text(translate('Swap control-command key'))); + } } class _KeyboardMenu extends StatelessWidget { @@ -1564,9 +1583,8 @@ class _KeyboardMenu extends StatelessWidget { @override Widget build(BuildContext context) { - // Do not check permission here? - // var ffiModel = Provider.of(context); - // if (ffiModel.permissions['keyboard'] == false) return Offstage(); + var ffiModel = Provider.of(context); + if (ffiModel.permissions['keyboard'] == false) return Offstage(); if (stateGlobal.grabKeyboard) { if (bind.sessionIsKeyboardModeSupported(id: id, mode: _kKeyMapMode)) { bind.sessionSetKeyboardMode(id: id, value: _kKeyMapMode); diff --git a/flutter/lib/desktop/widgets/scroll_wrapper.dart b/flutter/lib/desktop/widgets/scroll_wrapper.dart index 32ed149e5..c5bc3394b 100644 --- a/flutter/lib/desktop/widgets/scroll_wrapper.dart +++ b/flutter/lib/desktop/widgets/scroll_wrapper.dart @@ -14,6 +14,7 @@ class DesktopScrollWrapper extends StatelessWidget { return ImprovedScrolling( scrollController: scrollController, enableCustomMouseWheelScrolling: true, + // enableKeyboardScrolling: true, // strange behavior on mac customMouseWheelScrollConfig: CustomMouseWheelScrollConfig( scrollDuration: kDefaultScrollDuration, scrollCurve: Curves.linearToEaseOut, diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index ee3aaaf2c..edc779fba 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -53,6 +53,7 @@ enum DesktopTabType { remoteScreen, fileTransfer, portForward, + install, } class DesktopTabState { @@ -249,8 +250,9 @@ class DesktopTab extends StatelessWidget { this.unSelectedTabBackgroundColor, }) : super(key: key) { tabType = controller.tabType; - isMainWindow = - tabType == DesktopTabType.main || tabType == DesktopTabType.cm; + isMainWindow = tabType == DesktopTabType.main || + tabType == DesktopTabType.cm || + tabType == DesktopTabType.install; } static RxString labelGetterAlias(String peerId) { @@ -361,7 +363,8 @@ class DesktopTab extends StatelessWidget { /// - hide single item when only has one item (home) on [DesktopTabPage]. bool isHideSingleItem() { return state.value.tabs.length == 1 && - controller.tabType == DesktopTabType.main; + (controller.tabType == DesktopTabType.main || + controller.tabType == DesktopTabType.install); } Widget _buildBar() { @@ -523,12 +526,18 @@ class WindowActionPanelState extends State super.dispose(); } + void _setMaximize(bool maximize) { + stateGlobal.setMaximize(maximize); + setState(() {}); + } + @override void onWindowMaximize() { // catch maximize from system if (!widget.isMaximized.value) { widget.isMaximized.value = true; } + _setMaximize(true); super.onWindowMaximize(); } @@ -538,6 +547,7 @@ class WindowActionPanelState extends State if (widget.isMaximized.value) { widget.isMaximized.value = false; } + _setMaximize(false); super.onWindowUnmaximize(); } @@ -752,7 +762,8 @@ class _ListView extends StatelessWidget { /// - hide single item when only has one item (home) on [DesktopTabPage]. bool isHideSingleItem() { return state.value.tabs.length == 1 && - controller.tabType == DesktopTabType.main; + controller.tabType == DesktopTabType.main || + controller.tabType == DesktopTabType.install; } @override diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index c61287d4f..bb1b4f552 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -153,6 +153,7 @@ void runMainApp(bool startService) async { void runMobileApp() async { await initEnv(kAppTypeMain); if (isAndroid) androidChannelInit(); + platformFFI.syncAndroidServiceAppDirConfigPath(); runApp(App()); } @@ -291,17 +292,20 @@ void _runApp( void runInstallPage() async { await windowManager.ensureInitialized(); await initEnv(kAppTypeMain); - _runApp('', const InstallPage(), ThemeMode.light); - windowManager.waitUntilReadyToShow( - WindowOptions(size: Size(800, 600), center: true), () async { + _runApp('', const InstallPage(), MyTheme.currentThemeMode()); + WindowOptions windowOptions = + getHiddenTitleBarWindowOptions(size: Size(800, 600), center: true); + windowManager.waitUntilReadyToShow(windowOptions, () async { windowManager.show(); windowManager.focus(); windowManager.setOpacity(1); windowManager.setAlignment(Alignment.center); // ensure + windowManager.setTitle(getWindowName()); }); } -WindowOptions getHiddenTitleBarWindowOptions({Size? size}) { +WindowOptions getHiddenTitleBarWindowOptions( + {Size? size, bool center = false}) { var defaultTitleBarStyle = TitleBarStyle.hidden; // we do not hide titlebar on win7 because of the frame overflow. if (kUseCompatibleUiMode) { @@ -309,7 +313,7 @@ WindowOptions getHiddenTitleBarWindowOptions({Size? size}) { } return WindowOptions( size: size, - center: false, + center: center, backgroundColor: Colors.transparent, skipTaskbar: false, titleBarStyle: defaultTitleBarStyle, diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index 1a77b8983..218559a6e 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -6,6 +6,7 @@ import 'package:provider/provider.dart'; import '../../common.dart'; import '../../common/widgets/dialog.dart'; +import '../../consts.dart'; import '../../models/platform_model.dart'; import '../../models/server_model.dart'; import 'home_page.dart'; @@ -40,14 +41,14 @@ class ServerPage extends StatefulWidget implements PageShape { value: "setTemporaryPasswordLength", enabled: gFFI.serverModel.verificationMethod != kUsePermanentPassword, - child: Text(translate("Set temporary password length")), + child: Text(translate("One-time password length")), ), const PopupMenuDivider(), PopupMenuItem( padding: const EdgeInsets.symmetric(horizontal: 0.0), value: kUseTemporaryPassword, child: ListTile( - title: Text(translate("Use temporary password")), + title: Text(translate("Use one-time password")), trailing: Icon( Icons.check, color: gFFI.serverModel.verificationMethod == @@ -150,10 +151,11 @@ class _ServerPageState extends State { } void checkService() async { - gFFI.invokeMethod("check_service"); // jvm - // for Android 10/11,MANAGE_EXTERNAL_STORAGE permission from a system setting page - if (PermissionManager.isWaitingFile() && !gFFI.serverModel.fileOk) { - PermissionManager.complete("file", await PermissionManager.check("file")); + gFFI.invokeMethod("check_service"); + // for Android 10/11, request MANAGE_EXTERNAL_STORAGE permission from system setting page + if (AndroidPermissionManager.isWaitingFile() && !gFFI.serverModel.fileOk) { + AndroidPermissionManager.complete(kManageExternalStorage, + await AndroidPermissionManager.check(kManageExternalStorage)); debugPrint("file permission finished"); } } @@ -567,7 +569,7 @@ void androidChannelInit() { { var type = arguments["type"] as String; var result = arguments["result"] as bool; - PermissionManager.complete(type, result); + AndroidPermissionManager.complete(type, result); break; } case "on_media_projection_canceled": diff --git a/flutter/lib/mobile/pages/settings_page.dart b/flutter/lib/mobile/pages/settings_page.dart index c5f3b6935..e07f8f59f 100644 --- a/flutter/lib/mobile/pages/settings_page.dart +++ b/flutter/lib/mobile/pages/settings_page.dart @@ -10,6 +10,7 @@ import 'package:url_launcher/url_launcher.dart'; import '../../common.dart'; import '../../common/widgets/dialog.dart'; import '../../common/widgets/login.dart'; +import '../../consts.dart'; import '../../models/model.dart'; import '../../models/platform_model.dart'; import '../widgets/dialog.dart'; @@ -31,18 +32,20 @@ class SettingsPage extends StatefulWidget implements PageShape { } const url = 'https://rustdesk.com/'; -final _hasIgnoreBattery = androidVersion >= 26; -var _ignoreBatteryOpt = false; -var _enableAbr = false; -var _denyLANDiscovery = false; -var _onlyWhiteList = false; -var _enableDirectIPAccess = false; -var _enableRecordSession = false; -var _autoRecordIncomingSession = false; -var _localIP = ""; -var _directAccessPort = ""; class _SettingsState extends State with WidgetsBindingObserver { + final _hasIgnoreBattery = androidVersion >= 26; + var _ignoreBatteryOpt = false; + var _enableStartOnBoot = false; + var _enableAbr = false; + var _denyLANDiscovery = false; + var _onlyWhiteList = false; + var _enableDirectIPAccess = false; + var _enableRecordSession = false; + var _autoRecordIncomingSession = false; + var _localIP = ""; + var _directAccessPort = ""; + @override void initState() { super.initState(); @@ -50,11 +53,34 @@ class _SettingsState extends State with WidgetsBindingObserver { () async { var update = false; + if (_hasIgnoreBattery) { - update = await updateIgnoreBatteryStatus(); + if (await checkAndUpdateIgnoreBatteryStatus()) { + update = true; + } } - final enableAbrRes = await bind.mainGetOption(key: "enable-abr") != "N"; + if (await checkAndUpdateStartOnBoot()) { + update = true; + } + + // start on boot depends on ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS and SYSTEM_ALERT_WINDOW + var enableStartOnBoot = + await gFFI.invokeMethod(AndroidChannel.kGetStartOnBootOpt); + if (enableStartOnBoot) { + if (!await canStartOnBoot()) { + enableStartOnBoot = false; + gFFI.invokeMethod(AndroidChannel.kSetStartOnBootOpt, false); + } + } + + if (enableStartOnBoot != _enableStartOnBoot) { + update = true; + _enableStartOnBoot = enableStartOnBoot; + } + + final enableAbrRes = option2bool( + "enable-abr", await bind.mainGetOption(key: "enable-abr")); if (enableAbrRes != _enableAbr) { update = true; _enableAbr = enableAbrRes; @@ -125,15 +151,18 @@ class _SettingsState extends State with WidgetsBindingObserver { void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { () async { - if (await updateIgnoreBatteryStatus()) { + final ibs = await checkAndUpdateIgnoreBatteryStatus(); + final sob = await checkAndUpdateStartOnBoot(); + if (ibs || sob) { setState(() {}); } }(); } } - Future updateIgnoreBatteryStatus() async { - final res = await PermissionManager.check("ignore_battery_optimizations"); + Future checkAndUpdateIgnoreBatteryStatus() async { + final res = await AndroidPermissionManager.check( + kRequestIgnoreBatteryOptimizations); if (_ignoreBatteryOpt != res) { _ignoreBatteryOpt = res; return true; @@ -142,6 +171,18 @@ class _SettingsState extends State with WidgetsBindingObserver { } } + Future checkAndUpdateStartOnBoot() async { + if (!await canStartOnBoot() && _enableStartOnBoot) { + _enableStartOnBoot = false; + debugPrint( + "checkAndUpdateStartOnBoot and set _enableStartOnBoot -> false"); + gFFI.invokeMethod(AndroidChannel.kSetStartOnBootOpt, false); + return true; + } else { + return false; + } + } + @override Widget build(BuildContext context) { Provider.of(context); @@ -265,7 +306,8 @@ class _SettingsState extends State with WidgetsBindingObserver { ]), onToggle: (v) async { if (v) { - PermissionManager.request("ignore_battery_optimizations"); + await AndroidPermissionManager.request( + kRequestIgnoreBatteryOptimizations); } else { final res = await gFFI.dialogManager .show((setState, close) => CustomAlertDialog( @@ -282,11 +324,44 @@ class _SettingsState extends State with WidgetsBindingObserver { ], )); if (res == true) { - PermissionManager.request("application_details_settings"); + AndroidPermissionManager.startAction( + kActionApplicationDetailsSettings); } } })); } + enhancementsTiles.add(SettingsTile.switchTile( + initialValue: _enableStartOnBoot, + title: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text("${translate('Start on Boot')} (beta)"), + Text( + '* ${translate('Start the screen sharing service on boot, requires special permissions')}', + style: Theme.of(context).textTheme.bodySmall), + ]), + onToggle: (toValue) async { + if (toValue) { + // 1. request kIgnoreBatteryOptimizations + if (!await AndroidPermissionManager.check( + kRequestIgnoreBatteryOptimizations)) { + if (!await AndroidPermissionManager.request( + kRequestIgnoreBatteryOptimizations)) { + return; + } + } + + // 2. request kSystemAlertWindow + if (!await AndroidPermissionManager.check(kSystemAlertWindow)) { + if (!await AndroidPermissionManager.request(kSystemAlertWindow)) { + return; + } + } + + // (Optional) 3. request input permission + } + setState(() => _enableStartOnBoot = toValue); + + gFFI.invokeMethod(AndroidChannel.kSetStartOnBootOpt, toValue); + })); return SettingsList( sections: [ @@ -387,6 +462,17 @@ class _SettingsState extends State with WidgetsBindingObserver { ], ); } + + Future canStartOnBoot() async { + // start on boot depends on ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS and SYSTEM_ALERT_WINDOW + if (_hasIgnoreBattery && !_ignoreBatteryOpt) { + return false; + } + if (!await AndroidPermissionManager.check(kSystemAlertWindow)) { + return false; + } + return true; + } } void showServerSettings(OverlayDialogManager dialogManager) async { diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index fca73eac7..df9ad2585 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -458,10 +458,8 @@ class InputModel { return; } evt['type'] = type; - if (isDesktop) { - y = y - stateGlobal.tabBarHeight - stateGlobal.windowBorderWidth.value; - x -= stateGlobal.windowBorderWidth.value; - } + y -= CanvasModel.topToEdge; + x -= CanvasModel.leftToEdge; final canvasModel = parent.target!.canvasModel; final nearThr = 3; var nearRight = (canvasModel.size.width - x) < nearThr; @@ -503,8 +501,21 @@ class InputModel { } x += d.x; y += d.y; + var evtX = 0; + var evtY = 0; + try { + evtX = x.round(); + evtY = y.round(); + } catch (e) { + debugPrintStack( + label: 'canvasModel.scale value ${canvasModel.scale}, $e'); + return; + } - if (x < d.x || y < d.y || x > (d.x + d.width) || y > (d.y + d.height)) { + if (evtX < d.x || + evtY < d.y || + evtX > (d.x + d.width) || + evtY > (d.y + d.height)) { // If left mouse up, no early return. if (evt['buttons'] != kPrimaryMouseButton || type != 'up') { return; @@ -512,12 +523,12 @@ class InputModel { } if (type != '') { - x = 0; - y = 0; + evtX = 0; + evtY = 0; } - evt['x'] = '${x.round()}'; - evt['y'] = '${y.round()}'; + evt['x'] = '$evtX'; + evt['y'] = '$evtY'; var buttons = ''; switch (evt['buttons']) { case kPrimaryMouseButton: diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index e48d74dac..802a18a52 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -617,13 +617,28 @@ class ViewStyle { final int displayWidth; final int displayHeight; ViewStyle({ - this.style = '', - this.width = 0.0, - this.height = 0.0, - this.displayWidth = 0, - this.displayHeight = 0, + required this.style, + required this.width, + required this.height, + required this.displayWidth, + required this.displayHeight, }); + static defaultViewStyle() { + final desktop = (isDesktop || isWebDesktop); + final w = + desktop ? kDesktopDefaultDisplayWidth : kMobileDefaultDisplayWidth; + final h = + desktop ? kDesktopDefaultDisplayHeight : kMobileDefaultDisplayHeight; + return ViewStyle( + style: '', + width: w.toDouble(), + height: h.toDouble(), + displayWidth: w, + displayHeight: h, + ); + } + static int _double2Int(double v) => (v * 100).round().toInt(); @override @@ -652,9 +667,14 @@ class ViewStyle { double get scale { double s = 1.0; if (style == kRemoteViewStyleAdaptive) { - final s1 = width / displayWidth; - final s2 = height / displayHeight; - s = s1 < s2 ? s1 : s2; + if (width != 0 && + height != 0 && + displayWidth != 0 && + displayHeight != 0) { + final s1 = width / displayWidth; + final s2 = height / displayHeight; + s = s1 < s2 ? s1 : s2; + } } return s; } @@ -680,7 +700,7 @@ class CanvasModel with ChangeNotifier { // scroll offset y percent double _scrollY = 0.0; ScrollStyle _scrollStyle = ScrollStyle.scrollauto; - ViewStyle _lastViewStyle = ViewStyle(); + ViewStyle _lastViewStyle = ViewStyle.defaultViewStyle(); final _imageOverflow = false.obs; @@ -707,12 +727,25 @@ class CanvasModel with ChangeNotifier { double get scrollX => _scrollX; double get scrollY => _scrollY; + static double get leftToEdge => (isDesktop || isWebDesktop) + ? windowBorderWidth + kDragToResizeAreaPadding.left + : 0; + static double get rightToEdge => (isDesktop || isWebDesktop) + ? windowBorderWidth + kDragToResizeAreaPadding.right + : 0; + static double get topToEdge => (isDesktop || isWebDesktop) + ? tabBarHeight + windowBorderWidth + kDragToResizeAreaPadding.top + : 0; + static double get bottomToEdge => (isDesktop || isWebDesktop) + ? windowBorderWidth + kDragToResizeAreaPadding.bottom + : 0; + updateViewStyle() async { Size getSize() { final size = MediaQueryData.fromWindow(ui.window).size; // If minimized, w or h may be negative here. - double w = size.width - windowBorderWidth * 2; - double h = size.height - tabBarHeight - windowBorderWidth * 2; + double w = size.width - leftToEdge - rightToEdge; + double h = size.height - topToEdge - bottomToEdge; return Size(w < 0 ? 0 : w, h < 0 ? 0 : h); } @@ -786,10 +819,14 @@ class CanvasModel with ChangeNotifier { return parent.target?.ffiModel.display.height ?? defaultHeight; } - double get windowBorderWidth => stateGlobal.windowBorderWidth.value; - double get tabBarHeight => stateGlobal.tabBarHeight; + static double get windowBorderWidth => stateGlobal.windowBorderWidth.value; + static double get tabBarHeight => stateGlobal.tabBarHeight; moveDesktopMouse(double x, double y) { + if (size.width == 0 || size.height == 0) { + return; + } + // On mobile platforms, move the canvas with the cursor. final dw = getDisplayWidth() * _scale; final dh = getDisplayHeight() * _scale; @@ -803,7 +840,9 @@ class CanvasModel with ChangeNotifier { dyOffset = (y - dh * (y / size.height) - _y).toInt(); } } catch (e) { - // Unhandled Exception: Unsupported operation: Infinity or NaN toInt + debugPrintStack( + label: + '(x,y) ($x,$y), (_x,_y) ($_x,$_y), _scale $_scale, display size (${getDisplayWidth()},${getDisplayHeight()}), size $size, , $e'); return; } diff --git a/flutter/lib/models/native_model.dart b/flutter/lib/models/native_model.dart index 13f5b4587..28dc8085e 100644 --- a/flutter/lib/models/native_model.dart +++ b/flutter/lib/models/native_model.dart @@ -30,7 +30,7 @@ typedef F4Dart = int Function(Pointer); typedef F5 = Void Function(Pointer); typedef F5Dart = void Function(Pointer); typedef HandleEvent = Future Function(Map evt); -// pub fn session_register_texture(id: *const char, ptr: usize) +// pub fn session_register_texture(id: *const char, ptr: usize) typedef F6 = Void Function(Pointer, Uint64); typedef F6Dart = void Function(Pointer, int); @@ -56,7 +56,6 @@ class PlatformFFI { F4Dart? _session_get_rgba_size; F5Dart? _session_next_rgba; F6Dart? _session_register_texture; - static get localeName => Platform.localeName; @@ -162,7 +161,8 @@ class PlatformFFI { dylib.lookupFunction("session_get_rgba_size"); _session_next_rgba = dylib.lookupFunction("session_next_rgba"); - _session_register_texture = dylib.lookupFunction("session_register_texture"); + _session_register_texture = + dylib.lookupFunction("session_register_texture"); try { // SYSTEM user failed _dir = (await getApplicationDocumentsDirectory()).path; @@ -301,4 +301,8 @@ class PlatformFFI { if (!isAndroid) return Future(() => false); return await _toAndroidChannel.invokeMethod(method, arguments); } + + void syncAndroidServiceAppDirConfigPath() { + invokeMethod(AndroidChannel.kSyncAppDirConfigPath, _dir); + } } diff --git a/flutter/lib/models/server_model.dart b/flutter/lib/models/server_model.dart index b2043f3c2..7ee23ec40 100644 --- a/flutter/lib/models/server_model.dart +++ b/flutter/lib/models/server_model.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter_hbb/consts.dart'; import 'package:flutter_hbb/main.dart'; import 'package:flutter_hbb/models/platform_model.dart'; import 'package:get/get.dart'; @@ -154,7 +155,8 @@ class ServerModel with ChangeNotifier { /// file true by default (if permission on) checkAndroidPermission() async { // audio - if (androidVersion < 30 || !await PermissionManager.check("audio")) { + if (androidVersion < 30 || + !await AndroidPermissionManager.check(kRecordAudio)) { _audioOk = false; bind.mainSetOption(key: "enable-audio", value: "N"); } else { @@ -163,7 +165,7 @@ class ServerModel with ChangeNotifier { } // file - if (!await PermissionManager.check("file")) { + if (!await AndroidPermissionManager.check(kManageExternalStorage)) { _fileOk = false; bind.mainSetOption(key: "enable-file-transfer", value: "N"); } else { @@ -229,10 +231,10 @@ class ServerModel with ChangeNotifier { } toggleAudio() async { - if (!_audioOk && !await PermissionManager.check("audio")) { - final res = await PermissionManager.request("audio"); + if (!_audioOk && !await AndroidPermissionManager.check(kRecordAudio)) { + final res = await AndroidPermissionManager.request(kRecordAudio); if (!res) { - // TODO handle fail + showToast(translate('Failed')); return; } } @@ -243,10 +245,12 @@ class ServerModel with ChangeNotifier { } toggleFile() async { - if (!_fileOk && !await PermissionManager.check("file")) { - final res = await PermissionManager.request("file"); + if (!_fileOk && + !await AndroidPermissionManager.check(kManageExternalStorage)) { + final res = + await AndroidPermissionManager.request(kManageExternalStorage); if (!res) { - // TODO handle fail + showToast(translate('Failed')); return; } } @@ -344,10 +348,6 @@ class ServerModel with ChangeNotifier { } } - Future initInput() async { - await parent.target?.invokeMethod("init_input"); - } - Future setPermanentPassword(String newPW) async { await bind.mainSetPermanentPassword(password: newPW); await Future.delayed(Duration(milliseconds: 500)); @@ -561,7 +561,8 @@ class ServerModel with ChangeNotifier { } Future closeAll() async { - await Future.wait(_clients.map((client) => bind.cmCloseConnection(connId: client.id))); + await Future.wait( + _clients.map((client) => bind.cmCloseConnection(connId: client.id))); _clients.clear(); tabController.state.value.tabs.clear(); } @@ -684,7 +685,7 @@ String getLoginDialogTag(int id) { showInputWarnAlert(FFI ffi) { ffi.dialogManager.show((setState, close) { submit() { - ffi.serverModel.initInput(); + AndroidPermissionManager.startAction(kActionAccessibilitySettings); close(); } diff --git a/flutter/lib/models/state_model.dart b/flutter/lib/models/state_model.dart index 761c95ded..aa4fab86e 100644 --- a/flutter/lib/models/state_model.dart +++ b/flutter/lib/models/state_model.dart @@ -9,8 +9,10 @@ import '../consts.dart'; class StateGlobal { int _windowId = -1; bool _fullscreen = false; + bool _maximize = false; bool grabKeyboard = false; final RxBool _showTabBar = true.obs; + final RxBool _showResizeEdge = true.obs; final RxDouble _resizeEdgeSize = RxDouble(kWindowEdgeSize); final RxDouble _windowBorderWidth = RxDouble(kWindowBorderWidth); final RxBool showRemoteMenuBar = false.obs; @@ -18,12 +20,20 @@ class StateGlobal { int get windowId => _windowId; bool get fullscreen => _fullscreen; + bool get maximize => _maximize; double get tabBarHeight => fullscreen ? 0 : kDesktopRemoteTabBarHeight; RxBool get showTabBar => _showTabBar; RxDouble get resizeEdgeSize => _resizeEdgeSize; RxDouble get windowBorderWidth => _windowBorderWidth; setWindowId(int id) => _windowId = id; + setMaximize(bool v) { + if (_maximize != v) { + _maximize = v; + _resizeEdgeSize.value = + _maximize ? kMaximizeEdgeSize : kWindowEdgeSize; + } + } setFullscreen(bool v) { if (_fullscreen != v) { _fullscreen = v; diff --git a/flutter/macos/Runner.xcodeproj/project.pbxproj b/flutter/macos/Runner.xcodeproj/project.pbxproj index 0019335ef..c73e666c7 100644 --- a/flutter/macos/Runner.xcodeproj/project.pbxproj +++ b/flutter/macos/Runner.xcodeproj/project.pbxproj @@ -487,7 +487,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_IDENTITY = "Apple Development"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index 5ffe805b8..2202b2ccf 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -325,8 +325,8 @@ packages: dependency: "direct main" description: path: "." - ref: f37357ed98a10717576eb9ed8413e92b2ec5d13a - resolved-ref: f37357ed98a10717576eb9ed8413e92b2ec5d13a + ref: "3e2655677c54f421f9e378680d8171b95a211e0f" + resolved-ref: "3e2655677c54f421f9e378680d8171b95a211e0f" url: "https://github.com/Kingtous/rustdesk_desktop_multi_window" source: git version: "0.1.0" @@ -1563,5 +1563,5 @@ packages: source: hosted version: "0.1.1" sdks: - dart: ">=2.18.0 <4.0.0" + dart: ">=2.18.0 <3.0.0" flutter: ">=3.3.0" diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 572b3e20a..71a840c9c 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: f37357ed98a10717576eb9ed8413e92b2ec5d13a + ref: 3e2655677c54f421f9e378680d8171b95a211e0f freezed_annotation: ^2.0.3 flutter_custom_cursor: ^0.0.4 window_size: @@ -76,7 +76,7 @@ dependencies: file_picker: ^5.1.0 flutter_svg: ^1.1.5 flutter_improved_scrolling: - # currently, we use flutter 3.0.5 for windows build, latest for other builds. + # currently, we use flutter 3.7.0+. # # for flutter 3.0.5, please use official version(just comment code below). # if build rustdesk by flutter >=3.3, please use our custom pub below (uncomment code below). diff --git a/libs/hbb_common/examples/config.rs b/libs/hbb_common/examples/config.rs new file mode 100644 index 000000000..95169df8e --- /dev/null +++ b/libs/hbb_common/examples/config.rs @@ -0,0 +1,5 @@ +extern crate hbb_common; + +fn main() { + println!("{:?}", hbb_common::config::PeerConfig::load("455058072")); +} diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 3bfc885c5..ed7270a85 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -110,10 +110,10 @@ macro_rules! serde_field_string { } macro_rules! serde_field_bool { - ($struct_name: ident, $field_name: literal, $func: ident) => { + ($struct_name: ident, $field_name: literal, $func: ident, $default: literal) => { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct $struct_name { - #[serde(rename = $field_name)] + #[serde(default = $default, rename = $field_name)] pub v: bool, } impl Default for $struct_name { @@ -217,6 +217,8 @@ pub struct PeerConfig { pub lock_after_session_end: LockAfterSessionEnd, #[serde(flatten)] pub privacy_mode: PrivacyMode, + #[serde(flatten)] + pub allow_swap_key: AllowSwapKey, #[serde(default)] pub port_forwards: Vec<(i32, String, i32)>, #[serde(default)] @@ -1035,30 +1037,37 @@ impl PeerConfig { serde_field_bool!( ShowRemoteCursor, "show_remote_cursor", - default_show_remote_cursor + default_show_remote_cursor, + "ShowRemoteCursor::default_show_remote_cursor" ); serde_field_bool!( ShowQualityMonitor, "show_quality_monitor", - default_show_quality_monitor + default_show_quality_monitor, + "ShowQualityMonitor::default_show_quality_monitor" ); -serde_field_bool!(DisableAudio, "disable_audio", default_disable_audio); +serde_field_bool!(DisableAudio, "disable_audio", default_disable_audio, "DisableAudio::default_disable_audio"); serde_field_bool!( EnableFileTransfer, "enable_file_transfer", - default_enable_file_transfer + default_enable_file_transfer, + "EnableFileTransfer::default_enable_file_transfer" ); serde_field_bool!( DisableClipboard, "disable_clipboard", - default_disable_clipboard + default_disable_clipboard, + "DisableClipboard::default_disable_clipboard" ); serde_field_bool!( LockAfterSessionEnd, "lock_after_session_end", - default_lock_after_session_end + default_lock_after_session_end, + "LockAfterSessionEnd::default_lock_after_session_end" ); -serde_field_bool!(PrivacyMode, "privacy_mode", default_privacy_mode); +serde_field_bool!(PrivacyMode, "privacy_mode", default_privacy_mode, "PrivacyMode::default_privacy_mode"); + +serde_field_bool!(AllowSwapKey, "allow_swap_key", default_allow_swap_key, "AllowSwapKey::default_allow_swap_key"); #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct LocalConfig { diff --git a/res/lang.py b/res/lang.py index 481d65553..aa5f99f83 100644 --- a/res/lang.py +++ b/res/lang.py @@ -36,11 +36,11 @@ def main(): def expand(): for fn in glob.glob('./src/lang/*'): lang = os.path.basename(fn)[:-3] - if lang in ['en','cn']: continue + if lang in ['en','template']: continue print(lang) dict = get_lang(lang) fw = open("./src/lang/%s.rs"%lang, "wt", encoding='utf8') - for line in open('./src/lang/cn.rs', encoding='utf8'): + for line in open('./src/lang/template.rs', encoding='utf8'): line_strip = line.strip() if line_strip.startswith('("'): k, v = line_split(line_strip) diff --git a/src/client.rs b/src/client.rs index ebfda7283..40a9f05b0 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1230,6 +1230,8 @@ impl LoginConfigHandler { option.block_input = BoolOption::No.into(); } else if name == "show-quality-monitor" { config.show_quality_monitor.v = !config.show_quality_monitor.v; + } else if name == "allow_swap_key" { + config.allow_swap_key.v = !config.allow_swap_key.v; } else { let is_set = self .options @@ -1383,6 +1385,8 @@ impl LoginConfigHandler { self.config.disable_clipboard.v } else if name == "show-quality-monitor" { self.config.show_quality_monitor.v + } else if name == "allow_swap_key" { + self.config.allow_swap_key.v } else { !self.get_option(name).is_empty() } @@ -1807,6 +1811,7 @@ pub fn send_mouse( if check_scroll_on_mac(mask, x, y) { mouse_event.modifiers.push(ControlKey::Scroll.into()); } + interface.swap_modifier_mouse(&mut mouse_event); msg_out.set_mouse_event(mouse_event); interface.send(Data::Message(msg_out)); } @@ -2033,6 +2038,7 @@ pub trait Interface: Send + Clone + 'static + Sized { fn is_force_relay(&self) -> bool { self.get_login_config_handler().read().unwrap().force_relay } + fn swap_modifier_mouse(&self, _msg : &mut hbb_common::protos::message::MouseEvent) {} } /// Data used by the client interface. diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index e49ba65f7..e5b24fa53 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -1361,7 +1361,7 @@ pub fn send_url_scheme(_url: String) { #[cfg(target_os = "android")] pub mod server_side { - use hbb_common::log; + use hbb_common::{log, config}; use jni::{ objects::{JClass, JString}, sys::jstring, @@ -1374,11 +1374,25 @@ pub mod server_side { pub unsafe extern "system" fn Java_com_carriez_flutter_1hbb_MainService_startServer( env: JNIEnv, _class: JClass, + app_dir: JString, ) { - log::debug!("startServer from java"); + log::debug!("startServer from jvm"); + if let Ok(app_dir) = env.get_string(app_dir) { + *config::APP_DIR.write().unwrap() = app_dir.into(); + } std::thread::spawn(move || start_server(true)); } + #[no_mangle] + pub unsafe extern "system" fn Java_com_carriez_flutter_1hbb_MainService_startService( + env: JNIEnv, + _class: JClass, + ) { + log::debug!("startService from jvm"); + config::Config::set_option("stop-service".into(), "".into()); + crate::rendezvous_mediator::RendezvousMediator::restart(); + } + #[no_mangle] pub unsafe extern "system" fn Java_com_carriez_flutter_1hbb_MainService_translateLocale( env: JNIEnv, diff --git a/src/lang/ca.rs b/src/lang/ca.rs index aa33ae6e5..53ec69b5f 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Mantenir RustDesk com a servei en segon pla"), ("Ignore Battery Optimizations", "Ignorar optimizacions de la bateria"), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Connexió no disponible"), ("Legacy mode", "Mode heretat"), ("Map mode", "Mode mapa"), diff --git a/src/lang/cn.rs b/src/lang/cn.rs index f975e343f..4c037234b 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "保持 RustDesk 后台服务"), ("Ignore Battery Optimizations", "忽略电池优化"), ("android_open_battery_optimizations_tip", "如需关闭此功能,请在接下来的 RustDesk 应用设置页面中,找到并进入 [电源] 页面,取消勾选 [不受限制]"), + ("Start on Boot", "开机自启动"), + ("Start the screen sharing service on boot, requires special permissions", "开机自动启动屏幕共享服务,此功能需要一些特殊权限。"), ("Connection not allowed", "对方不允许连接"), ("Legacy mode", "传统模式"), ("Map mode", "1:1 传输"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index cfe69924c..25a494eef 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), @@ -454,8 +456,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), - ("No transfers in progress", ""), ("Codec", ""), ("Resolution", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 19310357b..8fd6f9be1 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Behold RustDesk baggrundstjeneste"), ("Ignore Battery Optimizations", "Ignorer betteri optimeringer"), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Forbindelse ikke tilladt"), ("Legacy mode", "Bagudkompatibilitetstilstand"), ("Map mode", ""), diff --git a/src/lang/de.rs b/src/lang/de.rs index ee28fe0e7..754d7b9ef 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk im Hintergrund ausführen"), ("Ignore Battery Optimizations", "Akkuoptimierung ignorieren"), ("android_open_battery_optimizations_tip", "Möchten Sie die Einstellungen zur Akkuoptimierung öffnen?"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Verbindung abgelehnt"), ("Legacy mode", "Kompatibilitätsmodus"), ("Map mode", "Kartenmodus"), @@ -454,8 +456,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Sprachanruf beenden"), ("relay_hint_tip", "Wenn eine direkte Verbindung nicht möglich ist, können Sie versuchen, eine Verbindung über einen Relay-Server herzustellen. \nWenn Sie eine Relay-Verbindung beim ersten Versuch herstellen möchten, können Sie das Suffix \"/r\" an die ID anhängen oder die Option \"Immer über Relay-Server verbinden\" auf der Gegenstelle auswählen."), ("Reconnect", "Erneut verbinden"), - ("Codec", ""), - ("Resolution", ""), - ("No transfers in progress", ""), + ("Codec", "Codec"), + ("Resolution", "Auflösung"), + ("No transfers in progress", "Keine Übertragungen im Gange"), ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index 3e87cd661..250530013 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -39,8 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("verification_tip", "A new device has been detected, and a verification code has been sent to the registered email address, enter the verification code to continue logging in."), ("software_render_tip", "If you have an Nvidia graphics card and the remote window closes immediately after connecting, installing the nouveau driver and choosing to use software rendering may help. A software restart is required."), ("config_input", "In order to control remote desktop with keyboard, you need to grant RustDesk \"Input Monitoring\" permissions."), - ("request_elevation_tip","You can also request elevation if there is someone on the remote side."), - ("wait_accept_uac_tip","Please wait for the remote user to accept the UAC dialog."), + ("request_elevation_tip", "You can also request elevation if there is someone on the remote side."), + ("wait_accept_uac_tip", "Please wait for the remote user to accept the UAC dialog."), ("still_click_uac_tip", "Still requires the remote user to click OK on the UAC window of running RustDesk."), ("config_microphone", "In order to speak remotely, you need to grant RustDesk \"Record Audio\" permissions."), ("relay_hint_tip", "It may not be possible to connect directly, you can try to connect via relay. \nIn addition, if you want to use relay on your first try, you can add the \"/r\" suffix to the ID, or select the option \"Always connect via relay\" in the peer card."), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 9b7912cff..dfee4fb87 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/es.rs b/src/lang/es.rs index af0da0479..dc28cdae0 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Dejar RustDesk como Servicio en 2do plano"), ("Ignore Battery Optimizations", "Ignorar optimizacioens de bateria"), ("android_open_battery_optimizations_tip", "Si deseas deshabilitar esta característica, por favor, ve a la página siguiente de ajustes, busca y entra en [Batería] y desmarca [Sin restricción]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Conexión no disponible"), ("Legacy mode", "Modo heredado"), ("Map mode", "Modo mapa"), @@ -456,6 +458,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Reconnect", "Reconectar"), ("Codec", "Códec"), ("Resolution", "Resolución"), - ("No transfers in progress", ""), + ("No transfers in progress", "No hay transferencias en curso"), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 0c31e1531..824bd039c 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "را در پس زمینه نگه دارید RustDesk سرویس"), ("Ignore Battery Optimizations", "بهینه سازی باتری نادیده گرفته شود"), ("android_open_battery_optimizations_tip", "به صفحه تنظیمات بعدی بروید"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "اتصال مجاز نیست"), ("Legacy mode", "legacy حالت"), ("Map mode", "map حالت"), @@ -454,8 +456,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "توقف تماس صوتی"), ("relay_hint_tip", " را به شناسه اضافه کنید یا گزینه \"همیشه از طریق رله متصل شوید\" را در کارت همتا انتخاب کنید. همچنین، اگر می‌خواهید فوراً از سرور رله استفاده کنید، می‌توانید پسوند \"/r\".\n اتصال مستقیم ممکن است امکان پذیر نباشد. در این صورت می توانید سعی کنید از طریق سرور رله متصل شوید"), ("Reconnect", "اتصال مجدد"), - ("No transfers in progress", ""), - ("Codec", ""), - ("Resolution", ""), + ("Codec", "کدک"), + ("Resolution", "وضوح"), + ("No transfers in progress", "هیچ انتقالی در حال انجام نیست"), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 0e45827f7..28f1dd9d1 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Gardez le service RustDesk en arrière plan"), ("Ignore Battery Optimizations", "Ignorer les optimisations batterie"), ("android_open_battery_optimizations_tip", "Conseil android d'optimisation de batterie"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Connexion non autorisée"), ("Legacy mode", "Mode hérité"), ("Map mode", ""), diff --git a/src/lang/gr.rs b/src/lang/gr.rs index fca98f228..55a3c9bb7 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Εκτέλεση του RustDesk στο παρασκήνιο"), ("Ignore Battery Optimizations", "Παράβλεψη βελτιστοποιήσεων μπαταρίας"), ("android_open_battery_optimizations_tip", "Θέλετε να ανοίξετε τις ρυθμίσεις βελτιστοποίησης μπαταρίας;"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Η σύνδεση απορρίφθηκε"), ("Legacy mode", "Λειτουργία συμβατότητας"), ("Map mode", "Map mode"), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 437cf445a..f47d522db 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk futtatása a háttérben"), ("Ignore Battery Optimizations", "Akkumulátorkímélő figyelmen kívűl hagyása"), ("android_open_battery_optimizations_tip", "Ha le szeretné tiltani ezt a funkciót, lépjen a RustDesk alkalmazás beállítási oldalára, keresse meg az [Akkumulátorkímélő] lehetőséget és válassza a nincs korlátozás lehetőséget."), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "A csatlakozás nem engedélyezett"), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/id.rs b/src/lang/id.rs index 84892a7f8..7d02e154d 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Pertahankan RustDesk berjalan pada background service"), ("Ignore Battery Optimizations", "Abaikan Pengoptimalan Baterai"), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Koneksi tidak dijinkan"), ("Legacy mode", "Mode lama"), ("Map mode", "Mode peta"), diff --git a/src/lang/it.rs b/src/lang/it.rs index 101685c4a..8aedc04f6 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Mantieni il servizio di RustDesk in background"), ("Ignore Battery Optimizations", "Ignora le ottimizzazioni della batteria"), ("android_open_battery_optimizations_tip", "Se si desidera disabilitare questa funzione, andare nelle impostazioni dell'applicazione RustDesk, aprire la sezione [Batteria] e deselezionare [Senza restrizioni]."), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Connessione non consentita"), ("Legacy mode", "Modalità legacy"), ("Map mode", "Modalità mappa"), @@ -454,8 +456,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Interrompi la chiamata vocale"), ("relay_hint_tip", "Se non è possibile connettersi direttamente, si può provare a farlo tramite relay.\nInoltre, se si desidera utilizzare il relay al primo tentativo, è possibile aggiungere il suffisso \"/r\" all'ID o selezionare l'opzione \"Collegati sempre tramite relay\" nella scheda peer."), ("Reconnect", "Riconnetti"), - ("No transfers in progress", "Nessun trasferimento in corso"), ("Codec", "Codec"), ("Resolution", "Risoluzione"), + ("No transfers in progress", "Nessun trasferimento in corso"), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index c19b607ca..d097a8b61 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk バックグラウンドサービスを維持"), ("Ignore Battery Optimizations", "バッテリーの最適化を無効にする"), ("android_open_battery_optimizations_tip", "この機能を使わない場合は、次のRestDeskアプリ設定ページから「バッテリー」に進み、「制限なし」の選択を外してください"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "接続が許可されていません"), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 97574e67d..8ca881f16 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk 백그라운드 서비스로 유지하기"), ("Ignore Battery Optimizations", "배터리 최적화 무시하기"), ("android_open_battery_optimizations_tip", "해당 기능을 비활성화하려면 RustDesk 응용 프로그램 설정 페이지로 이동하여 [배터리]에서 [제한 없음] 선택을 해제하십시오."), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "연결이 허용되지 않음"), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 54a51b439..a9acdce65 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Артжақтағы RustDesk сербесін сақтап тұру"), ("Ignore Battery Optimizations", "Бәтері Оңтайландыруларын Елемеу"), ("android_open_battery_optimizations_tip", "Егер де бұл ерекшелікті өшіруді қаласаңыз, келесі RustDesk апылқат орнатпалары бетіне барып, [Бәтері]'ні тауып кіріңіз де [Шектеусіз]'ден құсбелгіні алып тастауды өтінеміз"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Қосылу рұқсат етілмеген"), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/nl.rs b/src/lang/nl.rs index eb7c214ab..d1c154546 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk achtergronddienst behouden"), ("Ignore Battery Optimizations", "Negeer Batterij Optimalisaties"), ("android_open_battery_optimizations_tip", "Ga naar de volgende pagina met instellingen"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Verbinding niet toegestaan"), ("Legacy mode", "Verouderde modus"), ("Map mode", "Map mode"), @@ -444,7 +446,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Default View Style", "Standaard Weergave Stijl"), ("Default Scroll Style", "Standaard Scroll Stijl"), ("Default Image Quality", "Standaard Beeldkwaliteit"), - ("Default Codec", "tandaard Codec"), + ("Default Codec", "Standaard Codec"), ("Bitrate", "Bitrate"), ("FPS", "FPS"), ("Auto", "Auto"), @@ -452,10 +454,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Voice call", "Spraakoproep"), ("Text chat", "Tekst chat"), ("Stop voice call", "Stop spraakoproep"), - ("relay_hint_tip", ""), - ("Reconnect", ""), - ("Codec", ""), - ("Resolution", ""), - ("No transfers in progress", ""), + ("relay_hint_tip", "Indien een directe verbinding niet mogelijk is, kunt u proberen verbinding te maken via een Relay Server. \nAls u bij de eerste poging een relaisverbinding tot stand wilt brengen, kunt u het achtervoegsel \"/r\" toevoegen aan het ID of de optie \"Altijd verbinden via relaisserver\" selecteren op de externe terminal."), + ("Reconnect", "Herverbinden"), + ("Codec", "Codec"), + ("Resolution", "Resolutie"), + ("No transfers in progress", "Geen overdrachten in uitvoering"), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 13027a682..494715527 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Zachowaj usługę RustDesk w tle"), ("Ignore Battery Optimizations", "Ignoruj optymalizację baterii"), ("android_open_battery_optimizations_tip", "Jeśli chcesz wyłączyć tę funkcję, przejdź do następnej strony ustawień aplikacji RustDesk, znajdź i wprowadź [Bateria], odznacz [Bez ograniczeń]"), + ("Start on Boot", "Autostart"), + ("Start the screen sharing service on boot, requires special permissions", "Uruchom usługę udostępniania ekranu podczas startu, wymaga specjalnych uprawnień"), ("Connection not allowed", "Połączenie niedozwolone"), ("Legacy mode", "Tryb kompatybilności wstecznej (legacy)"), ("Map mode", "Tryb mapowania"), @@ -456,9 +458,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Reconnect", "Połącz ponownie"), ("Codec", "Kodek"), ("Resolution", "Rozdzielczość"), - ("Use temporary password", "Użyj hasła tymczasowego"), - ("Set temporary password length", "Ustaw długość hasła tymczasowego"), ("Key", "Klucz"), - ("No transfers in progress", ""), + ("No transfers in progress", "Brak transferów w toku"), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 923bbab05..b62bd5a31 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Manter o serviço RustDesk em funcionamento"), ("Ignore Battery Optimizations", "Ignorar optimizações de Bateria"), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Ligação não autorizada"), ("Legacy mode", ""), ("Map mode", ""), @@ -454,8 +456,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), - ("No transfers in progress", ""), ("Codec", ""), ("Resolution", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index aa491f951..546ef2a3c 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Manter o serviço do RustDesk executando em segundo plano"), ("Ignore Battery Optimizations", "Ignorar otimizações de bateria"), ("android_open_battery_optimizations_tip", "Abrir otimizações de bateria"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Conexão não permitida"), ("Legacy mode", "Modo legado"), ("Map mode", "Modo mapa"), diff --git a/src/lang/ro.rs b/src/lang/ro.rs index e992b19d8..af9389a29 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Rulează serviciul RustDesk în fundal"), ("Ignore Battery Optimizations", "Ignoră optimizările de baterie"), ("android_open_battery_optimizations_tip", "Pentru dezactivarea acestei funcții, accesează setările aplicației RustDesk, deschide secțiunea [Baterie] și deselectează [Fără restricții]."), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Conexiune neautoriztă"), ("Legacy mode", "Mod legacy"), ("Map mode", "Mod hartă"), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 07b8af998..b9af4ce98 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Держать в фоне службу RustDesk"), ("Ignore Battery Optimizations", "Игнорировать оптимизацию батареи"), ("android_open_battery_optimizations_tip", "Перейдите на следующую страницу настроек"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Подключение не разрешено"), ("Legacy mode", "Устаревший режим"), ("Map mode", "Режим сопоставления"), @@ -454,8 +456,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Завершить голосовой вызов"), ("relay_hint_tip", "Прямое подключение может оказаться невозможным. В этом случае можно попытаться подключиться через сервер ретрансляции. \nКроме того, если вы хотите сразу использовать сервер ретрансляции, можно добавить к ID суффикс \"/r\" или включить \"Всегда подключаться через ретранслятор\" в настройках удалённого узла."), ("Reconnect", "Переподключить"), - ("Codec", ""), - ("Resolution", ""), - ("No transfers in progress", ""), + ("Codec", "Кодек"), + ("Resolution", "Разрешение"), + ("No transfers in progress", "Передача не осуществляется"), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 6468b7eef..8a6b765be 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/sl.rs b/src/lang/sl.rs index d128e7322..5721d01f4 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Ohrani RustDeskovo storitev v ozadju"), ("Ignore Battery Optimizations", "Prezri optimizacije baterije"), ("android_open_battery_optimizations_tip", "Če želite izklopiti to možnost, pojdite v nastavitve aplikacije RustDesk, poiščite »Baterija« in izklopite »Neomejeno«"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Povezava ni dovoljena"), ("Legacy mode", "Stari način"), ("Map mode", "Način preslikave"), diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 29c5cbbf8..1c488d470 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Mbaje shërbimin e sfondit të RustDesk"), ("Ignore Battery Optimizations", "Injoro optimizimet e baterisë"), ("android_open_battery_optimizations_tip", "Nëse dëshironi ta çaktivizoni këtë veçori, ju lutemi shkoni te faqja tjetër e cilësimeve të aplikacionit RustDesk, gjeni dhe shtypni [Batteri], hiqni zgjedhjen [Te pakufizuara]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Lidhja nuk lejohet"), ("Legacy mode", "Modaliteti i trashëgimisë"), ("Map mode", "Modaliteti i hartës"), diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 63173dc11..249c0b599 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Zadrži RustDesk kao pozadinski servis"), ("Ignore Battery Optimizations", "Zanemari optimizacije baterije"), ("android_open_battery_optimizations_tip", "Ako želite da onemogućite ovu funkciju, molimo idite na sledeću stranicu za podešavanje RustDesk aplikacije, pronađite i uđite u [Battery], isključite [Unrestricted]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Konekcija nije dozvoljena"), ("Legacy mode", "Zastareli mod"), ("Map mode", "Mod mapiranja"), diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 1a00ece43..90ec8c1cf 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Behåll RustDesk i bakgrunden"), ("Ignore Battery Optimizations", "Ignorera batterioptimering"), ("android_open_battery_optimizations_tip", "Om du vill stänga av denna funktion, gå till nästa RustDesk programs inställningar, hitta [Batteri], Checka ur [Obegränsad]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Anslutning ej tillåten"), ("Legacy mode", "Legacy mode"), ("Map mode", "Kartläge"), diff --git a/src/lang/template.rs b/src/lang/template.rs index 2c83f9474..6563d6056 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/th.rs b/src/lang/th.rs index 6fcf02ed2..316622395 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "คงสถานะการทำงานเบื้องหลังของเซอร์วิส RustDesk"), ("Ignore Battery Optimizations", "เพิกเฉยการตั้งค่าการใช้งาน Battery Optimization"), ("android_open_battery_optimizations_tip", "หากคุณต้องการปิดการใช้งานฟีเจอร์นี้ กรุณาไปยังหน้าตั้งค่าในแอปพลิเคชัน RustDesk ค้นหาหัวข้อ [Battery] และยกเลิกการเลือกรายการ [Unrestricted]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "การเชื่อมต่อไม่อนุญาต"), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index d35d288d6..7359bf064 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk arka plan hizmetini sürdürün"), ("Ignore Battery Optimizations", "Pil Optimizasyonlarını Yoksay"), ("android_open_battery_optimizations_tip", ""), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "bağlantıya izin verilmedi"), ("Legacy mode", "Eski mod"), ("Map mode", "Haritalama modu"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 20a2998ec..70533c482 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "保持RustDesk後台服務"), ("Ignore Battery Optimizations", "忽略電池優化"), ("android_open_battery_optimizations_tip", "如需關閉此功能,請在接下來的RustDesk應用設置頁面中,找到並進入 [電源] 頁面,取消勾選 [不受限制]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "對方不允許連接"), ("Legacy mode", "傳統模式"), ("Map mode", "1:1傳輸"), diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 4c4b5d4bc..6b54c83c3 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Зберегти фонову службу RustDesk"), ("Ignore Battery Optimizations", "Ігнорувати оптимізацію батареї"), ("android_open_battery_optimizations_tip", "Перейдіть на наступну сторінку налаштувань"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Підключення не дозволено"), ("Legacy mode", "Застарілий режим"), ("Map mode", "Режим карти"), diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 32cd084cb..a379b3185 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -312,6 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Giữ dịch vụ nền RustDesk"), ("Ignore Battery Optimizations", "Bỏ qua các tối ưu pin"), ("android_open_battery_optimizations_tip", "Nếu bạn muốn tắt tính năng này, vui lòng chuyển đến trang cài đặt ứng dụng RustDesk tiếp theo, tìm và nhập [Pin], Bỏ chọn [Không hạn chế]"), + ("Start on Boot", ""), + ("Start the screen sharing service on boot, requires special permissions", ""), ("Connection not allowed", "Kết nối không đuợc phép"), ("Legacy mode", ""), ("Map mode", ""), diff --git a/src/main.rs b/src/main.rs index 169515425..3759f6056 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ -// Specify the Windows subsystem to eliminate console window. -// Requires Rust 1.18. -//#![windows_subsystem = "windows"] + #![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" + )] use librustdesk::*; diff --git a/src/platform/macos.mm b/src/platform/macos.mm index 8be0c6db5..3c90981c4 100644 --- a/src/platform/macos.mm +++ b/src/platform/macos.mm @@ -1,6 +1,9 @@ #import #import #import +#include +#include + // https://github.com/codebytere/node-mac-permissions/blob/main/permissions.mm @@ -35,6 +38,33 @@ extern "C" bool InputMonitoringAuthStatus(bool prompt) { return false; } +extern "C" bool MacCheckAdminAuthorization() { + AuthorizationRef authRef; + OSStatus status; + + status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, + kAuthorizationFlagDefaults, &authRef); + if (status != errAuthorizationSuccess) { + printf("Failed to create AuthorizationRef\n"); + return false; + } + + AuthorizationItem authItem = {kAuthorizationRightExecute, 0, NULL, 0}; + AuthorizationRights authRights = {1, &authItem}; + AuthorizationFlags flags = kAuthorizationFlagDefaults | + kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagPreAuthorize | + kAuthorizationFlagExtendRights; + status = AuthorizationCopyRights(authRef, &authRights, kAuthorizationEmptyEnvironment, flags, NULL); + if (status != errAuthorizationSuccess) { + printf("Failed to authorize\n"); + return false; + } + + AuthorizationFree(authRef, kAuthorizationFlagDefaults); + return true; +} + extern "C" float BackingScaleFactor() { NSScreen* s = [NSScreen mainScreen]; if (s) return [s backingScaleFactor]; @@ -44,6 +74,33 @@ extern "C" float BackingScaleFactor() { // https://github.com/jhford/screenresolution/blob/master/cg_utils.c // https://github.com/jdoupe/screenres/blob/master/setgetscreen.m +size_t bitDepth(CGDisplayModeRef mode) { + size_t depth = 0; + // Deprecated, same display same bpp? + // https://stackoverflow.com/questions/8210824/how-to-avoid-cgdisplaymodecopypixelencoding-to-get-bpp + // https://github.com/libsdl-org/SDL/pull/6628 + CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); + // my numerical representation for kIO16BitFloatPixels and kIO32bitFloatPixels + // are made up and possibly non-sensical + if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO32BitFloatPixels), kCFCompareCaseInsensitive)) { + depth = 96; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO64BitDirectPixels), kCFCompareCaseInsensitive)) { + depth = 64; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO16BitFloatPixels), kCFCompareCaseInsensitive)) { + depth = 48; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive)) { + depth = 32; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO30BitDirectPixels), kCFCompareCaseInsensitive)) { + depth = 30; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive)) { + depth = 16; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive)) { + depth = 8; + } + CFRelease(pixelEncoding); + return depth; +} + extern "C" bool MacGetModeNum(CGDirectDisplayID display, uint32_t *numModes) { CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); if (allModes == NULL) { @@ -55,16 +112,28 @@ extern "C" bool MacGetModeNum(CGDirectDisplayID display, uint32_t *numModes) { } extern "C" bool MacGetModes(CGDirectDisplayID display, uint32_t *widths, uint32_t *heights, uint32_t max, uint32_t *numModes) { - CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); - if (allModes == NULL) { + CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(display); + if (currentMode == NULL) { return false; } - *numModes = CFArrayGetCount(allModes); - for (uint32_t i = 0; i < *numModes && i < max; i++) { - CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); - widths[i] = (uint32_t)CGDisplayModeGetWidth(mode); - heights[i] = (uint32_t)CGDisplayModeGetHeight(mode); + CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); + if (allModes == NULL) { + CGDisplayModeRelease(currentMode); + return false; } + uint32_t allModeCount = CFArrayGetCount(allModes); + uint32_t realNum = 0; + for (uint32_t i = 0; i < allModeCount && realNum < max; i++) { + CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); + if (CGDisplayModeGetRefreshRate(currentMode) == CGDisplayModeGetRefreshRate(mode) && + bitDepth(currentMode) == bitDepth(mode)) { + widths[realNum] = (uint32_t)CGDisplayModeGetWidth(mode); + heights[realNum] = (uint32_t)CGDisplayModeGetHeight(mode); + realNum++; + } + } + *numModes = realNum; + CGDisplayModeRelease(currentMode); CFRelease(allModes); return true; } @@ -80,31 +149,8 @@ extern "C" bool MacGetMode(CGDirectDisplayID display, uint32_t *width, uint32_t return true; } -size_t bitDepth(CGDisplayModeRef mode) { - size_t depth = 0; - CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); - // my numerical representation for kIO16BitFloatPixels and kIO32bitFloatPixels - // are made up and possibly non-sensical - if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO32BitFloatPixels), kCFCompareCaseInsensitive)) { - depth = 96; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO64BitDirectPixels), kCFCompareCaseInsensitive)) { - depth = 64; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO16BitFloatPixels), kCFCompareCaseInsensitive)) { - depth = 48; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive)) { - depth = 32; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO30BitDirectPixels), kCFCompareCaseInsensitive)) { - depth = 30; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive)) { - depth = 16; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive)) { - depth = 8; - } - CFRelease(pixelEncoding); - return depth; -} -bool setDisplayToMode(CGDirectDisplayID display, CGDisplayModeRef mode) { +static bool setDisplayToMode(CGDirectDisplayID display, CGDisplayModeRef mode) { CGError rc; CGDisplayConfigRef config; rc = CGBeginDisplayConfiguration(&config); @@ -122,7 +168,6 @@ bool setDisplayToMode(CGDirectDisplayID display, CGDisplayModeRef mode) { return true; } - extern "C" bool MacSetMode(CGDirectDisplayID display, uint32_t width, uint32_t height) { bool ret = false; @@ -140,8 +185,8 @@ extern "C" bool MacSetMode(CGDirectDisplayID display, uint32_t width, uint32_t h CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); if (width == CGDisplayModeGetWidth(mode) && height == CGDisplayModeGetHeight(mode) && - bitDepth(currentMode) == bitDepth(mode) && - CGDisplayModeGetRefreshRate(currentMode) == CGDisplayModeGetRefreshRate(mode)) { + CGDisplayModeGetRefreshRate(currentMode) == CGDisplayModeGetRefreshRate(mode) && + bitDepth(currentMode) == bitDepth(mode)) { ret = setDisplayToMode(display, mode); break; } diff --git a/src/platform/macos.rs b/src/platform/macos.rs index b663b0f41..5c4c68e2c 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -34,6 +34,7 @@ extern "C" { static kAXTrustedCheckOptionPrompt: CFStringRef; fn AXIsProcessTrustedWithOptions(options: CFDictionaryRef) -> BOOL; fn InputMonitoringAuthStatus(_: BOOL) -> BOOL; + fn MacCheckAdminAuthorization() -> BOOL; fn MacGetModeNum(display: u32, numModes: *mut u32) -> BOOL; fn MacGetModes( display: u32, @@ -665,3 +666,10 @@ pub fn change_resolution(name: &str, width: usize, height: usize) -> ResultType< } Ok(()) } + + +pub fn check_super_user_permission() -> ResultType { + unsafe { + Ok(MacCheckAdminAuthorization() == YES) + } +} diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 6b3f8013c..561bb4570 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -976,7 +976,7 @@ fn get_after_install(exe: &str) -> String { } pub fn install_me(options: &str, path: String, silent: bool, debug: bool) -> ResultType<()> { - let uninstall_str = get_uninstall(); + let uninstall_str = get_uninstall(false); let mut path = path.trim_end_matches('\\').to_owned(); let (subkey, _path, start_menu, exe) = get_default_install_info(); let mut exe = exe; @@ -1188,30 +1188,35 @@ pub fn run_after_install() -> ResultType<()> { } pub fn run_before_uninstall() -> ResultType<()> { - run_cmds(get_before_uninstall(), true, "before_install") + run_cmds(get_before_uninstall(true), true, "before_install") } -fn get_before_uninstall() -> String { +fn get_before_uninstall(kill_self: bool) -> String { let app_name = crate::get_app_name(); let ext = app_name.to_lowercase(); + let filter = if kill_self { + "".to_string() + } else { + format!(" /FI \"PID ne {}\"", get_current_pid()) + }; format!( " chcp 65001 sc stop {app_name} sc delete {app_name} taskkill /F /IM {broker_exe} - taskkill /F /IM {app_name}.exe /FI \"PID ne {cur_pid}\" + taskkill /F /IM {app_name}.exe{filter} reg delete HKEY_CLASSES_ROOT\\.{ext} /f netsh advfirewall firewall delete rule name=\"{app_name} Service\" ", app_name = app_name, broker_exe = crate::win_privacy::INJECTED_PROCESS_EXE, ext = ext, - cur_pid = get_current_pid(), + filter = filter, ) } -fn get_uninstall() -> String { +fn get_uninstall(kill_self: bool) -> String { let (subkey, path, start_menu, _) = get_install_info(); format!( " @@ -1222,7 +1227,7 @@ fn get_uninstall() -> String { if exist \"%PUBLIC%\\Desktop\\{app_name}.lnk\" del /f /q \"%PUBLIC%\\Desktop\\{app_name}.lnk\" if exist \"%PROGRAMDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\{app_name} Tray.lnk\" del /f /q \"%PROGRAMDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\{app_name} Tray.lnk\" ", - before_uninstall=get_before_uninstall(), + before_uninstall=get_before_uninstall(kill_self), subkey=subkey, app_name = crate::get_app_name(), path = path, @@ -1231,11 +1236,20 @@ fn get_uninstall() -> String { } pub fn uninstall_me() -> ResultType<()> { - run_cmds(get_uninstall(), true, "uninstall") + run_cmds(get_uninstall(true), true, "uninstall") } fn write_cmds(cmds: String, ext: &str, tip: &str) -> ResultType { let mut tmp = std::env::temp_dir(); + // When dir contains these characters, the bat file will not execute in elevated mode. + if vec!["&", "@", "^"] + .drain(..) + .any(|s| tmp.to_string_lossy().to_string().contains(s)) + { + if let Ok(dir) = user_accessible_folder() { + tmp = dir; + } + } tmp.push(format!("{}_{}.{}", crate::get_app_name(), tip, ext)); let mut file = std::fs::File::create(&tmp)?; // in case cmds mixed with \r\n and \n, make sure all ending with \r\n @@ -1872,3 +1886,19 @@ pub fn change_resolution(name: &str, width: usize, height: usize) -> ResultType< Ok(()) } } + +pub fn user_accessible_folder() -> ResultType { + let disk = std::env::var("SystemDrive").unwrap_or("C:".to_string()); + let dir1 = PathBuf::from(format!("{}\\ProgramData", disk)); + // NOTICE: "C:\Windows\Temp" requires permanent authorization. + let dir2 = PathBuf::from(format!("{}\\Windows\\Temp", disk)); + let dir; + if dir1.exists() { + dir = dir1; + } else if dir2.exists() { + dir = dir2; + } else { + bail!("no vaild user accessible folder"); + } + Ok(dir) +} diff --git a/src/server/portable_service.rs b/src/server/portable_service.rs index 7514ead38..c49f974a7 100644 --- a/src/server/portable_service.rs +++ b/src/server/portable_service.rs @@ -117,17 +117,7 @@ impl SharedMemory { } fn flink(name: String) -> ResultType { - let disk = std::env::var("SystemDrive").unwrap_or("C:".to_string()); - let dir1 = PathBuf::from(format!("{}\\ProgramData", disk)); - let dir2 = PathBuf::from(format!("{}\\Windows\\Temp", disk)); - let mut dir; - if dir1.exists() { - dir = dir1; - } else if dir2.exists() { - dir = dir2; - } else { - bail!("no vaild flink directory"); - } + let mut dir = crate::platform::user_accessible_folder()?; dir = dir.join(hbb_common::config::APP_NAME.read().unwrap().clone()); if !dir.exists() { std::fs::create_dir(&dir)?; diff --git a/src/ui/header.tis b/src/ui/header.tis index e25c0d544..257ba417e 100644 --- a/src/ui/header.tis +++ b/src/ui/header.tis @@ -198,6 +198,7 @@ class Header: Reactor.Component { {keyboard_enabled && clipboard_enabled ?
  • {svg_checkmark}{translate('Disable clipboard')}
  • : ""} {keyboard_enabled ?
  • {svg_checkmark}{translate('Lock after session end')}
  • : ""} {keyboard_enabled && pi.platform == "Windows" ?
  • {svg_checkmark}{translate('Privacy mode')}
  • : ""} + {keyboard_enabled && ((is_osx && pi.platform != "Mac OS") || (!is_osx && pi.platform == "Mac OS")) ?
  • {svg_checkmark}{translate('Swap control-command key')}
  • : ""} ; } @@ -440,7 +441,7 @@ function toggleMenuState() { for (var el in $$(menu#keyboard-options>li)) { el.attributes.toggleClass("selected", values.indexOf(el.id) >= 0); } - for (var id in ["show-remote-cursor", "show-quality-monitor", "disable-audio", "enable-file-transfer", "disable-clipboard", "lock-after-session-end"]) { + for (var id in ["show-remote-cursor", "show-quality-monitor", "disable-audio", "enable-file-transfer", "disable-clipboard", "lock-after-session-end", "allow_swap_key"]) { var el = self.select('#' + id); if (el) { var value = handler.get_toggle_option(id); diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 62eba25c1..471150f60 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -707,10 +707,10 @@ pub fn is_root() -> bool { pub fn check_super_user_permission() -> bool { #[cfg(feature = "flatpak")] return true; - #[cfg(any(windows, target_os = "linux"))] + #[cfg(any(windows, target_os = "linux", target_os = "macos"))] return crate::platform::check_super_user_permission().unwrap_or(false); - #[cfg(not(any(windows, target_os = "linux")))] - true + #[cfg(not(any(windows, target_os = "linux", target_os = "macos")))] + return true; } #[allow(dead_code)] diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index f726ed526..11bcff925 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -373,10 +373,87 @@ impl Session { return "".to_owned(); } + pub fn swab_modifier_key(&self, msg: &mut KeyEvent) { + + let allow_swap_key = self.get_toggle_option("allow_swap_key".to_string()); + if allow_swap_key { + if let Some(key_event::Union::ControlKey(ck)) = msg.union { + let ck = ck.enum_value_or_default(); + let ck = match ck { + ControlKey::Control => ControlKey::Meta, + ControlKey::Meta => ControlKey::Control, + ControlKey::RControl => ControlKey::Meta, + ControlKey::RWin => ControlKey::Control, + _ => ck, + }; + msg.set_control_key(ck); + } + msg.modifiers = msg.modifiers.iter().map(|ck| { + let ck = ck.enum_value_or_default(); + let ck = match ck { + ControlKey::Control => ControlKey::Meta, + ControlKey::Meta => ControlKey::Control, + ControlKey::RControl => ControlKey::Meta, + ControlKey::RWin => ControlKey::Control, + _ => ck, + }; + hbb_common::protobuf::EnumOrUnknown::new(ck) + }).collect(); + + + let code = msg.chr(); + if code != 0 { + let mut peer = self.peer_platform().to_lowercase(); + peer.retain(|c| !c.is_whitespace()); + + let key = match peer.as_str() { + "windows" => { + let key = rdev::win_key_from_scancode(code); + let key = match key { + rdev::Key::ControlLeft => rdev::Key::MetaLeft, + rdev::Key::MetaLeft => rdev::Key::ControlLeft, + rdev::Key::ControlRight => rdev::Key::MetaLeft, + rdev::Key::MetaRight => rdev::Key::ControlLeft, + _ => key, + }; + rdev::win_scancode_from_key(key).unwrap_or_default() + } + "macos" => { + let key = rdev::macos_key_from_code(code); + let key = match key { + rdev::Key::ControlLeft => rdev::Key::MetaLeft, + rdev::Key::MetaLeft => rdev::Key::ControlLeft, + rdev::Key::ControlRight => rdev::Key::MetaLeft, + rdev::Key::MetaRight => rdev::Key::ControlLeft, + _ => key, + }; + rdev::macos_keycode_from_key(key).unwrap_or_default() + } + _ => { + let key = rdev::linux_key_from_code(code); + let key = match key { + rdev::Key::ControlLeft => rdev::Key::MetaLeft, + rdev::Key::MetaLeft => rdev::Key::ControlLeft, + rdev::Key::ControlRight => rdev::Key::MetaLeft, + rdev::Key::MetaRight => rdev::Key::ControlLeft, + _ => key, + }; + rdev::linux_keycode_from_key(key).unwrap_or_default() + } + }; + msg.set_chr(key); + } + } + + } + pub fn send_key_event(&self, evt: &KeyEvent) { // mode: legacy(0), map(1), translate(2), auto(3) + + let mut msg = evt.clone(); + self.swab_modifier_key(&mut msg); let mut msg_out = Message::new(); - msg_out.set_key_event(evt.clone()); + msg_out.set_key_event(msg); self.send(Data::Message(msg_out)); } @@ -934,6 +1011,23 @@ impl Interface for Session { handle_test_delay(t, peer).await; } } + + fn swap_modifier_mouse(&self, msg : &mut hbb_common::protos::message::MouseEvent) { + let allow_swap_key = self.get_toggle_option("allow_swap_key".to_string()); + if allow_swap_key { + msg.modifiers = msg.modifiers.iter().map(|ck| { + let ck = ck.enum_value_or_default(); + let ck = match ck { + ControlKey::Control => ControlKey::Meta, + ControlKey::Meta => ControlKey::Control, + ControlKey::RControl => ControlKey::Meta, + ControlKey::RWin => ControlKey::Control, + _ => ck, + }; + hbb_common::protobuf::EnumOrUnknown::new(ck) + }).collect(); + }; + } } impl Session { diff --git a/vdi/host/.devcontainer/devcontainer.json b/vdi/host/.devcontainer/devcontainer.json index 02c6e589b..f0016b5b1 100644 --- a/vdi/host/.devcontainer/devcontainer.json +++ b/vdi/host/.devcontainer/devcontainer.json @@ -4,8 +4,8 @@ "dockerfile": "./Dockerfile", "context": "." }, - "workspaceMount": "source=${localWorkspaceFolder},target=/home/vscode/rustdesk,type=bind,consistency=cache", - "workspaceFolder": "/home/vscode/rustdesk", + "workspaceMount": "source=${localWorkspaceFolder}/../..,target=/home/vscode/rustdesk,type=bind,consistency=cache", + "workspaceFolder": "/home/vscode/rustdesk/vdi/host", "customizations": { "vscode": { "extensions": [ @@ -15,6 +15,7 @@ "tamasfe.even-better-toml", "serayuzgur.crates", "mhutchie.git-graph", + "formulahendry.terminal", "eamodio.gitlens" ], "settings": { diff --git a/vdi/host/Cargo.lock b/vdi/host/Cargo.lock index d4254717e..7b7cf26bd 100644 --- a/vdi/host/Cargo.lock +++ b/vdi/host/Cargo.lock @@ -2,6 +2,32 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.20" @@ -11,6 +37,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" + [[package]] name = "async-broadcast" version = "0.3.4" @@ -73,7 +114,7 @@ dependencies = [ "parking", "polling", "slab", - "socket2", + "socket2 0.4.7", "waker-fn", "windows-sys 0.42.0", ] @@ -116,29 +157,73 @@ dependencies = [ "syn", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +dependencies = [ + "serde", +] + [[package]] name = "cc" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] [[package]] name = "cfg-if" @@ -146,6 +231,31 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "time", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "concurrent-queue" version = "2.1.0" @@ -155,6 +265,57 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "confy" +version = "0.4.0" +source = "git+https://github.com/open-trade/confy#630cc28a396cb7d01eefdd9f3824486fe4d8554b" +dependencies = [ + "directories-next", + "serde", + "thiserror", + "toml", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset 0.7.1", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.8.14" @@ -164,6 +325,50 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "cxx" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "derivative" version = "2.2.0" @@ -175,6 +380,16 @@ dependencies = [ "syn", ] +[[package]] +name = "directories-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + [[package]] name = "dirs" version = "4.0.0" @@ -184,6 +399,16 @@ dependencies = [ "dirs-sys", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + [[package]] name = "dirs-sys" version = "0.3.7" @@ -195,12 +420,38 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "easy-parallel" version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6907e25393cdcc1f4f3f513d9aac1e840eb1cc341a0fccb01171f7d14d10b946" +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "signature", +] + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + [[package]] name = "enumflags2" version = "0.7.5" @@ -222,6 +473,19 @@ dependencies = [ "syn", ] +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -237,6 +501,18 @@ dependencies = [ "instant", ] +[[package]] +name = "filetime" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "windows-sys 0.45.0", +] + [[package]] name = "futures" version = "0.3.26" @@ -349,14 +625,78 @@ checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "gimli" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hbb_common" +version = "0.1.0" +dependencies = [ + "anyhow", + "backtrace", + "bytes", + "chrono", + "confy", + "directories-next", + "dirs-next", + "env_logger", + "filetime", + "futures", + "futures-util", + "lazy_static", + "libc", + "log", + "mac_address", + "machine-uid", + "osascript", + "protobuf", + "protobuf-codegen", + "rand", + "regex", + "serde", + "serde_derive", + "socket2 0.3.19", + "sodiumoxide", + "sysinfo", + "tokio", + "tokio-socks", + "tokio-util", + "winapi", + "zstd", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] [[package]] name = "hex" @@ -364,6 +704,36 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "indexmap" version = "1.9.2" @@ -383,12 +753,54 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "jobserver" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +[[package]] +name = "libsodium-sys" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b779387cd56adfbc02ea4a668e704f729be8d6a6abd2c27ca5ee537849a92fd" +dependencies = [ + "cc", + "libc", + "pkg-config", + "walkdir", +] + [[package]] name = "libusb1-sys" version = "0.6.4" @@ -401,6 +813,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + [[package]] name = "lock_api" version = "0.4.9" @@ -420,6 +841,25 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "mac_address" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b238e3235c8382b7653c6408ed1b08dd379bdb9fdf990fb0bbae3db2cc0ae963" +dependencies = [ + "nix 0.23.2", + "winapi", +] + +[[package]] +name = "machine-uid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f1595709b0a7386bcd56ba34d250d626e5503917d05d32cdccddcd68603e212" +dependencies = [ + "winreg", +] + [[package]] name = "memchr" version = "2.5.0" @@ -435,6 +875,49 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.45.0", +] + +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset 0.6.5", +] + [[package]] name = "nix" version = "0.24.3" @@ -444,7 +927,7 @@ dependencies = [ "bitflags", "cfg-if", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] @@ -456,6 +939,53 @@ dependencies = [ "memchr", ] +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "object" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.17.1" @@ -472,6 +1002,17 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "osascript" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38731fa859ef679f1aec66ca9562165926b442f298467f76f5990f431efe87dc" +dependencies = [ + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "parking" version = "2.0.0" @@ -501,6 +1042,26 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "pin-project" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -558,6 +1119,58 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "protobuf" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55bad9126f378a853655831eb7363b7b01b81d19f8cb1218861086ca4a1a61e" +dependencies = [ + "bytes", + "once_cell", + "protobuf-support", + "thiserror", +] + +[[package]] +name = "protobuf-codegen" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd418ac3c91caa4032d37cb80ff0d44e2ebe637b2fb243b6234bf89cdac4901" +dependencies = [ + "anyhow", + "once_cell", + "protobuf", + "protobuf-parse", + "regex", + "tempfile", + "thiserror", +] + +[[package]] +name = "protobuf-parse" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d39b14605eaa1f6a340aec7f320b34064feb26c93aec35d6a9a2272a8ddfa49" +dependencies = [ + "anyhow", + "indexmap", + "log", + "protobuf", + "protobuf-support", + "tempfile", + "thiserror", + "which", +] + +[[package]] +name = "protobuf-support" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d4d7b8601c814cfb36bcebb79f0e61e45e1e93640cf778837833bbed05c372" +dependencies = [ + "thiserror", +] + [[package]] name = "qemu-display" version = "0.1.0" @@ -588,6 +1201,7 @@ dependencies = [ name = "qemu-rustdesk" version = "0.1.0" dependencies = [ + "hbb_common", "qemu-display", ] @@ -630,6 +1244,28 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -686,12 +1322,39 @@ dependencies = [ "libusb1-sys", ] +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + [[package]] name = "serde" version = "1.0.152" @@ -733,6 +1396,17 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_repr" version = "0.1.10" @@ -759,6 +1433,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" + [[package]] name = "slab" version = "0.4.8" @@ -774,6 +1463,17 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "socket2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +dependencies = [ + "cfg-if", + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.4.7" @@ -784,6 +1484,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "sodiumoxide" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e26be3acb6c2d9a7aac28482586a7856436af4cfe7100031d219de2d2ecb0028" +dependencies = [ + "ed25519", + "libc", + "libsodium-sys", + "serde", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -801,6 +1513,21 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sysinfo" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54cb4ebf3d49308b99e6e9dc95e989e2fdbdc210e4f67c39db0bb89ba927001c" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "winapi", +] + [[package]] name = "tempfile" version = "3.3.0" @@ -815,6 +1542,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.38" @@ -835,6 +1571,91 @@ dependencies = [ "syn", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "tokio" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.4.7", + "tokio-macros", + "windows-sys 0.42.0", +] + +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-socks" +version = "0.5.1-1" +source = "git+https://github.com/open-trade/tokio-socks#7034e79263ce25c348be072808d7601d82cd892d" +dependencies = [ + "bytes", + "either", + "futures-core", + "futures-sink", + "futures-util", + "pin-project", + "thiserror", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "futures-util", + "hashbrown", + "pin-project-lite", + "slab", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml_datetime" version = "0.5.1" @@ -900,6 +1721,12 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + [[package]] name = "usbredirhost" version = "0.0.1" @@ -948,18 +1775,95 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "waker-fn" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + [[package]] name = "wepoll-ffi" version = "0.1.2" @@ -969,6 +1873,17 @@ dependencies = [ "cc", ] +[[package]] +name = "which" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +dependencies = [ + "either", + "libc", + "once_cell", +] + [[package]] name = "winapi" version = "0.3.9" @@ -985,6 +1900,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -1087,6 +2011,15 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +[[package]] +name = "winreg" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +dependencies = [ + "winapi", +] + [[package]] name = "xml-rs" version = "0.8.4" @@ -1116,7 +2049,7 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix", + "nix 0.24.3", "once_cell", "ordered-stream", "rand", @@ -1157,6 +2090,35 @@ dependencies = [ "zvariant", ] +[[package]] +name = "zstd" +version = "0.9.2+zstd.1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2390ea1bf6c038c39674f22d95f0564725fc06034a47129179810b2fc58caa54" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "4.1.3+zstd.1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e99d81b99fb3c2c2c794e3fe56c305c63d5173a16a46b5850b07c935ffc7db79" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "1.6.2+zstd.1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2daf2f248d9ea44454bfcb2516534e8b8ad2fc91bf818a1885495fc42bc8ac9f" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "zvariant" version = "3.11.0" diff --git a/vdi/host/Cargo.toml b/vdi/host/Cargo.toml index 62c964122..6a67813a2 100644 --- a/vdi/host/Cargo.toml +++ b/vdi/host/Cargo.toml @@ -4,6 +4,6 @@ version = "0.1.0" authors = ["rustdesk "] edition = "2021" - [dependencies] -qemu-display = { git = "https://gitlab.com/marcandre.lureau/qemu-display" } \ No newline at end of file +qemu-display = { git = "https://gitlab.com/marcandre.lureau/qemu-display" } +hbb_common = { path = "../../libs/hbb_common" } From 05c0edca49a898698fdff87e033d9bb5d783517f Mon Sep 17 00:00:00 2001 From: Kingtous Date: Thu, 2 Mar 2023 09:34:08 +0800 Subject: [PATCH 099/382] fix: add texture rgba renderer so to rpm build --- res/rpm-flutter-suse.spec | 2 +- res/rpm-flutter.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/res/rpm-flutter-suse.spec b/res/rpm-flutter-suse.spec index 6c7055b4a..77c28a94e 100644 --- a/res/rpm-flutter-suse.spec +++ b/res/rpm-flutter-suse.spec @@ -4,7 +4,7 @@ Release: 0 Summary: RPM package License: GPL-3.0 Requires: gtk3 libxcb1 xdotool libXfixes3 alsa-utils curl libXtst6 libappindicator-gtk3 libvdpau1 libva2 -Provides: libdesktop_drop_plugin.so()(64bit), libdesktop_multi_window_plugin.so()(64bit), libflutter_custom_cursor_plugin.so()(64bit), libflutter_linux_gtk.so()(64bit), libscreen_retriever_plugin.so()(64bit), libtray_manager_plugin.so()(64bit), liburl_launcher_linux_plugin.so()(64bit), libwindow_manager_plugin.so()(64bit), libwindow_size_plugin.so()(64bit) +Provides: libdesktop_drop_plugin.so()(64bit), libdesktop_multi_window_plugin.so()(64bit), libflutter_custom_cursor_plugin.so()(64bit), libflutter_linux_gtk.so()(64bit), libscreen_retriever_plugin.so()(64bit), libtray_manager_plugin.so()(64bit), liburl_launcher_linux_plugin.so()(64bit), libwindow_manager_plugin.so()(64bit), libwindow_size_plugin.so()(64bit), libtexture_rgba_renderer_plugin.so()(64bit) %description The best open-source remote desktop client software, written in Rust. diff --git a/res/rpm-flutter.spec b/res/rpm-flutter.spec index 73bb993aa..6124cbb70 100644 --- a/res/rpm-flutter.spec +++ b/res/rpm-flutter.spec @@ -4,7 +4,7 @@ Release: 0 Summary: RPM package License: GPL-3.0 Requires: gtk3 libxcb libxdo libXfixes alsa-lib curl libappindicator-gtk3 libvdpau libva -Provides: libdesktop_drop_plugin.so()(64bit), libdesktop_multi_window_plugin.so()(64bit), libflutter_custom_cursor_plugin.so()(64bit), libflutter_linux_gtk.so()(64bit), libscreen_retriever_plugin.so()(64bit), libtray_manager_plugin.so()(64bit), liburl_launcher_linux_plugin.so()(64bit), libwindow_manager_plugin.so()(64bit), libwindow_size_plugin.so()(64bit) +Provides: libdesktop_drop_plugin.so()(64bit), libdesktop_multi_window_plugin.so()(64bit), libflutter_custom_cursor_plugin.so()(64bit), libflutter_linux_gtk.so()(64bit), libscreen_retriever_plugin.so()(64bit), libtray_manager_plugin.so()(64bit), liburl_launcher_linux_plugin.so()(64bit), libwindow_manager_plugin.so()(64bit), libwindow_size_plugin.so()(64bit), libtexture_rgba_renderer_plugin.so()(64bit) %description The best open-source remote desktop client software, written in Rust. From c5d7e5dfdad00da79985eec843acf75e56b776d5 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Thu, 2 Mar 2023 13:32:21 +0800 Subject: [PATCH 100/382] fix: #3369 --- src/{ui/macos.rs => platform/delegate.rs} | 11 +++++++---- src/platform/mod.rs | 3 +++ src/tray.rs | 4 ++++ src/ui.rs | 6 ++---- 4 files changed, 16 insertions(+), 8 deletions(-) rename src/{ui/macos.rs => platform/delegate.rs} (97%) diff --git a/src/ui/macos.rs b/src/platform/delegate.rs similarity index 97% rename from src/ui/macos.rs rename to src/platform/delegate.rs index cd0e5871b..01855536e 100644 --- a/src/ui/macos.rs +++ b/src/platform/delegate.rs @@ -26,7 +26,7 @@ const SHOW_SETTINGS_TAG: u32 = 2; const RUN_ME_TAG: u32 = 3; const AWAKE: u32 = 4; -trait AppHandler { +pub trait AppHandler { fn command(&mut self, cmd: u32); } @@ -63,9 +63,12 @@ impl AppHandler for Rc { } // https://github.com/xi-editor/druid/blob/master/druid-shell/src/platform/mac/application.rs -unsafe fn set_delegate(handler: Option>) { - let mut decl = - ClassDecl::new("AppDelegate", class!(NSObject)).expect("App Delegate definition failed"); +pub unsafe fn set_delegate(handler: Option>) { + let decl = ClassDecl::new("AppDelegate", class!(NSObject)); + if decl.is_none() { + return; + } + let mut decl = decl.unwrap(); decl.add_ivar::<*mut c_void>(APP_HANDLER_IVAR); decl.add_method( diff --git a/src/platform/mod.rs b/src/platform/mod.rs index ad058d4c0..f2b609d3f 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -11,6 +11,9 @@ pub mod windows; #[cfg(target_os = "macos")] pub mod macos; +#[cfg(target_os = "macos")] +pub mod delegate; + #[cfg(target_os = "linux")] pub mod linux; diff --git a/src/tray.rs b/src/tray.rs index 617ec2c93..38ed9b0cb 100644 --- a/src/tray.rs +++ b/src/tray.rs @@ -131,6 +131,10 @@ pub fn make_tray() -> hbb_common::ResultType<()> { let event_loop = EventLoopBuilder::new().build(); + unsafe { + crate::platform::delegate::set_delegate(None); + } + let tray_menu = Menu::new(); let quit_i = MenuItem::new(crate::client::translate("Exit".to_owned()), true, None); tray_menu.append_items(&[&quit_i]); diff --git a/src/ui.rs b/src/ui.rs index 22c44ec5f..f7419cd34 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -20,8 +20,6 @@ use crate::{common::get_app_name, ipc, ui_interface::*}; mod cm; #[cfg(feature = "inline")] pub mod inline; -#[cfg(target_os = "macos")] -pub mod macos; pub mod remote; pub type Children = Arc)>>; @@ -43,7 +41,7 @@ struct UIHostHandler; pub fn start(args: &mut [String]) { #[cfg(target_os = "macos")] - macos::show_dock(); + crate::platform::delegate::show_dock(); #[cfg(all(target_os = "linux", feature = "inline"))] { #[cfg(feature = "appimage")] @@ -75,7 +73,7 @@ pub fn start(args: &mut [String]) { allow_err!(sciter::set_options(sciter::RuntimeOptions::UxTheming(true))); frame.set_title(&crate::get_app_name()); #[cfg(target_os = "macos")] - macos::make_menubar(frame.get_host(), args.is_empty()); + crate::platform::delegate::make_menubar(frame.get_host(), args.is_empty()); let page; if args.len() > 1 && args[0] == "--play" { args[0] = "--connect".to_owned(); From 381b1c0cc69b6bd34a7d5023dfa8cdb3bcb87ec4 Mon Sep 17 00:00:00 2001 From: mehdi-song Date: Thu, 2 Mar 2023 09:16:25 +0330 Subject: [PATCH 101/382] Update fa.rs --- src/lang/fa.rs | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 824bd039c..158e16f75 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -37,23 +37,23 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Clipboard is empty", "کلیپبورد خالی است"), ("Stop service", "توقف سرویس"), ("Change ID", "تعویض شناسه"), - ("Your new ID", ""), - ("length %min% to %max%", ""), - ("starts with a letter", ""), - ("allowed characters", ""), + ("Your new ID", "جدید ID"), + ("length %min% to %max%", "%max% تا %min% طول از"), + ("starts with a letter", "با حرف شروع می شود"), + ("allowed characters", "کارکترهای مجاز"), ("id_change_tip", "شناسه باید طبق این شرایط باشد : حروف کوچک و بزرگ انگلیسی و اعداد از 0 تا 9، _ و همچنین حرف اول آن فقط حروف بزرگ یا کوچک انگلیسی و طول آن بین 6 الی 16 کاراکتر باشد"), ("Website", "وب سایت"), ("About", "درباره"), - ("Slogan_tip", ""), - ("Privacy Statement", ""), + ("Slogan_tip", "ساخته شده با قلب(عشق) در این دنیای پر هرج و مرج!"), + ("Privacy Statement", "بیانیه حریم خصوصی"), ("Mute", "بستن صدا"), - ("Build Date", ""), - ("Version", ""), - ("Home", ""), + ("Build Date", "تاریخ ساخت"), + ("Version", "نسخه"), + ("Home", "صفحه اصلی"), ("Audio Input", "ورودی صدا"), ("Enhancements", "بهبودها"), ("Hardware Codec", "کدک سخت افزاری"), - ("Adaptive Bitrate", ""), + ("Adaptive Bitrate", "سازگار Bitrate"), ("ID Server", "شناسه سرور"), ("Relay Server", "Relay سرور"), ("API Server", "API سرور"), @@ -213,7 +213,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the peer", "به صورت دستی توسط میزبان بسته شد"), ("Enable remote configuration modification", "فعال بودن اعمال تغییرات پیکربندی از راه دور"), ("Run without install", "بدون نصب اجرا شود"), - ("Connect via relay", ""), + ("Connect via relay", "اتصال با رله"), ("Always connect via relay", "برای اتصال استفاده شود Relay از"), ("whitelist_tip", "های مجاز می توانند به این دسکتاپ متصل شوند IP فقط"), ("Login", "ورود"), @@ -312,8 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "را در پس زمینه نگه دارید RustDesk سرویس"), ("Ignore Battery Optimizations", "بهینه سازی باتری نادیده گرفته شود"), ("android_open_battery_optimizations_tip", "به صفحه تنظیمات بعدی بروید"), - ("Start on Boot", ""), - ("Start the screen sharing service on boot, requires special permissions", ""), + ("Start on Boot", "در هنگام بوت شروع شود"), + ("Start the screen sharing service on boot, requires special permissions", "سرویس اشتراک‌گذاری صفحه را در بوت راه‌اندازی کنید، به مجوزهای خاصی نیاز دارد"), ("Connection not allowed", "اتصال مجاز نیست"), ("Legacy mode", "legacy حالت"), ("Map mode", "map حالت"), @@ -381,8 +381,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Deny LAN Discovery", "غیر فعالسازی جستجو در شبکه"), ("Write a message", "یک پیام بنویسید"), ("Prompt", ""), - ("Please wait for confirmation of UAC...", ""), - ("elevated_foreground_window_tip", ""), + ("Please wait for confirmation of UAC...", "باشید UAC لطفا منتظر تایید"), + ("elevated_foreground_window_tip", "پنجره فعلی دسکتاپ راه دور برای کار کردن به دسترسی بالاتری نیاز دارد، بنابراین نمی‌تواند به طور موقت از ماوس و صفحه کلید استفاده کند. می توانید از کاربر راه دور درخواست کنید که پنجره فعلی را به پایین منتقل کند یا روی دکمه ارتقاء دسترسی در پنجره مدیریت اتصال کلیک کنید. برای جلوگیری از این مشکل، توصیه می شود نرم افزار را روی دستگاه از راه دور نصب کنید."), ("Disconnected", "قطع ارتباط"), ("Other", "سایر"), ("Confirm before closing multiple tabs", "تایید بستن دسته ای برگه ها"), @@ -397,7 +397,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("This PC", "This PC"), ("or", "یا"), ("Continue with", "ادامه با"), - ("Elevate", "افزایش سطح"), + ("Elevate", "ارتقاء"), ("Zoom cursor", " بزرگنمایی نشانگر ماوس"), ("Accept sessions via password", "قبول درخواست با رمز عبور"), ("Accept sessions via click", "قبول درخواست با کلیک موس"), @@ -421,17 +421,17 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", "اگر کارت گرافیک Nvidia دارید و پنجره راه دور بلافاصله پس از اتصال بسته می شود، درایور nouveau را نصب نمایید و انتخاب گزینه استفاده از رندر نرم افزار می تواند کمک کننده باشد. راه اندازی مجدد نرم افزار مورد نیاز است."), ("Always use software rendering", "همیشه از رندر نرم افزاری استفاده کنید"), ("config_input", "برای کنترل دسکتاپ از راه دور با صفحه کلید، باید مجوز RustDesk \"Input Monitoring\" را بدهید."), - ("config_microphone", ""), - ("request_elevation_tip", "همچنین می توانید در صورت وجود شخصی در سمت راه دور درخواست ارتفاع دهید."), + ("config_microphone", "را بدهید. RustDesk \"Record Audio\" برای صحبت از راه دور، باید مجوز"), + ("request_elevation_tip", "همچنین می توانید در صورت وجود شخصی در سمت راه دور درخواست ارتقاء دسترسی دهید."), ("Wait", "صبر کنید"), - ("Elevation Error", "خطای ارتفاع"), + ("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", "همچنان کاربر از راه دور نیاز دارد که روی OK در پنجره UAC اجرای RustDesk کلیک کند."), - ("Request Elevation", "درخواست ارتفاع"), + ("Request Elevation", "درخواست ارتقاء دسترسی"), ("wait_accept_uac_tip", "لطفاً منتظر بمانید تا کاربر راه دور درخواست پنجره UAC را بپذیرد."), - ("Elevate successfully", "با موفقیت بالا ببرید"), + ("Elevate successfully", "ارتقاء دسترسی با موفقیت انجام شد"), ("uppercase", "حروف بزرگ"), ("lowercase", "حروف کوچک"), ("digit", "عدد"), From 9388837c4217b03077131b89765f47506c415aee Mon Sep 17 00:00:00 2001 From: RustDesk <71636191+rustdesk@users.noreply.github.com> Date: Thu, 2 Mar 2023 17:18:12 +0800 Subject: [PATCH 102/382] Update pubspec.lock --- flutter/pubspec.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index 2202b2ccf..76fe929e5 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -1563,5 +1563,5 @@ packages: source: hosted version: "0.1.1" sdks: - dart: ">=2.18.0 <3.0.0" + dart: ">=2.18.0 <4.0.0" flutter: ">=3.3.0" From 336e826ab9bfb5b09cee65b6874842351c5fa779 Mon Sep 17 00:00:00 2001 From: Georg Stadler Date: Thu, 2 Mar 2023 10:20:12 +0100 Subject: [PATCH 103/382] Update de.rs Added two lines of German translation --- src/lang/de.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/de.rs b/src/lang/de.rs index 754d7b9ef..d6ebe7f1a 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -312,8 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk im Hintergrund ausführen"), ("Ignore Battery Optimizations", "Akkuoptimierung ignorieren"), ("android_open_battery_optimizations_tip", "Möchten Sie die Einstellungen zur Akkuoptimierung öffnen?"), - ("Start on Boot", ""), - ("Start the screen sharing service on boot, requires special permissions", ""), + ("Start on Boot", "Beim Booten Starten"), + ("Start the screen sharing service on boot, requires special permissions", "Bildschirmfreigabedienst beim Booten starten, benötigt zusätzliche Berechtigungen"), ("Connection not allowed", "Verbindung abgelehnt"), ("Legacy mode", "Kompatibilitätsmodus"), ("Map mode", "Kartenmodus"), From e198f3ac21e4cc6e00c674154a9b8d10531570b0 Mon Sep 17 00:00:00 2001 From: NicKoehler <53040044+NicKoehler@users.noreply.github.com> Date: Thu, 2 Mar 2023 13:49:23 +0100 Subject: [PATCH 104/382] Update it.rs --- src/lang/it.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/it.rs b/src/lang/it.rs index 8aedc04f6..05fffedbd 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -312,8 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Mantieni il servizio di RustDesk in background"), ("Ignore Battery Optimizations", "Ignora le ottimizzazioni della batteria"), ("android_open_battery_optimizations_tip", "Se si desidera disabilitare questa funzione, andare nelle impostazioni dell'applicazione RustDesk, aprire la sezione [Batteria] e deselezionare [Senza restrizioni]."), - ("Start on Boot", ""), - ("Start the screen sharing service on boot, requires special permissions", ""), + ("Start on Boot", "Avvia all'accensione"), + ("Start the screen sharing service on boot, requires special permissions", "L'avvio del servizio di condivisione dello schermo all'accensione, richiede autorizzazioni speciali"), ("Connection not allowed", "Connessione non consentita"), ("Legacy mode", "Modalità legacy"), ("Map mode", "Modalità mappa"), From 896da1b1539e980243163001f8b836b0cc2035dd Mon Sep 17 00:00:00 2001 From: 21pages Date: Thu, 2 Mar 2023 21:40:03 +0800 Subject: [PATCH 105/382] fix reinstall Signed-off-by: 21pages --- src/core_main.rs | 4 ++-- src/platform/windows.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core_main.rs b/src/core_main.rs index 2619a1c07..8db8b6467 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -129,7 +129,7 @@ pub fn core_main() -> Option> { { use crate::platform; if args[0] == "--uninstall" { - if let Err(err) = platform::uninstall_me() { + if let Err(err) = platform::uninstall_me(true) { log::error!("Failed to uninstall: {}", err); } return None; @@ -147,7 +147,7 @@ pub fn core_main() -> Option> { hbb_common::allow_err!(platform::update_me()); return None; } else if args[0] == "--reinstall" { - hbb_common::allow_err!(platform::uninstall_me()); + hbb_common::allow_err!(platform::uninstall_me(false)); hbb_common::allow_err!(platform::install_me( "desktopicon startmenu", "".to_owned(), diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 561bb4570..3d8b415b5 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1235,8 +1235,8 @@ fn get_uninstall(kill_self: bool) -> String { ) } -pub fn uninstall_me() -> ResultType<()> { - run_cmds(get_uninstall(true), true, "uninstall") +pub fn uninstall_me(kill_self: bool) -> ResultType<()> { + run_cmds(get_uninstall(kill_self), true, "uninstall") } fn write_cmds(cmds: String, ext: &str, tip: &str) -> ResultType { From 7296a37ccc8113479210420c30cf187ff97decc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bojan=20Nem=C4=8Di=C4=87?= Date: Thu, 2 Mar 2023 16:37:32 +0100 Subject: [PATCH 106/382] Make the switch name clearer --- src/core_main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core_main.rs b/src/core_main.rs index 1b9d18aa3..4c21f1bdb 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -227,7 +227,7 @@ pub fn core_main() -> Option> { } } return None; - } else if args[0] == "--id" { + } else if args[0] == "--get-id" { if crate::platform::is_root() { println!("{}", crate::ipc::get_id()); } else { From 42c95f71f6f243653dbda04ec0a4c25c59a1fbf6 Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 2 Mar 2023 18:46:00 +0800 Subject: [PATCH 107/382] fix macos strid align Signed-off-by: fufesou --- libs/scrap/src/common/codec.rs | 6 ++++-- src/client.rs | 4 ++-- src/common.rs | 5 +++++ src/flutter.rs | 4 +++- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index 3adc24a14..868a93f5a 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -306,12 +306,13 @@ impl Decoder { pub fn handle_video_frame( &mut self, frame: &video_frame::Union, + stride_align: usize, fmt: ImageFormat, rgb: &mut Vec, ) -> ResultType { match frame { video_frame::Union::Vp9s(vp9s) => { - Decoder::handle_vp9s_video_frame(&mut self.vpx, vp9s, fmt, rgb) + Decoder::handle_vp9s_video_frame(&mut self.vpx, vp9s, stride_align, fmt, rgb) } #[cfg(feature = "hwcodec")] video_frame::Union::H264s(h264s) => { @@ -352,6 +353,7 @@ impl Decoder { fn handle_vp9s_video_frame( decoder: &mut VpxDecoder, vp9s: &EncodedVideoFrames, + stride_align: usize, fmt: ImageFormat, rgb: &mut Vec, ) -> ResultType { @@ -369,7 +371,7 @@ impl Decoder { if last_frame.is_null() { Ok(false) } else { - last_frame.to(fmt, 1, rgb); + last_frame.to(fmt, stride_align, rgb); Ok(true) } } diff --git a/src/client.rs b/src/client.rs index 40a9f05b0..a2e893c49 100644 --- a/src/client.rs +++ b/src/client.rs @@ -49,7 +49,7 @@ use scrap::{ }; use crate::{ - common::{self, is_keyboard_mode_supported}, + common::{self, is_keyboard_mode_supported, STRIDE_ALIGN}, server::video_service::{SCRAP_X11_REF_URL, SCRAP_X11_REQUIRED}, }; @@ -949,7 +949,7 @@ impl VideoHandler { let fmt = ImageFormat::ABGR; #[cfg(not(all(target_os = "windows", feature = "flutter_texture_render")))] let fmt = ImageFormat::ARGB; - let res = self.decoder.handle_video_frame(frame, fmt, &mut self.rgb); + let res = self.decoder.handle_video_frame(frame, STRIDE_ALIGN, fmt, &mut self.rgb); if self.record { self.recorder .lock() diff --git a/src/common.rs b/src/common.rs index 5f24fd5c3..a6ef0142b 100644 --- a/src/common.rs +++ b/src/common.rs @@ -39,6 +39,11 @@ pub const CLIPBOARD_INTERVAL: u64 = 333; pub const SYNC_PEER_INFO_DISPLAYS: i32 = 1; +#[cfg(all(target_os = "macos", feature = "flutter_texture_render"))] +pub const STRIDE_ALIGN: usize = 16; +#[cfg(not(all(target_os = "macos", feature = "flutter_texture_render")))] +pub const STRIDE_ALIGN: usize = 1; + // the executable name of the portable version pub const PORTABLE_APPNAME_RUNTIME_ENV_KEY: &str = "RUSTDESK_APPNAME"; diff --git a/src/flutter.rs b/src/flutter.rs index 2f660775f..6d4f143fb 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -206,7 +206,9 @@ impl VideoRenderer { self.width = width; self.height = height; self.data_len = if width > 0 && height > 0 { - (width * height * 4) as usize + let sa1 = crate::common::STRIDE_ALIGN - 1; + let w = (width as usize + sa1) & !sa1; + w * (height as usize) * 4 } else { 0 }; From 5aa97faedd6e7b286801aab8fc02f33d5a8de787 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 3 Mar 2023 09:27:51 +0800 Subject: [PATCH 108/382] Fix stride align Signed-off-by: fufesou --- libs/scrap/src/common/codec.rs | 6 ++++-- libs/scrap/src/common/hwcodec.rs | 10 +++++----- libs/scrap/src/common/mediacodec.rs | 3 ++- libs/scrap/src/common/vpxcodec.rs | 16 +++++++++------- src/common.rs | 4 +++- src/flutter.rs | 4 ++-- 6 files changed, 25 insertions(+), 18 deletions(-) diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index 868a93f5a..1aada72e2 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -380,6 +380,7 @@ impl Decoder { fn handle_hw_video_frame( decoder: &mut HwDecoder, frames: &EncodedVideoFrames, + stride_align: usize, fmt: ImageFormat, raw: &mut Vec, i420: &mut Vec, @@ -388,7 +389,7 @@ impl Decoder { for h264 in frames.frames.iter() { for image in decoder.decode(&h264.data)? { // TODO: just process the last frame - if image.to_fmt(fmt, raw, i420).is_ok() { + if image.to_fmt(stride_align, fmt, raw, i420).is_ok() { ret = true; } } @@ -400,12 +401,13 @@ impl Decoder { fn handle_mediacodec_video_frame( decoder: &mut MediaCodecDecoder, frames: &EncodedVideoFrames, + stride_align: usize, fmt: ImageFormat, raw: &mut Vec, ) -> ResultType { let mut ret = false; for h264 in frames.frames.iter() { - return decoder.decode(&h264.data, fmt, raw); + return decoder.decode(&h264.data, stride_align, fmt, raw); } return Ok(false); } diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index d2b9f414f..82f8b7283 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -236,7 +236,7 @@ pub struct HwDecoderImage<'a> { } impl HwDecoderImage<'_> { - pub fn to_fmt(&self, fmt: ImageFormat, fmt_data: &mut Vec, i420: &mut Vec) -> ResultType<()> { + pub fn to_fmt(&self, stride_align: usize, fmt: ImageFormat, fmt_data: &mut Vec, i420: &mut Vec) -> ResultType<()> { let frame = self.frame; match frame.pixfmt { AVPixelFormat::AV_PIX_FMT_NV12 => hw::hw_nv12_to( @@ -269,12 +269,12 @@ impl HwDecoderImage<'_> { } } - pub fn bgra(&self, bgra: &mut Vec, i420: &mut Vec) -> ResultType<()> { - self.to_fmt(ImageFormat::ARGB, bgra, i420) + pub fn bgra(&self, stride_align: usize, bgra: &mut Vec, i420: &mut Vec) -> ResultType<()> { + self.to_fmt(stride_align, ImageFormat::ARGB, bgra, i420) } - pub fn rgba(&self, rgba: &mut Vec, i420: &mut Vec) -> ResultType<()> { - self.to_fmt(ImageFormat::ABGR, rgba, i420) + pub fn rgba(&self, stride_align: usize, rgba: &mut Vec, i420: &mut Vec) -> ResultType<()> { + self.to_fmt(stride_align, ImageFormat::ABGR, rgba, i420) } } diff --git a/libs/scrap/src/common/mediacodec.rs b/libs/scrap/src/common/mediacodec.rs index 7bda0b69d..694a5e3ed 100644 --- a/libs/scrap/src/common/mediacodec.rs +++ b/libs/scrap/src/common/mediacodec.rs @@ -50,7 +50,8 @@ impl MediaCodecDecoder { MediaCodecDecoders { h264, h265 } } - pub fn decode(&mut self, data: &[u8], fmt: ImageFormat, raw: &mut Vec) -> ResultType { + // to-do: apply stride_align to raw output data + pub fn decode(&mut self, data: &[u8], stride_align: usize, fmt: ImageFormat, raw: &mut Vec) -> ResultType { match self.dequeue_input_buffer(Duration::from_millis(10))? { Some(mut input_buffer) => { let mut buf = input_buffer.buffer_mut(); diff --git a/libs/scrap/src/common/vpxcodec.rs b/libs/scrap/src/common/vpxcodec.rs index 7a65b193d..a94db61b4 100644 --- a/libs/scrap/src/common/vpxcodec.rs +++ b/libs/scrap/src/common/vpxcodec.rs @@ -541,13 +541,15 @@ impl Image { pub fn to(&self, fmt: ImageFormat, stride_align: usize, dst: &mut Vec) { let h = self.height(); - let mut w = self.width(); - let bps = match fmt { + let w = self.width(); + let bytes_per_pixel = match fmt { ImageFormat::Raw => 3, ImageFormat::ARGB | ImageFormat::ABGR => 4, }; - w = (w + stride_align - 1) & !(stride_align - 1); - dst.resize(h * w * bps, 0); + // https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L128 + // https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L129 + let bytes_per_row = (w * bytes_per_pixel + stride_align - 1) & !(stride_align - 1); + dst.resize(h * bytes_per_row, 0); let img = self.inner(); unsafe { match fmt { @@ -560,7 +562,7 @@ impl Image { img.planes[2], img.stride[2], dst.as_mut_ptr(), - (w * bps) as _, + bytes_per_row as _, self.width() as _, self.height() as _, ); @@ -574,7 +576,7 @@ impl Image { img.planes[2], img.stride[2], dst.as_mut_ptr(), - (w * bps) as _, + bytes_per_row as _, self.width() as _, self.height() as _, ); @@ -588,7 +590,7 @@ impl Image { img.planes[2], img.stride[2], dst.as_mut_ptr(), - (w * bps) as _, + bytes_per_row as _, self.width() as _, self.height() as _, ); diff --git a/src/common.rs b/src/common.rs index a6ef0142b..181f283e1 100644 --- a/src/common.rs +++ b/src/common.rs @@ -40,7 +40,9 @@ pub const CLIPBOARD_INTERVAL: u64 = 333; pub const SYNC_PEER_INFO_DISPLAYS: i32 = 1; #[cfg(all(target_os = "macos", feature = "flutter_texture_render"))] -pub const STRIDE_ALIGN: usize = 16; +// https://developer.apple.com/forums/thread/712709 +// Memory alignment should be multiple of 64. +pub const STRIDE_ALIGN: usize = 64; #[cfg(not(all(target_os = "macos", feature = "flutter_texture_render")))] pub const STRIDE_ALIGN: usize = 1; diff --git a/src/flutter.rs b/src/flutter.rs index 6d4f143fb..4984dbdb4 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -207,8 +207,8 @@ impl VideoRenderer { self.height = height; self.data_len = if width > 0 && height > 0 { let sa1 = crate::common::STRIDE_ALIGN - 1; - let w = (width as usize + sa1) & !sa1; - w * (height as usize) * 4 + let row_bytes = (width as usize * 4 + sa1) & !sa1; + row_bytes * height as usize } else { 0 }; From f709c260ffeeb68015a504af0ec8d1b1f48b9244 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 3 Mar 2023 09:45:36 +0800 Subject: [PATCH 109/382] update pub Signed-off-by: fufesou --- src/client.rs | 7 +------ src/flutter.rs | 4 +++- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/client.rs b/src/client.rs index a2e893c49..66eccfe20 100644 --- a/src/client.rs +++ b/src/client.rs @@ -944,12 +944,7 @@ impl VideoHandler { } match &vf.union { Some(frame) => { - // windows && flutter_texture_render, fmt is ImageFormat::ABGR - #[cfg(all(target_os = "windows", feature = "flutter_texture_render"))] - let fmt = ImageFormat::ABGR; - #[cfg(not(all(target_os = "windows", feature = "flutter_texture_render")))] - let fmt = ImageFormat::ARGB; - let res = self.decoder.handle_video_frame(frame, STRIDE_ALIGN, fmt, &mut self.rgb); + let res = self.decoder.handle_video_frame(frame, STRIDE_ALIGN, ImageFormat::ARGB, &mut self.rgb); if self.record { self.recorder .lock() diff --git a/src/flutter.rs b/src/flutter.rs index 4984dbdb4..76583eb3d 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -154,7 +154,7 @@ pub struct FlutterHandler { #[cfg(feature = "flutter_texture_render")] pub type FlutterRgbaRendererPluginOnRgba = - unsafe extern "C" fn(texture_rgba: *mut c_void, buffer: *const u8, width: c_int, height: c_int); + unsafe extern "C" fn(texture_rgba: *mut c_void, buffer: *const u8, len: c_int, width: c_int, height: c_int, stride_align: c_int); // Video Texture Renderer in Flutter #[cfg(feature = "flutter_texture_render")] @@ -223,8 +223,10 @@ impl VideoRenderer { func( self.ptr as _, rgba.as_ptr() as _, + rgba.len() as _, self.width as _, self.height as _, + crate::common::STRIDE_ALIGN as _, ) }; } From c8ae6a3ba37e221d7b594392aca8a7580dc5b970 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 3 Mar 2023 10:22:24 +0800 Subject: [PATCH 110/382] update flutter pub 'texture_rgba_renderer' Signed-off-by: fufesou --- flutter/pubspec.lock | 4 ++-- flutter/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index 76fe929e5..63f6c804c 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -1228,10 +1228,10 @@ packages: dependency: "direct main" description: name: texture_rgba_renderer - sha256: fbb09b2c6b4ce71261927f9e7e4ea339af3e2f3f2b175f6fb921de1c66ec848d + sha256: ec8d124e4c1d7dfff854ae34e95d7d9d877b8f9d291c383c67686e4b15cf538e url: "https://pub.dev" source: hosted - version: "0.0.8" + version: "0.0.12" timing: dependency: transitive description: diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 71a840c9c..ccb53cc9c 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -92,7 +92,7 @@ dependencies: password_strength: ^0.2.0 flutter_launcher_icons: ^0.11.0 flutter_keyboard_visibility: ^5.4.0 - texture_rgba_renderer: ^0.0.8 + texture_rgba_renderer: ^0.0.12 percent_indicator: ^4.2.2 dev_dependencies: From 0c3ccb3f60eca6b9bdb329faf1d00cf09b91ceb8 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 3 Mar 2023 10:47:31 +0800 Subject: [PATCH 111/382] Differentiate stride align between encoding and decoding Signed-off-by: fufesou --- src/client.rs | 4 ++-- src/common.rs | 4 ++-- src/flutter.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/client.rs b/src/client.rs index 66eccfe20..2249c98e4 100644 --- a/src/client.rs +++ b/src/client.rs @@ -49,7 +49,7 @@ use scrap::{ }; use crate::{ - common::{self, is_keyboard_mode_supported, STRIDE_ALIGN}, + common::{self, is_keyboard_mode_supported, STRIDE_ALIGN_RGBA_OUTPUT}, server::video_service::{SCRAP_X11_REF_URL, SCRAP_X11_REQUIRED}, }; @@ -944,7 +944,7 @@ impl VideoHandler { } match &vf.union { Some(frame) => { - let res = self.decoder.handle_video_frame(frame, STRIDE_ALIGN, ImageFormat::ARGB, &mut self.rgb); + let res = self.decoder.handle_video_frame(frame, STRIDE_ALIGN_RGBA_OUTPUT, ImageFormat::ARGB, &mut self.rgb); if self.record { self.recorder .lock() diff --git a/src/common.rs b/src/common.rs index 181f283e1..c781d3eaf 100644 --- a/src/common.rs +++ b/src/common.rs @@ -42,9 +42,9 @@ pub const SYNC_PEER_INFO_DISPLAYS: i32 = 1; #[cfg(all(target_os = "macos", feature = "flutter_texture_render"))] // https://developer.apple.com/forums/thread/712709 // Memory alignment should be multiple of 64. -pub const STRIDE_ALIGN: usize = 64; +pub const STRIDE_ALIGN_RGBA_OUTPUT: usize = 64; #[cfg(not(all(target_os = "macos", feature = "flutter_texture_render")))] -pub const STRIDE_ALIGN: usize = 1; +pub const STRIDE_ALIGN_RGBA_OUTPUT: usize = 1; // the executable name of the portable version pub const PORTABLE_APPNAME_RUNTIME_ENV_KEY: &str = "RUSTDESK_APPNAME"; diff --git a/src/flutter.rs b/src/flutter.rs index 76583eb3d..03949f89d 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -206,7 +206,7 @@ impl VideoRenderer { self.width = width; self.height = height; self.data_len = if width > 0 && height > 0 { - let sa1 = crate::common::STRIDE_ALIGN - 1; + let sa1 = crate::common::STRIDE_ALIGN_RGBA_OUTPUT - 1; let row_bytes = (width as usize * 4 + sa1) & !sa1; row_bytes * height as usize } else { @@ -226,7 +226,7 @@ impl VideoRenderer { rgba.len() as _, self.width as _, self.height as _, - crate::common::STRIDE_ALIGN as _, + crate::common::STRIDE_ALIGN_RGBA_OUTPUT as _, ) }; } From c419819c0f56d18758c99270b9a010c1d348908d Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 3 Mar 2023 10:58:48 +0800 Subject: [PATCH 112/382] rename all stride_align to stride Signed-off-by: fufesou --- libs/scrap/examples/record-screen.rs | 4 ++-- libs/scrap/src/common/codec.rs | 24 ++++++++++++------------ libs/scrap/src/common/convert.rs | 12 ++++++------ libs/scrap/src/common/hwcodec.rs | 18 +++++++++--------- libs/scrap/src/common/mediacodec.rs | 4 ++-- libs/scrap/src/common/mod.rs | 4 ++-- libs/scrap/src/common/vpxcodec.rs | 12 ++++++------ src/client.rs | 4 ++-- src/common.rs | 4 ++-- src/flutter.rs | 6 +++--- 10 files changed, 46 insertions(+), 46 deletions(-) diff --git a/libs/scrap/examples/record-screen.rs b/libs/scrap/examples/record-screen.rs index 5df97838e..13ebc5f7d 100644 --- a/libs/scrap/examples/record-screen.rs +++ b/libs/scrap/examples/record-screen.rs @@ -18,7 +18,7 @@ use webm::mux; use webm::mux::Track; use scrap::vpxcodec as vpx_encode; -use scrap::{TraitCapturer, Capturer, Display, STRIDE_ALIGN}; +use scrap::{TraitCapturer, Capturer, Display, STRIDE}; const USAGE: &'static str = " Simple WebM screen capture. @@ -137,7 +137,7 @@ fn main() -> io::Result<()> { if let Ok(frame) = c.frame(Duration::from_millis(0)) { let ms = time.as_secs() * 1000 + time.subsec_millis() as u64; - for frame in vpx.encode(ms as i64, &frame, STRIDE_ALIGN).unwrap() { + for frame in vpx.encode(ms as i64, &frame, STRIDE).unwrap() { vt.add_frame(frame.data, frame.pts as u64 * 1_000_000, frame.key); } } diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index 1aada72e2..1f02f86d7 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -306,18 +306,18 @@ impl Decoder { pub fn handle_video_frame( &mut self, frame: &video_frame::Union, - stride_align: usize, + stride: usize, fmt: ImageFormat, rgb: &mut Vec, ) -> ResultType { match frame { video_frame::Union::Vp9s(vp9s) => { - Decoder::handle_vp9s_video_frame(&mut self.vpx, vp9s, stride_align, fmt, rgb) + Decoder::handle_vp9s_video_frame(&mut self.vpx, vp9s, stride, fmt, rgb) } #[cfg(feature = "hwcodec")] video_frame::Union::H264s(h264s) => { if let Some(decoder) = &mut self.hw.h264 { - Decoder::handle_hw_video_frame(decoder, h264s, fmt, rgb, &mut self.i420) + Decoder::handle_hw_video_frame(decoder, h264s, stride, fmt, rgb, &mut self.i420) } else { Err(anyhow!("don't support h264!")) } @@ -325,7 +325,7 @@ impl Decoder { #[cfg(feature = "hwcodec")] video_frame::Union::H265s(h265s) => { if let Some(decoder) = &mut self.hw.h265 { - Decoder::handle_hw_video_frame(decoder, h265s, fmt, rgb, &mut self.i420) + Decoder::handle_hw_video_frame(decoder, h265s, stride, fmt, rgb, &mut self.i420) } else { Err(anyhow!("don't support h265!")) } @@ -333,7 +333,7 @@ impl Decoder { #[cfg(feature = "mediacodec")] video_frame::Union::H264s(h264s) => { if let Some(decoder) = &mut self.media_codec.h264 { - Decoder::handle_mediacodec_video_frame(decoder, h264s, fmt, rgb) + Decoder::handle_mediacodec_video_frame(decoder, h264s, stride, fmt, rgb) } else { Err(anyhow!("don't support h264!")) } @@ -341,7 +341,7 @@ impl Decoder { #[cfg(feature = "mediacodec")] video_frame::Union::H265s(h265s) => { if let Some(decoder) = &mut self.media_codec.h265 { - Decoder::handle_mediacodec_video_frame(decoder, h265s, fmt, rgb) + Decoder::handle_mediacodec_video_frame(decoder, h265s, stride, fmt, rgb) } else { Err(anyhow!("don't support h265!")) } @@ -353,7 +353,7 @@ impl Decoder { fn handle_vp9s_video_frame( decoder: &mut VpxDecoder, vp9s: &EncodedVideoFrames, - stride_align: usize, + stride: usize, fmt: ImageFormat, rgb: &mut Vec, ) -> ResultType { @@ -371,7 +371,7 @@ impl Decoder { if last_frame.is_null() { Ok(false) } else { - last_frame.to(fmt, stride_align, rgb); + last_frame.to(fmt, stride, rgb); Ok(true) } } @@ -380,7 +380,7 @@ impl Decoder { fn handle_hw_video_frame( decoder: &mut HwDecoder, frames: &EncodedVideoFrames, - stride_align: usize, + stride: usize, fmt: ImageFormat, raw: &mut Vec, i420: &mut Vec, @@ -389,7 +389,7 @@ impl Decoder { for h264 in frames.frames.iter() { for image in decoder.decode(&h264.data)? { // TODO: just process the last frame - if image.to_fmt(stride_align, fmt, raw, i420).is_ok() { + if image.to_fmt(stride, fmt, raw, i420).is_ok() { ret = true; } } @@ -401,13 +401,13 @@ impl Decoder { fn handle_mediacodec_video_frame( decoder: &mut MediaCodecDecoder, frames: &EncodedVideoFrames, - stride_align: usize, + stride: usize, fmt: ImageFormat, raw: &mut Vec, ) -> ResultType { let mut ret = false; for h264 in frames.frames.iter() { - return decoder.decode(&h264.data, stride_align, fmt, raw); + return decoder.decode(&h264.data, stride, fmt, raw); } return Ok(false); } diff --git a/libs/scrap/src/common/convert.rs b/libs/scrap/src/common/convert.rs index f3ad51a21..1c19ac0c0 100644 --- a/libs/scrap/src/common/convert.rs +++ b/libs/scrap/src/common/convert.rs @@ -144,7 +144,7 @@ extern "C" { fn get_vpx_i420_stride( width: usize, height: usize, - stride_align: usize, + stride: usize, ) -> (usize, usize, usize, usize, usize, usize) { let mut img = Default::default(); unsafe { @@ -153,7 +153,7 @@ fn get_vpx_i420_stride( vpx_img_fmt::VPX_IMG_FMT_I420, width as _, height as _, - stride_align as _, + stride as _, 0x1 as _, ); } @@ -169,7 +169,7 @@ fn get_vpx_i420_stride( pub fn i420_to_rgb(width: usize, height: usize, src: &[u8], dst: &mut Vec) { let (_, _, src_stride_y, src_stride_uv, u, v) = - get_vpx_i420_stride(width, height, super::STRIDE_ALIGN); + get_vpx_i420_stride(width, height, super::STRIDE); let src_y = src.as_ptr(); let src_u = src[u..].as_ptr(); let src_v = src[v..].as_ptr(); @@ -192,7 +192,7 @@ pub fn i420_to_rgb(width: usize, height: usize, src: &[u8], dst: &mut Vec) { pub fn bgra_to_i420(width: usize, height: usize, src: &[u8], dst: &mut Vec) { let (_, h, dst_stride_y, dst_stride_uv, u, v) = - get_vpx_i420_stride(width, height, super::STRIDE_ALIGN); + get_vpx_i420_stride(width, height, super::STRIDE); dst.resize(h * dst_stride_y * 2, 0); // waste some memory to ensure memory safety let dst_y = dst.as_mut_ptr(); let dst_u = dst[u..].as_mut_ptr(); @@ -215,7 +215,7 @@ pub fn bgra_to_i420(width: usize, height: usize, src: &[u8], dst: &mut Vec) pub fn rgba_to_i420(width: usize, height: usize, src: &[u8], dst: &mut Vec) { let (_, h, dst_stride_y, dst_stride_uv, u, v) = - get_vpx_i420_stride(width, height, super::STRIDE_ALIGN); + get_vpx_i420_stride(width, height, super::STRIDE); dst.resize(h * dst_stride_y * 2, 0); // waste some memory to ensure memory safety let dst_y = dst.as_mut_ptr(); let dst_u = dst[u..].as_mut_ptr(); @@ -246,7 +246,7 @@ pub unsafe fn nv12_to_i420( dst: &mut Vec, ) { let (_, h, dst_stride_y, dst_stride_uv, u, v) = - get_vpx_i420_stride(width, height, super::STRIDE_ALIGN); + get_vpx_i420_stride(width, height, super::STRIDE); dst.resize(h * dst_stride_y * 2, 0); // waste some memory to ensure memory safety let dst_y = dst.as_mut_ptr(); let dst_u = dst[u..].as_mut_ptr(); diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index 82f8b7283..0047672a4 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -1,6 +1,6 @@ use crate::{ codec::{EncoderApi, EncoderCfg}, - hw, ImageFormat, HW_STRIDE_ALIGN, + hw, ImageFormat, HW_STRIDE, }; use hbb_common::{ anyhow::{anyhow, Context}, @@ -52,7 +52,7 @@ impl EncoderApi for HwEncoder { width: config.width as _, height: config.height as _, pixfmt: DEFAULT_PIXFMT, - align: HW_STRIDE_ALIGN as _, + align: HW_STRIDE as _, bitrate: config.bitrate * 1000, timebase: DEFAULT_TIME_BASE, gop: DEFAULT_GOP, @@ -236,7 +236,7 @@ pub struct HwDecoderImage<'a> { } impl HwDecoderImage<'_> { - pub fn to_fmt(&self, stride_align: usize, fmt: ImageFormat, fmt_data: &mut Vec, i420: &mut Vec) -> ResultType<()> { + pub fn to_fmt(&self, stride: usize, fmt: ImageFormat, fmt_data: &mut Vec, i420: &mut Vec) -> ResultType<()> { let frame = self.frame; match frame.pixfmt { AVPixelFormat::AV_PIX_FMT_NV12 => hw::hw_nv12_to( @@ -249,7 +249,7 @@ impl HwDecoderImage<'_> { frame.linesize[1] as _, fmt_data, i420, - HW_STRIDE_ALIGN, + HW_STRIDE, ), AVPixelFormat::AV_PIX_FMT_YUV420P => { hw::hw_i420_to( @@ -269,12 +269,12 @@ impl HwDecoderImage<'_> { } } - pub fn bgra(&self, stride_align: usize, bgra: &mut Vec, i420: &mut Vec) -> ResultType<()> { - self.to_fmt(stride_align, ImageFormat::ARGB, bgra, i420) + pub fn bgra(&self, stride: usize, bgra: &mut Vec, i420: &mut Vec) -> ResultType<()> { + self.to_fmt(stride, ImageFormat::ARGB, bgra, i420) } - pub fn rgba(&self, stride_align: usize, rgba: &mut Vec, i420: &mut Vec) -> ResultType<()> { - self.to_fmt(stride_align, ImageFormat::ABGR, rgba, i420) + pub fn rgba(&self, stride: usize, rgba: &mut Vec, i420: &mut Vec) -> ResultType<()> { + self.to_fmt(stride, ImageFormat::ABGR, rgba, i420) } } @@ -296,7 +296,7 @@ pub fn check_config() { width: 1920, height: 1080, pixfmt: DEFAULT_PIXFMT, - align: HW_STRIDE_ALIGN as _, + align: HW_STRIDE as _, bitrate: 0, timebase: DEFAULT_TIME_BASE, gop: DEFAULT_GOP, diff --git a/libs/scrap/src/common/mediacodec.rs b/libs/scrap/src/common/mediacodec.rs index 694a5e3ed..306b511f6 100644 --- a/libs/scrap/src/common/mediacodec.rs +++ b/libs/scrap/src/common/mediacodec.rs @@ -50,8 +50,8 @@ impl MediaCodecDecoder { MediaCodecDecoders { h264, h265 } } - // to-do: apply stride_align to raw output data - pub fn decode(&mut self, data: &[u8], stride_align: usize, fmt: ImageFormat, raw: &mut Vec) -> ResultType { + // to-do: apply stride to raw output data + pub fn decode(&mut self, data: &[u8], stride: usize, fmt: ImageFormat, raw: &mut Vec) -> ResultType { match self.dequeue_input_buffer(Duration::from_millis(10))? { Some(mut input_buffer) => { let mut buf = input_buffer.buffer_mut(); diff --git a/libs/scrap/src/common/mod.rs b/libs/scrap/src/common/mod.rs index c7da57734..bc193d22d 100644 --- a/libs/scrap/src/common/mod.rs +++ b/libs/scrap/src/common/mod.rs @@ -37,8 +37,8 @@ pub mod hwcodec; pub mod mediacodec; pub mod vpxcodec; pub use self::convert::*; -pub const STRIDE_ALIGN: usize = 64; // commonly used in libvpx vpx_img_alloc caller -pub const HW_STRIDE_ALIGN: usize = 0; // recommended by av_frame_get_buffer +pub const STRIDE: usize = 64; // commonly used in libvpx vpx_img_alloc caller +pub const HW_STRIDE: usize = 0; // recommended by av_frame_get_buffer pub mod record; mod vpx; diff --git a/libs/scrap/src/common/vpxcodec.rs b/libs/scrap/src/common/vpxcodec.rs index a94db61b4..3ee3e391f 100644 --- a/libs/scrap/src/common/vpxcodec.rs +++ b/libs/scrap/src/common/vpxcodec.rs @@ -6,7 +6,7 @@ use hbb_common::anyhow::{anyhow, Context}; use hbb_common::message_proto::{EncodedVideoFrame, EncodedVideoFrames, Message, VideoFrame}; use hbb_common::{get_time, ResultType}; -use crate::STRIDE_ALIGN; +use crate::STRIDE; use crate::{codec::EncoderApi, ImageFormat}; use super::vpx::{vp8e_enc_control_id::*, vpx_codec_err_t::*, *}; @@ -202,7 +202,7 @@ impl EncoderApi for VpxEncoder { fn encode_to_message(&mut self, frame: &[u8], ms: i64) -> ResultType { let mut frames = Vec::new(); for ref frame in self - .encode(ms, frame, STRIDE_ALIGN) + .encode(ms, frame, STRIDE) .with_context(|| "Failed to encode")? { frames.push(VpxEncoder::create_frame(frame)); @@ -232,7 +232,7 @@ impl EncoderApi for VpxEncoder { } impl VpxEncoder { - pub fn encode(&mut self, pts: i64, data: &[u8], stride_align: usize) -> Result { + pub fn encode(&mut self, pts: i64, data: &[u8], stride: usize) -> Result { if 2 * data.len() < 3 * self.width * self.height { return Err(Error::FailedCall("len not enough".to_string())); } @@ -243,7 +243,7 @@ impl VpxEncoder { vpx_img_fmt::VPX_IMG_FMT_I420, self.width as _, self.height as _, - stride_align as _, + stride as _, data.as_ptr() as _, )); @@ -539,7 +539,7 @@ impl Image { self.inner().stride[iplane] } - pub fn to(&self, fmt: ImageFormat, stride_align: usize, dst: &mut Vec) { + pub fn to(&self, fmt: ImageFormat, stride: usize, dst: &mut Vec) { let h = self.height(); let w = self.width(); let bytes_per_pixel = match fmt { @@ -548,7 +548,7 @@ impl Image { }; // https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L128 // https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L129 - let bytes_per_row = (w * bytes_per_pixel + stride_align - 1) & !(stride_align - 1); + let bytes_per_row = (w * bytes_per_pixel + stride - 1) & !(stride - 1); dst.resize(h * bytes_per_row, 0); let img = self.inner(); unsafe { diff --git a/src/client.rs b/src/client.rs index 2249c98e4..14cba6c85 100644 --- a/src/client.rs +++ b/src/client.rs @@ -49,7 +49,7 @@ use scrap::{ }; use crate::{ - common::{self, is_keyboard_mode_supported, STRIDE_ALIGN_RGBA_OUTPUT}, + common::{self, is_keyboard_mode_supported, DST_STRIDE_RGBA}, server::video_service::{SCRAP_X11_REF_URL, SCRAP_X11_REQUIRED}, }; @@ -944,7 +944,7 @@ impl VideoHandler { } match &vf.union { Some(frame) => { - let res = self.decoder.handle_video_frame(frame, STRIDE_ALIGN_RGBA_OUTPUT, ImageFormat::ARGB, &mut self.rgb); + let res = self.decoder.handle_video_frame(frame, DST_STRIDE_RGBA, ImageFormat::ARGB, &mut self.rgb); if self.record { self.recorder .lock() diff --git a/src/common.rs b/src/common.rs index c781d3eaf..28d8dddc4 100644 --- a/src/common.rs +++ b/src/common.rs @@ -42,9 +42,9 @@ pub const SYNC_PEER_INFO_DISPLAYS: i32 = 1; #[cfg(all(target_os = "macos", feature = "flutter_texture_render"))] // https://developer.apple.com/forums/thread/712709 // Memory alignment should be multiple of 64. -pub const STRIDE_ALIGN_RGBA_OUTPUT: usize = 64; +pub const DST_STRIDE_RGBA: usize = 64; #[cfg(not(all(target_os = "macos", feature = "flutter_texture_render")))] -pub const STRIDE_ALIGN_RGBA_OUTPUT: usize = 1; +pub const DST_STRIDE_RGBA: usize = 1; // the executable name of the portable version pub const PORTABLE_APPNAME_RUNTIME_ENV_KEY: &str = "RUSTDESK_APPNAME"; diff --git a/src/flutter.rs b/src/flutter.rs index 03949f89d..1fbf92c12 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -154,7 +154,7 @@ pub struct FlutterHandler { #[cfg(feature = "flutter_texture_render")] pub type FlutterRgbaRendererPluginOnRgba = - unsafe extern "C" fn(texture_rgba: *mut c_void, buffer: *const u8, len: c_int, width: c_int, height: c_int, stride_align: c_int); + unsafe extern "C" fn(texture_rgba: *mut c_void, buffer: *const u8, len: c_int, width: c_int, height: c_int, stride: c_int); // Video Texture Renderer in Flutter #[cfg(feature = "flutter_texture_render")] @@ -206,7 +206,7 @@ impl VideoRenderer { self.width = width; self.height = height; self.data_len = if width > 0 && height > 0 { - let sa1 = crate::common::STRIDE_ALIGN_RGBA_OUTPUT - 1; + let sa1 = crate::common::DST_STRIDE_RGBA - 1; let row_bytes = (width as usize * 4 + sa1) & !sa1; row_bytes * height as usize } else { @@ -226,7 +226,7 @@ impl VideoRenderer { rgba.len() as _, self.width as _, self.height as _, - crate::common::STRIDE_ALIGN_RGBA_OUTPUT as _, + crate::common::DST_STRIDE_RGBA as _, ) }; } From 968b3642a9dc16714433e456a60d9983d8c45e49 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Fri, 3 Mar 2023 11:36:12 +0800 Subject: [PATCH 113/382] sort langs #2948 --- src/lang.rs | 92 ++++++++++++++++++++++----------------------- src/ui_interface.rs | 8 +++- 2 files changed, 51 insertions(+), 49 deletions(-) diff --git a/src/lang.rs b/src/lang.rs index dbf599086..f3f4c1cc6 100644 --- a/src/lang.rs +++ b/src/lang.rs @@ -1,6 +1,6 @@ -use serde_json::{json, value::Value}; use std::ops::Deref; +mod ca; mod cn; mod cs; mod da; @@ -8,69 +8,65 @@ mod de; mod en; mod eo; mod es; +mod fa; mod fr; +mod gr; mod hu; mod id; mod it; mod ja; mod ko; +mod kz; mod nl; mod pl; mod ptbr; mod ro; mod ru; mod sk; -mod tr; -mod tw; -mod vn; -mod kz; -mod ua; -mod fa; -mod ca; -mod gr; -mod sv; +mod sl; mod sq; mod sr; +mod sv; mod th; -mod sl; +mod tr; +mod tw; +mod ua; +mod vn; -lazy_static::lazy_static! { - pub static ref LANGS: Value = - json!(vec![ - ("en", "English"), - ("it", "Italiano"), - ("fr", "Français"), - ("de", "Deutsch"), - ("nl", "Nederlands"), - ("cn", "简体中文"), - ("tw", "繁體中文"), - ("pt", "Português"), - ("es", "Español"), - ("hu", "Magyar"), - ("ru", "Русский"), - ("sk", "Slovenčina"), - ("id", "Indonesia"), - ("cs", "Čeština"), - ("da", "Dansk"), - ("eo", "Esperanto"), - ("tr", "Türkçe"), - ("vn", "Tiếng Việt"), - ("pl", "Polski"), - ("ja", "日本語"), - ("ko", "한국어"), - ("kz", "Қазақ"), - ("ua", "Українська"), - ("fa", "فارسی"), - ("ca", "Català"), - ("gr", "Ελληνικά"), - ("sv", "Svenska"), - ("sq", "Shqip"), - ("sr", "Srpski"), - ("th", "ภาษาไทย"), - ("sl", "Slovenščina"), - ("ro", "Română"), - ]); -} +pub const LANGS: &[(&str, &str)] = &[ + ("en", "English"), + ("it", "Italiano"), + ("fr", "Français"), + ("de", "Deutsch"), + ("nl", "Nederlands"), + ("cn", "简体中文"), + ("tw", "繁體中文"), + ("pt", "Português"), + ("es", "Español"), + ("hu", "Magyar"), + ("ru", "Русский"), + ("sk", "Slovenčina"), + ("id", "Indonesia"), + ("cs", "Čeština"), + ("da", "Dansk"), + ("eo", "Esperanto"), + ("tr", "Türkçe"), + ("vn", "Tiếng Việt"), + ("pl", "Polski"), + ("ja", "日本語"), + ("ko", "한국어"), + ("kz", "Қазақ"), + ("ua", "Українська"), + ("fa", "فارسی"), + ("ca", "Català"), + ("gr", "Ελληνικά"), + ("sv", "Svenska"), + ("sq", "Shqip"), + ("sr", "Srpski"), + ("th", "ภาษาไทย"), + ("sl", "Slovenščina"), + ("ro", "Română"), +]; #[cfg(not(any(target_os = "android", target_os = "ios")))] pub fn translate(name: String) -> String { diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 471150f60..03d6787f8 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -636,7 +636,13 @@ pub fn get_async_job_status() -> String { #[inline] pub fn get_langs() -> String { - crate::lang::LANGS.to_string() + use serde_json::json; + let mut x: Vec<(&str, String)> = crate::lang::LANGS + .iter() + .map(|a| (a.0, format!("{} - {}", a.1, a.0))) + .collect(); + x.sort_by(|a, b| a.0.cmp(b.0)); + json!(x).to_string() } #[inline] From 4c930ff0b1efd5ef989de55814fc3623261f6b37 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Fri, 3 Mar 2023 11:49:02 +0800 Subject: [PATCH 114/382] polish langs --- src/lang.rs | 16 ++++++++++------ src/ui_interface.rs | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/lang.rs b/src/lang.rs index f3f4c1cc6..23ffa08d4 100644 --- a/src/lang.rs +++ b/src/lang.rs @@ -39,8 +39,8 @@ pub const LANGS: &[(&str, &str)] = &[ ("fr", "Français"), ("de", "Deutsch"), ("nl", "Nederlands"), - ("cn", "简体中文"), - ("tw", "繁體中文"), + ("zh-cn", "简体中文"), + ("zh-tw", "繁體中文"), ("pt", "Português"), ("es", "Español"), ("hu", "Magyar"), @@ -79,7 +79,12 @@ pub fn translate_locale(name: String, locale: &str) -> String { if lang.is_empty() { // zh_CN on Linux, zh-Hans-CN on mac, zh_CN_#Hans on Android if locale.starts_with("zh") { - lang = (if locale.contains("tw") { "tw" } else { "cn" }).to_owned(); + lang = (if locale.contains("tw") { + "zh-tw" + } else { + "zh-cn" + }) + .to_owned(); } } if lang.is_empty() { @@ -93,9 +98,9 @@ pub fn translate_locale(name: String, locale: &str) -> String { let lang = lang.to_lowercase(); let m = match lang.as_str() { "fr" => fr::T.deref(), - "cn" => cn::T.deref(), + "zh-cn" => cn::T.deref(), "it" => it::T.deref(), - "tw" => tw::T.deref(), + "zh-tw" => tw::T.deref(), "de" => de::T.deref(), "nl" => nl::T.deref(), "es" => es::T.deref(), @@ -103,7 +108,6 @@ pub fn translate_locale(name: String, locale: &str) -> String { "ru" => ru::T.deref(), "eo" => eo::T.deref(), "id" => id::T.deref(), - "ptbr" => ptbr::T.deref(), "br" => ptbr::T.deref(), "pt" => ptbr::T.deref(), "tr" => tr::T.deref(), diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 03d6787f8..1d4bd5cf4 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -639,7 +639,7 @@ pub fn get_langs() -> String { use serde_json::json; let mut x: Vec<(&str, String)> = crate::lang::LANGS .iter() - .map(|a| (a.0, format!("{} - {}", a.1, a.0))) + .map(|a| (a.0, format!("{} ({})", a.1, a.0))) .collect(); x.sort_by(|a, b| a.0.cmp(b.0)); json!(x).to_string() From 6f6d42570d471190c664e0aabb91459d7e8d2b4d Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 3 Mar 2023 11:51:33 +0800 Subject: [PATCH 115/382] reset session shared state on init Signed-off-by: fufesou --- flutter/lib/common/shared_state.dart | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/flutter/lib/common/shared_state.dart b/flutter/lib/common/shared_state.dart index ebac18dac..bc1a562b9 100644 --- a/flutter/lib/common/shared_state.dart +++ b/flutter/lib/common/shared_state.dart @@ -19,6 +19,8 @@ class PrivacyModeState { final key = tag(id); if (Get.isRegistered(tag: key)) { Get.delete(tag: key); + } else { + Get.find(tag: key).value = false; } } @@ -33,6 +35,8 @@ class BlockInputState { if (!Get.isRegistered(tag: key)) { final RxBool state = false.obs; Get.put(state, tag: key); + } else { + Get.find(tag: key).value = false; } } @@ -54,6 +58,8 @@ class CurrentDisplayState { if (!Get.isRegistered(tag: key)) { final RxInt state = RxInt(0); Get.put(state, tag: key); + } else { + Get.find(tag: key).value = 0; } } @@ -123,6 +129,8 @@ class ShowRemoteCursorState { if (!Get.isRegistered(tag: key)) { final RxBool state = false.obs; Get.put(state, tag: key); + } else { + Get.find(tag: key).value = false; } } @@ -145,6 +153,8 @@ class KeyboardEnabledState { // Server side, default true final RxBool state = true.obs; Get.put(state, tag: key); + } else { + Get.find(tag: key).value = true; } } @@ -164,9 +174,10 @@ class RemoteCursorMovedState { static void init(String id) { final key = tag(id); if (!Get.isRegistered(tag: key)) { - // Server side, default true final RxBool state = false.obs; Get.put(state, tag: key); + } else { + Get.find(tag: key).value = false; } } @@ -186,9 +197,10 @@ class RemoteCountState { static void init() { final key = tag(); if (!Get.isRegistered(tag: key)) { - // Server side, default true final RxInt state = 1.obs; Get.put(state, tag: key); + } else { + Get.find(tag: key).value = 1; } } @@ -210,6 +222,8 @@ class PeerBoolOption { if (!Get.isRegistered(tag: key)) { final RxBool value = RxBool(init_getter()); Get.put(value, tag: key); + } else { + Get.find(tag: key).value = init_getter(); } } @@ -232,6 +246,8 @@ class PeerStringOption { if (!Get.isRegistered(tag: key)) { final RxString value = RxString(init_getter()); Get.put(value, tag: key); + } else { + Get.find(tag: key).value = init_getter(); } } From 29abda56df30d57c606a53ce650ddb53029a5d93 Mon Sep 17 00:00:00 2001 From: RustDesk <71636191+rustdesk@users.noreply.github.com> Date: Fri, 3 Mar 2023 13:18:34 +0800 Subject: [PATCH 116/382] Revert "Fix/macos texture stride align" --- flutter/pubspec.lock | 4 ++-- flutter/pubspec.yaml | 2 +- libs/scrap/examples/record-screen.rs | 4 ++-- libs/scrap/src/common/codec.rs | 20 ++++++++------------ libs/scrap/src/common/convert.rs | 12 ++++++------ libs/scrap/src/common/hwcodec.rs | 18 +++++++++--------- libs/scrap/src/common/mediacodec.rs | 3 +-- libs/scrap/src/common/mod.rs | 4 ++-- libs/scrap/src/common/vpxcodec.rs | 26 ++++++++++++-------------- src/client.rs | 9 +++++++-- src/common.rs | 7 ------- src/flutter.rs | 8 ++------ 12 files changed, 52 insertions(+), 65 deletions(-) diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index 63f6c804c..76fe929e5 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -1228,10 +1228,10 @@ packages: dependency: "direct main" description: name: texture_rgba_renderer - sha256: ec8d124e4c1d7dfff854ae34e95d7d9d877b8f9d291c383c67686e4b15cf538e + sha256: fbb09b2c6b4ce71261927f9e7e4ea339af3e2f3f2b175f6fb921de1c66ec848d url: "https://pub.dev" source: hosted - version: "0.0.12" + version: "0.0.8" timing: dependency: transitive description: diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index ccb53cc9c..71a840c9c 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -92,7 +92,7 @@ dependencies: password_strength: ^0.2.0 flutter_launcher_icons: ^0.11.0 flutter_keyboard_visibility: ^5.4.0 - texture_rgba_renderer: ^0.0.12 + texture_rgba_renderer: ^0.0.8 percent_indicator: ^4.2.2 dev_dependencies: diff --git a/libs/scrap/examples/record-screen.rs b/libs/scrap/examples/record-screen.rs index 13ebc5f7d..5df97838e 100644 --- a/libs/scrap/examples/record-screen.rs +++ b/libs/scrap/examples/record-screen.rs @@ -18,7 +18,7 @@ use webm::mux; use webm::mux::Track; use scrap::vpxcodec as vpx_encode; -use scrap::{TraitCapturer, Capturer, Display, STRIDE}; +use scrap::{TraitCapturer, Capturer, Display, STRIDE_ALIGN}; const USAGE: &'static str = " Simple WebM screen capture. @@ -137,7 +137,7 @@ fn main() -> io::Result<()> { if let Ok(frame) = c.frame(Duration::from_millis(0)) { let ms = time.as_secs() * 1000 + time.subsec_millis() as u64; - for frame in vpx.encode(ms as i64, &frame, STRIDE).unwrap() { + for frame in vpx.encode(ms as i64, &frame, STRIDE_ALIGN).unwrap() { vt.add_frame(frame.data, frame.pts as u64 * 1_000_000, frame.key); } } diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index 1f02f86d7..3adc24a14 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -306,18 +306,17 @@ impl Decoder { pub fn handle_video_frame( &mut self, frame: &video_frame::Union, - stride: usize, fmt: ImageFormat, rgb: &mut Vec, ) -> ResultType { match frame { video_frame::Union::Vp9s(vp9s) => { - Decoder::handle_vp9s_video_frame(&mut self.vpx, vp9s, stride, fmt, rgb) + Decoder::handle_vp9s_video_frame(&mut self.vpx, vp9s, fmt, rgb) } #[cfg(feature = "hwcodec")] video_frame::Union::H264s(h264s) => { if let Some(decoder) = &mut self.hw.h264 { - Decoder::handle_hw_video_frame(decoder, h264s, stride, fmt, rgb, &mut self.i420) + Decoder::handle_hw_video_frame(decoder, h264s, fmt, rgb, &mut self.i420) } else { Err(anyhow!("don't support h264!")) } @@ -325,7 +324,7 @@ impl Decoder { #[cfg(feature = "hwcodec")] video_frame::Union::H265s(h265s) => { if let Some(decoder) = &mut self.hw.h265 { - Decoder::handle_hw_video_frame(decoder, h265s, stride, fmt, rgb, &mut self.i420) + Decoder::handle_hw_video_frame(decoder, h265s, fmt, rgb, &mut self.i420) } else { Err(anyhow!("don't support h265!")) } @@ -333,7 +332,7 @@ impl Decoder { #[cfg(feature = "mediacodec")] video_frame::Union::H264s(h264s) => { if let Some(decoder) = &mut self.media_codec.h264 { - Decoder::handle_mediacodec_video_frame(decoder, h264s, stride, fmt, rgb) + Decoder::handle_mediacodec_video_frame(decoder, h264s, fmt, rgb) } else { Err(anyhow!("don't support h264!")) } @@ -341,7 +340,7 @@ impl Decoder { #[cfg(feature = "mediacodec")] video_frame::Union::H265s(h265s) => { if let Some(decoder) = &mut self.media_codec.h265 { - Decoder::handle_mediacodec_video_frame(decoder, h265s, stride, fmt, rgb) + Decoder::handle_mediacodec_video_frame(decoder, h265s, fmt, rgb) } else { Err(anyhow!("don't support h265!")) } @@ -353,7 +352,6 @@ impl Decoder { fn handle_vp9s_video_frame( decoder: &mut VpxDecoder, vp9s: &EncodedVideoFrames, - stride: usize, fmt: ImageFormat, rgb: &mut Vec, ) -> ResultType { @@ -371,7 +369,7 @@ impl Decoder { if last_frame.is_null() { Ok(false) } else { - last_frame.to(fmt, stride, rgb); + last_frame.to(fmt, 1, rgb); Ok(true) } } @@ -380,7 +378,6 @@ impl Decoder { fn handle_hw_video_frame( decoder: &mut HwDecoder, frames: &EncodedVideoFrames, - stride: usize, fmt: ImageFormat, raw: &mut Vec, i420: &mut Vec, @@ -389,7 +386,7 @@ impl Decoder { for h264 in frames.frames.iter() { for image in decoder.decode(&h264.data)? { // TODO: just process the last frame - if image.to_fmt(stride, fmt, raw, i420).is_ok() { + if image.to_fmt(fmt, raw, i420).is_ok() { ret = true; } } @@ -401,13 +398,12 @@ impl Decoder { fn handle_mediacodec_video_frame( decoder: &mut MediaCodecDecoder, frames: &EncodedVideoFrames, - stride: usize, fmt: ImageFormat, raw: &mut Vec, ) -> ResultType { let mut ret = false; for h264 in frames.frames.iter() { - return decoder.decode(&h264.data, stride, fmt, raw); + return decoder.decode(&h264.data, fmt, raw); } return Ok(false); } diff --git a/libs/scrap/src/common/convert.rs b/libs/scrap/src/common/convert.rs index 1c19ac0c0..f3ad51a21 100644 --- a/libs/scrap/src/common/convert.rs +++ b/libs/scrap/src/common/convert.rs @@ -144,7 +144,7 @@ extern "C" { fn get_vpx_i420_stride( width: usize, height: usize, - stride: usize, + stride_align: usize, ) -> (usize, usize, usize, usize, usize, usize) { let mut img = Default::default(); unsafe { @@ -153,7 +153,7 @@ fn get_vpx_i420_stride( vpx_img_fmt::VPX_IMG_FMT_I420, width as _, height as _, - stride as _, + stride_align as _, 0x1 as _, ); } @@ -169,7 +169,7 @@ fn get_vpx_i420_stride( pub fn i420_to_rgb(width: usize, height: usize, src: &[u8], dst: &mut Vec) { let (_, _, src_stride_y, src_stride_uv, u, v) = - get_vpx_i420_stride(width, height, super::STRIDE); + get_vpx_i420_stride(width, height, super::STRIDE_ALIGN); let src_y = src.as_ptr(); let src_u = src[u..].as_ptr(); let src_v = src[v..].as_ptr(); @@ -192,7 +192,7 @@ pub fn i420_to_rgb(width: usize, height: usize, src: &[u8], dst: &mut Vec) { pub fn bgra_to_i420(width: usize, height: usize, src: &[u8], dst: &mut Vec) { let (_, h, dst_stride_y, dst_stride_uv, u, v) = - get_vpx_i420_stride(width, height, super::STRIDE); + get_vpx_i420_stride(width, height, super::STRIDE_ALIGN); dst.resize(h * dst_stride_y * 2, 0); // waste some memory to ensure memory safety let dst_y = dst.as_mut_ptr(); let dst_u = dst[u..].as_mut_ptr(); @@ -215,7 +215,7 @@ pub fn bgra_to_i420(width: usize, height: usize, src: &[u8], dst: &mut Vec) pub fn rgba_to_i420(width: usize, height: usize, src: &[u8], dst: &mut Vec) { let (_, h, dst_stride_y, dst_stride_uv, u, v) = - get_vpx_i420_stride(width, height, super::STRIDE); + get_vpx_i420_stride(width, height, super::STRIDE_ALIGN); dst.resize(h * dst_stride_y * 2, 0); // waste some memory to ensure memory safety let dst_y = dst.as_mut_ptr(); let dst_u = dst[u..].as_mut_ptr(); @@ -246,7 +246,7 @@ pub unsafe fn nv12_to_i420( dst: &mut Vec, ) { let (_, h, dst_stride_y, dst_stride_uv, u, v) = - get_vpx_i420_stride(width, height, super::STRIDE); + get_vpx_i420_stride(width, height, super::STRIDE_ALIGN); dst.resize(h * dst_stride_y * 2, 0); // waste some memory to ensure memory safety let dst_y = dst.as_mut_ptr(); let dst_u = dst[u..].as_mut_ptr(); diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index 0047672a4..d2b9f414f 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -1,6 +1,6 @@ use crate::{ codec::{EncoderApi, EncoderCfg}, - hw, ImageFormat, HW_STRIDE, + hw, ImageFormat, HW_STRIDE_ALIGN, }; use hbb_common::{ anyhow::{anyhow, Context}, @@ -52,7 +52,7 @@ impl EncoderApi for HwEncoder { width: config.width as _, height: config.height as _, pixfmt: DEFAULT_PIXFMT, - align: HW_STRIDE as _, + align: HW_STRIDE_ALIGN as _, bitrate: config.bitrate * 1000, timebase: DEFAULT_TIME_BASE, gop: DEFAULT_GOP, @@ -236,7 +236,7 @@ pub struct HwDecoderImage<'a> { } impl HwDecoderImage<'_> { - pub fn to_fmt(&self, stride: usize, fmt: ImageFormat, fmt_data: &mut Vec, i420: &mut Vec) -> ResultType<()> { + pub fn to_fmt(&self, fmt: ImageFormat, fmt_data: &mut Vec, i420: &mut Vec) -> ResultType<()> { let frame = self.frame; match frame.pixfmt { AVPixelFormat::AV_PIX_FMT_NV12 => hw::hw_nv12_to( @@ -249,7 +249,7 @@ impl HwDecoderImage<'_> { frame.linesize[1] as _, fmt_data, i420, - HW_STRIDE, + HW_STRIDE_ALIGN, ), AVPixelFormat::AV_PIX_FMT_YUV420P => { hw::hw_i420_to( @@ -269,12 +269,12 @@ impl HwDecoderImage<'_> { } } - pub fn bgra(&self, stride: usize, bgra: &mut Vec, i420: &mut Vec) -> ResultType<()> { - self.to_fmt(stride, ImageFormat::ARGB, bgra, i420) + pub fn bgra(&self, bgra: &mut Vec, i420: &mut Vec) -> ResultType<()> { + self.to_fmt(ImageFormat::ARGB, bgra, i420) } - pub fn rgba(&self, stride: usize, rgba: &mut Vec, i420: &mut Vec) -> ResultType<()> { - self.to_fmt(stride, ImageFormat::ABGR, rgba, i420) + pub fn rgba(&self, rgba: &mut Vec, i420: &mut Vec) -> ResultType<()> { + self.to_fmt(ImageFormat::ABGR, rgba, i420) } } @@ -296,7 +296,7 @@ pub fn check_config() { width: 1920, height: 1080, pixfmt: DEFAULT_PIXFMT, - align: HW_STRIDE as _, + align: HW_STRIDE_ALIGN as _, bitrate: 0, timebase: DEFAULT_TIME_BASE, gop: DEFAULT_GOP, diff --git a/libs/scrap/src/common/mediacodec.rs b/libs/scrap/src/common/mediacodec.rs index 306b511f6..7bda0b69d 100644 --- a/libs/scrap/src/common/mediacodec.rs +++ b/libs/scrap/src/common/mediacodec.rs @@ -50,8 +50,7 @@ impl MediaCodecDecoder { MediaCodecDecoders { h264, h265 } } - // to-do: apply stride to raw output data - pub fn decode(&mut self, data: &[u8], stride: usize, fmt: ImageFormat, raw: &mut Vec) -> ResultType { + pub fn decode(&mut self, data: &[u8], fmt: ImageFormat, raw: &mut Vec) -> ResultType { match self.dequeue_input_buffer(Duration::from_millis(10))? { Some(mut input_buffer) => { let mut buf = input_buffer.buffer_mut(); diff --git a/libs/scrap/src/common/mod.rs b/libs/scrap/src/common/mod.rs index bc193d22d..c7da57734 100644 --- a/libs/scrap/src/common/mod.rs +++ b/libs/scrap/src/common/mod.rs @@ -37,8 +37,8 @@ pub mod hwcodec; pub mod mediacodec; pub mod vpxcodec; pub use self::convert::*; -pub const STRIDE: usize = 64; // commonly used in libvpx vpx_img_alloc caller -pub const HW_STRIDE: usize = 0; // recommended by av_frame_get_buffer +pub const STRIDE_ALIGN: usize = 64; // commonly used in libvpx vpx_img_alloc caller +pub const HW_STRIDE_ALIGN: usize = 0; // recommended by av_frame_get_buffer pub mod record; mod vpx; diff --git a/libs/scrap/src/common/vpxcodec.rs b/libs/scrap/src/common/vpxcodec.rs index 3ee3e391f..7a65b193d 100644 --- a/libs/scrap/src/common/vpxcodec.rs +++ b/libs/scrap/src/common/vpxcodec.rs @@ -6,7 +6,7 @@ use hbb_common::anyhow::{anyhow, Context}; use hbb_common::message_proto::{EncodedVideoFrame, EncodedVideoFrames, Message, VideoFrame}; use hbb_common::{get_time, ResultType}; -use crate::STRIDE; +use crate::STRIDE_ALIGN; use crate::{codec::EncoderApi, ImageFormat}; use super::vpx::{vp8e_enc_control_id::*, vpx_codec_err_t::*, *}; @@ -202,7 +202,7 @@ impl EncoderApi for VpxEncoder { fn encode_to_message(&mut self, frame: &[u8], ms: i64) -> ResultType { let mut frames = Vec::new(); for ref frame in self - .encode(ms, frame, STRIDE) + .encode(ms, frame, STRIDE_ALIGN) .with_context(|| "Failed to encode")? { frames.push(VpxEncoder::create_frame(frame)); @@ -232,7 +232,7 @@ impl EncoderApi for VpxEncoder { } impl VpxEncoder { - pub fn encode(&mut self, pts: i64, data: &[u8], stride: usize) -> Result { + pub fn encode(&mut self, pts: i64, data: &[u8], stride_align: usize) -> Result { if 2 * data.len() < 3 * self.width * self.height { return Err(Error::FailedCall("len not enough".to_string())); } @@ -243,7 +243,7 @@ impl VpxEncoder { vpx_img_fmt::VPX_IMG_FMT_I420, self.width as _, self.height as _, - stride as _, + stride_align as _, data.as_ptr() as _, )); @@ -539,17 +539,15 @@ impl Image { self.inner().stride[iplane] } - pub fn to(&self, fmt: ImageFormat, stride: usize, dst: &mut Vec) { + pub fn to(&self, fmt: ImageFormat, stride_align: usize, dst: &mut Vec) { let h = self.height(); - let w = self.width(); - let bytes_per_pixel = match fmt { + let mut w = self.width(); + let bps = match fmt { ImageFormat::Raw => 3, ImageFormat::ARGB | ImageFormat::ABGR => 4, }; - // https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L128 - // https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L129 - let bytes_per_row = (w * bytes_per_pixel + stride - 1) & !(stride - 1); - dst.resize(h * bytes_per_row, 0); + w = (w + stride_align - 1) & !(stride_align - 1); + dst.resize(h * w * bps, 0); let img = self.inner(); unsafe { match fmt { @@ -562,7 +560,7 @@ impl Image { img.planes[2], img.stride[2], dst.as_mut_ptr(), - bytes_per_row as _, + (w * bps) as _, self.width() as _, self.height() as _, ); @@ -576,7 +574,7 @@ impl Image { img.planes[2], img.stride[2], dst.as_mut_ptr(), - bytes_per_row as _, + (w * bps) as _, self.width() as _, self.height() as _, ); @@ -590,7 +588,7 @@ impl Image { img.planes[2], img.stride[2], dst.as_mut_ptr(), - bytes_per_row as _, + (w * bps) as _, self.width() as _, self.height() as _, ); diff --git a/src/client.rs b/src/client.rs index 14cba6c85..40a9f05b0 100644 --- a/src/client.rs +++ b/src/client.rs @@ -49,7 +49,7 @@ use scrap::{ }; use crate::{ - common::{self, is_keyboard_mode_supported, DST_STRIDE_RGBA}, + common::{self, is_keyboard_mode_supported}, server::video_service::{SCRAP_X11_REF_URL, SCRAP_X11_REQUIRED}, }; @@ -944,7 +944,12 @@ impl VideoHandler { } match &vf.union { Some(frame) => { - let res = self.decoder.handle_video_frame(frame, DST_STRIDE_RGBA, ImageFormat::ARGB, &mut self.rgb); + // windows && flutter_texture_render, fmt is ImageFormat::ABGR + #[cfg(all(target_os = "windows", feature = "flutter_texture_render"))] + let fmt = ImageFormat::ABGR; + #[cfg(not(all(target_os = "windows", feature = "flutter_texture_render")))] + let fmt = ImageFormat::ARGB; + let res = self.decoder.handle_video_frame(frame, fmt, &mut self.rgb); if self.record { self.recorder .lock() diff --git a/src/common.rs b/src/common.rs index 28d8dddc4..5f24fd5c3 100644 --- a/src/common.rs +++ b/src/common.rs @@ -39,13 +39,6 @@ pub const CLIPBOARD_INTERVAL: u64 = 333; pub const SYNC_PEER_INFO_DISPLAYS: i32 = 1; -#[cfg(all(target_os = "macos", feature = "flutter_texture_render"))] -// https://developer.apple.com/forums/thread/712709 -// Memory alignment should be multiple of 64. -pub const DST_STRIDE_RGBA: usize = 64; -#[cfg(not(all(target_os = "macos", feature = "flutter_texture_render")))] -pub const DST_STRIDE_RGBA: usize = 1; - // the executable name of the portable version pub const PORTABLE_APPNAME_RUNTIME_ENV_KEY: &str = "RUSTDESK_APPNAME"; diff --git a/src/flutter.rs b/src/flutter.rs index 1fbf92c12..2f660775f 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -154,7 +154,7 @@ pub struct FlutterHandler { #[cfg(feature = "flutter_texture_render")] pub type FlutterRgbaRendererPluginOnRgba = - unsafe extern "C" fn(texture_rgba: *mut c_void, buffer: *const u8, len: c_int, width: c_int, height: c_int, stride: c_int); + unsafe extern "C" fn(texture_rgba: *mut c_void, buffer: *const u8, width: c_int, height: c_int); // Video Texture Renderer in Flutter #[cfg(feature = "flutter_texture_render")] @@ -206,9 +206,7 @@ impl VideoRenderer { self.width = width; self.height = height; self.data_len = if width > 0 && height > 0 { - let sa1 = crate::common::DST_STRIDE_RGBA - 1; - let row_bytes = (width as usize * 4 + sa1) & !sa1; - row_bytes * height as usize + (width * height * 4) as usize } else { 0 }; @@ -223,10 +221,8 @@ impl VideoRenderer { func( self.ptr as _, rgba.as_ptr() as _, - rgba.len() as _, self.width as _, self.height as _, - crate::common::DST_STRIDE_RGBA as _, ) }; } From b8941c15c0ebc6ec01a5d1b78e53384fb9be660b Mon Sep 17 00:00:00 2001 From: rustdesk Date: Fri, 3 Mar 2023 14:02:49 +0800 Subject: [PATCH 117/382] refactor DST_STRIDE_RGBA --- flutter/pubspec.lock | 4 ++-- flutter/pubspec.yaml | 2 +- libs/scrap/src/common/codec.rs | 10 +++++----- libs/scrap/src/common/hwcodec.rs | 8 +++++++- libs/scrap/src/common/mediacodec.rs | 10 ++++++++-- src/client.rs | 16 +++++++--------- src/common.rs | 7 +++++++ src/flutter.rs | 14 +++++++++++--- 8 files changed, 48 insertions(+), 23 deletions(-) diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index 76fe929e5..63f6c804c 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -1228,10 +1228,10 @@ packages: dependency: "direct main" description: name: texture_rgba_renderer - sha256: fbb09b2c6b4ce71261927f9e7e4ea339af3e2f3f2b175f6fb921de1c66ec848d + sha256: ec8d124e4c1d7dfff854ae34e95d7d9d877b8f9d291c383c67686e4b15cf538e url: "https://pub.dev" source: hosted - version: "0.0.8" + version: "0.0.12" timing: dependency: transitive description: diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 71a840c9c..ccb53cc9c 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -92,7 +92,7 @@ dependencies: password_strength: ^0.2.0 flutter_launcher_icons: ^0.11.0 flutter_keyboard_visibility: ^5.4.0 - texture_rgba_renderer: ^0.0.8 + texture_rgba_renderer: ^0.0.12 percent_indicator: ^4.2.2 dev_dependencies: diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index 3adc24a14..9e4b6fce4 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -306,7 +306,7 @@ impl Decoder { pub fn handle_video_frame( &mut self, frame: &video_frame::Union, - fmt: ImageFormat, + fmt: (ImageFormat, usize), rgb: &mut Vec, ) -> ResultType { match frame { @@ -352,7 +352,7 @@ impl Decoder { fn handle_vp9s_video_frame( decoder: &mut VpxDecoder, vp9s: &EncodedVideoFrames, - fmt: ImageFormat, + fmt: (ImageFormat, usize), rgb: &mut Vec, ) -> ResultType { let mut last_frame = Image::new(); @@ -369,7 +369,7 @@ impl Decoder { if last_frame.is_null() { Ok(false) } else { - last_frame.to(fmt, 1, rgb); + last_frame.to(fmt.0, fmt.1, rgb); Ok(true) } } @@ -378,7 +378,7 @@ impl Decoder { fn handle_hw_video_frame( decoder: &mut HwDecoder, frames: &EncodedVideoFrames, - fmt: ImageFormat, + fmt: (ImageFormat, usize), raw: &mut Vec, i420: &mut Vec, ) -> ResultType { @@ -398,7 +398,7 @@ impl Decoder { fn handle_mediacodec_video_frame( decoder: &mut MediaCodecDecoder, frames: &EncodedVideoFrames, - fmt: ImageFormat, + fmt: (ImageFormat, usize), raw: &mut Vec, ) -> ResultType { let mut ret = false; diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index d2b9f414f..4425c412d 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -236,7 +236,13 @@ pub struct HwDecoderImage<'a> { } impl HwDecoderImage<'_> { - pub fn to_fmt(&self, fmt: ImageFormat, fmt_data: &mut Vec, i420: &mut Vec) -> ResultType<()> { + // take dst_stride into account when you convert + pub fn to_fmt( + &self, + (fmt, dst_stride): (ImageFormat, usize), + fmt_data: &mut Vec, + i420: &mut Vec, + ) -> ResultType<()> { let frame = self.frame; match frame.pixfmt { AVPixelFormat::AV_PIX_FMT_NV12 => hw::hw_nv12_to( diff --git a/libs/scrap/src/common/mediacodec.rs b/libs/scrap/src/common/mediacodec.rs index 7bda0b69d..a0272d867 100644 --- a/libs/scrap/src/common/mediacodec.rs +++ b/libs/scrap/src/common/mediacodec.rs @@ -1,4 +1,4 @@ -use hbb_common::{log, anyhow::Error, bail, ResultType}; +use hbb_common::{anyhow::Error, bail, log, ResultType}; use ndk::media::media_codec::{MediaCodec, MediaCodecDirection, MediaFormat}; use std::ops::Deref; use std::{ @@ -50,7 +50,13 @@ impl MediaCodecDecoder { MediaCodecDecoders { h264, h265 } } - pub fn decode(&mut self, data: &[u8], fmt: ImageFormat, raw: &mut Vec) -> ResultType { + // take dst_stride into account please + pub fn decode( + &mut self, + data: &[u8], + (fmt, dst_stride): (ImageFormat, usize), + raw: &mut Vec, + ) -> ResultType { match self.dequeue_input_buffer(Duration::from_millis(10))? { Some(mut input_buffer) => { let mut buf = input_buffer.buffer_mut(); diff --git a/src/client.rs b/src/client.rs index 40a9f05b0..ab27c0185 100644 --- a/src/client.rs +++ b/src/client.rs @@ -44,8 +44,7 @@ pub use helper::*; use scrap::{ codec::{Decoder, DecoderCfg}, record::{Recorder, RecorderContext}, - VpxDecoderConfig, VpxVideoCodecId, - ImageFormat, + ImageFormat, VpxDecoderConfig, VpxVideoCodecId, }; use crate::{ @@ -944,12 +943,11 @@ impl VideoHandler { } match &vf.union { Some(frame) => { - // windows && flutter_texture_render, fmt is ImageFormat::ABGR - #[cfg(all(target_os = "windows", feature = "flutter_texture_render"))] - let fmt = ImageFormat::ABGR; - #[cfg(not(all(target_os = "windows", feature = "flutter_texture_render")))] - let fmt = ImageFormat::ARGB; - let res = self.decoder.handle_video_frame(frame, fmt, &mut self.rgb); + let res = self.decoder.handle_video_frame( + frame, + (ImageFormat::ARGB, crate::DST_STRIDE_RGBA), + &mut self.rgb, + ); if self.record { self.recorder .lock() @@ -2038,7 +2036,7 @@ pub trait Interface: Send + Clone + 'static + Sized { fn is_force_relay(&self) -> bool { self.get_login_config_handler().read().unwrap().force_relay } - fn swap_modifier_mouse(&self, _msg : &mut hbb_common::protos::message::MouseEvent) {} + fn swap_modifier_mouse(&self, _msg: &mut hbb_common::protos::message::MouseEvent) {} } /// Data used by the client interface. diff --git a/src/common.rs b/src/common.rs index 5f24fd5c3..28d8dddc4 100644 --- a/src/common.rs +++ b/src/common.rs @@ -39,6 +39,13 @@ pub const CLIPBOARD_INTERVAL: u64 = 333; pub const SYNC_PEER_INFO_DISPLAYS: i32 = 1; +#[cfg(all(target_os = "macos", feature = "flutter_texture_render"))] +// https://developer.apple.com/forums/thread/712709 +// Memory alignment should be multiple of 64. +pub const DST_STRIDE_RGBA: usize = 64; +#[cfg(not(all(target_os = "macos", feature = "flutter_texture_render")))] +pub const DST_STRIDE_RGBA: usize = 1; + // the executable name of the portable version pub const PORTABLE_APPNAME_RUNTIME_ENV_KEY: &str = "RUSTDESK_APPNAME"; diff --git a/src/flutter.rs b/src/flutter.rs index 2f660775f..c69c2f802 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -153,8 +153,13 @@ pub struct FlutterHandler { } #[cfg(feature = "flutter_texture_render")] -pub type FlutterRgbaRendererPluginOnRgba = - unsafe extern "C" fn(texture_rgba: *mut c_void, buffer: *const u8, width: c_int, height: c_int); +pub type FlutterRgbaRendererPluginOnRgba = unsafe extern "C" fn( + texture_rgba: *mut c_void, + buffer: *const u8, + width: c_int, + height: c_int, + dst_rgba_stride: c_int, +); // Video Texture Renderer in Flutter #[cfg(feature = "flutter_texture_render")] @@ -206,7 +211,9 @@ impl VideoRenderer { self.width = width; self.height = height; self.data_len = if width > 0 && height > 0 { - (width * height * 4) as usize + let sa1 = crate::DST_STRIDE_RGBA - 1; + let row_bytes = (width as usize * 4 + sa1) & !sa1; + row_bytes * height as usize } else { 0 }; @@ -223,6 +230,7 @@ impl VideoRenderer { rgba.as_ptr() as _, self.width as _, self.height as _, + crate::DST_STRIDE_RGBA as _, ) }; } From 02191e1014b93d2c053d0046cc7b2bbc7a685a0d Mon Sep 17 00:00:00 2001 From: solokot Date: Fri, 3 Mar 2023 09:16:32 +0300 Subject: [PATCH 118/382] Update ru.rs --- src/lang/ru.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lang/ru.rs b/src/lang/ru.rs index b9af4ce98..d524b8f4d 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -269,7 +269,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No permission of file transfer", "Нет разрешения на передачу файлов"), ("Note", "Примечание"), ("Connection", "Соединение"), - ("Share Screen", "Поделиться экраном"), + ("Share Screen", "Демонстрация экрана"), ("CLOSE", "ЗАКРЫТЬ"), ("OPEN", "ОТКРЫТЬ"), ("Chat", "Чат"), @@ -312,8 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Держать в фоне службу RustDesk"), ("Ignore Battery Optimizations", "Игнорировать оптимизацию батареи"), ("android_open_battery_optimizations_tip", "Перейдите на следующую страницу настроек"), - ("Start on Boot", ""), - ("Start the screen sharing service on boot, requires special permissions", ""), + ("Start on Boot", "Начинать при загрузке"), + ("Start the screen sharing service on boot, requires special permissions", "Запускать службу демонстрации экрана при загрузке (требуются специальные разрешения)"), ("Connection not allowed", "Подключение не разрешено"), ("Legacy mode", "Устаревший режим"), ("Map mode", "Режим сопоставления"), @@ -388,11 +388,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Confirm before closing multiple tabs", "Подтверждать закрытие несколько вкладок"), ("Keyboard Settings", "Настройки клавиатуры"), ("Full Access", "Полный доступ"), - ("Screen Share", "Поделиться экраном"), + ("Screen Share", "Демонстрация экрана"), ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland требует Ubuntu 21.04 или более позднюю версию."), ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Для Wayland требуется более поздняя версия дистрибутива Linux. Пожалуйста, попробуйте рабочий стол X11 или смените ОС."), ("JumpLink", "Просмотр"), - ("Please Select the screen to be shared(Operate on the peer side).", "Выберите экран для совместного использования (работайте на одноранговой стороне)."), + ("Please Select the screen to be shared(Operate on the peer side).", "Выберите экран для демонстрации (работайте на одноранговой стороне)."), ("Show RustDesk", "Показать RustDesk"), ("This PC", "Этот компьютер"), ("or", "или"), @@ -441,7 +441,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?", "Подтверждаете, что хотите поделиться своим рабочим столом?"), + ("Please confirm if you want to share your desktop?", "Подтверждаете, что разрешаете демонстрацию рабочего стола?"), ("Display", "Отображение"), ("Default View Style", "Стиль отображения по умолчанию"), ("Default Scroll Style", "Стиль прокрутки по умолчанию"), From 6ec4d6d9ca88cf08caaf4b916970f0a70c61c5fd Mon Sep 17 00:00:00 2001 From: rustdesk Date: Fri, 3 Mar 2023 14:34:47 +0800 Subject: [PATCH 119/382] fix ci --- libs/scrap/src/common/hwcodec.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index 4425c412d..3c86af94e 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -276,11 +276,11 @@ impl HwDecoderImage<'_> { } pub fn bgra(&self, bgra: &mut Vec, i420: &mut Vec) -> ResultType<()> { - self.to_fmt(ImageFormat::ARGB, bgra, i420) + self.to_fmt((ImageFormat::ARGB, 1), bgra, i420) } pub fn rgba(&self, rgba: &mut Vec, i420: &mut Vec) -> ResultType<()> { - self.to_fmt(ImageFormat::ABGR, rgba, i420) + self.to_fmt((ImageFormat::ABGR, 1), rgba, i420) } } From 876fb26a672377de5e9688cc99851f33a2db7905 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Fri, 3 Mar 2023 15:34:57 +0800 Subject: [PATCH 120/382] fix #3424 --- libs/scrap/src/common/vpxcodec.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/libs/scrap/src/common/vpxcodec.rs b/libs/scrap/src/common/vpxcodec.rs index 7a65b193d..b91871c8f 100644 --- a/libs/scrap/src/common/vpxcodec.rs +++ b/libs/scrap/src/common/vpxcodec.rs @@ -539,15 +539,17 @@ impl Image { self.inner().stride[iplane] } - pub fn to(&self, fmt: ImageFormat, stride_align: usize, dst: &mut Vec) { + pub fn to(&self, fmt: ImageFormat, stride: usize, dst: &mut Vec) { let h = self.height(); - let mut w = self.width(); - let bps = match fmt { + let w = self.width(); + let bytes_per_pixel = match fmt { ImageFormat::Raw => 3, ImageFormat::ARGB | ImageFormat::ABGR => 4, }; - w = (w + stride_align - 1) & !(stride_align - 1); - dst.resize(h * w * bps, 0); + // https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L128 + // https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L129 + let bytes_per_row = (w * bytes_per_pixel + stride - 1) & !(stride - 1); + dst.resize(h * bytes_per_row, 0); let img = self.inner(); unsafe { match fmt { @@ -560,7 +562,7 @@ impl Image { img.planes[2], img.stride[2], dst.as_mut_ptr(), - (w * bps) as _, + bytes_per_row as _, self.width() as _, self.height() as _, ); @@ -574,7 +576,7 @@ impl Image { img.planes[2], img.stride[2], dst.as_mut_ptr(), - (w * bps) as _, + bytes_per_row as _, self.width() as _, self.height() as _, ); @@ -588,7 +590,7 @@ impl Image { img.planes[2], img.stride[2], dst.as_mut_ptr(), - (w * bps) as _, + bytes_per_row as _, self.width() as _, self.height() as _, ); From 4c31c7e26da4ee6e36d99ef772a81036afe0a0e7 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Fri, 3 Mar 2023 15:36:15 +0800 Subject: [PATCH 121/382] remove data_len check --- src/flutter.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/flutter.rs b/src/flutter.rs index c69c2f802..9ea4dc840 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -169,7 +169,6 @@ struct VideoRenderer { ptr: usize, width: i32, height: i32, - data_len: usize, on_rgba_func: Option>, } @@ -198,7 +197,6 @@ impl Default for VideoRenderer { ptr: 0, width: 0, height: 0, - data_len: 0, on_rgba_func, } } @@ -210,17 +208,10 @@ impl VideoRenderer { pub fn set_size(&mut self, width: i32, height: i32) { self.width = width; self.height = height; - self.data_len = if width > 0 && height > 0 { - let sa1 = crate::DST_STRIDE_RGBA - 1; - let row_bytes = (width as usize * 4 + sa1) & !sa1; - row_bytes * height as usize - } else { - 0 - }; } pub fn on_rgba(&self, rgba: &Vec) { - if self.ptr == usize::default() || rgba.len() != self.data_len { + if self.ptr == usize::default() { return; } if let Some(func) = &self.on_rgba_func { From 976d4626b3da32396e0cd8f2d54c967cade4c84c Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 3 Mar 2023 16:03:06 +0800 Subject: [PATCH 122/382] fix flutter texture render Signed-off-by: fufesou --- src/flutter.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/flutter.rs b/src/flutter.rs index 9ea4dc840..a39b992bf 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -156,6 +156,7 @@ pub struct FlutterHandler { pub type FlutterRgbaRendererPluginOnRgba = unsafe extern "C" fn( texture_rgba: *mut c_void, buffer: *const u8, + len: c_int, width: c_int, height: c_int, dst_rgba_stride: c_int, @@ -219,6 +220,7 @@ impl VideoRenderer { func( self.ptr as _, rgba.as_ptr() as _, + rgba.len() as _, self.width as _, self.height as _, crate::DST_STRIDE_RGBA as _, From e30f690f9ca1784c35f5dc09fe240ba7356f3a2a Mon Sep 17 00:00:00 2001 From: rustdesk Date: Fri, 3 Mar 2023 16:50:45 +0800 Subject: [PATCH 123/382] fix desktop id padding --- flutter/lib/desktop/pages/desktop_home_page.dart | 16 ++++++++-------- flutter/run.sh | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index dfa5762b0..8f16e3652 100644 --- a/flutter/lib/desktop/pages/desktop_home_page.dart +++ b/flutter/lib/desktop/pages/desktop_home_page.dart @@ -158,7 +158,7 @@ class _DesktopHomePageState extends State readOnly: true, decoration: InputDecoration( border: InputBorder.none, - contentPadding: EdgeInsets.only(bottom: 20), + contentPadding: EdgeInsets.only(top: 10, bottom: 10), ), style: TextStyle( fontSize: 22, @@ -242,7 +242,8 @@ class _DesktopHomePageState extends State readOnly: true, decoration: InputDecoration( border: InputBorder.none, - contentPadding: EdgeInsets.only(bottom: 2), + contentPadding: + EdgeInsets.only(top: 14, bottom: 10), ), style: TextStyle(fontSize: 15), ), @@ -254,9 +255,9 @@ class _DesktopHomePageState extends State Icons.refresh, color: refreshHover.value ? textColor - : Color(0xFFDDDDDD), // TODO + : Color(0xFFDDDDDD), size: 22, - ).marginOnly(right: 8, bottom: 2), + ).marginOnly(right: 8, top: 4), ), onTap: () => bind.mainUpdateTemporaryPassword(), onHover: (value) => refreshHover.value = value, @@ -265,11 +266,10 @@ class _DesktopHomePageState extends State child: Obx( () => Icon( Icons.edit, - color: editHover.value - ? textColor - : Color(0xFFDDDDDD), // TODO + color: + editHover.value ? textColor : Color(0xFFDDDDDD), size: 22, - ).marginOnly(right: 8, bottom: 2), + ).marginOnly(right: 8, top: 4), ), onTap: () => DesktopSettingPage.switch2page(1), onHover: (value) => editHover.value = value, diff --git a/flutter/run.sh b/flutter/run.sh index f1066306a..78fd1e80c 100755 --- a/flutter/run.sh +++ b/flutter/run.sh @@ -4,5 +4,5 @@ dart pub global activate ffigen --version 5.0.1 flutter pub get # call `flutter clean` if cargo build fails # export LLVM_HOME=/Library/Developer/CommandLineTools/usr/ -cargo build --features flutter +cargo build --features "flutter,flutter_texture_render" flutter run $@ From c0d367f7b183d2e8f8362fde550d6c3816f0a4ed Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 3 Mar 2023 21:04:19 +0800 Subject: [PATCH 124/382] fix some incorrect capture magnifier logic Signed-off-by: fufesou --- libs/scrap/src/dxgi/mag.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libs/scrap/src/dxgi/mag.rs b/libs/scrap/src/dxgi/mag.rs index 0de86055e..b2bea1dd1 100644 --- a/libs/scrap/src/dxgi/mag.rs +++ b/libs/scrap/src/dxgi/mag.rs @@ -282,10 +282,10 @@ impl CapturerMag { let y = GetSystemMetrics(SM_YVIRTUALSCREEN); let w = GetSystemMetrics(SM_CXVIRTUALSCREEN); let h = GetSystemMetrics(SM_CYVIRTUALSCREEN); - if !(origin.0 == x as i32 - && origin.1 == y as i32 - && width == w as usize - && height == h as usize) + if !(origin.0 >= x as i32 + && origin.1 >= y as i32 + && width <= w as usize + && height <= h as usize) { return Err(Error::new( ErrorKind::Other, @@ -518,10 +518,10 @@ impl CapturerMag { let y = GetSystemMetrics(SM_YVIRTUALSCREEN); let w = GetSystemMetrics(SM_CXVIRTUALSCREEN); let h = GetSystemMetrics(SM_CYVIRTUALSCREEN); - if !(self.rect.left == x as i32 - && self.rect.top == y as i32 - && self.rect.right == (x + w) as i32 - && self.rect.bottom == (y + h) as i32) + if !(self.rect.left >= x as i32 + && self.rect.top >= y as i32 + && self.rect.right <= (x + w) as i32 + && self.rect.bottom <= (y + h) as i32) { return Err(Error::new( ErrorKind::Other, @@ -545,8 +545,8 @@ impl CapturerMag { HWND_TOP, self.rect.left, self.rect.top, - self.rect.right, - self.rect.bottom, + self.rect.right - self.rect.left, + self.rect.bottom - self.rect.top, 0, ) { @@ -556,8 +556,8 @@ impl CapturerMag { "Failed SetWindowPos (x, y, w , h) - ({}, {}, {}, {}), error {}", self.rect.left, self.rect.top, - self.rect.right, - self.rect.bottom, + self.rect.right - self.rect.left, + self.rect.bottom - self.rect.top, GetLastError() ), )); From b4aea69bdb369461828f83f104a13476c30ca682 Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 3 Mar 2023 16:07:30 +0800 Subject: [PATCH 125/382] codec benchmark Signed-off-by: 21pages --- libs/scrap/examples/benchmark.rs | 295 +++++++++++++++++++++++++++++++ libs/scrap/src/common/convert.rs | 32 +++- 2 files changed, 321 insertions(+), 6 deletions(-) create mode 100644 libs/scrap/examples/benchmark.rs diff --git a/libs/scrap/examples/benchmark.rs b/libs/scrap/examples/benchmark.rs new file mode 100644 index 000000000..ccd47b240 --- /dev/null +++ b/libs/scrap/examples/benchmark.rs @@ -0,0 +1,295 @@ +use docopt::Docopt; +use hbb_common::env_logger::{init_from_env, Env, DEFAULT_FILTER_ENV}; +#[cfg(feature = "hwcodec")] +use hwcodec::{ + decode::{DecodeContext, Decoder}, + encode::{EncodeContext, Encoder}, + ffmpeg::{CodecInfo, CodecInfos}, + AVPixelFormat, + Quality::*, + RateControl::*, +}; +use scrap::{ + codec::{EncoderApi, EncoderCfg}, + Capturer, Display, TraitCapturer, VpxDecoder, VpxDecoderConfig, VpxEncoder, VpxEncoderConfig, + VpxVideoCodecId, STRIDE_ALIGN, +}; +use std::{io::Write, time::Instant}; + +// cargo run --package scrap --example benchmark --release --features hwcodec + +const USAGE: &'static str = " +Codec benchmark. + +Usage: + benchmark [--count=COUNT] [--bitrate=KBS] [--hw-pixfmt=PIXFMT] + benchmark (-h | --help) + +Options: + -h --help Show this screen. + --count=COUNT Capture frame count [default: 100]. + --bitrate=KBS Video bitrate in kilobits per second [default: 5000]. + --hw-pixfmt=PIXFMT Hareware codec pixfmt. [default: i420] + Valid values: i420, nv12. +"; + +#[derive(Debug, serde::Deserialize)] +struct Args { + flag_count: u32, + flag_bitrate: u32, + flag_hw_pixfmt: Pixfmt, +} + +#[derive(Debug, serde::Deserialize)] +enum Pixfmt { + I420, + NV12, +} + +fn main() { + init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); + let args: Args = Docopt::new(USAGE) + .and_then(|d| d.deserialize()) + .unwrap_or_else(|e| e.exit()); + let bitrate_k = args.flag_bitrate as usize; + let yuv_count = args.flag_count as usize; + let (yuvs, width, height) = capture_yuv(yuv_count); + println!( + "benchmark {}x{} bitrate:{}k hw_pixfmt:{:?} count:{:?}", + width, height, bitrate_k, args.flag_hw_pixfmt, yuv_count + ); + test_vp9(&yuvs, width, height, bitrate_k, yuv_count); + #[cfg(feature = "hwcodec")] + { + let hw_pixfmt = match args.flag_hw_pixfmt { + Pixfmt::I420 => AVPixelFormat::AV_PIX_FMT_YUV420P, + Pixfmt::NV12 => AVPixelFormat::AV_PIX_FMT_NV12, + }; + let yuvs = hw::vp9_yuv_to_hw_yuv(yuvs, width, height, hw_pixfmt); + hw::test(&yuvs, width, height, bitrate_k, yuv_count, hw_pixfmt); + } +} + +fn capture_yuv(yuv_count: usize) -> (Vec>, usize, usize) { + let mut index = 0; + let mut displays = Display::all().unwrap(); + for i in 0..displays.len() { + if displays[i].is_primary() { + index = i; + break; + } + } + let d = displays.remove(index); + let mut c = Capturer::new(d, true).unwrap(); + let mut v = vec![]; + let start = Instant::now(); + loop { + if let Ok(frame) = c.frame(std::time::Duration::from_millis(30)) { + v.push(frame.0.to_vec()); + print!( + "\rcapture {}/{}...{}s", + v.len(), + yuv_count, + start.elapsed().as_secs() + ); + std::io::stdout().flush().ok(); + if v.len() == yuv_count { + println!("\rcapture {}/{} finish", yuv_count, yuv_count); + return (v, c.width(), c.height()); + } + } + } +} + +fn test_vp9(yuvs: &Vec>, width: usize, height: usize, bitrate_k: usize, yuv_count: usize) { + let config = EncoderCfg::VPX(VpxEncoderConfig { + width: width as _, + height: height as _, + timebase: [1, 1000], + bitrate: bitrate_k as _, + codec: VpxVideoCodecId::VP9, + num_threads: (num_cpus::get() / 2) as _, + }); + let mut encoder = VpxEncoder::new(config).unwrap(); + let start = Instant::now(); + for yuv in yuvs { + let _ = encoder + .encode(start.elapsed().as_millis() as _, yuv, STRIDE_ALIGN) + .unwrap(); + let _ = encoder.flush().unwrap(); + } + println!("vp9 encode: {:?}", start.elapsed() / yuv_count as _); + + // prepare data separately + let mut vp9s = vec![]; + let start = Instant::now(); + for yuv in yuvs { + for ref frame in encoder + .encode(start.elapsed().as_millis() as _, yuv, STRIDE_ALIGN) + .unwrap() + { + vp9s.push(frame.data.to_vec()); + } + for ref frame in encoder.flush().unwrap() { + vp9s.push(frame.data.to_vec()); + } + } + + let mut decoder = VpxDecoder::new(VpxDecoderConfig { + codec: VpxVideoCodecId::VP9, + num_threads: (num_cpus::get() / 2) as _, + }) + .unwrap(); + let start = Instant::now(); + for vp9 in vp9s { + let _ = decoder.decode(&vp9); + let _ = decoder.flush(); + } + println!("vp9 decode: {:?}", start.elapsed() / yuv_count as _); +} + +#[cfg(feature = "hwcodec")] +mod hw { + use hwcodec::ffmpeg::ffmpeg_linesize_offset_length; + use scrap::{ + convert::{ + hw::{hw_bgra_to_i420, hw_bgra_to_nv12}, + i420_to_bgra, + }, + HW_STRIDE_ALIGN, + }; + + use super::*; + pub fn test( + yuvs: &Vec>, + width: usize, + height: usize, + bitrate_k: usize, + _yuv_count: usize, + pixfmt: AVPixelFormat, + ) { + let ctx = EncodeContext { + name: String::from(""), + width: width as _, + height: height as _, + pixfmt, + align: 0, + bitrate: (bitrate_k * 1000) as _, + timebase: [1, 30], + gop: 60, + quality: Quality_Default, + rc: RC_DEFAULT, + }; + + println!("hw encoders:"); + let encoders = Encoder::available_encoders(ctx.clone()); + let best = CodecInfo::score(encoders.clone()); + for info in encoders { + test_encoder(info.clone(), ctx.clone(), yuvs, is_best(&best, &info)); + } + + let (h264s, h265s) = prepare_h26x(best, ctx.clone(), yuvs); + + println!("hw decoders:"); + let decoders = Decoder::available_decoders(); + let best = CodecInfo::score(decoders.clone()); + for info in decoders { + let h26xs = if info.name.contains("h264") { + &h264s + } else { + &h265s + }; + if h264s.len() == yuvs.len() { + test_decoder(info.clone(), h26xs, is_best(&best, &info)); + } + } + } + + fn test_encoder(info: CodecInfo, ctx: EncodeContext, yuvs: &Vec>, best: bool) { + let mut ctx = ctx; + ctx.name = info.name; + let mut encoder = Encoder::new(ctx.clone()).unwrap(); + let start = Instant::now(); + for yuv in yuvs { + let _ = encoder.encode(yuv).unwrap(); + } + println!( + "{}{}: {:?}", + if best { "*" } else { "" }, + ctx.name, + start.elapsed() / yuvs.len() as _ + ); + } + + fn test_decoder(info: CodecInfo, h26xs: &Vec>, best: bool) { + let ctx = DecodeContext { + name: info.name, + device_type: info.hwdevice, + }; + + let mut decoder = Decoder::new(ctx.clone()).unwrap(); + let start = Instant::now(); + let mut cnt = 0; + for h26x in h26xs { + let _ = decoder.decode(h26x).unwrap(); + cnt += 1; + } + println!( + "{}{} {:?}: {:?}", + if best { "*" } else { "" }, + ctx.name, + ctx.device_type, + start.elapsed() / cnt + ); + } + + fn prepare_h26x( + best: CodecInfos, + ctx: EncodeContext, + yuvs: &Vec>, + ) -> (Vec>, Vec>) { + let f = |info: Option| { + let mut h26xs = vec![]; + if let Some(info) = info { + let mut ctx = ctx.clone(); + ctx.name = info.name; + let mut encoder = Encoder::new(ctx).unwrap(); + for yuv in yuvs { + let h26x = encoder.encode(yuv).unwrap(); + for frame in h26x { + h26xs.push(frame.data.to_vec()); + } + } + } + h26xs + }; + (f(best.h264), f(best.h265)) + } + + fn is_best(best: &CodecInfos, info: &CodecInfo) -> bool { + Some(info.clone()) == best.h264 || Some(info.clone()) == best.h265 + } + + pub fn vp9_yuv_to_hw_yuv( + yuvs: Vec>, + width: usize, + height: usize, + pixfmt: AVPixelFormat, + ) -> Vec> { + let yuvs = yuvs; + let mut bgra = vec![]; + let mut v = vec![]; + let (linesize, offset, length) = + ffmpeg_linesize_offset_length(pixfmt, width, height, HW_STRIDE_ALIGN).unwrap(); + for mut yuv in yuvs { + i420_to_bgra(width, height, &yuv, &mut bgra); + if pixfmt == AVPixelFormat::AV_PIX_FMT_YUV420P { + hw_bgra_to_i420(width, height, &linesize, &offset, length, &bgra, &mut yuv); + } else { + hw_bgra_to_nv12(width, height, &linesize, &offset, length, &bgra, &mut yuv); + } + v.push(yuv); + } + v + } +} diff --git a/libs/scrap/src/common/convert.rs b/libs/scrap/src/common/convert.rs index f3ad51a21..65e3a16ad 100644 --- a/libs/scrap/src/common/convert.rs +++ b/libs/scrap/src/common/convert.rs @@ -190,6 +190,29 @@ pub fn i420_to_rgb(width: usize, height: usize, src: &[u8], dst: &mut Vec) { }; } +pub fn i420_to_bgra(width: usize, height: usize, src: &[u8], dst: &mut Vec) { + let (_, _, src_stride_y, src_stride_uv, u, v) = + get_vpx_i420_stride(width, height, super::STRIDE_ALIGN); + let src_y = src.as_ptr(); + let src_u = src[u..].as_ptr(); + let src_v = src[v..].as_ptr(); + dst.resize(width * height * 4, 0); + unsafe { + super::I420ToARGB( + src_y, + src_stride_y as _, + src_u, + src_stride_uv as _, + src_v, + src_stride_uv as _, + dst.as_mut_ptr(), + (width * 3) as _, + width as _, + height as _, + ); + }; +} + pub fn bgra_to_i420(width: usize, height: usize, src: &[u8], dst: &mut Vec) { let (_, h, dst_stride_y, dst_stride_uv, u, v) = get_vpx_i420_stride(width, height, super::STRIDE_ALIGN); @@ -269,8 +292,8 @@ pub unsafe fn nv12_to_i420( #[cfg(feature = "hwcodec")] pub mod hw { - use hbb_common::{anyhow::anyhow, ResultType}; use crate::ImageFormat; + use hbb_common::{anyhow::anyhow, ResultType}; #[cfg(target_os = "windows")] use hwcodec::{ffmpeg::ffmpeg_linesize_offset_length, AVPixelFormat}; @@ -466,9 +489,7 @@ pub mod hw { _ => Err(anyhow!("NV12ToABGR failed")), } } - _ => { - Err(anyhow!("unsupported image format")) - } + _ => Err(anyhow!("unsupported image format")), } } } @@ -519,8 +540,7 @@ pub mod hw { height as _, ); } - _ => { - } + _ => {} } }; } From 5634b428ca907be68bff8bb77f5fd7a193d6dee0 Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 3 Mar 2023 22:43:02 +0800 Subject: [PATCH 126/382] fix build Signed-off-by: 21pages --- libs/scrap/src/common/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/scrap/src/common/mod.rs b/libs/scrap/src/common/mod.rs index c7da57734..9e15cf084 100644 --- a/libs/scrap/src/common/mod.rs +++ b/libs/scrap/src/common/mod.rs @@ -30,7 +30,7 @@ cfg_if! { } pub mod codec; -mod convert; +pub mod convert; #[cfg(feature = "hwcodec")] pub mod hwcodec; #[cfg(feature = "mediacodec")] From 88bab7c2d06824558375d5c3d1b465264bd5c72a Mon Sep 17 00:00:00 2001 From: grummbeer Date: Fri, 3 Mar 2023 18:38:37 +0100 Subject: [PATCH 127/382] Fix. Android settings theme always show "Dark theme" --- flutter/lib/mobile/pages/settings_page.dart | 9 +++++++-- 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/nl.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 + 34 files changed, 40 insertions(+), 2 deletions(-) diff --git a/flutter/lib/mobile/pages/settings_page.dart b/flutter/lib/mobile/pages/settings_page.dart index e07f8f59f..c19601956 100644 --- a/flutter/lib/mobile/pages/settings_page.dart +++ b/flutter/lib/mobile/pages/settings_page.dart @@ -397,8 +397,13 @@ class _SettingsState extends State with WidgetsBindingObserver { showLanguageSettings(gFFI.dialogManager); }), SettingsTile.navigation( - title: Text(translate('Dark Theme')), - leading: Icon(Icons.dark_mode), + title: Text(translate( + Theme.of(context).brightness == Brightness.light + ? 'Dark Theme' + : 'Light Theme')), + leading: Icon(Theme.of(context).brightness == Brightness.light + ? Icons.dark_mode + : Icons.light_mode), onPressed: (context) { showThemeSettings(gFFI.dialogManager); }, diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 53ec69b5f..89cc46920 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Seguretat"), ("Theme", "Tema"), ("Dark Theme", "Tema Fosc"), + ("Light Theme", ""), ("Dark", "Fosc"), ("Light", "Clar"), ("Follow System", "Tema del sistema"), diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 4c037234b..3f4f6d25c 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "安全"), ("Theme", "主题"), ("Dark Theme", "暗黑主题"), + ("Light Theme", ""), ("Dark", "黑暗"), ("Light", "明亮"), ("Follow System", "跟随系统"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 25a494eef..a2813815b 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", ""), ("Theme", ""), ("Dark Theme", ""), + ("Light Theme", ""), ("Dark", ""), ("Light", ""), ("Follow System", ""), diff --git a/src/lang/da.rs b/src/lang/da.rs index 8fd6f9be1..2760f94fb 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Sikkerhed"), ("Theme", "Thema"), ("Dark Theme", "Mørk Tema"), + ("Light Theme", ""), ("Dark", "Mørk"), ("Light", "Lys"), ("Follow System", "Følg System"), diff --git a/src/lang/de.rs b/src/lang/de.rs index d6ebe7f1a..dd8d2e8f0 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Sicherheit"), ("Theme", "Farbgebung"), ("Dark Theme", "Dunkle Farbgebung"), + ("Light Theme", "Helle Farbgebung"), ("Dark", "Dunkel"), ("Light", "Hell"), ("Follow System", "Systemstandard"), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index dfee4fb87..7a191f05d 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", ""), ("Theme", ""), ("Dark Theme", ""), + ("Light Theme", ""), ("Dark", ""), ("Light", ""), ("Follow System", ""), diff --git a/src/lang/es.rs b/src/lang/es.rs index dc28cdae0..b290c7696 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Seguridad"), ("Theme", "Tema"), ("Dark Theme", "Tema Oscuro"), + ("Light Theme", ""), ("Dark", "Oscuro"), ("Light", "Claro"), ("Follow System", "Tema del sistema"), diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 158e16f75..22ecf0355 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "امنیت"), ("Theme", "نمایه"), ("Dark Theme", "نمایه تیره"), + ("Light Theme", ""), ("Dark", "تیره"), ("Light", "روشن"), ("Follow System", "پیروی از سیستم"), diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 28f1dd9d1..dd436831e 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Sécurité"), ("Theme", "Thème"), ("Dark Theme", "Thème somble"), + ("Light Theme", ""), ("Dark", "Sombre"), ("Light", "Clair"), ("Follow System", "Suivi système"), diff --git a/src/lang/gr.rs b/src/lang/gr.rs index 55a3c9bb7..cbd4f89e0 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Ασφάλεια"), ("Theme", "Θέμα"), ("Dark Theme", "Σκούρο θέμα"), + ("Light Theme", ""), ("Dark", "Σκούρο"), ("Light", "Φωτεινό"), ("Follow System", "Από το σύστημα"), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index f47d522db..8727c53c2 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Biztonság"), ("Theme", "Téma"), ("Dark Theme", "Sötét téma"), + ("Light Theme", ""), ("Dark", "Sötét"), ("Light", "Világos"), ("Follow System", ""), diff --git a/src/lang/id.rs b/src/lang/id.rs index 7d02e154d..b363a2ae8 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Keamanan"), ("Theme", "Tema"), ("Dark Theme", "Tema gelap"), + ("Light Theme", ""), ("Dark", "Gelap"), ("Light", "Terang"), ("Follow System", "Ikuti sistem"), diff --git a/src/lang/it.rs b/src/lang/it.rs index 05fffedbd..340794ceb 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Sicurezza"), ("Theme", "Tema"), ("Dark Theme", "Tema Scuro"), + ("Light Theme", ""), ("Dark", "Scuro"), ("Light", "Chiaro"), ("Follow System", "Segui il sistema"), diff --git a/src/lang/ja.rs b/src/lang/ja.rs index d097a8b61..260c27607 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", ""), ("Theme", ""), ("Dark Theme", ""), + ("Light Theme", ""), ("Dark", ""), ("Light", ""), ("Follow System", ""), diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 8ca881f16..f101ae20b 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", ""), ("Theme", ""), ("Dark Theme", ""), + ("Light Theme", ""), ("Dark", ""), ("Light", ""), ("Follow System", ""), diff --git a/src/lang/kz.rs b/src/lang/kz.rs index a9acdce65..fe0937a65 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", ""), ("Theme", ""), ("Dark Theme", ""), + ("Light Theme", ""), ("Dark", ""), ("Light", ""), ("Follow System", ""), diff --git a/src/lang/nl.rs b/src/lang/nl.rs index d1c154546..63d3cee7b 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Beveiliging"), ("Theme", "Thema"), ("Dark Theme", "Donker Thema"), + ("Light Theme", ""), ("Dark", "Donker"), ("Light", "Licht"), ("Follow System", "Volg Systeem"), diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 494715527..162dec052 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Zabezpieczenia"), ("Theme", "Motyw"), ("Dark Theme", "Ciemny motyw"), + ("Light Theme", ""), ("Dark", "Ciemny"), ("Light", "Jasny"), ("Follow System", "Zgodny z systemem"), diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index b62bd5a31..8eb4df2ad 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", ""), ("Theme", ""), ("Dark Theme", ""), + ("Light Theme", ""), ("Dark", ""), ("Light", ""), ("Follow System", ""), diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 546ef2a3c..973048f3d 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Segurança"), ("Theme", "Tema"), ("Dark Theme", "Tema escuro"), + ("Light Theme", ""), ("Dark", "Escuro"), ("Light", "Claro"), ("Follow System", "Seguir sistema"), diff --git a/src/lang/ro.rs b/src/lang/ro.rs index af9389a29..9e252aa8a 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Securitate"), ("Theme", "Temă"), ("Dark Theme", "Temă întunecată"), + ("Light Theme", ""), ("Dark", "Întunecat"), ("Light", "Luminos"), ("Follow System", "Urmărește sistem"), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index d524b8f4d..4c1f9ae34 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Безопасность"), ("Theme", "Тема"), ("Dark Theme", "Тёмная тема"), + ("Light Theme", ""), ("Dark", "Тёмная"), ("Light", "Светлая"), ("Follow System", "Системная"), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 8a6b765be..d60384286 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", ""), ("Theme", ""), ("Dark Theme", ""), + ("Light Theme", ""), ("Dark", ""), ("Light", ""), ("Follow System", ""), diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 5721d01f4..bd07b1acb 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Varnost"), ("Theme", "Tema"), ("Dark Theme", "Temna tema"), + ("Light Theme", ""), ("Dark", "Temna"), ("Light", "Svetla"), ("Follow System", "Sistemska"), diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 1c488d470..b8f9203ca 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Siguria"), ("Theme", "Theme"), ("Dark Theme", "Theme e errët"), + ("Light Theme", ""), ("Dark", "E errët"), ("Light", "Drita"), ("Follow System", "Ndiq sistemin"), diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 249c0b599..4a9b73374 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Bezbednost"), ("Theme", "Tema"), ("Dark Theme", "Tamna tema"), + ("Light Theme", ""), ("Dark", "Tamno"), ("Light", "Svetlo"), ("Follow System", "Prema sistemu"), diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 90ec8c1cf..f73154e3e 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Säkerhet"), ("Theme", "Tema"), ("Dark Theme", "Mörkt tema"), + ("Light Theme", ""), ("Dark", "Mörk"), ("Light", "Ljus"), ("Follow System", "Följ system"), diff --git a/src/lang/template.rs b/src/lang/template.rs index 6563d6056..e51a095c0 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", ""), ("Theme", ""), ("Dark Theme", ""), + ("Light Theme", ""), ("Dark", ""), ("Light", ""), ("Follow System", ""), diff --git a/src/lang/th.rs b/src/lang/th.rs index 316622395..3214c3452 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "ความปลอดภัย"), ("Theme", "ธีม"), ("Dark Theme", "ธีมมืด"), + ("Light Theme", ""), ("Dark", "มืด"), ("Light", "สว่าง"), ("Follow System", "ตามระบบ"), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 7359bf064..82f95ef84 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Güvenlik"), ("Theme", "Tema"), ("Dark Theme", "Koyu Tema"), + ("Light Theme", ""), ("Dark", "Koyu"), ("Light", "Açık"), ("Follow System", "Sisteme Uy"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 70533c482..d0f12cdfa 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "安全"), ("Theme", "主題"), ("Dark Theme", "暗黑主題"), + ("Light Theme", ""), ("Dark", "黑暗"), ("Light", "明亮"), ("Follow System", "跟隨系統"), diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 6b54c83c3..793d1e147 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Безпека"), ("Theme", "Тема"), ("Dark Theme", "Темна тема"), + ("Light Theme", ""), ("Dark", "Темна"), ("Light", "Світла"), ("Follow System", "Як у системі"), diff --git a/src/lang/vn.rs b/src/lang/vn.rs index a379b3185..fc665834d 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -349,6 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", ""), ("Theme", ""), ("Dark Theme", ""), + ("Light Theme", ""), ("Dark", ""), ("Light", ""), ("Follow System", ""), From 63b72598c4e4cd22b327fb93066389b41e11bb5a Mon Sep 17 00:00:00 2001 From: grummbeer Date: Fri, 3 Mar 2023 19:33:55 +0100 Subject: [PATCH 128/382] File Manager. Textoverflow for column file time --- flutter/lib/desktop/pages/file_manager_page.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 9c72caa5f..0afff2630 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -430,6 +430,7 @@ class _FileManagerPageState extends State message: lastModifiedStr, child: Text( lastModifiedStr, + overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 12, color: MyTheme.darkGray, From dd4c80a7798b1459a73ee5e99a79ad5ea59ef38d Mon Sep 17 00:00:00 2001 From: grummbeer Date: Fri, 3 Mar 2023 20:26:13 +0100 Subject: [PATCH 129/382] File Manager. Show filename instead of path in tranfer list --- flutter/lib/desktop/pages/file_manager_page.dart | 2 +- flutter/lib/models/file_model.dart | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 9c72caa5f..476e2e50f 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -644,7 +644,7 @@ class _FileManagerPageState extends State Duration(milliseconds: 500), message: item.jobName, child: Text( - item.jobName, + item.fileName, maxLines: 1, overflow: TextOverflow.ellipsis, ).paddingSymmetric(vertical: 10), diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index 56c9339f3..feaecd356 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -500,6 +500,7 @@ class FileModel extends ChangeNotifier { for (var from in items.items) { final jobId = ++_jobId; _jobTable.add(JobProgress() + ..fileName = path.basename(from.path) ..jobName = from.path ..totalSize = from.size ..state = JobState.inProgress @@ -853,7 +854,9 @@ class FileModel extends ChangeNotifier { int fileNum = jobDetail['file_num']; bool isRemote = jobDetail['is_remote']; final currJobId = _jobId++; + String fileName = path.basename(isRemote ? remote : to); var jobProgress = JobProgress() + ..fileName = fileName ..jobName = isRemote ? remote : to ..id = currJobId ..isRemote = isRemote @@ -1121,6 +1124,7 @@ class JobProgress { var fileCount = 0; var isRemote = false; var jobName = ""; + var fileName = ""; var remote = ""; var to = ""; var showHidden = false; @@ -1133,6 +1137,7 @@ class JobProgress { speed = 0; finishedSize = 0; jobName = ""; + fileName = ""; fileCount = 0; remote = ""; to = ""; From 656a7c6e26fe102f95407d40bd12fda1d040e8ac Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Fri, 3 Mar 2023 20:53:42 +0100 Subject: [PATCH 130/382] implemented sorting in every tab except "recent sessions" --- flutter/lib/common/widgets/peer_tab_page.dart | 86 +++++++++++++++---- flutter/lib/common/widgets/peers_view.dart | 41 ++++++++- 2 files changed, 107 insertions(+), 20 deletions(-) diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index da7e37e6b..d0ab51058 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -12,6 +12,7 @@ import 'package:flutter_hbb/desktop/widgets/popup_menu.dart'; import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; import 'package:flutter_hbb/desktop/widgets/material_mod_popup_menu.dart' as mod_menu; +import 'package:flutter_hbb/models/file_model.dart'; import 'package:flutter_hbb/models/peer_tab_model.dart'; import 'package:get/get.dart'; import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart'; @@ -39,6 +40,8 @@ EdgeInsets? _menuPadding() { class _PeerTabPageState extends State with SingleTickerProviderStateMixin { + bool _hideSort = bind.getLocalFlutterConfig(k: 'peer-tab-index') == '0'; + final List<_TabEntry> entries = [ _TabEntry( RecentPeersView( @@ -83,6 +86,7 @@ class _PeerTabPageState extends State if (tabIndex < entries.length) { gFFI.peerTabModel.setCurrentTab(tabIndex); entries[tabIndex].load(); + _hideSort = tabIndex == 0; } } @@ -95,22 +99,27 @@ class _PeerTabPageState extends State SizedBox( height: 28, child: Container( - padding: isDesktop ? null : EdgeInsets.symmetric(horizontal: 2), - constraints: isDesktop ? null : kMobilePageConstraints, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: visibleContextMenuListener( - _createSwitchBar(context))), - buildScrollJumper(), - const PeerSearchBar(), - Offstage( - offstage: !isDesktop, - child: _createPeerViewTypeSwitch(context) - .marginOnly(left: 13)), - ], - )), + padding: isDesktop ? null : EdgeInsets.symmetric(horizontal: 2), + constraints: isDesktop ? null : kMobilePageConstraints, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: + visibleContextMenuListener(_createSwitchBar(context))), + buildScrollJumper(), + const PeerSearchBar(), + Offstage( + offstage: !isDesktop, + child: _createPeerViewTypeSwitch(context) + .marginOnly(left: 13)), + Offstage( + offstage: _hideSort, + child: PeerSortDropdown(), + ) + ], + ), + ), ), _createPeersView(), ], @@ -417,3 +426,48 @@ class _PeerSearchBarState extends State { ); } } + +class PeerSortDropdown extends StatefulWidget { + const PeerSortDropdown({super.key}); + + @override + State createState() => _PeerSortDropdownState(); +} + +class _PeerSortDropdownState extends State { + final List sort_names = ['id', 'username', "status"]; + String _sortType = peerSort.value; + + @override + Widget build(BuildContext context) { + return DropdownButton( + value: _sortType, + elevation: 16, + underline: SizedBox(), + onChanged: (v) { + if (v != null) { + setState(() { + _sortType = v; + bind.setLocalFlutterConfig( + k: "peer-sorting", + v: _sortType, + ); + }); + peerSort.value = _sortType; + } + }, + dropdownColor: Theme.of(context).cardColor, + items: sort_names + .map>( + (String value) => DropdownMenuItem( + value: value, + child: Text( + value, + overflow: TextOverflow.ellipsis, + ), + ), + ) + .toList(), + ); + } +} diff --git a/flutter/lib/common/widgets/peers_view.dart b/flutter/lib/common/widgets/peers_view.dart index 9c98f24b8..88e05238e 100644 --- a/flutter/lib/common/widgets/peers_view.dart +++ b/flutter/lib/common/widgets/peers_view.dart @@ -18,6 +18,13 @@ typedef PeerCardBuilder = Widget Function(Peer peer); /// for peer search text, global obs value final peerSearchText = "".obs; + +/// for peer sort, global obs value +final peerSort = bind.getLocalFlutterConfig(k: 'peer-sorting').obs; + +// list for listener +final obslist = [peerSearchText, peerSort].obs; + final peerSearchTextController = TextEditingController(text: peerSearchText.value); @@ -101,7 +108,7 @@ class _PeersViewState extends State<_PeersView> with WindowListener { } Widget _buildPeersView(Peers peers) { - final body = ObxValue((searchText) { + final body = ObxValue((filters) { return FutureBuilder>( builder: (context, snapshot) { if (snapshot.hasData) { @@ -139,9 +146,9 @@ class _PeersViewState extends State<_PeersView> with WindowListener { ); } }, - future: matchPeers(searchText.value, peers.peers), + future: matchPeers(filters[0].value, filters[1].value, peers.peers), ); - }, peerSearchText); + }, obslist); return body; } @@ -179,11 +186,36 @@ class _PeersViewState extends State<_PeersView> with WindowListener { }(); } - Future>? matchPeers(String searchText, List peers) async { + Future>? matchPeers( + String searchText, String sortedBy, List peers) async { if (widget.peerFilter != null) { peers = peers.where((peer) => widget.peerFilter!(peer)).toList(); } + // fallback to id sorting + if (sortedBy.isEmpty) { + sortedBy = 'id'; + bind.setLocalFlutterConfig( + k: "peer-sorting", + v: sortedBy, + ); + } + + if (widget.peers.loadEvent != 'load_recent_peers') { + switch (sortedBy) { + case 'id': + peers.sort((p1, p2) => p1.id.compareTo(p2.id)); + break; + case 'username': + peers.sort((p1, p2) => + p1.username.toLowerCase().compareTo(p2.username.toLowerCase())); + break; + case 'status': + peers.sort((p1, p2) => p1.online ? 1 : -1); + break; + } + } + searchText = searchText.trim(); if (searchText.isEmpty) { return peers; @@ -197,6 +229,7 @@ class _PeersViewState extends State<_PeersView> with WindowListener { filteredList.add(peers[i]); } } + return filteredList; } } From 705eb233776afec2fab903fc264d23dfa11e46f4 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Fri, 3 Mar 2023 21:54:24 +0100 Subject: [PATCH 131/382] Update de.rs --- src/lang/de.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/lang/de.rs b/src/lang/de.rs index d6ebe7f1a..3798ee199 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -213,7 +213,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the peer", "Von der Gegenstelle manuell geschlossen"), ("Enable remote configuration modification", "Änderung der Konfiguration aus der Ferne zulassen"), ("Run without install", "Ohne Installation ausführen"), - ("Connect via relay", "Verbindung über Relay-Server"), + ("Connect via relay", "Über Relay-Server verbinden"), ("Always connect via relay", "Immer über Relay-Server verbinden"), ("whitelist_tip", "Nur IPs auf der Whitelist können zugreifen."), ("Login", "Anmelden"), @@ -221,10 +221,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Remember me", "Login speichern"), ("Trust this device", "Diesem Gerät vertrauen"), ("Verification code", "Verifizierungscode"), - ("verification_tip", "Es wurde ein neues Gerät erkannt und ein Verifizierungscode an die registrierte E-Mail-Adresse gesendet. Geben Sie den Verifizierungscode ein, um sich weiter anzumelden."), + ("verification_tip", "Es wurde ein neues Gerät erkannt und ein Verifizierungscode an die registrierte E-Mail-Adresse gesendet. Geben Sie den Verifizierungscode ein, um sich erneut anzumelden."), ("Logout", "Abmelden"), ("Tags", "Schlagworte"), - ("Search ID", "Suche ID"), + ("Search ID", "ID suchen"), ("whitelist_sep", "Getrennt durch Komma, Semikolon, Leerzeichen oder Zeilenumbruch"), ("Add ID", "ID hinzufügen"), ("Add Tag", "Stichwort hinzufügen"), @@ -270,8 +270,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Hinweis"), ("Connection", "Verbindung"), ("Share Screen", "Bildschirm freigeben"), - ("CLOSE", "SCHLIEẞEN"), - ("OPEN", "ÖFFNEN"), + ("CLOSE", "DEAKTIVIEREN"), + ("OPEN", "AKTIVIEREN"), ("Chat", "Chat"), ("Total", "Gesamt"), ("items", "Einträge"), @@ -290,7 +290,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Durch das Aktivieren der Bildschirmfreigabe wird der Dienst automatisch gestartet, sodass andere Geräte dieses Android-Gerät steuern können."), ("android_stop_service_tip", "Durch das Deaktivieren des Dienstes werden automatisch alle hergestellten Verbindungen getrennt."), ("android_version_audio_tip", "Ihre Android-Version unterstützt keine Audioaufnahme, bitte aktualisieren Sie auf Android 10 oder höher, falls möglich."), - ("android_start_service_tip", "Tippen Sie auf \"Dienst aktivieren\" oder aktivieren Sie die Berechtigung \"Bildschirmaufnahme\", um den Bildschirmfreigabedienst zu starten."), + ("android_start_service_tip", "Tippen Sie auf \"Vermittlungsdienst starten\" oder aktivieren Sie die Berechtigung \"Bildschirmaufnahme\", um den Bildschirmfreigabedienst zu starten."), ("Account", "Konto"), ("Overwrite", "Überschreiben"), ("This file exists, skip or overwrite this file?", "Diese Datei existiert; überspringen oder überschreiben?"), @@ -312,8 +312,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk im Hintergrund ausführen"), ("Ignore Battery Optimizations", "Akkuoptimierung ignorieren"), ("android_open_battery_optimizations_tip", "Möchten Sie die Einstellungen zur Akkuoptimierung öffnen?"), - ("Start on Boot", "Beim Booten Starten"), - ("Start the screen sharing service on boot, requires special permissions", "Bildschirmfreigabedienst beim Booten starten, benötigt zusätzliche Berechtigungen"), + ("Start on Boot", "Beim Booten starten"), + ("Start the screen sharing service on boot, requires special permissions", "Bildschirmfreigabedienst beim Booten starten, erfordert zusätzliche Berechtigungen"), ("Connection not allowed", "Verbindung abgelehnt"), ("Legacy mode", "Kompatibilitätsmodus"), ("Map mode", "Kartenmodus"), @@ -340,7 +340,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Show Menubar", "Menüleiste anzeigen"), ("Hide Menubar", "Menüleiste ausblenden"), ("Direct Connection", "Direkte Verbindung"), - ("Relay Connection", "Relaisverbindung"), + ("Relay Connection", "Relay-Verbindung"), ("Secure Connection", "Sichere Verbindung"), ("Insecure Connection", "Unsichere Verbindung"), ("Scale original", "Keine Skalierung"), @@ -382,7 +382,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Write a message", "Nachricht schreiben"), ("Prompt", "Meldung"), ("Please wait for confirmation of UAC...", "Bitte auf die Bestätigung des Nutzers warten..."), - ("elevated_foreground_window_tip", "Das aktuell geöffnete Fenster des ferngesteuerten Computers benötigt höhere Rechte. Deshalb ist es derzeit nicht möglich, die Maus und die Tastatur zu verwenden. Bitten Sie den Nutzer, dessen Computer Sie fernsteuern, das Fenster zu minimieren oder die Rechte zu erhöhen. Um dieses Problem zukünftig zu vermeiden, wird empfohlen, die Software auf dem ferngesteuerten Computer zu installieren."), + ("elevated_foreground_window_tip", "Das aktuell geöffnete Fenster des ferngesteuerten Computers erfordert höhere Rechte. Deshalb ist es derzeit nicht möglich, die Maus und die Tastatur zu verwenden. Bitten Sie den Nutzer, dessen Computer Sie fernsteuern, das Fenster zu minimieren oder die Rechte zu erhöhen. Um dieses Problem zukünftig zu vermeiden, wird empfohlen, die Software auf dem ferngesteuerten Computer zu installieren."), ("Disconnected", "Verbindung abgebrochen"), ("Other", "Weitere Einstellungen"), ("Confirm before closing multiple tabs", "Nachfragen, wenn mehrere Tabs geschlossen werden"), @@ -397,7 +397,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("This PC", "Dieser PC"), ("or", "oder"), ("Continue with", "Fortfahren mit"), - ("Elevate", "Erheben"), + ("Elevate", "Erhöhen"), ("Zoom cursor", "Cursor vergrößern"), ("Accept sessions via password", "Sitzung mit Passwort bestätigen"), ("Accept sessions via click", "Sitzung mit einem Klick bestätigen"), From 3d913f8e66c739b28c028bb8e75e4f073c83097f Mon Sep 17 00:00:00 2001 From: mehdi-song Date: Sat, 4 Mar 2023 07:47:59 +0330 Subject: [PATCH 132/382] Update fa.rs --- 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 22ecf0355..7fe279a1b 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -349,7 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "امنیت"), ("Theme", "نمایه"), ("Dark Theme", "نمایه تیره"), - ("Light Theme", ""), + ("Light Theme", "نمایه روشن"), ("Dark", "تیره"), ("Light", "روشن"), ("Follow System", "پیروی از سیستم"), From c11f1b3a511f556bd8de80056b0303cfe8ea14ea Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sat, 4 Mar 2023 13:23:35 +0800 Subject: [PATCH 133/382] remove id input card background --- flutter/lib/desktop/pages/connection_page.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flutter/lib/desktop/pages/connection_page.dart b/flutter/lib/desktop/pages/connection_page.dart index edbd5b7c6..30fe07b95 100644 --- a/flutter/lib/desktop/pages/connection_page.dart +++ b/flutter/lib/desktop/pages/connection_page.dart @@ -161,9 +161,8 @@ class _ConnectionPageState extends State width: 320 + 20 * 2, padding: const EdgeInsets.fromLTRB(20, 24, 20, 22), decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, - borderRadius: const BorderRadius.all(Radius.circular(13)), - ), + borderRadius: const BorderRadius.all(Radius.circular(13)), + border: Border.all(color: Theme.of(context).colorScheme.background)), child: Ink( child: Column( children: [ @@ -200,6 +199,7 @@ class _ConnectionPageState extends State cursorColor: Theme.of(context).textTheme.titleLarge?.color, decoration: InputDecoration( + filled: false, counterText: '', hintText: _idInputFocused.value ? null From 122f0f961175dc46531a97714a124a17740ad816 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sat, 4 Mar 2023 14:28:43 +0800 Subject: [PATCH 134/382] small light theme redesign --- flutter/lib/common.dart | 19 ++++++++----------- .../lib/desktop/pages/desktop_home_page.dart | 8 ++------ .../desktop/pages/desktop_setting_page.dart | 2 +- .../lib/desktop/widgets/tabbar_widget.dart | 2 -- 4 files changed, 11 insertions(+), 20 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index ceff7480e..dc91e9414 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -156,8 +156,7 @@ class ColorThemeExtension extends ThemeExtension { class MyTheme { MyTheme._(); - static const Color grayBg = Color(0xFFEEEEEE); - static const Color white = Color(0xFFFFFFFF); + static const Color grayBg = Color(0xFFEFEFF2); static const Color accent = Color(0xFF0071FF); static const Color accent50 = Color(0x770071FF); static const Color accent80 = Color(0xAA0071FF); @@ -173,20 +172,20 @@ class MyTheme { static ThemeData lightTheme = ThemeData( brightness: Brightness.light, hoverColor: Color.fromARGB(255, 224, 224, 224), - scaffoldBackgroundColor: Color(0xFFFFFFFF), - dialogBackgroundColor: Color(0xFFFFFFFF), + scaffoldBackgroundColor: Colors.white, + dialogBackgroundColor: Colors.white, dialogTheme: DialogTheme( elevation: 15, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(18.0), side: BorderSide( width: 1, - color: Color(0xFFEEEEEE), + color: grayBg, ), ), ), inputDecorationTheme: InputDecorationTheme( - fillColor: Color(0xFFEEEEEE), + fillColor: grayBg, filled: true, isDense: true, contentPadding: EdgeInsets.all(15), @@ -202,7 +201,7 @@ class MyTheme { bodyMedium: TextStyle(fontSize: 14, color: Colors.black87, height: 1.25), labelLarge: TextStyle(fontSize: 16.0, color: MyTheme.accent80)), - cardColor: Color(0xFFEEEEEE), + cardColor: grayBg, hintColor: Color(0xFFAAAAAA), visualDensity: VisualDensity.adaptivePlatformDensity, tabBarTheme: const TabBarTheme( @@ -231,9 +230,7 @@ class MyTheme { ), outlinedButtonTheme: OutlinedButtonThemeData( style: OutlinedButton.styleFrom( - backgroundColor: Color( - 0xFFEEEEEE, - ), + backgroundColor: grayBg, foregroundColor: Colors.black87, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), @@ -259,7 +256,7 @@ class MyTheme { primarySwatch: Colors.blue, ).copyWith( brightness: Brightness.light, - background: Color(0xFFEEEEEE), + background: grayBg, ), ).copyWith( extensions: >[ diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index 8f16e3652..541ec6aa8 100644 --- a/flutter/lib/desktop/pages/desktop_home_page.dart +++ b/flutter/lib/desktop/pages/desktop_home_page.dart @@ -3,7 +3,7 @@ import 'dart:io'; import 'dart:convert'; import 'package:auto_size_text/auto_size_text.dart'; -import 'package:flutter/material.dart' hide MenuItem; +import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/common/widgets/custom_password.dart'; @@ -14,7 +14,6 @@ import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart'; import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart'; import 'package:flutter_hbb/models/platform_model.dart'; import 'package:flutter_hbb/models/server_model.dart'; -import 'package:flutter_hbb/models/state_model.dart'; import 'package:flutter_hbb/utils/multi_window_manager.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; @@ -55,10 +54,7 @@ class _DesktopHomePageState extends State crossAxisAlignment: CrossAxisAlignment.start, children: [ buildLeftPane(context), - const VerticalDivider( - width: 1, - thickness: 1, - ), + const VerticalDivider(width: 1), Expanded( child: buildRightPane(context), ), diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 0aafd48bb..f4d77c79b 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -120,7 +120,7 @@ class _DesktopSettingPageState extends State ], ), ), - const VerticalDivider(thickness: 1, width: 1), + const VerticalDivider(width: 1), Expanded( child: Container( color: Theme.of(context).scaffoldBackgroundColor, diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index edc779fba..1e62fb33d 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -280,7 +280,6 @@ class DesktopTab extends StatelessWidget { ), const Divider( height: 1, - thickness: 1, ), ], ), @@ -957,7 +956,6 @@ class _TabState extends State<_Tab> with RestorationMixin { indent: _kDividerIndent, endIndent: _kDividerIndent, color: MyTheme.tabbar(context).dividerColor, - thickness: 1, ), ) ], From 5052ba5f00b96ef5db5b9784177bb176a30369f1 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sat, 4 Mar 2023 17:26:24 +0800 Subject: [PATCH 135/382] refactor log --- Cargo.lock | 2 +- Cargo.toml | 1 - libs/hbb_common/Cargo.toml | 1 + libs/hbb_common/src/lib.rs | 40 +++++++++++++++++++++++++++++++++++++- src/core_main.rs | 36 ++++++---------------------------- 5 files changed, 47 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8f8895bd5..d0f22a0ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2675,6 +2675,7 @@ dependencies = [ "dirs-next", "env_logger 0.9.3", "filetime", + "flexi_logger", "futures", "futures-util", "lazy_static", @@ -4938,7 +4939,6 @@ dependencies = [ "enigo", "errno", "evdev", - "flexi_logger", "flutter_rust_bridge", "flutter_rust_bridge_codegen", "fruitbasket", diff --git a/Cargo.toml b/Cargo.toml index b53615c4e..ba92733ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,6 @@ lazy_static = "1.4" sha2 = "0.10" repng = "0.2" parity-tokio-ipc = { git = "https://github.com/open-trade/parity-tokio-ipc" } -flexi_logger = { version = "0.22", features = ["async", "use_chrono_for_offset"] } runas = "0.2" magnum-opus = { git = "https://github.com/rustdesk/magnum-opus" } dasp = { version = "0.11", features = ["signal", "interpolate-linear", "interpolate"], optional = true } diff --git a/libs/hbb_common/Cargo.toml b/libs/hbb_common/Cargo.toml index a125078d2..c77f11eb5 100644 --- a/libs/hbb_common/Cargo.toml +++ b/libs/hbb_common/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +flexi_logger = { version = "0.22", features = ["async", "use_chrono_for_offset"] } protobuf = { version = "3.1", features = ["with-bytes"] } tokio = { version = "1.20", features = ["full"] } tokio-util = { version = "0.7", features = ["full"] } diff --git a/libs/hbb_common/src/lib.rs b/libs/hbb_common/src/lib.rs index bfb773908..21566aa23 100644 --- a/libs/hbb_common/src/lib.rs +++ b/libs/hbb_common/src/lib.rs @@ -39,8 +39,8 @@ pub use tokio_socks::IntoTargetAddr; pub use tokio_socks::TargetAddr; pub mod password_security; pub use chrono; -pub use libc; pub use directories_next; +pub use libc; pub mod keyboard; pub use sysinfo; @@ -312,6 +312,44 @@ pub fn is_domain_port_str(id: &str) -> bool { .is_match(id) } +pub fn init_log(_is_async: bool, _name: &str) -> Option { + #[cfg(debug_assertions)] + { + use env_logger::*; + init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); + None + } + #[cfg(not(debug_assertions))] + { + // https://docs.rs/flexi_logger/latest/flexi_logger/error_info/index.html#write + // though async logger more efficient, but it also causes more problems, disable it for now + let mut logger_holder: Option = None; + let mut path = config::Config::log_path(); + if !_name.is_empty() { + path.push(_name); + } + use flexi_logger::*; + if let Ok(x) = Logger::try_with_env_or_str("debug") { + logger_holder = x + .log_to_file(FileSpec::default().directory(path)) + .write_mode(if _is_async { + WriteMode::Async + } else { + WriteMode::Direct + }) + .format(opt_format) + .rotate( + Criterion::Age(Age::Day), + Naming::Timestamps, + Cleanup::KeepLogFiles(6), + ) + .start() + .ok(); + } + logger_holder + } +} + #[cfg(test)] mod test { use super::*; diff --git a/src/core_main.rs b/src/core_main.rs index 0eeb2c6f9..60a7d9c9c 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -8,9 +8,6 @@ use hbb_common::platform::register_breakdown_handler; /// If it returns [`None`], then the process will terminate, and flutter gui will not be started. /// If it returns [`Some`], then the process will continue, and flutter gui will be started. pub fn core_main() -> Option> { - // https://docs.rs/flexi_logger/latest/flexi_logger/error_info/index.html#write - // though async logger more efficient, but it also causes more problems, disable it for now - // let mut _async_logger_holder: Option = None; let mut args = Vec::new(); let mut flutter_args = Vec::new(); let mut i = 0; @@ -76,35 +73,14 @@ pub fn core_main() -> Option> { || (!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::*; - init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); - } - #[cfg(not(debug_assertions))] - { - let mut path = hbb_common::config::Config::log_path(); - if args.len() > 0 && args[0].starts_with("--") { - let name = args[0].replace("--", ""); - if !name.is_empty() { - path.push(name); - } - } - use flexi_logger::*; - if let Ok(x) = Logger::try_with_env_or_str("debug") { - // _async_logger_holder = - x.log_to_file(FileSpec::default().directory(path)) - //.write_mode(WriteMode::Async) - .format(opt_format) - .rotate( - Criterion::Age(Age::Day), - Naming::Timestamps, - Cleanup::KeepLogFiles(6), - ) - .start() - .ok(); + let mut log_name = "".to_owned(); + if args.len() > 0 && args[0].starts_with("--") { + let name = args[0].replace("--", ""); + if !name.is_empty() { + log_name = name; } } + hbb_common::init_log(false, &log_name); #[cfg(windows)] if !crate::platform::is_installed() && args.is_empty() From 384ddffb09a738a8d4ae090633d834db68764f71 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Sat, 4 Mar 2023 16:33:40 +0100 Subject: [PATCH 136/382] Update de.rs --- src/lang/de.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/lang/de.rs b/src/lang/de.rs index 23c091a5c..36493f747 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -7,7 +7,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Password", "Passwort"), ("Ready", "Bereit"), ("Established", "Verbunden"), - ("connecting_status", "Verbinden mit dem RustDesk-Netzwerk..."), + ("connecting_status", "Verbinden mit dem RustDesk-Netzwerk …"), ("Enable Service", "Vermittlungsdienst aktivieren"), ("Start Service", "Vermittlungsdienst starten"), ("Service is running", "Vermittlungsdienst aktiv"), @@ -76,12 +76,12 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection Error", "Verbindungsfehler"), ("Error", "Fehler"), ("Reset by the peer", "Verbindung wurde von der Gegenstelle zurückgesetzt."), - ("Connecting...", "Verbindung wird hergestellt..."), - ("Connection in progress. Please wait.", "Die Verbindung wird hergestellt. Bitte warten..."), + ("Connecting...", "Verbindung wird hergestellt …"), + ("Connection in progress. Please wait.", "Die Verbindung wird hergestellt. Bitte warten …"), ("Please try 1 minute later", "Bitte versuchen Sie es später erneut"), ("Login Error", "Anmeldefehler"), ("Successful", "Erfolgreich"), - ("Connected, waiting for image...", "Verbindung hergestellt. Warten auf Bild..."), + ("Connected, waiting for image...", "Verbindung hergestellt. Warte auf anderen Bildschirm …"), ("Name", "Name"), ("Type", "Typ"), ("Modified", "Geändert"), @@ -152,7 +152,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Configure", "Konfigurieren"), ("config_acc", "Um Ihren PC aus der Ferne zu steuern, müssen Sie RustDesk Zugriffsrechte erteilen."), ("config_screen", "Um aus der Ferne auf Ihren PC zugreifen zu können, müssen Sie RustDesk die Berechtigung \"Bildschirmaufnahme\" erteilen."), - ("Installing ...", "Installieren..."), + ("Installing ...", "Installiere …"), ("Install", "Installieren"), ("Installation", "Installation"), ("Installation Path", "Installationspfad"), @@ -161,10 +161,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("agreement_tip", "Durch die Installation akzeptieren Sie die Lizenzvereinbarung."), ("Accept and Install", "Akzeptieren und Installieren"), ("End-user license agreement", "Lizenzvereinbarung für Endbenutzer"), - ("Generating ...", "Wird generiert..."), + ("Generating ...", "Wird generiert …"), ("Your installation is lower version.", "Ihre Version ist veraltet."), ("not_close_tcp_tip", "Schließen Sie dieses Fenster nicht, solange Sie den Tunnel benutzen."), - ("Listening ...", "Lauschen..."), + ("Listening ...", "Lauschen …"), ("Remote Host", "Entfernter PC"), ("Remote Port", "Entfernter Port"), ("Action", "Aktion"), @@ -190,7 +190,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Relayed and unencrypted connection", "Vermittelte und unverschlüsselte Verbindung"), ("Enter Remote ID", "Remote-ID eingeben"), ("Enter your password", "Geben Sie Ihr Passwort ein"), - ("Logging in...", "Anmelden..."), + ("Logging in...", "Anmelden …"), ("Enable RDP session sharing", "RDP-Sitzungsfreigabe aktivieren"), ("Auto Login", "Automatisch anmelden (nur gültig, wenn Sie \"Nach Sitzungsende sperren\" aktiviert haben)"), ("Enable Direct IP Access", "Direkten IP-Zugang aktivieren"), @@ -299,7 +299,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Help", "Hilfe"), ("Failed", "Fehlgeschlagen"), ("Succeeded", "Erfolgreich"), - ("Someone turns on privacy mode, exit", "Jemand hat den Datenschutzmodus aktiviert, beende..."), + ("Someone turns on privacy mode, exit", "Jemand hat den Datenschutzmodus aktiviert, beende …"), ("Unsupported", "Nicht unterstützt"), ("Peer denied", "Die Gegenstelle hat die Verbindung abgelehnt."), ("Please install plugins", "Bitte installieren Sie Plugins"), @@ -382,7 +382,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Deny LAN Discovery", "LAN-Erkennung verbieten"), ("Write a message", "Nachricht schreiben"), ("Prompt", "Meldung"), - ("Please wait for confirmation of UAC...", "Bitte auf die Bestätigung des Nutzers warten..."), + ("Please wait for confirmation of UAC...", "Bitte auf die Bestätigung des Nutzers warten …"), ("elevated_foreground_window_tip", "Das aktuell geöffnete Fenster des ferngesteuerten Computers erfordert höhere Rechte. Deshalb ist es derzeit nicht möglich, die Maus und die Tastatur zu verwenden. Bitten Sie den Nutzer, dessen Computer Sie fernsteuern, das Fenster zu minimieren oder die Rechte zu erhöhen. Um dieses Problem zukünftig zu vermeiden, wird empfohlen, die Software auf dem ferngesteuerten Computer zu installieren."), ("Disconnected", "Verbindung abgebrochen"), ("Other", "Weitere Einstellungen"), @@ -398,12 +398,12 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("This PC", "Dieser PC"), ("or", "oder"), ("Continue with", "Fortfahren mit"), - ("Elevate", "Erhöhen"), + ("Elevate", "Zugriff gewähren"), ("Zoom cursor", "Cursor vergrößern"), ("Accept sessions via password", "Sitzung mit Passwort bestätigen"), ("Accept sessions via click", "Sitzung mit einem Klick bestätigen"), ("Accept sessions via both", "Sitzung mit Klick und Passwort bestätigen"), - ("Please wait for the remote side to accept your session request...", "Bitte warten Sie, bis die Gegenseite Ihre Sitzungsanfrage akzeptiert hat..."), + ("Please wait for the remote side to accept your session request...", "Bitte warten Sie, bis die Gegenseite Ihre Sitzungsanfrage akzeptiert hat …"), ("One-time Password", "Einmalpasswort"), ("Use one-time password", "Einmalpasswort verwenden"), ("One-time password length", "Länge des Einmalpassworts"), From 2c88e492e2c9b1f5054eb22a9e87bc102d34742c Mon Sep 17 00:00:00 2001 From: grummbeer Date: Sat, 4 Mar 2023 22:45:19 +0100 Subject: [PATCH 137/382] fix input style of whitelisting for mobile --- flutter/lib/common/widgets/dialog.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/lib/common/widgets/dialog.dart b/flutter/lib/common/widgets/dialog.dart index cdce6f12a..71d281ea1 100644 --- a/flutter/lib/common/widgets/dialog.dart +++ b/flutter/lib/common/widgets/dialog.dart @@ -180,7 +180,7 @@ void changeWhiteList({Function()? callback}) async { child: TextField( maxLines: null, decoration: InputDecoration( - border: const OutlineInputBorder(), + border: isDesktop ? const OutlineInputBorder() : null, errorText: msg.isEmpty ? null : translate(msg), ), controller: controller, From 0392fc0c847e7af425d25d4bf9976d5f6af9012c Mon Sep 17 00:00:00 2001 From: grummbeer Date: Sat, 4 Mar 2023 23:23:10 +0100 Subject: [PATCH 138/382] fix. Mobile style of input on "changeId" dialog --- flutter/lib/common/widgets/dialog.dart | 52 +++++++++++++------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/flutter/lib/common/widgets/dialog.dart b/flutter/lib/common/widgets/dialog.dart index cdce6f12a..4e4b24519 100644 --- a/flutter/lib/common/widgets/dialog.dart +++ b/flutter/lib/common/widgets/dialog.dart @@ -63,8 +63,9 @@ void changeIdDialog() { final Iterable violations = rules.where((r) => !r.validate(newId)); if (violations.isNotEmpty) { setState(() { - msg = - '${translate('Prompt')}: ${violations.map((r) => r.name).join(', ')}'; + msg = isDesktop + ? '${translate('Prompt')}: ${violations.map((r) => r.name).join(', ')}' + : violations.map((r) => r.name).join(', '); }); return; } @@ -87,7 +88,9 @@ void changeIdDialog() { } setState(() { isInProgress = false; - msg = '${translate('Prompt')}: ${translate(status)}'; + msg = isDesktop + ? '${translate('Prompt')}: ${translate(status)}' + : translate(status); }); } @@ -103,7 +106,7 @@ void changeIdDialog() { TextField( decoration: InputDecoration( labelText: translate('Your new ID'), - border: const OutlineInputBorder(), + border: isDesktop ? const OutlineInputBorder() : null, errorText: msg.isEmpty ? null : translate(msg), suffixText: '${rxId.value.length}/16', suffixStyle: const TextStyle(fontSize: 12, color: Colors.grey)), @@ -123,27 +126,26 @@ void changeIdDialog() { const SizedBox( height: 8.0, ), - Obx(() => Wrap( - runSpacing: 8, - spacing: 4, - children: rules.map((e) { - var checked = e.validate(rxId.value); - return Chip( - label: Text( - e.name, - style: TextStyle( - color: checked - ? const Color(0xFF0A9471) - : Color.fromARGB(255, 198, 86, 157)), - ), - backgroundColor: checked - ? const Color(0xFFD0F7ED) - : Color.fromARGB(255, 247, 205, 232)); - }).toList(), - )), - const SizedBox( - height: 8.0, - ), + isDesktop + ? Obx(() => Wrap( + runSpacing: 8, + spacing: 4, + children: rules.map((e) { + var checked = e.validate(rxId.value); + return Chip( + label: Text( + e.name, + style: TextStyle( + color: checked + ? const Color(0xFF0A9471) + : Color.fromARGB(255, 198, 86, 157)), + ), + backgroundColor: checked + ? const Color(0xFFD0F7ED) + : Color.fromARGB(255, 247, 205, 232)); + }).toList(), + )).marginOnly(bottom: 8) + : SizedBox.shrink(), Offstage( offstage: !isInProgress, child: const LinearProgressIndicator()) ], From 196ceb8d9182f29fd0f34203ab9ad5bd353b637f Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 01:10:15 +0200 Subject: [PATCH 139/382] Update gr.rs --- src/lang/gr.rs | 130 ++++++++++++++++++++++++------------------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/src/lang/gr.rs b/src/lang/gr.rs index cbd4f89e0..f517f61a1 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -12,7 +12,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Start Service", "Έναρξη υπηρεσίας"), ("Service is running", "Η υπηρεσία εκτελείται"), ("Service is not running", "Η υπηρεσία δεν εκτελείται"), - ("not_ready_status", "Δεν είναι έτοιμο. Ελέγξτε τη σύνδεσή σας"), + ("not_ready_status", "Δεν είναι έτοιμο. Ελέγξτε τη σύνδεσή σας στο δίκτυο"), ("Control Remote Desktop", "Έλεγχος απομακρυσμένου σταθμού εργασίας"), ("Transfer File", "Μεταφορά αρχείου"), ("Connect", "Σύνδεση"), @@ -37,19 +37,19 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Clipboard is empty", "Το πρόχειρο είναι κενό"), ("Stop service", "Διακοπή υπηρεσίας"), ("Change ID", "Αλλαγή αναγνωριστικού ID"), - ("Your new ID", ""), - ("length %min% to %max%", ""), - ("starts with a letter", ""), - ("allowed characters", ""), + ("Your new ID", "Το νέο σας ID"), + ("length %min% to %max%", "μέγεθος από %min% έως %max%"), + ("starts with a letter", "ξεκινά με γράμμα"), + ("allowed characters", "επιτρεπόμενοι χαρακτήρες"), ("id_change_tip", "Επιτρέπονται μόνο οι χαρακτήρες a-z, A-Z, 0-9 και _ (υπογράμμιση). Το πρώτο γράμμα πρέπει να είναι a-z, A-Z και το μήκος πρέπει να είναι μεταξύ 6 και 16 χαρακτήρων."), ("Website", "Ιστότοπος"), ("About", "Πληροφορίες"), - ("Slogan_tip", ""), - ("Privacy Statement", ""), + ("Slogan_tip", "Προγραμματισμένος με πάθος - σε έναν κόσμο που βυθίζεται στο χάος!"), + ("Privacy Statement", "Πολιτική απορρήτου"), ("Mute", "Σίγαση"), - ("Build Date", ""), - ("Version", ""), - ("Home", ""), + ("Build Date", "Ημερομηνία δημιουργίας"), + ("Version", "Έκδοση"), + ("Home", "Αρχική"), ("Audio Input", "Είσοδος ήχου"), ("Enhancements", "Βελτιώσεις"), ("Hardware Codec", "Κωδικοποιητής υλικού"), @@ -60,14 +60,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("invalid_http", "Πρέπει να ξεκινά με http:// ή https://"), ("Invalid IP", "Μη έγκυρη διεύθυνση IP"), ("Invalid format", "Μη έγκυρη μορφή"), - ("server_not_support", "Αυτή η δυνατότητα δεν υποστηρίζεται ακόμη από τον διακομιστή"), + ("server_not_support", "Αυτή η δυνατότητα δεν υποστηρίζεται από τον διακομιστή"), ("Not available", "Μη διαθέσιμο"), ("Too frequent", "Πολύ συχνά"), ("Cancel", "Ακύρωση"), ("Skip", "Παράλειψη"), ("Close", "Κλείσιμο"), ("Retry", "Δοκίμασε ξανά"), - ("OK", "Εντάξει"), + ("OK", "ΟΚ"), ("Password Required", "Απαιτείται κωδικός πρόσβασης"), ("Please enter your password", "Παρακαλώ εισάγετε τον κωδικό πρόσβασης"), ("Remember password", "Απομνημόνευση κωδικού πρόσβασης"), @@ -108,7 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Do this for all conflicts", "Κάνε αυτό για όλες τις διενέξεις"), ("This is irreversible!", "Αυτό είναι μη αναστρέψιμο!"), ("Deleting", "Διαγραφή"), - ("files", "αρχεία"), + ("files", "αρχείων"), ("Waiting", "Αναμονή"), ("Finished", "Ολοκληρώθηκε"), ("Speed", "Ταχύτητα"), @@ -130,7 +130,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Show quality monitor", "Εμφάνιση παρακολούθησης ποιότητας σύνδεσης"), ("Disable clipboard", "Απενεργοποίηση προχείρου"), ("Lock after session end", "Κλείδωμα μετά το τέλος της συνεδρίας"), - ("Insert", ""), + ("Insert", "Εισαγωγή"), ("Insert Lock", "Κλείδωμα απομακρυσμένου σταθμού"), ("Refresh", "Ανανέωση"), ("ID does not exist", "Το αναγνωριστικό ID δεν υπάρχει"), @@ -139,11 +139,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Remote desktop is offline", "Ο απομακρυσμένος σταθμός εργασίας είναι εκτός σύνδεσης"), ("Key mismatch", "Μη έγκυρο κλειδί"), ("Timeout", "Τέλος χρόνου"), - ("Failed to connect to relay server", "Αποτυχία σύνδεσης με διακομιστή αναμετάδοσης"), + ("Failed to connect to relay server", "Αποτυχία σύνδεσης με τον διακομιστή αναμετάδοσης"), ("Failed to connect via rendezvous server", "Απέτυχε η σύνδεση μέσω διακομιστή"), ("Failed to connect via relay server", "Απέτυχε η σύνδεση μέσω διακομιστή αναμετάδοσης"), ("Failed to make direct connection to remote desktop", "Απέτυχε η απευθείας σύνδεση με τον απομακρυσμένο σταθμό εργασίας"), - ("Set Password", "Ορίστε κωδικό"), + ("Set Password", "Ορίστε κωδικό πρόσβασης"), ("OS Password", "Κωδικός πρόσβασης λειτουργικού συστήματος"), ("install_tip", "Λόγω UAC, το RustDesk ενδέχεται να μην λειτουργεί σωστά σε ορισμένες περιπτώσεις. Για να αποφύγετε το UAC, κάντε κλικ στο κουμπί παρακάτω για να εγκαταστήσετε το RustDesk στο σύστημα"), ("Click to upgrade", "Κάντε κλικ για αναβάθμιση"), @@ -152,9 +152,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Configure", "Διαμόρφωση"), ("config_acc", "Για τον απομακρυσμένο έλεγχο του υπολογιστή σας, πρέπει να εκχωρήσετε δικαιώματα πρόσβασης στο RustDesk."), ("config_screen", "Για να αποκτήσετε απομακρυσμένη πρόσβαση στον υπολογιστή σας, πρέπει να εκχωρήσετε το δικαίωμα RustDesk \"Screen Capture\"."), - ("Installing ...", "Εγκατάσταση ..."), + ("Installing ...", "Γίνεται εγκατάσταση ..."), ("Install", "Εγκατάσταση"), - ("Installation", "Εγκατάσταση"), + ("Installation", "Η εγκατάσταση"), ("Installation Path", "Διαδρομή εγκατάστασης"), ("Create start menu shortcuts", "Δημιουργία συντομεύσεων μενού έναρξης"), ("Create desktop icon", "Δημιουργία εικονιδίου επιφάνειας εργασίας"), @@ -182,7 +182,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Allow using keyboard and mouse", "Να επιτρέπεται η χρήση πληκτρολογίου και ποντικιού"), ("Allow using clipboard", "Να επιτρέπεται η χρήση του προχείρου"), ("Allow hearing sound", "Να επιτρέπεται η αναπαραγωγή ήχου"), - ("Allow file copy and paste", "Να επιτρέπεται η αντιγραφή και επικόλληση αρχείου"), + ("Allow file copy and paste", "Να επιτρέπεται η αντιγραφή και επικόλληση αρχείων"), ("Connected", "Συνδεδεμένο"), ("Direct and encrypted connection", "Άμεση και κρυπτογραφημένη σύνδεση"), ("Relayed and encrypted connection", "Κρυπτογραφημένη σύνδεση με αναμετάδοση"), @@ -190,14 +190,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Relayed and unencrypted connection", "Μη κρυπτογραφημένη σύνδεση με αναμετάδοση"), ("Enter Remote ID", "Εισαγωγή απομακρυσμένου ID"), ("Enter your password", "Εισάγετε τον κωδικό σας"), - ("Logging in...", "Σύνδεση..."), + ("Logging in...", "Γίνεται σύνδεση..."), ("Enable RDP session sharing", "Ενεργοποίηση κοινής χρήσης RDP"), ("Auto Login", "Αυτόματη είσοδος"), ("Enable Direct IP Access", "Ενεργοποίηση άμεσης πρόσβασης IP"), ("Rename", "Μετονομασία"), ("Space", "Χώρος"), ("Create Desktop Shortcut", "Δημιουργία συντόμευσης στην επιφάνεια εργασίας"), - ("Change Path", "Αλλαγή διαδρομής"), + ("Change Path", "Αλλαγή διαδρομής δίσκου"), ("Create Folder", "Δημιουργία φακέλου"), ("Please enter the folder name", "Παρακαλώ εισάγετε το όνομα του φακέλου"), ("Fix it", "Επιδιόρθωσε το"), @@ -213,15 +213,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the peer", "Έκλεισε από τον απομακρυσμένο σταθμό"), ("Enable remote configuration modification", "Ενεργοποίηση απομακρυσμένης τροποποίησης ρυθμίσεων"), ("Run without install", "Εκτέλεση χωρίς εγκατάσταση"), - ("Connect via relay", ""), - ("Always connect via relay", "Σύνδεση πάντα μέσω αναμετάδοσης"), + ("Connect via relay", "Πραγματοποίηση σύνδεση μέσω αναμεταδότη"), + ("Always connect via relay", "Σύνδεση πάντα μέσω αναμεταδότη"), ("whitelist_tip", "Μόνο οι IP της λίστας επιτρεπόμενων έχουν πρόσβαση"), ("Login", "Σύνδεση"), - ("Verify", ""), - ("Remember me", ""), - ("Trust this device", ""), - ("Verification code", ""), - ("verification_tip", ""), + ("Verify", "Επαλήθευση"), + ("Remember me", "Να με θυμάσαι"), + ("Trust this device", "Εμπιστεύομαι αυτή την συσκευή"), + ("Verification code", "Κωδικός επαλήθευσης"), + ("verification_tip", "Εντοπίστηκε νέα συσκευή και εστάλη ένας κωδικός επαλήθευσης στην καταχωρισμένη διεύθυνση email. Εισαγάγετε τον κωδικό επαλήθευσης για να συνδεθείτε ξανά."), ("Logout", "Αποσύνδεση"), ("Tags", "Ετικέτες"), ("Search ID", "Αναζήτηση ID"), @@ -278,7 +278,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Selected", "Επιλεγμένο"), ("Screen Capture", "Αποτύπωση οθόνης"), ("Input Control", "Έλεγχος εισόδου"), - ("Audio Capture", "Λήψη ήχου"), + ("Audio Capture", "Εγγραφή ήχου"), ("File Connection", "Σύνδεση αρχείου"), ("Screen Connection", "Σύνδεση οθόνης"), ("Do you accept?", "Δέχεσαι;"), @@ -302,7 +302,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Someone turns on privacy mode, exit", "Κάποιος ενεργοποιεί τη λειτουργία απορρήτου, έξοδος"), ("Unsupported", "Δεν υποστηρίζεται"), ("Peer denied", "Ο απομακρυσμένος σταθμός απέρριψε τη σύνδεση"), - ("Please install plugins", "Παρακαλώ εγκαταστήστε πρόσθετα"), + ("Please install plugins", "Παρακαλώ εγκαταστήστε τα πρόσθετα"), ("Peer exit", "Ο απομακρυσμένος σταθμός έχει αποσυνδεθεί"), ("Failed to turn off", "Αποτυχία απενεργοποίησης"), ("Turned off", "Απενεργοποιημένο"), @@ -312,9 +312,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Εκτέλεση του RustDesk στο παρασκήνιο"), ("Ignore Battery Optimizations", "Παράβλεψη βελτιστοποιήσεων μπαταρίας"), ("android_open_battery_optimizations_tip", "Θέλετε να ανοίξετε τις ρυθμίσεις βελτιστοποίησης μπαταρίας;"), - ("Start on Boot", ""), - ("Start the screen sharing service on boot, requires special permissions", ""), - ("Connection not allowed", "Η σύνδεση απορρίφθηκε"), + ("Start on Boot", "Έναρξη κατά την εκκίνηση"), + ("Start the screen sharing service on boot, requires special permissions", "Η έναρξη της υπηρεσίας κοινής χρήσης οθόνης κατά την εκκίνηση, απαιτεί ειδικά δικαιώματα"), + ("Connection not allowed", "Η σύνδεση δεν επιτρέπεται"), ("Legacy mode", "Λειτουργία συμβατότητας"), ("Map mode", "Map mode"), ("Translate mode", "Λειτουργία μετάφρασης"), @@ -325,7 +325,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Allow remote restart", "Να επιτρέπεται η απομακρυσμένη επανεκκίνηση"), ("Restart Remote Device", "Επανεκκίνηση απομακρυσμένης συσκευής"), ("Are you sure you want to restart", "Είστε βέβαιοι ότι θέλετε να κάνετε επανεκκίνηση"), - ("Restarting Remote Device", "Επανεκκίνηση απομακρυσμένης συσκευής"), + ("Restarting Remote Device", "Γίνεται επανεκκίνηση της απομακρυσμένης συσκευής"), ("remote_restarting_tip", "Η απομακρυσμένη συσκευή επανεκκινείται, κλείστε αυτό το μήνυμα και επανασυνδεθείτε χρησιμοποιώντας τον μόνιμο κωδικό πρόσβασης."), ("Copied", "Αντιγράφηκε"), ("Exit Fullscreen", "Έξοδος από πλήρη οθόνη"), @@ -349,7 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Ασφάλεια"), ("Theme", "Θέμα"), ("Dark Theme", "Σκούρο θέμα"), - ("Light Theme", ""), + ("Light Theme", "Φωτεινό θέμα"), ("Dark", "Σκούρο"), ("Light", "Φωτεινό"), ("Follow System", "Από το σύστημα"), @@ -358,7 +358,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable Audio", "Ενεργοποίηση ήχου"), ("Unlock Network Settings", "Ξεκλείδωμα ρυθμίσεων δικτύου"), ("Server", "Διακομιστής"), - ("Direct IP Access", "Άμεση πρόσβαση IP"), + ("Direct IP Access", "Πρόσβαση με χρήση IP"), ("Proxy", "Διαμεσολαβητής"), ("Apply", "Εφαρμογή"), ("Disconnect all devices?", "Αποσύνδεση όλων των συσκευών;"), @@ -371,17 +371,17 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Pin menubar", "Καρφίτσωμα γραμμής μενού"), ("Unpin menubar", "Ξεκαρφίτσωμα γραμμής μενού"), ("Recording", "Εγγραφή"), - ("Directory", "Φάκελος εγγραφών"), + ("Directory", "Φάκελος εγγράφων"), ("Automatically record incoming sessions", "Αυτόματη εγγραφή εισερχόμενων συνεδριών"), ("Change", "Αλλαγή"), ("Start session recording", "Έναρξη εγγραφής συνεδρίας"), ("Stop session recording", "Διακοπή εγγραφής συνεδρίας"), ("Enable Recording Session", "Ενεργοποίηση εγγραφής συνεδρίας"), - ("Allow recording session", "Να επιτρέπεται η εγγραφή"), + ("Allow recording session", "Να επιτρέπεται η εγγραφή συνεδρίας"), ("Enable LAN Discovery", "Ενεργοποίηση εντοπισμού LAN"), ("Deny LAN Discovery", "Απαγόρευση εντοπισμού LAN"), ("Write a message", "Γράψτε ένα μήνυμα"), - ("Prompt", "Προτροπή"), + ("Prompt", "Υπενθυμίζω"), ("Please wait for confirmation of UAC...", "Παρακαλώ περιμένετε για επιβεβαίωση του UAC..."), ("elevated_foreground_window_tip", "Το τρέχον παράθυρο της απομακρυσμένης επιφάνειας εργασίας απαιτεί υψηλότερα δικαιώματα για να λειτουργήσει, επομένως δεν μπορεί να χρησιμοποιήσει προσωρινά το ποντίκι και το πληκτρολόγιο. Μπορείτε να ζητήσετε από τον απομακρυσμένο χρήστη να ελαχιστοποιήσει το τρέχον παράθυρο ή να κάνετε κλικ στο κουμπί ανύψωσης στο παράθυρο διαχείρισης σύνδεσης. Για να αποφύγετε αυτό το πρόβλημα, συνιστάται η εγκατάσταση του λογισμικού στην απομακρυσμένη συσκευή."), ("Disconnected", "Αποσυνδέθηκε"), @@ -399,10 +399,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("or", "ή"), ("Continue with", "Συνέχεια με"), ("Elevate", "Ανύψωση"), - ("Zoom cursor", "Μεγέθυνση στον κέρσορα"), - ("Accept sessions via password", "Αποδοχή συνεδριών μέσω κωδικού πρόσβασης"), - ("Accept sessions via click", "Αποδοχή συνεδριών μέσω κλικ"), - ("Accept sessions via both", "Αποδοχή συνεδριών και από τα δύο"), + ("Zoom cursor", "Kέρσορας μεγέθυνσης"), + ("Accept sessions via password", "Αποδοχή συνεδριών με κωδικό πρόσβασης"), + ("Accept sessions via click", "Αποδοχή συνεδριών με κλικ"), + ("Accept sessions via both", "Αποδοχή συνεδριών και με τα δύο"), ("Please wait for the remote side to accept your session request...", "Παρακαλώ περιμένετε μέχρι η απομακρυσμένη πλευρά να αποδεχτεί το αίτημα συνεδρίας σας..."), ("One-time Password", "Κωδικός μίας χρήσης"), ("Use one-time password", "Χρήση κωδικού πρόσβασης μίας χρήσης"), @@ -422,43 +422,43 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", "Εάν έχετε κάρτα γραφικών Nvidia και το παράθυρο σύνδεσης κλείνει αμέσως μετά τη σύνδεση, η εγκατάσταση του προγράμματος οδήγησης nouveau και η επιλογή χρήσης της επιτάχυνσης γραφικών μέσω λογισμικού μπορεί να βοηθήσει. Απαιτείται επανεκκίνηση."), ("Always use software rendering", "Επιτάχυνση γραφικών μέσω λογισμικού"), ("config_input", "Για να ελέγξετε την απομακρυσμένη επιφάνεια εργασίας με πληκτρολόγιο, πρέπει να εκχωρήσετε δικαιώματα στο RustDesk"), - ("config_microphone", ""), + ("config_microphone", "Ρύθμιση μικροφώνου"), ("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", "Μεταβίβαση του ονόματος χρήστη και του κωδικού πρόσβασης του διαχειριστή"), + ("Transmit the username and password of administrator", "Αποστολή του ονόματος χρήστη και του κωδικού πρόσβασης του διαχειριστή"), ("still_click_uac_tip", "Εξακολουθεί να απαιτεί από τον απομακρυσμένο χρήστη να κάνει κλικ στο OK στο παράθυρο UAC όπου εκτελείται το RustDesk."), ("Request Elevation", "Αίτημα ανύψωσης δικαιωμάτων χρήστη"), ("wait_accept_uac_tip", "Περιμένετε να αποδεχτεί ο απομακρυσμένος χρήστης το παράθυρο διαλόγου UAC."), ("Elevate successfully", "Επιτυχής ανύψωση δικαιωμάτων χρήστη"), ("uppercase", "κεφαλαία γράμματα"), ("lowercase", "πεζά γράμματα"), - ("digit", "Αριθμός"), + ("digit", "αριθμός"), ("special character", "ειδικός χαρακτήρας"), ("length>=8", "μήκος>=8"), ("Weak", "Αδύναμο"), ("Medium", "Μέτριο"), ("Strong", "Δυνατό"), - ("Switch Sides", ""), - ("Please confirm if you want to share your desktop?", ""), - ("Display", ""), - ("Default View Style", ""), - ("Default Scroll Style", ""), - ("Default Image Quality", ""), - ("Default Codec", ""), - ("Bitrate", ""), - ("FPS", ""), - ("Auto", ""), - ("Other Default Options", ""), - ("Voice call", ""), - ("Text chat", ""), - ("Stop voice call", ""), - ("relay_hint_tip", ""), - ("Reconnect", ""), - ("Codec", ""), - ("Resolution", ""), - ("No transfers in progress", ""), + ("Switch Sides", "Εναλλαγή πλευράς"), + ("Please confirm if you want to share your desktop?", "Παρακαλώ επιβεβαιώστε αν επιθυμείτε την κοινή χρήση της επιφάνειας εργασίας;"), + ("Display", "Εμφάνιση"), + ("Default View Style", "Προκαθορισμένος τρόπος εμφάνισης"), + ("Default Scroll Style", "Προκαθορισμένος τρόπος κύλισης"), + ("Default Image Quality", "Προκαθορισμένη ποιότητα εικόνας"), + ("Default Codec", "Προκαθορισμένη κωδικοποίηση"), + ("Bitrate", "Bitrate"), + ("FPS", "FPS"), + ("Auto", "Αυτόματο"), + ("Other Default Options", "Άλλες προκαθορισμένες ρυθμίσεις"), + ("Voice call", "Φωνητική κλήση"), + ("Text chat", "Συνομιλία κειμένου"), + ("Stop voice call", "Διακοπή φωνητικής κλήσης"), + ("relay_hint_tip", "Εάν δεν είναι δυνατή η απευθείας σύνδεση, μπορείτε να δοκιμάσετε να συνδεθείτε μέσω διακομιστή αναμετάδοσης"), + ("Reconnect", "Επανασύνδεση"), + ("Codec", "Κωδικοποίηση"), + ("Resolution", "Ανάλυση"), + ("No transfers in progress", "Δεν υπάρχει μεταφορά σε εξέλιξη"), ].iter().cloned().collect(); } From 7812799f4a2ff90e473e07011670ecf652c9554f Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 12:43:55 +0200 Subject: [PATCH 140/382] Update gr.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Φάκελος εγγραφών - recordings directory --- src/lang/gr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/gr.rs b/src/lang/gr.rs index f517f61a1..8629879ca 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -371,7 +371,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Pin menubar", "Καρφίτσωμα γραμμής μενού"), ("Unpin menubar", "Ξεκαρφίτσωμα γραμμής μενού"), ("Recording", "Εγγραφή"), - ("Directory", "Φάκελος εγγράφων"), + ("Directory", "Φάκελος εγγραφών"), ("Automatically record incoming sessions", "Αυτόματη εγγραφή εισερχόμενων συνεδριών"), ("Change", "Αλλαγή"), ("Start session recording", "Έναρξη εγγραφής συνεδρίας"), From 10d4571a521057eaf5e06d6f003275c5fe0dfbf1 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sun, 5 Mar 2023 22:00:44 +0800 Subject: [PATCH 141/382] opt: add icon file to flatpak recipe --- flatpak/rustdesk.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/flatpak/rustdesk.json b/flatpak/rustdesk.json index d7f6e316e..3ded34b20 100644 --- a/flatpak/rustdesk.json +++ b/flatpak/rustdesk.json @@ -13,8 +13,12 @@ "build-commands": [ "bsdtar -zxvf rustdesk-1.2.0.deb", "tar -xvf ./data.tar.xz", - "cp -r ./usr /app/", - "mkdir -p /app/bin && ln -s /app/usr/lib/rustdesk/rustdesk /app/bin/rustdesk" + "cp -r ./usr/* /app/", + "mkdir -p /app/bin && ln -s /app/lib/rustdesk/rustdesk /app/bin/rustdesk", + "sed -i '/^Icon=/ c\\Icon=/app/share/rustdesk/files/rustdesk.png' /app/share/applications/rustdesk.desktop", + "sed -i '/^Icon=/ c\\Icon=/app/share/rustdesk/files/rustdesk.png' /app/share/applications/rustdesk-link.desktop", + "sed -i '/^Exec=/ c\\Exec=/app/bin/rustdesk %u' /app/share/applications/rustdesk.desktop", + "sed -i '/^Exec=/ c\\Exec=/app/bin/rustdesk --connect \"%u\"' /app/share/applications/rustdesk-link.desktop" ], "sources": [ { From 101cf61813f65b6e38edaed0b0dfe26154fc3f44 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 17:28:20 +0200 Subject: [PATCH 142/382] Create README-GR.md --- docs/README-GR.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/README-GR.md diff --git a/docs/README-GR.md b/docs/README-GR.md new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/docs/README-GR.md @@ -0,0 +1 @@ + From 4278e69d307f8b0b8cd47c40e08627eba2af9788 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 17:29:38 +0200 Subject: [PATCH 143/382] Update README-GR.md --- docs/README-GR.md | 218 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) diff --git a/docs/README-GR.md b/docs/README-GR.md index 8b1378917..8af79915b 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -1 +1,219 @@ +

    + RustDesk - Your remote desktop
    + Servers • + Build • + Docker • + Structure • + Snapshot
    + [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    + We need your help to translate this README, RustDesk UI and Doc to your native language +

    +Chat with us: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk) + +[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09) + +Yet another remote desktop software, written in Rust. Works out of the box, no configuration required. You have full control of your data, with no concerns about security. You can use our rendezvous/relay server, [set up your own](https://rustdesk.com/server), or [write your own rendezvous/relay server](https://github.com/rustdesk/rustdesk-server-demo). + +![image](https://user-images.githubusercontent.com/71636191/171661982-430285f0-2e12-4b1d-9957-4a58e375304d.png) + +RustDesk welcomes contribution from everyone. See [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) for help getting started. + +[**FAQ**](https://github.com/rustdesk/rustdesk/wiki/FAQ) + +[**BINARY DOWNLOAD**](https://github.com/rustdesk/rustdesk/releases) + +[**NIGHTLY BUILD**](https://github.com/rustdesk/rustdesk/releases/tag/nightly) + +[Get it on F-Droid](https://f-droid.org/en/packages/com.carriez.flutter_hbb) + +## Free Public Servers + +Below are the servers you are using for free, they may change over time. If you are not close to one of these, your network may be slow. +| Location | Vendor | Specification | +| --------- | ------------- | ------------------ | +| Seoul | AWS lightsail | 1 vCPU / 0.5GB RAM | +| Germany | Hetzner | 2 vCPU / 4GB RAM | +| Germany | Codext | 4 vCPU / 8GB RAM | +| Finland (Helsinki) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | +| USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | +| Ukraine (Kyiv) | dc.volia (2VM) | 2 vCPU / 4GB RAM | + +## Dev Container + +[![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Container&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/rustdesk/rustdesk) + +If you already have VS Code and Docker installed, you can click the badge above to get started. Clicking will cause VS Code to automatically install the Dev Containers extension if needed, clone the source code into a container volume, and spin up a dev container for use. + +Go through [DEVCONTAINER.md](docs/DEVCONTAINER.md) for more info. + +## Dependencies + +Desktop versions use [sciter](https://sciter.com/) or Flutter for GUI, this tutorial is for Sciter only. + +Please download sciter dynamic library yourself. + +[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) | +[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) | +[MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib) + +## Raw steps to build + +- Prepare your Rust development env and C++ build env + +- Install [vcpkg](https://github.com/microsoft/vcpkg), and set `VCPKG_ROOT` env variable correctly + + - Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static + - Linux/MacOS: vcpkg install libvpx libyuv opus + +- run `cargo run` + +## [Build](https://rustdesk.com/docs/en/dev/build/) + +## How to build on Linux + +### Ubuntu 18 (Debian 10) + +```sh +sudo apt install -y zip g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev \ + libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake make \ + libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev +``` + +### openSUSE Tumbleweed + +```sh +sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel +``` +### Fedora 28 (CentOS 8) + +```sh +sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel +``` + +### Arch (Manjaro) + +```sh +sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pipewire +``` + +### Install vcpkg + +```sh +git clone https://github.com/microsoft/vcpkg +cd vcpkg +git checkout 2021.12.01 +cd .. +vcpkg/bootstrap-vcpkg.sh +export VCPKG_ROOT=$HOME/vcpkg +vcpkg/vcpkg install libvpx libyuv opus +``` + +### Fix libvpx (For Fedora) + +```sh +cd vcpkg/buildtrees/libvpx/src +cd * +./configure +sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile +sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile +make +cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/ +cd +``` + +### Build + +```sh +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +source $HOME/.cargo/env +git clone https://github.com/rustdesk/rustdesk +cd rustdesk +mkdir -p target/debug +wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so +mv libsciter-gtk.so target/debug +VCPKG_ROOT=$HOME/vcpkg cargo run +``` + +### Change Wayland to X11 (Xorg) + +RustDesk does not support Wayland. Check [this](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) to configuring Xorg as the default GNOME session. + +## Wayland support + +Wayland does not seem to provide any API for sending keypresses to other windows. Therefore, the rustdesk uses an API from a lower level, namely the `/dev/uinput` device (Linux kernel level). + +When wayland is the controlled side, you have to start in the following way: +```bash +# Start uinput service +$ sudo rustdesk --service +$ rustdesk +``` +**Notice**: Wayland screen recording uses different interfaces. RustDesk currently only supports org.freedesktop.portal.ScreenCast. +```bash +$ dbus-send --session --print-reply \ + --dest=org.freedesktop.portal.Desktop \ + /org/freedesktop/portal/desktop \ + org.freedesktop.DBus.Properties.Get \ + string:org.freedesktop.portal.ScreenCast string:version +# Not support +Error org.freedesktop.DBus.Error.InvalidArgs: No such interface “org.freedesktop.portal.ScreenCast” +# Support +method return time=1662544486.931020 sender=:1.54 -> destination=:1.139 serial=257 reply_serial=2 + variant uint32 4 +``` + +## How to build with Docker + +Begin by cloning the repository and building the docker container: + +```sh +git clone https://github.com/rustdesk/rustdesk +cd rustdesk +docker build -t "rustdesk-builder" . +``` + +Then, each time you need to build the application, run the following command: + +```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 +``` + +Note that the first build may take longer before dependencies are cached, subsequent builds will be faster. Additionally, if you need to specify different arguments to the build command, you may do so at the end of the command in the `` position. For instance, if you wanted to build an optimized release version, you would run the command above followed by `--release`. The resulting executable will be available in the target folder on your system, and can be run with: + +```sh +target/debug/rustdesk +``` + +Or, if you're running a release executable: + +```sh +target/release/rustdesk +``` + +Please ensure that you are running these commands from the root of the RustDesk repository, otherwise the application might not be able to find the required resources. Also note that other cargo subcommands such as `install` or `run` are not currently supported via this method as they would install or run the program inside the container instead of the host. + +## File Structure + +- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: video codec, config, tcp/udp wrapper, protobuf, fs functions for file transfer, and some other utility functions +- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: screen capture +- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: platform specific keyboard/mouse control +- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: GUI +- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: audio/clipboard/input/video services, and network connections +- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: start a peer connection +- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: Communicate with [rustdesk-server](https://github.com/rustdesk/rustdesk-server), wait for remote direct (TCP hole punching) or relayed connection +- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: platform specific code +- **[flutter](https://github.com/rustdesk/rustdesk/tree/master/flutter)**: Flutter code for mobile +- **[flutter/web/js](https://github.com/rustdesk/rustdesk/tree/master/flutter/web/js)**: JavaScript for Flutter web client + +## Snapshot + +![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png) + +![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png) + +![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png) + +![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png) From a771a5dc50fbb45f61c81ea8244bfab52f5ecf13 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 17:31:47 +0200 Subject: [PATCH 144/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 8af79915b..29860bc45 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -5,7 +5,7 @@ DockerStructureSnapshot
    - [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    + [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [ΕΛΛΗΝΙΚΑ] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    We need your help to translate this README, RustDesk UI and Doc to your native language

    From eeee6a3ce31be2733c08b97d0da45351d3613cbc Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 17:32:06 +0200 Subject: [PATCH 145/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 29860bc45..6a8047300 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -5,7 +5,7 @@ DockerStructureSnapshot
    - [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [ΕΛΛΗΝΙΚΑ] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    + [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Ελληνικά] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    We need your help to translate this README, RustDesk UI and Doc to your native language

    From fec88db5e5d1fa16007d0c4f314a15b57dd59dec Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 17:34:24 +0200 Subject: [PATCH 146/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 6a8047300..eee370dc3 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -5,7 +5,7 @@ DockerStructureSnapshot
    - [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Ελληνικά] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    + [English] | [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    We need your help to translate this README, RustDesk UI and Doc to your native language

    From 01f842592bbe8182f8f8919238beac3b3d9de775 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 17:50:11 +0200 Subject: [PATCH 147/382] Update README-GR.md --- docs/README-GR.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index eee370dc3..9821517fa 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -6,14 +6,14 @@ StructureSnapshot
    [English] | [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    - We need your help to translate this README, RustDesk UI and Doc to your native language + Χρειαζόμαστε τη βοήθειά σας για να μεταφράσουμε αυτό το αρχείο README, το RustDesk UI και το Doc στη μητρική σας γλώσσα

    -Chat with us: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk) +Επικοινωνία μαζί μας μέσω: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk) [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09) -Yet another remote desktop software, written in Rust. Works out of the box, no configuration required. You have full control of your data, with no concerns about security. You can use our rendezvous/relay server, [set up your own](https://rustdesk.com/server), or [write your own rendezvous/relay server](https://github.com/rustdesk/rustdesk-server-demo). +Ένα λογισμικό απομακρυσμένης επιφάνειας εργασίας, γραμμένο σε γλώσσα Rust. Δεν χρειάζεται κάποια παραμετροποίηση, λειτουργεί αμέσως μετά την εγκατάσταση. Έχετε τον πλήρη έλεγχο των δεδομένων σας, χωρίς να ανησυχείτε για την ασφάλεια τους. Μπορείτε να χρησιμοποιήσετε τους προκαθορισμένους διακομιστές rendezvous/αναμετάδοσης, [να εγκαταστήσετε τον δικός σας](https://rustdesk.com/server), ή [να αναπτύξετε ενα δικό σας διακομιστή rendezvous/αναμετάδοσης](https://github.com/rustdesk/rustdesk-server-demo). ![image](https://user-images.githubusercontent.com/71636191/171661982-430285f0-2e12-4b1d-9957-4a58e375304d.png) From 2dad56d3d34c21cb8c80a0b623dd631dcd202173 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 18:03:34 +0200 Subject: [PATCH 148/382] Update README-GR.md --- docs/README-GR.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 9821517fa..24bc139fd 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -17,11 +17,11 @@ ![image](https://user-images.githubusercontent.com/71636191/171661982-430285f0-2e12-4b1d-9957-4a58e375304d.png) -RustDesk welcomes contribution from everyone. See [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) for help getting started. +Το RustDesk ενθαρρύνει τη συνεισφορά όλων. Διαβάστε το [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) για βοήθεια στο πως να ξεκινήσετε. -[**FAQ**](https://github.com/rustdesk/rustdesk/wiki/FAQ) +[**Συχνές ερωτήσεις**](https://github.com/rustdesk/rustdesk/wiki/FAQ) -[**BINARY DOWNLOAD**](https://github.com/rustdesk/rustdesk/releases) +[**Κατεβάστε τα αρχεία**](https://github.com/rustdesk/rustdesk/releases) [**NIGHTLY BUILD**](https://github.com/rustdesk/rustdesk/releases/tag/nightly) @@ -29,17 +29,17 @@ RustDesk welcomes contribution from everyone. See [`docs/CONTRIBUTING.md`](docs/ alt="Get it on F-Droid" height="80">](https://f-droid.org/en/packages/com.carriez.flutter_hbb) -## Free Public Servers +## Δωρεάν δημόσιοι διακομιστές -Below are the servers you are using for free, they may change over time. If you are not close to one of these, your network may be slow. -| Location | Vendor | Specification | +Παρακάτω είναι οι διακομιστές που χρησιμοποιούνται δωρεάν, ενδέχεται να αλλάξουν με την πάροδο του χρόνου. Εάν δεν είστε κοντά σε ένα από αυτούς, το δίκτυό σας ίσως να είναι αργό. +| Περιοχή | Πάροχος | Προδιαγραφές | | --------- | ------------- | ------------------ | -| Seoul | AWS lightsail | 1 vCPU / 0.5GB RAM | -| Germany | Hetzner | 2 vCPU / 4GB RAM | -| Germany | Codext | 4 vCPU / 8GB RAM | -| Finland (Helsinki) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| Ukraine (Kyiv) | dc.volia (2VM) | 2 vCPU / 4GB RAM | +| Σεούλ | AWS lightsail | 1 vCPU / 0.5GB RAM | +| Γερμανία | Hetzner | 2 vCPU / 4GB RAM | +| Γερμανία | Codext | 4 vCPU / 8GB RAM | +| Φινλανδία (Ελσίνκι) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | +| ΗΠΑ (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | +| Ουκρανία (Κίεβο) | dc.volia (2VM) | 2 vCPU / 4GB RAM | ## Dev Container From 269c035e8f53d263bfc3e30c6b3665a2cf6b8544 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 18:05:31 +0200 Subject: [PATCH 149/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 24bc139fd..0c298122a 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -38,7 +38,7 @@ | Γερμανία | Hetzner | 2 vCPU / 4GB RAM | | Γερμανία | Codext | 4 vCPU / 8GB RAM | | Φινλανδία (Ελσίνκι) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| ΗΠΑ (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | +| ΗΠΑ (Άσμπερν) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | | Ουκρανία (Κίεβο) | dc.volia (2VM) | 2 vCPU / 4GB RAM | ## Dev Container From c76de5fe201cc38ef16e96a2fdfb15d28baa952f Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 18:17:54 +0200 Subject: [PATCH 150/382] Update README-GR.md --- docs/README-GR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 0c298122a..656c8aabb 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -45,9 +45,9 @@ [![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Container&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/rustdesk/rustdesk) -If you already have VS Code and Docker installed, you can click the badge above to get started. Clicking will cause VS Code to automatically install the Dev Containers extension if needed, clone the source code into a container volume, and spin up a dev container for use. +Αν έχετε εγκατεστημένα το VS Code και το Docker, μπορείτε να ξεκινήσετε κάνοντας κλικ στην παραπάνω εικόνα. Αυτό θα έχει ως αποτέλεσμα, το VS Code να εγκαταστήσει αυτόματα την επέκταση Dev Containers, εάν χρειάζεται, θα κλωνοποιήσει τον πηγαίο κώδικα σε έναν νέο container και θα εκκινήσει ένα Dev Container για χρήση προγραμματισμού. -Go through [DEVCONTAINER.md](docs/DEVCONTAINER.md) for more info. +Για περισσότερες πληροφορίες μεταβείτε στο [DEVCONTAINER.md](docs/DEVCONTAINER.md). ## Dependencies From b8d72b3839bcefb54c7e6ad490c35e7833b1a78c Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 18:34:38 +0200 Subject: [PATCH 151/382] Update README-GR.md --- docs/README-GR.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 656c8aabb..6605f9054 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -49,17 +49,17 @@ Για περισσότερες πληροφορίες μεταβείτε στο [DEVCONTAINER.md](docs/DEVCONTAINER.md). -## Dependencies +## Προ απαιτούμενα για build -Desktop versions use [sciter](https://sciter.com/) or Flutter for GUI, this tutorial is for Sciter only. +Για τις παραθυρικές εκδόσεις χρησιμοποιείται είτε το [sciter](https://sciter.com/) είτε το Flutter, τα παρακάτω βήματα είναι μόνο για το Sciter. -Please download sciter dynamic library yourself. +Παρακαλώ κατεβάστε μόνοι σας την δυναμική βιβλιοθήκη sciter. [Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) | [Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) | [MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib) -## Raw steps to build +## Λιτά βήματα ώστε να κάνετε build - Prepare your Rust development env and C++ build env @@ -72,7 +72,7 @@ Please download sciter dynamic library yourself. ## [Build](https://rustdesk.com/docs/en/dev/build/) -## How to build on Linux +## Πως να το κάνετε build στο Linux ### Ubuntu 18 (Debian 10) From 60ce92705cea8f05cf52b287c9271dbafc4b8739 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 18:36:07 +0200 Subject: [PATCH 152/382] Update README.md added Greek file README-GR.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8af79915b..3e0fb463f 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ DockerStructureSnapshot
    - [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    + [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk] | [Ελληνικά]
    We need your help to translate this README, RustDesk UI and Doc to your native language

    From bdbfa120a88d428ced418a14db91b3383b2576aa Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 18:43:59 +0200 Subject: [PATCH 153/382] Update README-GR.md --- docs/README-GR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 6605f9054..02c46cd43 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -61,9 +61,9 @@ ## Λιτά βήματα ώστε να κάνετε build -- Prepare your Rust development env and C++ build env +- Προετοιμάστε τα παρακάτω περιβάλλοντα προγραμματισμού Rust και C++ -- Install [vcpkg](https://github.com/microsoft/vcpkg), and set `VCPKG_ROOT` env variable correctly +- Εγκαταστήσετε το [vcpkg](https://github.com/microsoft/vcpkg), και ρυθμίστε σωστά την παράμετρο συστήματος `VCPKG_ROOT` - Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static - Linux/MacOS: vcpkg install libvpx libyuv opus From 3e75a554c5c056c20cd91bf070079f08563d944c Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 18:45:19 +0200 Subject: [PATCH 154/382] Update README-GR.md --- docs/README-GR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 02c46cd43..1534c4260 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -68,7 +68,7 @@ - Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static - Linux/MacOS: vcpkg install libvpx libyuv opus -- run `cargo run` +- Εκτέλεση `cargo run` ## [Build](https://rustdesk.com/docs/en/dev/build/) @@ -99,7 +99,7 @@ sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb- sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pipewire ``` -### Install vcpkg +### Εγκατάσταση vcpkg ```sh git clone https://github.com/microsoft/vcpkg From 063fcd884e4e246e2c6b6dca5c76367ff5069bf7 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 18:48:13 +0200 Subject: [PATCH 155/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 1534c4260..667e6a1de 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -68,7 +68,7 @@ - Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static - Linux/MacOS: vcpkg install libvpx libyuv opus -- Εκτέλεση `cargo run` +- Εκτελέστε `cargo run` ## [Build](https://rustdesk.com/docs/en/dev/build/) From 134b082fd2dbe7b8bc8b956800104bb774ba03db Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 18:49:07 +0200 Subject: [PATCH 156/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 667e6a1de..4cdcbaea3 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -61,7 +61,7 @@ ## Λιτά βήματα ώστε να κάνετε build -- Προετοιμάστε τα παρακάτω περιβάλλοντα προγραμματισμού Rust και C++ +- Προετοιμάστε τα περιβάλλοντα προγραμματισμού Rust και C++ - Εγκαταστήσετε το [vcpkg](https://github.com/microsoft/vcpkg), και ρυθμίστε σωστά την παράμετρο συστήματος `VCPKG_ROOT` From cca4c4fa924cbc876f1fac3e826fbab047d838e4 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 18:50:30 +0200 Subject: [PATCH 157/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 4cdcbaea3..7f52f4947 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -111,7 +111,7 @@ export VCPKG_ROOT=$HOME/vcpkg vcpkg/vcpkg install libvpx libyuv opus ``` -### Fix libvpx (For Fedora) +### Διόρθωση libvpx (για Fedora) ```sh cd vcpkg/buildtrees/libvpx/src From 86c8e20980c4f407b32b52de0751ca103d1f4a40 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 18:53:41 +0200 Subject: [PATCH 158/382] Update README-GR.md --- docs/README-GR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 7f52f4947..6e6f3cb0b 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -137,9 +137,9 @@ mv libsciter-gtk.so target/debug VCPKG_ROOT=$HOME/vcpkg cargo run ``` -### Change Wayland to X11 (Xorg) +### Αλλαγή του Wayland σε X11 (Xorg) -RustDesk does not support Wayland. Check [this](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) to configuring Xorg as the default GNOME session. +Το RustDesk δεν υποστιρίζει το Wayland. Διβάστε [εδώ](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) ώστε να ορίσετε Xorg ως το προκαθορισμένο GNOME περιβάλλον. ## Wayland support From 47ca68967851e52b5ae3bc834452ff1778a57425 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sun, 5 Mar 2023 23:35:30 +0800 Subject: [PATCH 159/382] fix: specify the app-id and desktop file name opt: add application and polkit opt: add polkit --- .github/workflows/flutter-nightly.yml | 2 +- flatpak/rustdesk.json | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/workflows/flutter-nightly.yml b/.github/workflows/flutter-nightly.yml index ffcadd18b..4ae281583 100644 --- a/.github/workflows/flutter-nightly.yml +++ b/.github/workflows/flutter-nightly.yml @@ -1511,7 +1511,7 @@ jobs: pushd flatpak git clone https://github.com/flathub/shared-modules.git --depth=1 flatpak-builder --user --force-clean --repo=repo ./build ./rustdesk.json - flatpak build-bundle ./repo rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}.flatpak org.rustdesk.rustdesk + flatpak build-bundle ./repo rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}.flatpak com.rustdesk.RustDesk - name: Publish flatpak package uses: softprops/action-gh-release@v1 diff --git a/flatpak/rustdesk.json b/flatpak/rustdesk.json index 3ded34b20..3cfca4d30 100644 --- a/flatpak/rustdesk.json +++ b/flatpak/rustdesk.json @@ -1,9 +1,10 @@ { - "app-id": "org.rustdesk.rustdesk", + "id": "com.rustdesk.RustDesk", "runtime": "org.freedesktop.Platform", "runtime-version": "21.08", "sdk": "org.freedesktop.Sdk", "command": "rustdesk", + "icon": "share/rustdesk/files/rustdesk.png", "modules": [ "shared-modules/libappindicator/libappindicator-gtk3-12.10.json", "xdotool.json", @@ -15,15 +16,20 @@ "tar -xvf ./data.tar.xz", "cp -r ./usr/* /app/", "mkdir -p /app/bin && ln -s /app/lib/rustdesk/rustdesk /app/bin/rustdesk", - "sed -i '/^Icon=/ c\\Icon=/app/share/rustdesk/files/rustdesk.png' /app/share/applications/rustdesk.desktop", - "sed -i '/^Icon=/ c\\Icon=/app/share/rustdesk/files/rustdesk.png' /app/share/applications/rustdesk-link.desktop", - "sed -i '/^Exec=/ c\\Exec=/app/bin/rustdesk %u' /app/share/applications/rustdesk.desktop", - "sed -i '/^Exec=/ c\\Exec=/app/bin/rustdesk --connect \"%u\"' /app/share/applications/rustdesk-link.desktop" + "mv /app/share/applications/rustdesk.desktop /app/share/applications/com.rustdesk.RustDesk.desktop", + "sed -i '/^Icon=/ c\\Icon=com.rustdesk.RustDesk' /app/share/applications/com.rustdesk.RustDesk.desktop", + "sed -i '/^Icon=/ c\\Icon=com.rustdesk.RustDesk' /app/share/applications/rustdesk-link.desktop", + "for size in 16 24 32 48 64 128 256 512; do\n rsvg-convert -w $size -h $size -f png -o $size.png logo.svg\n install -Dm644 $size.png /app/share/icons/hicolor/${size}x${size}/apps/com.rustdesk.RustDesk.png\n done" ], + "cleanup": ["/include", "/lib/pkgconfig", "/share/gtk-doc"], "sources": [ { "type": "file", "path": "../rustdesk-1.2.0.deb" + }, + { + "type": "file", + "path": "../res/logo.svg" } ] } @@ -39,4 +45,4 @@ "--socket=pulseaudio", "--talk-name=org.freedesktop.Flatpak" ] -} \ No newline at end of file +} From 5cf5e586d551f837f4906211c15f9a7d8f815953 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 19:00:49 +0200 Subject: [PATCH 160/382] Update README-GR.md --- docs/README-GR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 6e6f3cb0b..b30d5047a 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -139,9 +139,9 @@ VCPKG_ROOT=$HOME/vcpkg cargo run ### Αλλαγή του Wayland σε X11 (Xorg) -Το RustDesk δεν υποστιρίζει το Wayland. Διβάστε [εδώ](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) ώστε να ορίσετε Xorg ως το προκαθορισμένο GNOME περιβάλλον. +Το RustDesk δεν υποστιρίζει το πρωτόκολλο Wayland. Διαβάστε [εδώ](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) ώστε να ορίσετε το Xorg ως το προκαθορισμένο GNOME περιβάλλον. -## Wayland support +## Υποστήριξη Wayland Wayland does not seem to provide any API for sending keypresses to other windows. Therefore, the rustdesk uses an API from a lower level, namely the `/dev/uinput` device (Linux kernel level). From f43c7998833d4aac4c09a45e320a4a660081713b Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 19:08:32 +0200 Subject: [PATCH 161/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index b30d5047a..77a11f700 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -143,7 +143,7 @@ VCPKG_ROOT=$HOME/vcpkg cargo run ## Υποστήριξη Wayland -Wayland does not seem to provide any API for sending keypresses to other windows. Therefore, the rustdesk uses an API from a lower level, namely the `/dev/uinput` device (Linux kernel level). +Το Wayland προς το παρόν δεν διαθέτει κάποιο API το οποίο να στέλνει τα πατήματα πλήκτρων στα υπόλοιπα παράθυρα. Για τον λόγο αυτό, το Rustdesk χρησιμοποιεί ένα API από κατώτερο επίπεδο, όπως το `/dev/uinput` συσκευή (Linux kernel level). When wayland is the controlled side, you have to start in the following way: ```bash From 5f3c9f5f6e54071d2bb3c5ed8ede06b9c7cba234 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 19:09:28 +0200 Subject: [PATCH 162/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 77a11f700..346271487 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -143,7 +143,7 @@ VCPKG_ROOT=$HOME/vcpkg cargo run ## Υποστήριξη Wayland -Το Wayland προς το παρόν δεν διαθέτει κάποιο API το οποίο να στέλνει τα πατήματα πλήκτρων στα υπόλοιπα παράθυρα. Για τον λόγο αυτό, το Rustdesk χρησιμοποιεί ένα API από κατώτερο επίπεδο, όπως το `/dev/uinput` συσκευή (Linux kernel level). +Το Wayland προς το παρόν δεν διαθέτει κάποιο API το οποίο να στέλνει τα πατήματα πλήκτρων στα υπόλοιπα παράθυρα. Για τον λόγο αυτό, το Rustdesk χρησιμοποιεί ένα API από κατώτερο επίπεδο, όπως το `/dev/uinput` (Linux kernel level). When wayland is the controlled side, you have to start in the following way: ```bash From 24f40d1f48d4728410b599bd365bebdc5c56d39b Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 19:12:09 +0200 Subject: [PATCH 163/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 346271487..841c6ef44 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -145,7 +145,7 @@ VCPKG_ROOT=$HOME/vcpkg cargo run Το Wayland προς το παρόν δεν διαθέτει κάποιο API το οποίο να στέλνει τα πατήματα πλήκτρων στα υπόλοιπα παράθυρα. Για τον λόγο αυτό, το Rustdesk χρησιμοποιεί ένα API από κατώτερο επίπεδο, όπως το `/dev/uinput` (Linux kernel level). -When wayland is the controlled side, you have to start in the following way: +Σε περίπτωση που το Wayland είναι η ελεγχόμενη πλευρά, θα πρέπει να ξεκινήσετε με τον παρακάτω τρόπο: ```bash # Start uinput service $ sudo rustdesk --service From 4ffe551c4fd3307c7bd7cd047c00c0b8fe3f7e33 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 19:13:47 +0200 Subject: [PATCH 164/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 841c6ef44..33328f7e1 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -151,7 +151,7 @@ VCPKG_ROOT=$HOME/vcpkg cargo run $ sudo rustdesk --service $ rustdesk ``` -**Notice**: Wayland screen recording uses different interfaces. RustDesk currently only supports org.freedesktop.portal.ScreenCast. +**Σημείωση**: Η εγγραφή οθόνης του Wayland χρησιμοποιεί διαφορετικές διεπαφές. Το RustDesk προς το παρόν υποστηρίζει μόνο org.freedesktop.portal.ScreenCast. ```bash $ dbus-send --session --print-reply \ --dest=org.freedesktop.portal.Desktop \ From 60b3dc63f293641f108ffd578ce622e0b687c954 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 19:17:36 +0200 Subject: [PATCH 165/382] Update README-GR.md --- docs/README-GR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 33328f7e1..fec17f7af 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -165,9 +165,9 @@ method return time=1662544486.931020 sender=:1.54 -> destination=:1.139 serial=2 variant uint32 4 ``` -## How to build with Docker +## Πως να το κάνετε build στο Docker -Begin by cloning the repository and building the docker container: +Ξεκινήστε κλωνοποιόντας το αποθετήριο και κάνοντας build το docker container: ```sh git clone https://github.com/rustdesk/rustdesk From 9e8736eb1e0613b5b68a5e74406767e2a4eba00a Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 19:18:35 +0200 Subject: [PATCH 166/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index fec17f7af..e8b18c224 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -13,7 +13,7 @@ [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09) -Ένα λογισμικό απομακρυσμένης επιφάνειας εργασίας, γραμμένο σε γλώσσα Rust. Δεν χρειάζεται κάποια παραμετροποίηση, λειτουργεί αμέσως μετά την εγκατάσταση. Έχετε τον πλήρη έλεγχο των δεδομένων σας, χωρίς να ανησυχείτε για την ασφάλεια τους. Μπορείτε να χρησιμοποιήσετε τους προκαθορισμένους διακομιστές rendezvous/αναμετάδοσης, [να εγκαταστήσετε τον δικός σας](https://rustdesk.com/server), ή [να αναπτύξετε ενα δικό σας διακομιστή rendezvous/αναμετάδοσης](https://github.com/rustdesk/rustdesk-server-demo). +Ένα λογισμικό απομακρυσμένης επιφάνειας εργασίας, γραμμένο σε γλώσσα Rust. Δεν χρειάζεται κάποια παραμετροποίηση, λειτουργεί αμέσως μετά την εγκατάσταση. Έχετε τον πλήρη έλεγχο των δεδομένων σας, χωρίς να ανησυχείτε για την ασφάλειά τους. Μπορείτε να χρησιμοποιήσετε τους προκαθορισμένους διακομιστές rendezvous/αναμετάδοσης, [να εγκαταστήσετε τον δικό σας](https://rustdesk.com/server), ή [να αναπτύξετε ενα δικό σας διακομιστή rendezvous/αναμετάδοσης](https://github.com/rustdesk/rustdesk-server-demo). ![image](https://user-images.githubusercontent.com/71636191/171661982-430285f0-2e12-4b1d-9957-4a58e375304d.png) From 0fea3929920a71906b50fd01fcbe71b5798b6f3a Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 19:18:58 +0200 Subject: [PATCH 167/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index e8b18c224..20a880ca1 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -49,7 +49,7 @@ Για περισσότερες πληροφορίες μεταβείτε στο [DEVCONTAINER.md](docs/DEVCONTAINER.md). -## Προ απαιτούμενα για build +## Προαπαιτούμενα για build Για τις παραθυρικές εκδόσεις χρησιμοποιείται είτε το [sciter](https://sciter.com/) είτε το Flutter, τα παρακάτω βήματα είναι μόνο για το Sciter. From a56a6f6c9a4cd35796e991dad556c7823f3351ca Mon Sep 17 00:00:00 2001 From: asur4s Date: Sun, 5 Mar 2023 09:59:14 -0800 Subject: [PATCH 168/382] Add label for issue templates --- .github/ISSUE_TEMPLATE/bug_report.yaml | 1 + .github/ISSUE_TEMPLATE/feature_request.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index fea1a3672..f83a72de9 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -1,5 +1,6 @@ name: 🐞 Bug report description: Thanks for taking the time to fill out this bug report! Please fill the form in **English** +labels: ["bug"] body: - type: textarea id: desc diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml index 29b0d0e0f..ae2d0aa4c 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -1,5 +1,6 @@ name: 🛠️ Feature request description: Suggest an idea for RustDesk +labels: ["enhancement"] body: - type: textarea id: desc From 4e7b035e66f68bea22077ceb64ed2588a3535a73 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 20:56:53 +0200 Subject: [PATCH 169/382] Update README-GR.md --- docs/README-GR.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 20a880ca1..b1ca7b712 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -51,7 +51,7 @@ ## Προαπαιτούμενα για build -Για τις παραθυρικές εκδόσεις χρησιμοποιείται είτε το [sciter](https://sciter.com/) είτε το Flutter, τα παρακάτω βήματα είναι μόνο για το Sciter. +Στις παραθυρικές εκδόσεις χρησιμοποιείται είτε το [sciter](https://sciter.com/) είτε το Flutter, τα παρακάτω βήματα είναι μόνο για το Sciter. Παρακαλώ κατεβάστε μόνοι σας την δυναμική βιβλιοθήκη sciter. @@ -59,7 +59,7 @@ [Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) | [MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib) -## Λιτά βήματα ώστε να κάνετε build +## Γενικά βήματα ώστε να κάνετε build - Προετοιμάστε τα περιβάλλοντα προγραμματισμού Rust και C++ @@ -167,7 +167,7 @@ method return time=1662544486.931020 sender=:1.54 -> destination=:1.139 serial=2 ## Πως να το κάνετε build στο Docker -Ξεκινήστε κλωνοποιόντας το αποθετήριο και κάνοντας build το docker container: +Ξεκινήστε κλωνοποιώντας το αποθετήριο και κάνοντας build το docker container: ```sh git clone https://github.com/rustdesk/rustdesk From 88bf06fe0a582f394d9524e2cf7ec4b81fd75c1b Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 21:00:44 +0200 Subject: [PATCH 170/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index b1ca7b712..ffa95dc9a 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -1,6 +1,6 @@

    RustDesk - Your remote desktop
    - Servers • + ServersBuildDockerStructure • From e7031d28af3c6130876572170f723b8febbef28e Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 21:01:15 +0200 Subject: [PATCH 171/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index ffa95dc9a..62fae34fe 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -1,6 +1,6 @@

    RustDesk - Your remote desktop
    - Servers • + ServersBuildDockerStructure • From 0950beeca28396d585ee354f9a64216d53317087 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 21:03:06 +0200 Subject: [PATCH 172/382] Update README-GR.md --- docs/README-GR.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 62fae34fe..0a63e5f8f 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -1,8 +1,8 @@

    RustDesk - Your remote desktop
    Servers • - Build • - Docker • + Build • + DockerStructureSnapshot
    [English] | [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    @@ -165,7 +165,7 @@ method return time=1662544486.931020 sender=:1.54 -> destination=:1.139 serial=2 variant uint32 4 ``` -## Πως να το κάνετε build στο Docker +## Πως να κάνετε build στο Docker Ξεκινήστε κλωνοποιώντας το αποθετήριο και κάνοντας build το docker container: From efc4d172055894178d12cfc5c2b47b610d3017bd Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 21:05:29 +0200 Subject: [PATCH 173/382] Update README-GR.md --- docs/README-GR.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 0a63e5f8f..e0d6c64e8 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -1,10 +1,10 @@

    RustDesk - Your remote desktop
    - Servers • + ΔιακομιστέςBuildDocker • - Structure • - Snapshot
    + Δομή • + Snapshot
    [English] | [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    Χρειαζόμαστε τη βοήθειά σας για να μεταφράσουμε αυτό το αρχείο README, το RustDesk UI και το Doc στη μητρική σας γλώσσα

    @@ -195,7 +195,7 @@ target/release/rustdesk Please ensure that you are running these commands from the root of the RustDesk repository, otherwise the application might not be able to find the required resources. Also note that other cargo subcommands such as `install` or `run` are not currently supported via this method as they would install or run the program inside the container instead of the host. -## File Structure +## Δομή φακέλων - **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: video codec, config, tcp/udp wrapper, protobuf, fs functions for file transfer, and some other utility functions - **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: screen capture @@ -208,7 +208,7 @@ Please ensure that you are running these commands from the root of the RustDesk - **[flutter](https://github.com/rustdesk/rustdesk/tree/master/flutter)**: Flutter code for mobile - **[flutter/web/js](https://github.com/rustdesk/rustdesk/tree/master/flutter/web/js)**: JavaScript for Flutter web client -## Snapshot +## Στιγμιότυπα ![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png) From f168b4685223f87728e9b6d78424e7010f9ec640 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:21:42 +0200 Subject: [PATCH 174/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index e0d6c64e8..a16a644ab 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -175,7 +175,7 @@ cd rustdesk docker build -t "rustdesk-builder" . ``` -Then, each time you need to build the application, run the following command: +Στη συνέχεια, κάθε φορά που επιθυμείτε να κάνετε build την εφαρμογή, εκτελέστε την ακόλουθη εντολή: ```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 b08130a4ba3262ec5968875fb17808f82561894c Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:38:32 +0200 Subject: [PATCH 175/382] Update README-GR.md --- docs/README-GR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index a16a644ab..284e12356 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -181,13 +181,13 @@ docker build -t "rustdesk-builder" . 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 ``` -Note that the first build may take longer before dependencies are cached, subsequent builds will be faster. Additionally, if you need to specify different arguments to the build command, you may do so at the end of the command in the `` position. For instance, if you wanted to build an optimized release version, you would run the command above followed by `--release`. The resulting executable will be available in the target folder on your system, and can be run with: +Σημειώστε ότι το πρώτο build μπορεί να διαρκέσει περισσότερο, ώστε να αποθηκευτούν στην προσωρινή μνήμη οι εξαρτήσεις, τα επόμενα build θα είναι ταχύτερα. Επιπλέον, εάν πρέπει να καθορίσετε διαφορετικές παραμέτρους στην εντολή build, μπορείτε να το κάνετε στο τέλος της εντολής με την χρήση ``. Για παράδειγμα, εάν επιθυμείτε να δημιουργήσετε μια βελτιστοποιημένη έκδοση της εφαρμογής, θα εκτελέσετε την παραπάνω εντολή ακολουθούμενη από το `--release`. Το εκτελέσιμο αρχείο θα είναι διαθέσιμο στον προκαθορισμένο φάκελο στο σύστημά σας και μπορεί να εκτελεστεί με: ```sh target/debug/rustdesk ``` -Or, if you're running a release executable: +Ή στην περίπτωση μιας βελτιστοποιημένης έκδοσης της εφαρμογής εκτελέστε: ```sh target/release/rustdesk From b51463aeb90ce2d5f4651a63e80641219fec8d3e Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:46:09 +0200 Subject: [PATCH 176/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 284e12356..92c2d04e5 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -193,7 +193,7 @@ target/debug/rustdesk target/release/rustdesk ``` -Please ensure that you are running these commands from the root of the RustDesk repository, otherwise the application might not be able to find the required resources. Also note that other cargo subcommands such as `install` or `run` are not currently supported via this method as they would install or run the program inside the container instead of the host. +Βεβαιωθείτε ότι εκτελείτε αυτές τις εντολές από την αρχική διαδρομή του αποθετηρίου του Rustdesk, διαφορετικά η εφαρμογή ενδέχεται να μην είναι σε θέση να βρει τους απαιτούμενους πόρους. Σημειώστε επίσης ότι άλλες υποεντολές, όπως το `install` ή το `run` δεν υποστηρίζονται επί του παρόντος μέσω αυτής της μεθόδου καθώς θα εγκαταστήσουν ή θα εκτελέσουν το πρόγραμμα εντός του container αντί του κεντρικού υπολογιστή. ## Δομή φακέλων From 865d3a99c774b4c9a0693ce655570c1cd3723ff6 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:54:12 +0200 Subject: [PATCH 177/382] Update README-AR.md added link for Greek language --- docs/README-AR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-AR.md b/docs/README-AR.md index ad7303806..10b5f0cf5 100644 --- a/docs/README-AR.md +++ b/docs/README-AR.md @@ -5,7 +5,7 @@ DockerStructureSnapshot
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [Tiếng Việt] | [Ελληνικά]
    لغتك الأم, Doc و RustDesk UI, README نحن بحاجة إلى مساعدتك لترجمة هذا

    From 10856150a1913da12792ba87177d0a3d53c64660 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:54:43 +0200 Subject: [PATCH 178/382] Update README-CS.md added link for Greek language --- docs/README-CS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-CS.md b/docs/README-CS.md index d56464eff..592b28eb2 100644 --- a/docs/README-CS.md +++ b/docs/README-CS.md @@ -5,7 +5,7 @@ DockerStrukturaUkázky
    - [English] | [Українська] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Potřebujeme Vaši pomoc s překláním textů tohoto ČTIMNE, uživatelského rozhraní aplikace RustDesk a dokumentace k ní do vašeho jazyka

    From 17365ac1312e7897141f7dec68573ebb7624329c Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:56:09 +0200 Subject: [PATCH 179/382] Update README-AR.md --- docs/README-AR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-AR.md b/docs/README-AR.md index 10b5f0cf5..4f5769839 100644 --- a/docs/README-AR.md +++ b/docs/README-AR.md @@ -5,7 +5,7 @@ DockerStructureSnapshot
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [Tiếng Việt] | [Ελληνικά]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [Tiếng Việt] | [Ελληνικά]
    لغتك الأم, Doc و RustDesk UI, README نحن بحاجة إلى مساعدتك لترجمة هذا

    From ecec63a6995f40d93630a70f4cf3e2a4d241190f Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:56:40 +0200 Subject: [PATCH 180/382] Update README-CS.md added link for Greek language --- docs/README-CS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-CS.md b/docs/README-CS.md index 592b28eb2..74c6fcb19 100644 --- a/docs/README-CS.md +++ b/docs/README-CS.md @@ -5,7 +5,7 @@ DockerStrukturaUkázky
    - [English] | [Українська] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    + [English] | [Українська] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Potřebujeme Vaši pomoc s překláním textů tohoto ČTIMNE, uživatelského rozhraní aplikace RustDesk a dokumentace k ní do vašeho jazyka

    From 743da0c0154e228dec8a5892b18997e9f5ad2d49 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:57:03 +0200 Subject: [PATCH 181/382] Update README-DA.md added link for Greek language --- docs/README-DA.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-DA.md b/docs/README-DA.md index dde5c7a0d..d7283d8ab 100644 --- a/docs/README-DA.md +++ b/docs/README-DA.md @@ -5,7 +5,7 @@ DockerFilstrukturSkærmbilleder
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Vi har brug for din hjælp til at oversætte denne README, RustDesk UI og Dokument til dit modersmål

    From 0477a7f218b9b8a19776c76f4c7ed364dba1dd7b Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:57:29 +0200 Subject: [PATCH 182/382] Update README-DE.md added link for Greek language --- docs/README-DE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-DE.md b/docs/README-DE.md index dd2aa8609..ff3ec1d7f 100644 --- a/docs/README-DE.md +++ b/docs/README-DE.md @@ -5,7 +5,7 @@ DockerDateistrukturScreenshots
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk] | [Ελληνικά]
    Wir brauchen deine Hilfe, um dieses README, die RustDesk-Benutzeroberfläche und die Dokumentation in deine Muttersprache zu übersetzen.

    From 7c826a735f82aaf382c5ae755c44d9888d661b8c Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:58:50 +0200 Subject: [PATCH 183/382] Update README-EO.md added link for Greek language --- docs/README-EO.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-EO.md b/docs/README-EO.md index 7471636eb..fdde88f11 100644 --- a/docs/README-EO.md +++ b/docs/README-EO.md @@ -5,7 +5,7 @@ DockerStrukturoEkrankopio
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Ni bezonas helpon traduki tiun README kaj la interfacon al via denaska lingvo

    From 3440e87303601f250209e9d074d750adeafa450c Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:59:11 +0200 Subject: [PATCH 184/382] Update README-ES.md added link for Greek language --- docs/README-ES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-ES.md b/docs/README-ES.md index 16f65adcc..b7b828f13 100644 --- a/docs/README-ES.md +++ b/docs/README-ES.md @@ -5,7 +5,7 @@ DockerEstructuraCapturas de pantalla
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Necesitamos tu ayuda para traducir este README a tu idioma

    From 3bc484dbcf4d4c45604c6580ee4596f0c09d6b98 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:59:32 +0200 Subject: [PATCH 185/382] Update README-FA.md added link for Greek language --- docs/README-FA.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-FA.md b/docs/README-FA.md index 496e81849..177e3c122 100644 --- a/docs/README-FA.md +++ b/docs/README-FA.md @@ -6,7 +6,7 @@ ساختسرور

    -

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

    +

    [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) From 9045b194af7b7f8c63c286cf46375008d779e3d5 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:59:55 +0200 Subject: [PATCH 186/382] Update README-FI.md added link for Greek language --- docs/README-FI.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-FI.md b/docs/README-FI.md index f7a087087..d110e195a 100644 --- a/docs/README-FI.md +++ b/docs/README-FI.md @@ -5,7 +5,7 @@ DockerRakenneTilannevedos
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Tarvitsemme apua tämän README-tiedoston kääntämiseksi äidinkielellesi

    From c4bea94e46508683fdc6cc86d2c038085a7eef85 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:00:19 +0200 Subject: [PATCH 187/382] Update README-FR.md added link for Greek language --- docs/README-FR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-FR.md b/docs/README-FR.md index fdb253bd0..c11edc211 100644 --- a/docs/README-FR.md +++ b/docs/README-FR.md @@ -5,7 +5,7 @@ Docker - Structure - Images
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Nous avons besoin de votre aide pour traduire ce README dans votre langue maternelle.

    From abf109a1184810ec3cf8e6ec85c318608bb7f0b7 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:00:39 +0200 Subject: [PATCH 188/382] Update README-HU.md added link for Greek language --- docs/README-HU.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-HU.md b/docs/README-HU.md index 6c22a3b7c..62ba33482 100644 --- a/docs/README-HU.md +++ b/docs/README-HU.md @@ -5,7 +5,7 @@ DockerStruktúraKépernyőképek
    - [English] | [Українська] | [česky] | [中文] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Kell a segítséged, hogy lefordítsuk ezt a README-t, a RustDesk UI-t és a Dokumentációt az anyanyelvedre

    From 782c78502669a2a2231cc4eeb7275f2d34ef2f79 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:01:04 +0200 Subject: [PATCH 189/382] Update README-ID.md added link for Greek language --- docs/README-ID.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-ID.md b/docs/README-ID.md index 9616cd31d..2fdcd3646 100644 --- a/docs/README-ID.md +++ b/docs/README-ID.md @@ -5,7 +5,7 @@ DockerStructureSnapshot
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Kami membutuhkan bantuan Anda untuk menerjemahkan README ini dan RustDesk UI ke bahasa asli anda

    From 233df733daf471286f88ce37a069c263f7b49e47 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:01:32 +0200 Subject: [PATCH 190/382] Update README-IT.md added link for Greek language --- docs/README-IT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-IT.md b/docs/README-IT.md index f074510c9..0b628f90d 100644 --- a/docs/README-IT.md +++ b/docs/README-IT.md @@ -5,7 +5,7 @@ DockerStrutturaScreenshots
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Abbiamo bisogno del tuo aiuto per tradurre questo README e la RustDesk UI nella tua lingua nativa

    From fd581be5899e06d3d58c56971e9942a27c3d6543 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:01:54 +0200 Subject: [PATCH 191/382] Update README-JP.md added link for Greek language --- docs/README-JP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-JP.md b/docs/README-JP.md index 36c74dfed..fafc5ef8c 100644 --- a/docs/README-JP.md +++ b/docs/README-JP.md @@ -5,7 +5,7 @@ DockerStructureSnapshot
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    このREADMEをあなたの母国語に翻訳するために、あなたの助けが必要です。

    From 55164bdf5b0eb1e280029f841012fa2d7c81f2dd Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:02:23 +0200 Subject: [PATCH 192/382] Update README-KR.md added link for Greek language --- docs/README-KR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-KR.md b/docs/README-KR.md index 8cefbbcee..6f9ba2221 100644 --- a/docs/README-KR.md +++ b/docs/README-KR.md @@ -5,7 +5,7 @@ DockerStructureSnapshot
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    README를 모국어로 번역하기 위한 당신의 도움의 필요합니다.

    From 8ad20fdd9aa2a642c7fb376563e1f3810a7d54a2 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:02:44 +0200 Subject: [PATCH 193/382] Update README-ML.md added link for Greek language --- docs/README-ML.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-ML.md b/docs/README-ML.md index 288a78db8..5b4c3782a 100644 --- a/docs/README-ML.md +++ b/docs/README-ML.md @@ -5,7 +5,7 @@ DockerStructureSnapshot
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    ഈ README നിങ്ങളുടെ മാതൃഭാഷയിലേക്ക് വിവർത്തനം ചെയ്യാൻ ഞങ്ങൾക്ക് നിങ്ങളുടെ സഹായം ആവശ്യമാണ്

    From a5092451c7e2d79a346a8e7cd854c3bc1014535b Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:03:05 +0200 Subject: [PATCH 194/382] Update README-NL.md added link for Greek language --- docs/README-NL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-NL.md b/docs/README-NL.md index 1aca2b893..422890827 100644 --- a/docs/README-NL.md +++ b/docs/README-NL.md @@ -5,7 +5,7 @@ DockerStructuurSnapshot
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    We hebben je hulp nodig om deze README te vertalen naar jouw moedertaal

    From 613624471fa04848cc5d9d786d29fae4ffe97db2 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:03:30 +0200 Subject: [PATCH 195/382] Update README-PL.md added link for Greek language --- docs/README-PL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-PL.md b/docs/README-PL.md index 85c5f4a61..05e6d8da5 100644 --- a/docs/README-PL.md +++ b/docs/README-PL.md @@ -5,7 +5,7 @@ DockerStrukturaSnapshot
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Potrzebujemy twojej pomocy w tłumaczeniu README na twój ojczysty język

    From fc0514fd5d894270b2de10b2a7b7d0400d4a00a1 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:04:01 +0200 Subject: [PATCH 196/382] Update README-PTBR.md added link for Greek language --- docs/README-PTBR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-PTBR.md b/docs/README-PTBR.md index f9d5e0fc3..491d53154 100644 --- a/docs/README-PTBR.md +++ b/docs/README-PTBR.md @@ -5,7 +5,7 @@ DockerEstruturaScreenshots
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Precisamos de sua ajuda para traduzir este README e a UI do RustDesk para sua língua nativa

    From 5bec6f1e2e0e5d7672b41a1542659e2ae18ae911 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:04:23 +0200 Subject: [PATCH 197/382] Update README-RU.md added link for Greek language --- docs/README-RU.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-RU.md b/docs/README-RU.md index 242341a6b..b050d40ac 100644 --- a/docs/README-RU.md +++ b/docs/README-RU.md @@ -5,7 +5,7 @@ DockerStructureSnapshot
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Нам нужна ваша помощь для перевода этого README и RustDesk UI на ваш родной язык

    From e9b740c9be64382e2ca31f6ef56e776b23ca6d91 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:04:47 +0200 Subject: [PATCH 198/382] Update README-UA.md added link for Greek language --- docs/README-UA.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-UA.md b/docs/README-UA.md index 3615b9064..5d4a0a1ad 100644 --- a/docs/README-UA.md +++ b/docs/README-UA.md @@ -5,7 +5,7 @@ DockerStructureSnapshot
    - [English] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Нам потрібна ваша допомога для перекладу цього README і RustDesk UI на вашу рідну мову

    From 75116f8f852d564e99475c5d916627ba9c4b0f8b Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:05:13 +0200 Subject: [PATCH 199/382] Update README-VN.md added link for Greek language --- docs/README-VN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-VN.md b/docs/README-VN.md index 295f54c6b..2f66d011d 100644 --- a/docs/README-VN.md +++ b/docs/README-VN.md @@ -5,7 +5,7 @@ DockerCấu trúc tệp tinSnapshot
    - [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي]
    + [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Ελληνικά]
    Chúng tôi cần sự gíup đỡ của bạn để dịch trang README này, RustDesk UItài liệu sang ngôn ngữ bản địa của bạn

    From 5c44da849ec166b717e82e7b2bd3a92f2ba2572b Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:05:39 +0200 Subject: [PATCH 200/382] Update README-ZH.md added link for Greek language --- docs/README-ZH.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-ZH.md b/docs/README-ZH.md index 7ec87ec50..27c35ff57 100644 --- a/docs/README-ZH.md +++ b/docs/README-ZH.md @@ -5,7 +5,7 @@ Docker结构截图
    - [English] | [Українська] | [česky] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt]
    + [English] | [Українська] | [česky] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]

    Chat with us: [知乎](https://www.zhihu.com/people/rustdesk) | [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk) From 7493270be86d56635fc9b103152834d3d757eec7 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:08:13 +0200 Subject: [PATCH 201/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 92c2d04e5..3fc202d75 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -5,7 +5,7 @@ DockerΔομήSnapshot
    - [English] | [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    + [English] | [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    Χρειαζόμαστε τη βοήθειά σας για να μεταφράσουμε αυτό το αρχείο README, το RustDesk UI και το Doc στη μητρική σας γλώσσα

    From 990e96f62e0f4feb404132810422c04ceffaa017 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:09:16 +0200 Subject: [PATCH 202/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 3fc202d75..30ec17037 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -5,7 +5,7 @@ DockerΔομήSnapshot
    - [English] | [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    + [English] | [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    Χρειαζόμαστε τη βοήθειά σας για να μεταφράσουμε αυτό το αρχείο README, το RustDesk UI και το Doc στη μητρική σας γλώσσα

    From 37eec738dbb90412658b7008a3d4a69c57ccf1af Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:13:09 +0200 Subject: [PATCH 203/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 30ec17037..2e73aacb8 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -9,7 +9,7 @@ Χρειαζόμαστε τη βοήθειά σας για να μεταφράσουμε αυτό το αρχείο README, το RustDesk UI και το Doc στη μητρική σας γλώσσα

    -Επικοινωνία μαζί μας μέσω: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk) +Επικοινωνήστε μαζί μας μέσω: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk) [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09) From a2d9b8652342a5b3a1d5b48f78c742ab3dcd58d1 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:14:26 +0200 Subject: [PATCH 204/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 2e73aacb8..ef1e2b510 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -13,7 +13,7 @@ [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09) -Ένα λογισμικό απομακρυσμένης επιφάνειας εργασίας, γραμμένο σε γλώσσα Rust. Δεν χρειάζεται κάποια παραμετροποίηση, λειτουργεί αμέσως μετά την εγκατάσταση. Έχετε τον πλήρη έλεγχο των δεδομένων σας, χωρίς να ανησυχείτε για την ασφάλειά τους. Μπορείτε να χρησιμοποιήσετε τους προκαθορισμένους διακομιστές rendezvous/αναμετάδοσης, [να εγκαταστήσετε τον δικό σας](https://rustdesk.com/server), ή [να αναπτύξετε ενα δικό σας διακομιστή rendezvous/αναμετάδοσης](https://github.com/rustdesk/rustdesk-server-demo). +Ένα λογισμικό απομακρυσμένης επιφάνειας εργασίας, γραμμένο σε γλώσσα Rust. Δεν χρειάζεται κάποια παραμετροποίηση, λειτουργεί αμέσως μετά την εγκατάσταση. Έχετε τον πλήρη έλεγχο των δεδομένων σας, χωρίς να ανησυχείτε για την ασφάλειά τους. Μπορείτε να χρησιμοποιήσετε τους προκαθορισμένους διακομιστές rendezvous/αναμετάδοσης, [να εγκαταστήσετε τον δικό σας διακομιστή](https://rustdesk.com/server), ή [να αναπτύξετε ενα δικό σας διακομιστή rendezvous/αναμετάδοσης](https://github.com/rustdesk/rustdesk-server-demo). ![image](https://user-images.githubusercontent.com/71636191/171661982-430285f0-2e12-4b1d-9957-4a58e375304d.png) From d2b94442b93fab47edda59ce51e92a24c71179ec Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:14:51 +0200 Subject: [PATCH 205/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index ef1e2b510..9a4a904c8 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -13,7 +13,7 @@ [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09) -Ένα λογισμικό απομακρυσμένης επιφάνειας εργασίας, γραμμένο σε γλώσσα Rust. Δεν χρειάζεται κάποια παραμετροποίηση, λειτουργεί αμέσως μετά την εγκατάσταση. Έχετε τον πλήρη έλεγχο των δεδομένων σας, χωρίς να ανησυχείτε για την ασφάλειά τους. Μπορείτε να χρησιμοποιήσετε τους προκαθορισμένους διακομιστές rendezvous/αναμετάδοσης, [να εγκαταστήσετε τον δικό σας διακομιστή](https://rustdesk.com/server), ή [να αναπτύξετε ενα δικό σας διακομιστή rendezvous/αναμετάδοσης](https://github.com/rustdesk/rustdesk-server-demo). +Ένα λογισμικό απομακρυσμένης επιφάνειας εργασίας, γραμμένο σε γλώσσα Rust. Δεν χρειάζεται κάποια παραμετροποίηση, λειτουργεί αμέσως μετά την εγκατάσταση. Έχετε τον πλήρη έλεγχο των δεδομένων σας, χωρίς να ανησυχείτε για την ασφάλειά τους. Μπορείτε να χρησιμοποιήσετε τους προκαθορισμένους διακομιστές rendezvous/αναμετάδοσης, [να εγκαταστήσετε τον δικό σας διακομιστή](https://rustdesk.com/server), ή [να αναπτύξετε ένα δικό σας διακομιστή rendezvous/αναμετάδοσης](https://github.com/rustdesk/rustdesk-server-demo). ![image](https://user-images.githubusercontent.com/71636191/171661982-430285f0-2e12-4b1d-9957-4a58e375304d.png) From 5c0633e6f045228c818e869376d370317e76b893 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:19:16 +0200 Subject: [PATCH 206/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 9a4a904c8..099998186 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -139,7 +139,7 @@ VCPKG_ROOT=$HOME/vcpkg cargo run ### Αλλαγή του Wayland σε X11 (Xorg) -Το RustDesk δεν υποστιρίζει το πρωτόκολλο Wayland. Διαβάστε [εδώ](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) ώστε να ορίσετε το Xorg ως το προκαθορισμένο GNOME περιβάλλον. +Το RustDesk δεν υποστηρίζει το πρωτόκολλο Wayland. Διαβάστε [εδώ](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) ώστε να ορίσετε το Xorg ως το προκαθορισμένο GNOME περιβάλλον. ## Υποστήριξη Wayland From 7f942ec6763f7fbe9c61cfb0a5e60d88c529f7f7 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:22:18 +0200 Subject: [PATCH 207/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 099998186..eb7ba02dd 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -193,7 +193,7 @@ target/debug/rustdesk target/release/rustdesk ``` -Βεβαιωθείτε ότι εκτελείτε αυτές τις εντολές από την αρχική διαδρομή του αποθετηρίου του Rustdesk, διαφορετικά η εφαρμογή ενδέχεται να μην είναι σε θέση να βρει τους απαιτούμενους πόρους. Σημειώστε επίσης ότι άλλες υποεντολές, όπως το `install` ή το `run` δεν υποστηρίζονται επί του παρόντος μέσω αυτής της μεθόδου καθώς θα εγκαταστήσουν ή θα εκτελέσουν το πρόγραμμα εντός του container αντί του κεντρικού υπολογιστή. +Βεβαιωθείτε ότι εκτελείτε αυτές τις εντολές από την αρχική διαδρομή του αποθετηρίου του Rustdesk, διαφορετικά η εφαρμογή ενδέχεται να μην είναι σε θέση να βρεί τους απαιτούμενους πόρους. Σημειώστε επίσης ότι άλλες υποεντολές, όπως το `install` ή το `run` δεν υποστηρίζονται επί του παρόντος μέσω αυτής της μεθόδου καθώς θα εγκαταστήσουν ή θα εκτελέσουν το πρόγραμμα εντός του container αντί του κεντρικού υπολογιστή. ## Δομή φακέλων From 7d2c8c2ba1959c24d59ccf485406ce4a5307e464 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:23:33 +0100 Subject: [PATCH 208/382] Update template.rs --- src/lang/template.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lang/template.rs b/src/lang/template.rs index e51a095c0..638bb4d21 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } From 24dd9ff362418482aff05045ad06d7dac790d2cb Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:25:17 +0100 Subject: [PATCH 209/382] Add files via upload --- 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/nl.rs | 3 ++- src/lang/pl.rs | 4 ++-- src/lang/pt_PT.rs | 3 ++- src/lang/ptbr.rs | 3 ++- src/lang/ro.rs | 3 ++- src/lang/ru.rs | 3 ++- src/lang/sk.rs | 3 ++- src/lang/sl.rs | 3 ++- src/lang/sq.rs | 3 ++- src/lang/sr.rs | 3 ++- src/lang/sv.rs | 3 ++- src/lang/th.rs | 3 ++- src/lang/tr.rs | 3 ++- src/lang/tw.rs | 3 ++- src/lang/ua.rs | 3 ++- src/lang/vn.rs | 3 ++- 32 files changed, 64 insertions(+), 33 deletions(-) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 89cc46920..a8f5758ee 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 3f4f6d25c..03e253bfb 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "编解码"), ("Resolution", "分辨率"), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index a2813815b..e85c95969 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 2760f94fb..f933972d9 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 36493f747..5ac7de62e 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Codec"), ("Resolution", "Auflösung"), ("No transfers in progress", "Keine Übertragungen im Gange"), - ].iter().cloned().collect(); + ("Set temporary password length", "Temporäre Passwortlänge festlegen"), + ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 7a191f05d..667071e3f 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index b290c7696..a93d0ccd9 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Códec"), ("Resolution", "Resolución"), ("No transfers in progress", "No hay transferencias en curso"), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 7fe279a1b..d20f321f3 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "کدک"), ("Resolution", "وضوح"), ("No transfers in progress", "هیچ انتقالی در حال انجام نیست"), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index dd436831e..bc6a23d71 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/gr.rs b/src/lang/gr.rs index f517f61a1..336b1092c 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Κωδικοποίηση"), ("Resolution", "Ανάλυση"), ("No transfers in progress", "Δεν υπάρχει μεταφορά σε εξέλιξη"), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 8727c53c2..62ec3b018 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index b363a2ae8..996fd3a3b 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 340794ceb..65e685f4c 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Codec"), ("Resolution", "Risoluzione"), ("No transfers in progress", "Nessun trasferimento in corso"), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 260c27607..00b71c57b 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index f101ae20b..f2cbc2ab0 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index fe0937a65..d0b712ff5 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 63d3cee7b..fc4490aae 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Codec"), ("Resolution", "Resolutie"), ("No transfers in progress", "Geen overdrachten in uitvoering"), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 162dec052..b1cd7eb7c 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -459,7 +459,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Reconnect", "Połącz ponownie"), ("Codec", "Kodek"), ("Resolution", "Rozdzielczość"), - ("Key", "Klucz"), ("No transfers in progress", "Brak transferów w toku"), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 8eb4df2ad..6f3504218 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 973048f3d..cbb0651a9 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 9e252aa8a..76a234aff 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 4c1f9ae34..a8705d531 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Кодек"), ("Resolution", "Разрешение"), ("No transfers in progress", "Передача не осуществляется"), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index d60384286..55bf55aff 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index bd07b1acb..39e54b66d 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index b8f9203ca..86f877aa0 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 4a9b73374..24ddb85be 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index f73154e3e..a565be50e 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 3214c3452..2f2c4fa31 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 82f95ef84..cf7e9997b 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index d0f12cdfa..fc1576db7 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "編解碼"), ("Resolution", "分辨率"), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 793d1e147..1eb6eea7a 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index fc665834d..193408b0e 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -460,5 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Set temporary password length", ""), + ].iter().cloned().collect(); } From 985e45be8d4786f4c724c40410f9042cb2139bb0 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:43:10 +0200 Subject: [PATCH 210/382] Update README-GR.md header logo fix --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index eb7ba02dd..65cf3fb15 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -1,5 +1,5 @@

    - RustDesk - Your remote desktop
    + RustDesk - Your remote desktop
    ΔιακομιστέςBuildDocker • From e6792bab26cc1ec273fccca2592f02a25e7953e4 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:44:47 +0200 Subject: [PATCH 211/382] Update README-GR.md --- docs/README-GR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index 65cf3fb15..b4a7d5c47 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -4,7 +4,7 @@ BuildDockerΔομή • - Snapshot
    + Στιγμιότυπα
    [English] | [Українська] | [česky] | [中文] | | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk]
    Χρειαζόμαστε τη βοήθειά σας για να μεταφράσουμε αυτό το αρχείο README, το RustDesk UI και το Doc στη μητρική σας γλώσσα

    From 0579ba5cfdc81ab2623d5453110e1f54b16b59c9 Mon Sep 17 00:00:00 2001 From: 21pages Date: Sat, 4 Mar 2023 11:06:22 +0800 Subject: [PATCH 212/382] opt benchmark code Signed-off-by: 21pages --- libs/scrap/examples/benchmark.rs | 65 +++++++++++++++----------------- libs/scrap/src/common/x11.rs | 2 +- 2 files changed, 32 insertions(+), 35 deletions(-) diff --git a/libs/scrap/examples/benchmark.rs b/libs/scrap/examples/benchmark.rs index ccd47b240..003830f95 100644 --- a/libs/scrap/examples/benchmark.rs +++ b/libs/scrap/examples/benchmark.rs @@ -1,14 +1,5 @@ use docopt::Docopt; use hbb_common::env_logger::{init_from_env, Env, DEFAULT_FILTER_ENV}; -#[cfg(feature = "hwcodec")] -use hwcodec::{ - decode::{DecodeContext, Decoder}, - encode::{EncodeContext, Encoder}, - ffmpeg::{CodecInfo, CodecInfos}, - AVPixelFormat, - Quality::*, - RateControl::*, -}; use scrap::{ codec::{EncoderApi, EncoderCfg}, Capturer, Display, TraitCapturer, VpxDecoder, VpxDecoderConfig, VpxEncoder, VpxEncoderConfig, @@ -26,17 +17,17 @@ Usage: benchmark (-h | --help) Options: - -h --help Show this screen. + -h --help Show this screen. --count=COUNT Capture frame count [default: 100]. --bitrate=KBS Video bitrate in kilobits per second [default: 5000]. - --hw-pixfmt=PIXFMT Hareware codec pixfmt. [default: i420] + --hw-pixfmt=PIXFMT Hardware codec pixfmt. [default: i420] Valid values: i420, nv12. "; #[derive(Debug, serde::Deserialize)] struct Args { - flag_count: u32, - flag_bitrate: u32, + flag_count: usize, + flag_bitrate: usize, flag_hw_pixfmt: Pixfmt, } @@ -51,16 +42,17 @@ fn main() { let args: Args = Docopt::new(USAGE) .and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); - let bitrate_k = args.flag_bitrate as usize; - let yuv_count = args.flag_count as usize; + let bitrate_k = args.flag_bitrate; + let yuv_count = args.flag_count; let (yuvs, width, height) = capture_yuv(yuv_count); println!( - "benchmark {}x{} bitrate:{}k hw_pixfmt:{:?} count:{:?}", - width, height, bitrate_k, args.flag_hw_pixfmt, yuv_count + "benchmark {}x{} bitrate:{}k hw_pixfmt:{:?}", + width, height, bitrate_k, args.flag_hw_pixfmt ); test_vp9(&yuvs, width, height, bitrate_k, yuv_count); #[cfg(feature = "hwcodec")] { + use hwcodec::AVPixelFormat; let hw_pixfmt = match args.flag_hw_pixfmt { Pixfmt::I420 => AVPixelFormat::AV_PIX_FMT_YUV420P, Pixfmt::NV12 => AVPixelFormat::AV_PIX_FMT_NV12, @@ -82,19 +74,13 @@ fn capture_yuv(yuv_count: usize) -> (Vec>, usize, usize) { let d = displays.remove(index); let mut c = Capturer::new(d, true).unwrap(); let mut v = vec![]; - let start = Instant::now(); loop { if let Ok(frame) = c.frame(std::time::Duration::from_millis(30)) { v.push(frame.0.to_vec()); - print!( - "\rcapture {}/{}...{}s", - v.len(), - yuv_count, - start.elapsed().as_secs() - ); + print!("\rcapture {}/{}", v.len(), yuv_count); std::io::stdout().flush().ok(); if v.len() == yuv_count { - println!("\rcapture {}/{} finish", yuv_count, yuv_count); + println!(); return (v, c.width(), c.height()); } } @@ -134,6 +120,7 @@ fn test_vp9(yuvs: &Vec>, width: usize, height: usize, bitrate_k: usize, vp9s.push(frame.data.to_vec()); } } + assert_eq!(vp9s.len(), yuv_count); let mut decoder = VpxDecoder::new(VpxDecoderConfig { codec: VpxVideoCodecId::VP9, @@ -150,7 +137,15 @@ fn test_vp9(yuvs: &Vec>, width: usize, height: usize, bitrate_k: usize, #[cfg(feature = "hwcodec")] mod hw { - use hwcodec::ffmpeg::ffmpeg_linesize_offset_length; + use super::*; + use hwcodec::{ + decode::{DecodeContext, Decoder}, + encode::{EncodeContext, Encoder}, + ffmpeg::{ffmpeg_linesize_offset_length, CodecInfo, CodecInfos}, + AVPixelFormat, + Quality::*, + RateControl::*, + }; use scrap::{ convert::{ hw::{hw_bgra_to_i420, hw_bgra_to_nv12}, @@ -159,13 +154,12 @@ mod hw { HW_STRIDE_ALIGN, }; - use super::*; pub fn test( yuvs: &Vec>, width: usize, height: usize, bitrate_k: usize, - _yuv_count: usize, + yuv_count: usize, pixfmt: AVPixelFormat, ) { let ctx = EncodeContext { @@ -181,17 +175,18 @@ mod hw { rc: RC_DEFAULT, }; - println!("hw encoders:"); let encoders = Encoder::available_encoders(ctx.clone()); + println!("hw encoders: {}", encoders.len()); let best = CodecInfo::score(encoders.clone()); for info in encoders { test_encoder(info.clone(), ctx.clone(), yuvs, is_best(&best, &info)); } let (h264s, h265s) = prepare_h26x(best, ctx.clone(), yuvs); - - println!("hw decoders:"); + assert!(h264s.is_empty() || h264s.len() == yuv_count); + assert!(h265s.is_empty() || h265s.len() == yuv_count); let decoders = Decoder::available_decoders(); + println!("hw decoders: {}", decoders.len()); let best = CodecInfo::score(decoders.clone()); for info in decoders { let h26xs = if info.name.contains("h264") { @@ -199,7 +194,7 @@ mod hw { } else { &h265s }; - if h264s.len() == yuvs.len() { + if h26xs.len() == yuvs.len() { test_decoder(info.clone(), h26xs, is_best(&best, &info)); } } @@ -234,11 +229,13 @@ mod hw { let _ = decoder.decode(h26x).unwrap(); cnt += 1; } + let device = format!("{:?}", ctx.device_type).to_lowercase(); + let device = device.split("_").last().unwrap(); println!( - "{}{} {:?}: {:?}", + "{}{} {}: {:?}", if best { "*" } else { "" }, ctx.name, - ctx.device_type, + device, start.elapsed() / cnt ); } diff --git a/libs/scrap/src/common/x11.rs b/libs/scrap/src/common/x11.rs index 6e3fc94fb..514608e4a 100644 --- a/libs/scrap/src/common/x11.rs +++ b/libs/scrap/src/common/x11.rs @@ -29,7 +29,7 @@ impl TraitCapturer for Capturer { } } -pub struct Frame<'a>(pub(crate) &'a [u8]); +pub struct Frame<'a>(pub &'a [u8]); impl<'a> ops::Deref for Frame<'a> { type Target = [u8]; From 3015a23e3dc6894b77b5ed1717274eda7d8e2c97 Mon Sep 17 00:00:00 2001 From: 21pages Date: Mon, 6 Mar 2023 10:55:34 +0800 Subject: [PATCH 213/382] fix dark theme menubar Signed-off-by: 21pages --- flutter/lib/common.dart | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index dc91e9414..50e6beac5 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -252,12 +252,7 @@ class MyTheme { ), ), ), - colorScheme: ColorScheme.fromSwatch( - primarySwatch: Colors.blue, - ).copyWith( - brightness: Brightness.light, - background: grayBg, - ), + colorScheme: ColorScheme.light(primary: Colors.blue, background: grayBg), ).copyWith( extensions: >[ ColorThemeExtension.light, @@ -356,10 +351,8 @@ class MyTheme { ), ), ), - colorScheme: ColorScheme.fromSwatch( - primarySwatch: Colors.blue, - ).copyWith( - brightness: Brightness.dark, + colorScheme: ColorScheme.dark( + primary: Colors.blue, background: Color(0xFF24252B), ), ).copyWith( From 6ae2fbdbc81c55437aacd3186d7ffc216c2e8ff2 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Mon, 6 Mar 2023 11:25:49 +0800 Subject: [PATCH 214/382] change "temporary password" to "one-time password" --- flutter/lib/mobile/widgets/dialog.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index 3832ca7b1..9a5891330 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -162,7 +162,7 @@ void setTemporaryPasswordLengthDialog( } return CustomAlertDialog( - title: Text(translate("Set temporary password length")), + title: Text(translate("Set one-time password length")), content: Column( mainAxisSize: MainAxisSize.min, children: From a04351baf4e8ea7cd3f38ea98228ce3578079034 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Fri, 3 Mar 2023 20:53:42 +0100 Subject: [PATCH 215/382] implemented sorting in every tab except "recent sessions" --- flutter/lib/common/widgets/peer_tab_page.dart | 86 +++++++++++++++---- flutter/lib/common/widgets/peers_view.dart | 41 ++++++++- 2 files changed, 107 insertions(+), 20 deletions(-) diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index da7e37e6b..d0ab51058 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -12,6 +12,7 @@ import 'package:flutter_hbb/desktop/widgets/popup_menu.dart'; import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; import 'package:flutter_hbb/desktop/widgets/material_mod_popup_menu.dart' as mod_menu; +import 'package:flutter_hbb/models/file_model.dart'; import 'package:flutter_hbb/models/peer_tab_model.dart'; import 'package:get/get.dart'; import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart'; @@ -39,6 +40,8 @@ EdgeInsets? _menuPadding() { class _PeerTabPageState extends State with SingleTickerProviderStateMixin { + bool _hideSort = bind.getLocalFlutterConfig(k: 'peer-tab-index') == '0'; + final List<_TabEntry> entries = [ _TabEntry( RecentPeersView( @@ -83,6 +86,7 @@ class _PeerTabPageState extends State if (tabIndex < entries.length) { gFFI.peerTabModel.setCurrentTab(tabIndex); entries[tabIndex].load(); + _hideSort = tabIndex == 0; } } @@ -95,22 +99,27 @@ class _PeerTabPageState extends State SizedBox( height: 28, child: Container( - padding: isDesktop ? null : EdgeInsets.symmetric(horizontal: 2), - constraints: isDesktop ? null : kMobilePageConstraints, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: visibleContextMenuListener( - _createSwitchBar(context))), - buildScrollJumper(), - const PeerSearchBar(), - Offstage( - offstage: !isDesktop, - child: _createPeerViewTypeSwitch(context) - .marginOnly(left: 13)), - ], - )), + padding: isDesktop ? null : EdgeInsets.symmetric(horizontal: 2), + constraints: isDesktop ? null : kMobilePageConstraints, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: + visibleContextMenuListener(_createSwitchBar(context))), + buildScrollJumper(), + const PeerSearchBar(), + Offstage( + offstage: !isDesktop, + child: _createPeerViewTypeSwitch(context) + .marginOnly(left: 13)), + Offstage( + offstage: _hideSort, + child: PeerSortDropdown(), + ) + ], + ), + ), ), _createPeersView(), ], @@ -417,3 +426,48 @@ class _PeerSearchBarState extends State { ); } } + +class PeerSortDropdown extends StatefulWidget { + const PeerSortDropdown({super.key}); + + @override + State createState() => _PeerSortDropdownState(); +} + +class _PeerSortDropdownState extends State { + final List sort_names = ['id', 'username', "status"]; + String _sortType = peerSort.value; + + @override + Widget build(BuildContext context) { + return DropdownButton( + value: _sortType, + elevation: 16, + underline: SizedBox(), + onChanged: (v) { + if (v != null) { + setState(() { + _sortType = v; + bind.setLocalFlutterConfig( + k: "peer-sorting", + v: _sortType, + ); + }); + peerSort.value = _sortType; + } + }, + dropdownColor: Theme.of(context).cardColor, + items: sort_names + .map>( + (String value) => DropdownMenuItem( + value: value, + child: Text( + value, + overflow: TextOverflow.ellipsis, + ), + ), + ) + .toList(), + ); + } +} diff --git a/flutter/lib/common/widgets/peers_view.dart b/flutter/lib/common/widgets/peers_view.dart index 9c98f24b8..88e05238e 100644 --- a/flutter/lib/common/widgets/peers_view.dart +++ b/flutter/lib/common/widgets/peers_view.dart @@ -18,6 +18,13 @@ typedef PeerCardBuilder = Widget Function(Peer peer); /// for peer search text, global obs value final peerSearchText = "".obs; + +/// for peer sort, global obs value +final peerSort = bind.getLocalFlutterConfig(k: 'peer-sorting').obs; + +// list for listener +final obslist = [peerSearchText, peerSort].obs; + final peerSearchTextController = TextEditingController(text: peerSearchText.value); @@ -101,7 +108,7 @@ class _PeersViewState extends State<_PeersView> with WindowListener { } Widget _buildPeersView(Peers peers) { - final body = ObxValue((searchText) { + final body = ObxValue((filters) { return FutureBuilder>( builder: (context, snapshot) { if (snapshot.hasData) { @@ -139,9 +146,9 @@ class _PeersViewState extends State<_PeersView> with WindowListener { ); } }, - future: matchPeers(searchText.value, peers.peers), + future: matchPeers(filters[0].value, filters[1].value, peers.peers), ); - }, peerSearchText); + }, obslist); return body; } @@ -179,11 +186,36 @@ class _PeersViewState extends State<_PeersView> with WindowListener { }(); } - Future>? matchPeers(String searchText, List peers) async { + Future>? matchPeers( + String searchText, String sortedBy, List peers) async { if (widget.peerFilter != null) { peers = peers.where((peer) => widget.peerFilter!(peer)).toList(); } + // fallback to id sorting + if (sortedBy.isEmpty) { + sortedBy = 'id'; + bind.setLocalFlutterConfig( + k: "peer-sorting", + v: sortedBy, + ); + } + + if (widget.peers.loadEvent != 'load_recent_peers') { + switch (sortedBy) { + case 'id': + peers.sort((p1, p2) => p1.id.compareTo(p2.id)); + break; + case 'username': + peers.sort((p1, p2) => + p1.username.toLowerCase().compareTo(p2.username.toLowerCase())); + break; + case 'status': + peers.sort((p1, p2) => p1.online ? 1 : -1); + break; + } + } + searchText = searchText.trim(); if (searchText.isEmpty) { return peers; @@ -197,6 +229,7 @@ class _PeersViewState extends State<_PeersView> with WindowListener { filteredList.add(peers[i]); } } + return filteredList; } } From 52970b0e5848058874c3390450cf81a21c7f2ffa Mon Sep 17 00:00:00 2001 From: 21pages Date: Mon, 6 Mar 2023 17:17:51 +0800 Subject: [PATCH 216/382] recover addToFav in lan Signed-off-by: 21pages --- flutter/lib/common/widgets/peer_card.dart | 11 +++----- src/flutter_ffi.rs | 32 ++++++++++++++++++----- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/flutter/lib/common/widgets/peer_card.dart b/flutter/lib/common/widgets/peer_card.dart index 5a7f2bfa7..7d2d0cd2d 100644 --- a/flutter/lib/common/widgets/peer_card.dart +++ b/flutter/lib/common/widgets/peer_card.dart @@ -890,13 +890,10 @@ class DiscoveredPeerCard extends BasePeerCard { menuItems.add(_createShortCutAction(peer.id)); } - final inRecent = await bind.mainIsInRecentPeers(id: peer.id); - if (inRecent) { - if (!favs.contains(peer.id)) { - menuItems.add(_addFavAction(peer.id)); - } else { - menuItems.add(_rmFavAction(peer.id, () async {})); - } + if (!favs.contains(peer.id)) { + menuItems.add(_addFavAction(peer.id)); + } else { + menuItems.add(_rmFavAction(peer.id, () async {})); } if (gFFI.userModel.userName.isNotEmpty) { diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index e5b24fa53..2a3baad95 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -10,7 +10,7 @@ use crate::{ }; use flutter_rust_bridge::{StreamSink, SyncReturn}; use hbb_common::{ - config::{self, LocalConfig, PeerConfig, ONLINE}, + config::{self, LocalConfig, PeerConfig, PeerInfoSerde, ONLINE}, fs, log, message_proto::KeyboardMode, ResultType, @@ -21,6 +21,7 @@ use std::{ ffi::{CStr, CString}, os::raw::c_char, str::FromStr, + time::SystemTime, }; // use crate::hbbs_http::account::AuthResult; @@ -726,10 +727,6 @@ pub fn main_peer_has_password(id: String) -> bool { peer_has_password(id) } -pub fn main_is_in_recent_peers(id: String) -> bool { - PeerConfig::peers().iter().any(|e| e.0 == id) -} - pub fn main_load_recent_peers() { if !config::APP_DIR.read().unwrap().is_empty() { let peers: Vec> = PeerConfig::peers() @@ -756,7 +753,28 @@ pub fn main_load_recent_peers() { pub fn main_load_fav_peers() { if !config::APP_DIR.read().unwrap().is_empty() { let favs = get_fav(); - let peers: Vec> = PeerConfig::peers() + let mut recent = PeerConfig::peers(); + let mut lan = config::LanPeers::load() + .peers + .iter() + .filter(|d| recent.iter().all(|r| r.0 != d.id)) + .map(|d| { + ( + d.id.clone(), + SystemTime::UNIX_EPOCH, + PeerConfig { + info: PeerInfoSerde { + username: d.username.clone(), + hostname: d.hostname.clone(), + platform: d.platform.clone(), + }, + ..Default::default() + }, + ) + }) + .collect(); + recent.append(&mut lan); + let peers: Vec> = recent .into_iter() .filter_map(|(id, _, p)| { if favs.contains(&id) { @@ -1361,7 +1379,7 @@ pub fn send_url_scheme(_url: String) { #[cfg(target_os = "android")] pub mod server_side { - use hbb_common::{log, config}; + use hbb_common::{config, log}; use jni::{ objects::{JClass, JString}, sys::jstring, From 507472e87e04930382660c289ff95571d068bea5 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 6 Mar 2023 15:29:37 +0800 Subject: [PATCH 217/382] show one display when privacy mode is on Signed-off-by: fufesou --- flutter/lib/desktop/widgets/remote_menubar.dart | 4 +++- libs/scrap/src/dxgi/mag.rs | 9 --------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 081cd1649..f5e791551 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -509,7 +509,9 @@ class _MonitorMenu extends StatelessWidget { @override Widget build(BuildContext context) { - if (stateGlobal.displaysCount.value < 2) return Offstage(); + if (PrivacyModeState.find(id).isTrue || stateGlobal.displaysCount.value < 2) { + return Offstage(); + } return _IconSubmenuButton( icon: icon(), ffi: ffi, diff --git a/libs/scrap/src/dxgi/mag.rs b/libs/scrap/src/dxgi/mag.rs index b2bea1dd1..62e90c08b 100644 --- a/libs/scrap/src/dxgi/mag.rs +++ b/libs/scrap/src/dxgi/mag.rs @@ -127,15 +127,6 @@ impl MagInterface { }; s.init_succeeded = false; unsafe { - if GetSystemMetrics(SM_CMONITORS) != 1 { - // Do not try to use the magnifier in multi-screen setup (where the API - // crashes sometimes). - return Err(Error::new( - ErrorKind::Other, - "Magnifier capturer cannot work on multi-screen system.", - )); - } - // load lib let lib_file_name = "Magnification.dll"; let lib_file_name_c = CString::new(lib_file_name).unwrap(); From 80326598413ec85e0c3258986d0cd9cb9c25db62 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 6 Mar 2023 16:41:26 +0800 Subject: [PATCH 218/382] Do not enable privacy mode if current display is not the primary one Signed-off-by: fufesou --- flutter/lib/desktop/widgets/remote_menubar.dart | 13 ++++++++++++- 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/nl.rs | 1 + src/lang/pl.rs | 2 +- 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 + 34 files changed, 45 insertions(+), 2 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index f5e791551..173ed038c 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -509,7 +509,8 @@ class _MonitorMenu extends StatelessWidget { @override Widget build(BuildContext context) { - if (PrivacyModeState.find(id).isTrue || stateGlobal.displaysCount.value < 2) { + if (PrivacyModeState.find(id).isTrue || + stateGlobal.displaysCount.value < 2) { return Offstage(); } return _IconSubmenuButton( @@ -1548,6 +1549,16 @@ class _DisplayMenuState extends State<_DisplayMenu> { value: rxValue.value, onChanged: (value) { if (value == null) return; + if (widget.ffi.ffiModel.pi.currentDisplay != 0) { + msgBox( + widget.id, + 'custom-nook-nocancel-hasclose', + 'info', + 'Please switch to Display 1 first', + '', + widget.ffi.dialogManager); + return; + } bind.sessionToggleOption(id: widget.id, value: option); }, ffi: widget.ffi, diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 89cc46920..ac7760321 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Aconseguit"), ("Someone turns on privacy mode, exit", "Algú ha activat el mode de privacitat, surti"), ("Unsupported", "No suportat"), + ("Please switch to Display 1 first", "") ("Peer denied", "Peer denegat"), ("Please install plugins", "Instal·li complements"), ("Peer exit", "El peer ha sortit"), diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 3f4f6d25c..3dfa63b83 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "成功"), ("Someone turns on privacy mode, exit", "其他用户使用隐私模式,退出"), ("Unsupported", "不支持"), + ("Please switch to Display 1 first", "请先切换到第一个屏幕") ("Peer denied", "被控端拒绝"), ("Please install plugins", "请安装插件"), ("Peer exit", "被控端退出"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index a2813815b..64874d2c7 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Uspěl"), ("Someone turns on privacy mode, exit", "Někdo zapne režim soukromí, ukončete ho"), ("Unsupported", "Nepodporováno"), + ("Please switch to Display 1 first", "") ("Peer denied", "Peer popřel"), ("Please install plugins", "Nainstalujte si prosím pluginy"), ("Peer exit", "Peer exit"), diff --git a/src/lang/da.rs b/src/lang/da.rs index 2760f94fb..5970f8932 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Vellykket"), ("Someone turns on privacy mode, exit", "Nogen aktiverede databeskyttelsestilstand, slut"), ("Unsupported", "Ikke understøttet"), + ("Please switch to Display 1 first", "") ("Peer denied", "Peer nægtet"), ("Please install plugins", "Venligst Installer plugins"), ("Peer exit", "Peer-Afslut"), diff --git a/src/lang/de.rs b/src/lang/de.rs index 36493f747..5907fb0cd 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Erfolgreich"), ("Someone turns on privacy mode, exit", "Jemand hat den Datenschutzmodus aktiviert, beende …"), ("Unsupported", "Nicht unterstützt"), + ("Please switch to Display 1 first", "") ("Peer denied", "Die Gegenstelle hat die Verbindung abgelehnt."), ("Please install plugins", "Bitte installieren Sie Plugins"), ("Peer exit", "Die Gegenstelle hat die Verbindung getrennt."), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 7a191f05d..d465b3de8 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", ""), ("Someone turns on privacy mode, exit", ""), ("Unsupported", ""), + ("Please switch to Display 1 first", "") ("Peer denied", ""), ("Please install plugins", ""), ("Peer exit", ""), diff --git a/src/lang/es.rs b/src/lang/es.rs index b290c7696..95f2f69e2 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Logrado"), ("Someone turns on privacy mode, exit", "Alguien active el modo privacidad, salga"), ("Unsupported", "No soportado"), + ("Please switch to Display 1 first", "") ("Peer denied", "Par denegado"), ("Please install plugins", "Instale complementos"), ("Peer exit", "Par salio"), diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 7fe279a1b..bd3e1b28d 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "موفقیت آمیز"), ("Someone turns on privacy mode, exit", "اگر شخصی حالت حریم خصوصی را روشن کرد، خارج شوید"), ("Unsupported", "پشتیبانی نشده"), + ("Please switch to Display 1 first", "") ("Peer denied", "توسط میزبان راه دور رد شد"), ("Please install plugins", "لطفا افزونه ها را نصب کنید"), ("Peer exit", "میزبان خارج شد"), diff --git a/src/lang/fr.rs b/src/lang/fr.rs index dd436831e..0eeb71afb 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Succès"), ("Someone turns on privacy mode, exit", "Quelqu'un active le mode de confidentialité, quittez"), ("Unsupported", "Non pris en charge"), + ("Please switch to Display 1 first", "") ("Peer denied", "Pair refusé"), ("Please install plugins", "Veuillez installer les plugins"), ("Peer exit", "Sortie des pairs"), diff --git a/src/lang/gr.rs b/src/lang/gr.rs index 8629879ca..ec961f2e1 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Επιτυχής"), ("Someone turns on privacy mode, exit", "Κάποιος ενεργοποιεί τη λειτουργία απορρήτου, έξοδος"), ("Unsupported", "Δεν υποστηρίζεται"), + ("Please switch to Display 1 first", "") ("Peer denied", "Ο απομακρυσμένος σταθμός απέρριψε τη σύνδεση"), ("Please install plugins", "Παρακαλώ εγκαταστήστε τα πρόσθετα"), ("Peer exit", "Ο απομακρυσμένος σταθμός έχει αποσυνδεθεί"), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 8727c53c2..6ea7c561e 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Sikeres"), ("Someone turns on privacy mode, exit", "Valaki bekacsolta az inkognitó módot, lépjen ki"), ("Unsupported", "Nem támogatott"), + ("Please switch to Display 1 first", "") ("Peer denied", "Elutasítva a távoli fél álltal"), ("Please install plugins", "Kérem telepítse a bővítményeket"), ("Peer exit", "A távoli fél kilépett"), diff --git a/src/lang/id.rs b/src/lang/id.rs index b363a2ae8..b617190fd 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Berhasil"), ("Someone turns on privacy mode, exit", "Seseorang mengaktifkan mode privasi, keluar"), ("Unsupported", "Tidak didukung"), + ("Please switch to Display 1 first", "") ("Peer denied", "Rekan ditolak"), ("Please install plugins", "Silakan instal plugin"), ("Peer exit", "keluar rekan"), diff --git a/src/lang/it.rs b/src/lang/it.rs index 340794ceb..713c73fa6 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Successo"), ("Someone turns on privacy mode, exit", "Qualcuno attiva la modalità privacy, esci"), ("Unsupported", "Non supportato"), + ("Please switch to Display 1 first", "") ("Peer denied", "Peer negato"), ("Please install plugins", "Si prega di installare i plugin"), ("Peer exit", "Uscita tra pari"), diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 260c27607..c4d29ad73 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "成功"), ("Someone turns on privacy mode, exit", "プライバシーモードがオンになりました。終了します。"), ("Unsupported", "サポートされていません"), + ("Please switch to Display 1 first", "") ("Peer denied", "相手が拒否しました"), ("Please install plugins", "プラグインをインストールしてください"), ("Peer exit", "相手が終了しました"), diff --git a/src/lang/ko.rs b/src/lang/ko.rs index f101ae20b..3d1330a31 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "성공"), ("Someone turns on privacy mode, exit", "누군가가 개인정보 보호 모드를 활성화하여 종료됩니다"), ("Unsupported", "지원되지 않음"), + ("Please switch to Display 1 first", "") ("Peer denied", "다른 사용자에 의해 거부됨"), ("Please install plugins", "플러그인을 설치해주세요"), ("Peer exit", "다른 사용자가 나감"), diff --git a/src/lang/kz.rs b/src/lang/kz.rs index fe0937a65..c1480377b 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Сәтті"), ("Someone turns on privacy mode, exit", "Біреу құпиялылық модасын қосты, шығу"), ("Unsupported", "Қолдаусыз"), + ("Please switch to Display 1 first", "") ("Peer denied", "Пир қабылдамады"), ("Please install plugins", "Плагиндерді орнатуды өтінеміз"), ("Peer exit", "Пирдің шығуы"), diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 63d3cee7b..377e40a1d 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Geslaagd"), ("Someone turns on privacy mode, exit", "Iemand schakelt privacymodus in, afsluiten"), ("Unsupported", "Niet Ondersteund"), + ("Please switch to Display 1 first", "") ("Peer denied", "Peer geweigerd"), ("Please install plugins", "Installeer plugins"), ("Peer exit", "Peer afgesloten"), diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 162dec052..e4c4839f5 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Udało się"), ("Someone turns on privacy mode, exit", "Ktoś włącza tryb prywatności, wyjdź"), ("Unsupported", "Niewspierane"), + ("Please switch to Display 1 first", "") ("Peer denied", "Odmowa dostępu"), ("Please install plugins", "Zainstaluj wtyczkę"), ("Peer exit", "Wyjście peer"), @@ -459,7 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Reconnect", "Połącz ponownie"), ("Codec", "Kodek"), ("Resolution", "Rozdzielczość"), - ("Key", "Klucz"), ("No transfers in progress", "Brak transferów w toku"), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 8eb4df2ad..541023197 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Conseguiu"), ("Someone turns on privacy mode, exit", "Alguém activou o modo de privacidade, desligue"), ("Unsupported", "Sem suporte"), + ("Please switch to Display 1 first", "") ("Peer denied", "Remoto negado"), ("Please install plugins", "Por favor instale plugins"), ("Peer exit", "Saída do Remoto"), diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 973048f3d..1a35421fd 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Sucesso"), ("Someone turns on privacy mode, exit", "Alguém habilitou o modo de privacidade, sair"), ("Unsupported", "Não suportado"), + ("Please switch to Display 1 first", "") ("Peer denied", "Parceiro negou"), ("Please install plugins", "Por favor instale plugins"), ("Peer exit", "Parceiro saiu"), diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 9e252aa8a..ccfeb412c 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Reușit"), ("Someone turns on privacy mode, exit", "Cineva activează modul privat, ieși din"), ("Unsupported", "Neacceptat"), + ("Please switch to Display 1 first", "") ("Peer denied", "Dispozitiv pereche refuzat"), ("Please install plugins", "Instalează pluginuri"), ("Peer exit", "Ieșire dispozitiv pereche"), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 4c1f9ae34..8692d1d87 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Выполнено"), ("Someone turns on privacy mode, exit", "Кто-то включает режим конфиденциальности, выход"), ("Unsupported", "Не поддерживается"), + ("Please switch to Display 1 first", "") ("Peer denied", "Отклонено удалённым узлом"), ("Please install plugins", "Установите плагины"), ("Peer exit", "Удалённый узел отключён"), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index d60384286..be48c7338 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Podarilo sa"), ("Someone turns on privacy mode, exit", "Niekto zapne režim súkromia, ukončite ho"), ("Unsupported", "Nepodporované"), + ("Please switch to Display 1 first", "") ("Peer denied", "Peer poprel"), ("Please install plugins", "Nainštalujte si prosím pluginy"), ("Peer exit", "Peer exit"), diff --git a/src/lang/sl.rs b/src/lang/sl.rs index bd07b1acb..0706c38c0 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Uspelo"), ("Someone turns on privacy mode, exit", "Vklopljen je zasebni način, izhod"), ("Unsupported", "Ni podprto"), + ("Please switch to Display 1 first", "") ("Peer denied", "Odjemalec zavrnil"), ("Please install plugins", "Namestite vključke"), ("Peer exit", "Odjemalec se je zaprl"), diff --git a/src/lang/sq.rs b/src/lang/sq.rs index b8f9203ca..fac32f1a7 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Sukses"), ("Someone turns on privacy mode, exit", "Dikush ka ndezur menyrën e privatësisë , largohu"), ("Unsupported", "Nuk mbështetet"), + ("Please switch to Display 1 first", "") ("Peer denied", "Peer mohohet"), ("Please install plugins", "Ju lutemi instaloni shtojcat"), ("Peer exit", "Dalje peer"), diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 4a9b73374..85903f03a 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Uspešno"), ("Someone turns on privacy mode, exit", "Neko je uključio mod privatnosti, izlaz."), ("Unsupported", "Nepodržano"), + ("Please switch to Display 1 first", "") ("Peer denied", "Klijent zabranjen"), ("Please install plugins", "Molimo instalirajte dodatke"), ("Peer exit", "Klijent izašao"), diff --git a/src/lang/sv.rs b/src/lang/sv.rs index f73154e3e..2987c9e57 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Lyckades"), ("Someone turns on privacy mode, exit", "Någon sätter på säkerhetesläge, avsluta"), ("Unsupported", "Stöds inte"), + ("Please switch to Display 1 first", "") ("Peer denied", "Klienten nekade"), ("Please install plugins", "Var god installera plugins"), ("Peer exit", "Avsluta klient"), diff --git a/src/lang/template.rs b/src/lang/template.rs index e51a095c0..94e0d8fa1 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", ""), ("Someone turns on privacy mode, exit", ""), ("Unsupported", ""), + ("Please switch to Display 1 first", "") ("Peer denied", ""), ("Please install plugins", ""), ("Peer exit", ""), diff --git a/src/lang/th.rs b/src/lang/th.rs index 3214c3452..05d727e7b 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "สำเร็จ"), ("Someone turns on privacy mode, exit", "มีใครบางคนเปิดใช้งานโหมดความเป็นส่วนตัว กำลังออก"), ("Unsupported", "ไม่รองรับ"), + ("Please switch to Display 1 first", "") ("Peer denied", "ถูกปฏิเสธโดยอีกฝั่ง"), ("Please install plugins", "กรุณาติดตั้งปลั๊กอิน"), ("Peer exit", "อีกฝั่งออก"), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 82f95ef84..280ed4099 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "başarılı"), ("Someone turns on privacy mode, exit", "Birisi gizlilik modunu açarsa, çık"), ("Unsupported", "desteklenmiyor"), + ("Please switch to Display 1 first", "") ("Peer denied", "eş reddedildi"), ("Please install plugins", "Lütfen eklentileri yükleyin"), ("Peer exit", "eş çıkışı"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index d0f12cdfa..7ad3074f9 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "成功"), ("Someone turns on privacy mode, exit", "其他用戶開啟隱私模式,退出"), ("Unsupported", "不支持"), + ("Please switch to Display 1 first", "") ("Peer denied", "被控端拒絕"), ("Please install plugins", "請安裝插件"), ("Peer exit", "被控端退出"), diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 793d1e147..9211bd286 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Успішно"), ("Someone turns on privacy mode, exit", "Хтось вмикає режим конфіденційності, вихід"), ("Unsupported", "Не підтримується"), + ("Please switch to Display 1 first", "") ("Peer denied", "Відхилено віддаленим комп'ютером"), ("Please install plugins", "Будь ласка, встановіть плагіни"), ("Peer exit", "Відключено віддаленим комп'ютером"), diff --git a/src/lang/vn.rs b/src/lang/vn.rs index fc665834d..a26ae1225 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -301,6 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Thành công"), ("Someone turns on privacy mode, exit", "Ai đó đã bật chế độ riêng tư, thoát"), ("Unsupported", "Không hỗ trợ"), + ("Please switch to Display 1 first", "") ("Peer denied", "Peer đã từ chối"), ("Please install plugins", "Hãy cài plugins"), ("Peer exit", "Peer đã thoát"), From c751ebee4e8fe0a498e7019d18d8b34723495dd9 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 6 Mar 2023 16:54:19 +0800 Subject: [PATCH 219/382] fix build Signed-off-by: fufesou --- libs/scrap/src/dxgi/mag.rs | 9 +++++++++ src/lang/ca.rs | 2 +- src/lang/cn.rs | 2 +- src/lang/cs.rs | 2 +- src/lang/da.rs | 2 +- src/lang/de.rs | 2 +- src/lang/eo.rs | 2 +- src/lang/es.rs | 2 +- src/lang/fa.rs | 2 +- src/lang/fr.rs | 2 +- src/lang/gr.rs | 2 +- src/lang/hu.rs | 2 +- src/lang/id.rs | 2 +- src/lang/it.rs | 2 +- src/lang/ja.rs | 2 +- src/lang/ko.rs | 2 +- src/lang/kz.rs | 2 +- src/lang/nl.rs | 2 +- src/lang/pl.rs | 2 +- src/lang/pt_PT.rs | 2 +- src/lang/ptbr.rs | 2 +- src/lang/ro.rs | 2 +- src/lang/ru.rs | 2 +- src/lang/sk.rs | 2 +- src/lang/sl.rs | 2 +- src/lang/sq.rs | 2 +- src/lang/sr.rs | 2 +- src/lang/sv.rs | 2 +- src/lang/template.rs | 2 +- src/lang/th.rs | 2 +- src/lang/tr.rs | 2 +- src/lang/tw.rs | 2 +- src/lang/ua.rs | 2 +- src/lang/vn.rs | 2 +- src/win_privacy.rs | 2 +- 35 files changed, 43 insertions(+), 34 deletions(-) diff --git a/libs/scrap/src/dxgi/mag.rs b/libs/scrap/src/dxgi/mag.rs index 62e90c08b..b2bea1dd1 100644 --- a/libs/scrap/src/dxgi/mag.rs +++ b/libs/scrap/src/dxgi/mag.rs @@ -127,6 +127,15 @@ impl MagInterface { }; s.init_succeeded = false; unsafe { + if GetSystemMetrics(SM_CMONITORS) != 1 { + // Do not try to use the magnifier in multi-screen setup (where the API + // crashes sometimes). + return Err(Error::new( + ErrorKind::Other, + "Magnifier capturer cannot work on multi-screen system.", + )); + } + // load lib let lib_file_name = "Magnification.dll"; let lib_file_name_c = CString::new(lib_file_name).unwrap(); diff --git a/src/lang/ca.rs b/src/lang/ca.rs index ac7760321..57787dead 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Aconseguit"), ("Someone turns on privacy mode, exit", "Algú ha activat el mode de privacitat, surti"), ("Unsupported", "No suportat"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Peer denegat"), ("Please install plugins", "Instal·li complements"), ("Peer exit", "El peer ha sortit"), diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 3dfa63b83..55e805848 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "成功"), ("Someone turns on privacy mode, exit", "其他用户使用隐私模式,退出"), ("Unsupported", "不支持"), - ("Please switch to Display 1 first", "请先切换到第一个屏幕") + ("Please switch to Display 1 first", "请先切换到第一个屏"), ("Peer denied", "被控端拒绝"), ("Please install plugins", "请安装插件"), ("Peer exit", "被控端退出"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 64874d2c7..3ee9e5233 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Uspěl"), ("Someone turns on privacy mode, exit", "Někdo zapne režim soukromí, ukončete ho"), ("Unsupported", "Nepodporováno"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Peer popřel"), ("Please install plugins", "Nainstalujte si prosím pluginy"), ("Peer exit", "Peer exit"), diff --git a/src/lang/da.rs b/src/lang/da.rs index 5970f8932..e3e5a4049 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Vellykket"), ("Someone turns on privacy mode, exit", "Nogen aktiverede databeskyttelsestilstand, slut"), ("Unsupported", "Ikke understøttet"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Peer nægtet"), ("Please install plugins", "Venligst Installer plugins"), ("Peer exit", "Peer-Afslut"), diff --git a/src/lang/de.rs b/src/lang/de.rs index 5907fb0cd..c562472be 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Erfolgreich"), ("Someone turns on privacy mode, exit", "Jemand hat den Datenschutzmodus aktiviert, beende …"), ("Unsupported", "Nicht unterstützt"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Die Gegenstelle hat die Verbindung abgelehnt."), ("Please install plugins", "Bitte installieren Sie Plugins"), ("Peer exit", "Die Gegenstelle hat die Verbindung getrennt."), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index d465b3de8..cbbeecc10 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", ""), ("Someone turns on privacy mode, exit", ""), ("Unsupported", ""), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", ""), ("Please install plugins", ""), ("Peer exit", ""), diff --git a/src/lang/es.rs b/src/lang/es.rs index 95f2f69e2..bd4df8e04 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Logrado"), ("Someone turns on privacy mode, exit", "Alguien active el modo privacidad, salga"), ("Unsupported", "No soportado"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Par denegado"), ("Please install plugins", "Instale complementos"), ("Peer exit", "Par salio"), diff --git a/src/lang/fa.rs b/src/lang/fa.rs index bd3e1b28d..66ec011c4 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "موفقیت آمیز"), ("Someone turns on privacy mode, exit", "اگر شخصی حالت حریم خصوصی را روشن کرد، خارج شوید"), ("Unsupported", "پشتیبانی نشده"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "توسط میزبان راه دور رد شد"), ("Please install plugins", "لطفا افزونه ها را نصب کنید"), ("Peer exit", "میزبان خارج شد"), diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 0eeb71afb..a343202e1 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Succès"), ("Someone turns on privacy mode, exit", "Quelqu'un active le mode de confidentialité, quittez"), ("Unsupported", "Non pris en charge"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Pair refusé"), ("Please install plugins", "Veuillez installer les plugins"), ("Peer exit", "Sortie des pairs"), diff --git a/src/lang/gr.rs b/src/lang/gr.rs index ec961f2e1..b38a96065 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Επιτυχής"), ("Someone turns on privacy mode, exit", "Κάποιος ενεργοποιεί τη λειτουργία απορρήτου, έξοδος"), ("Unsupported", "Δεν υποστηρίζεται"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Ο απομακρυσμένος σταθμός απέρριψε τη σύνδεση"), ("Please install plugins", "Παρακαλώ εγκαταστήστε τα πρόσθετα"), ("Peer exit", "Ο απομακρυσμένος σταθμός έχει αποσυνδεθεί"), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 6ea7c561e..2f6aafe95 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Sikeres"), ("Someone turns on privacy mode, exit", "Valaki bekacsolta az inkognitó módot, lépjen ki"), ("Unsupported", "Nem támogatott"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Elutasítva a távoli fél álltal"), ("Please install plugins", "Kérem telepítse a bővítményeket"), ("Peer exit", "A távoli fél kilépett"), diff --git a/src/lang/id.rs b/src/lang/id.rs index b617190fd..65f9f236e 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Berhasil"), ("Someone turns on privacy mode, exit", "Seseorang mengaktifkan mode privasi, keluar"), ("Unsupported", "Tidak didukung"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Rekan ditolak"), ("Please install plugins", "Silakan instal plugin"), ("Peer exit", "keluar rekan"), diff --git a/src/lang/it.rs b/src/lang/it.rs index 713c73fa6..b8a4af50e 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Successo"), ("Someone turns on privacy mode, exit", "Qualcuno attiva la modalità privacy, esci"), ("Unsupported", "Non supportato"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Peer negato"), ("Please install plugins", "Si prega di installare i plugin"), ("Peer exit", "Uscita tra pari"), diff --git a/src/lang/ja.rs b/src/lang/ja.rs index c4d29ad73..275b520c4 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "成功"), ("Someone turns on privacy mode, exit", "プライバシーモードがオンになりました。終了します。"), ("Unsupported", "サポートされていません"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "相手が拒否しました"), ("Please install plugins", "プラグインをインストールしてください"), ("Peer exit", "相手が終了しました"), diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 3d1330a31..2f303a2f4 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "성공"), ("Someone turns on privacy mode, exit", "누군가가 개인정보 보호 모드를 활성화하여 종료됩니다"), ("Unsupported", "지원되지 않음"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "다른 사용자에 의해 거부됨"), ("Please install plugins", "플러그인을 설치해주세요"), ("Peer exit", "다른 사용자가 나감"), diff --git a/src/lang/kz.rs b/src/lang/kz.rs index c1480377b..9966bb3ae 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Сәтті"), ("Someone turns on privacy mode, exit", "Біреу құпиялылық модасын қосты, шығу"), ("Unsupported", "Қолдаусыз"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Пир қабылдамады"), ("Please install plugins", "Плагиндерді орнатуды өтінеміз"), ("Peer exit", "Пирдің шығуы"), diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 377e40a1d..769bd24d2 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Geslaagd"), ("Someone turns on privacy mode, exit", "Iemand schakelt privacymodus in, afsluiten"), ("Unsupported", "Niet Ondersteund"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Peer geweigerd"), ("Please install plugins", "Installeer plugins"), ("Peer exit", "Peer afgesloten"), diff --git a/src/lang/pl.rs b/src/lang/pl.rs index e4c4839f5..16e14ad3a 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Udało się"), ("Someone turns on privacy mode, exit", "Ktoś włącza tryb prywatności, wyjdź"), ("Unsupported", "Niewspierane"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Odmowa dostępu"), ("Please install plugins", "Zainstaluj wtyczkę"), ("Peer exit", "Wyjście peer"), diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 541023197..90d832417 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Conseguiu"), ("Someone turns on privacy mode, exit", "Alguém activou o modo de privacidade, desligue"), ("Unsupported", "Sem suporte"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Remoto negado"), ("Please install plugins", "Por favor instale plugins"), ("Peer exit", "Saída do Remoto"), diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 1a35421fd..4dcf298aa 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Sucesso"), ("Someone turns on privacy mode, exit", "Alguém habilitou o modo de privacidade, sair"), ("Unsupported", "Não suportado"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Parceiro negou"), ("Please install plugins", "Por favor instale plugins"), ("Peer exit", "Parceiro saiu"), diff --git a/src/lang/ro.rs b/src/lang/ro.rs index ccfeb412c..69de05fd8 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Reușit"), ("Someone turns on privacy mode, exit", "Cineva activează modul privat, ieși din"), ("Unsupported", "Neacceptat"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Dispozitiv pereche refuzat"), ("Please install plugins", "Instalează pluginuri"), ("Peer exit", "Ieșire dispozitiv pereche"), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 8692d1d87..8d3ea0e37 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Выполнено"), ("Someone turns on privacy mode, exit", "Кто-то включает режим конфиденциальности, выход"), ("Unsupported", "Не поддерживается"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Отклонено удалённым узлом"), ("Please install plugins", "Установите плагины"), ("Peer exit", "Удалённый узел отключён"), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index be48c7338..24937438c 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Podarilo sa"), ("Someone turns on privacy mode, exit", "Niekto zapne režim súkromia, ukončite ho"), ("Unsupported", "Nepodporované"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Peer poprel"), ("Please install plugins", "Nainštalujte si prosím pluginy"), ("Peer exit", "Peer exit"), diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 0706c38c0..56dc7537b 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Uspelo"), ("Someone turns on privacy mode, exit", "Vklopljen je zasebni način, izhod"), ("Unsupported", "Ni podprto"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Odjemalec zavrnil"), ("Please install plugins", "Namestite vključke"), ("Peer exit", "Odjemalec se je zaprl"), diff --git a/src/lang/sq.rs b/src/lang/sq.rs index fac32f1a7..389f01dfc 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Sukses"), ("Someone turns on privacy mode, exit", "Dikush ka ndezur menyrën e privatësisë , largohu"), ("Unsupported", "Nuk mbështetet"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Peer mohohet"), ("Please install plugins", "Ju lutemi instaloni shtojcat"), ("Peer exit", "Dalje peer"), diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 85903f03a..15deabb30 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Uspešno"), ("Someone turns on privacy mode, exit", "Neko je uključio mod privatnosti, izlaz."), ("Unsupported", "Nepodržano"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Klijent zabranjen"), ("Please install plugins", "Molimo instalirajte dodatke"), ("Peer exit", "Klijent izašao"), diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 2987c9e57..2ba640b26 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Lyckades"), ("Someone turns on privacy mode, exit", "Någon sätter på säkerhetesläge, avsluta"), ("Unsupported", "Stöds inte"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Klienten nekade"), ("Please install plugins", "Var god installera plugins"), ("Peer exit", "Avsluta klient"), diff --git a/src/lang/template.rs b/src/lang/template.rs index 94e0d8fa1..4e4b20e41 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", ""), ("Someone turns on privacy mode, exit", ""), ("Unsupported", ""), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", ""), ("Please install plugins", ""), ("Peer exit", ""), diff --git a/src/lang/th.rs b/src/lang/th.rs index 05d727e7b..8fb653fd8 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "สำเร็จ"), ("Someone turns on privacy mode, exit", "มีใครบางคนเปิดใช้งานโหมดความเป็นส่วนตัว กำลังออก"), ("Unsupported", "ไม่รองรับ"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "ถูกปฏิเสธโดยอีกฝั่ง"), ("Please install plugins", "กรุณาติดตั้งปลั๊กอิน"), ("Peer exit", "อีกฝั่งออก"), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 280ed4099..424c18f14 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "başarılı"), ("Someone turns on privacy mode, exit", "Birisi gizlilik modunu açarsa, çık"), ("Unsupported", "desteklenmiyor"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "eş reddedildi"), ("Please install plugins", "Lütfen eklentileri yükleyin"), ("Peer exit", "eş çıkışı"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 7ad3074f9..3ec448132 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "成功"), ("Someone turns on privacy mode, exit", "其他用戶開啟隱私模式,退出"), ("Unsupported", "不支持"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "被控端拒絕"), ("Please install plugins", "請安裝插件"), ("Peer exit", "被控端退出"), diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 9211bd286..19b3aa355 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Успішно"), ("Someone turns on privacy mode, exit", "Хтось вмикає режим конфіденційності, вихід"), ("Unsupported", "Не підтримується"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Відхилено віддаленим комп'ютером"), ("Please install plugins", "Будь ласка, встановіть плагіни"), ("Peer exit", "Відключено віддаленим комп'ютером"), diff --git a/src/lang/vn.rs b/src/lang/vn.rs index a26ae1225..f2a2bb748 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Thành công"), ("Someone turns on privacy mode, exit", "Ai đó đã bật chế độ riêng tư, thoát"), ("Unsupported", "Không hỗ trợ"), - ("Please switch to Display 1 first", "") + ("Please switch to Display 1 first", ""), ("Peer denied", "Peer đã từ chối"), ("Please install plugins", "Hãy cài plugins"), ("Peer exit", "Peer đã thoát"), diff --git a/src/win_privacy.rs b/src/win_privacy.rs index 9944bf262..ad66c4639 100644 --- a/src/win_privacy.rs +++ b/src/win_privacy.rs @@ -245,7 +245,7 @@ pub fn start() -> ResultType<()> { wnd_handlers.hthread = proc_info.hThread as _; wnd_handlers.hprocess = proc_info.hProcess as _; - let hwnd = wait_find_privacy_hwnd(1_000)?; + let hwnd = wait_find_privacy_hwnd(30_000)?; if hwnd.is_null() { bail!("Failed to get hwnd after started"); } From 37d21d8db0f8fbc3e1975d97fa1fdfc748680e64 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 6 Mar 2023 17:26:26 +0800 Subject: [PATCH 220/382] remove unused logic Signed-off-by: fufesou --- libs/scrap/src/dxgi/mag.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libs/scrap/src/dxgi/mag.rs b/libs/scrap/src/dxgi/mag.rs index b2bea1dd1..62e90c08b 100644 --- a/libs/scrap/src/dxgi/mag.rs +++ b/libs/scrap/src/dxgi/mag.rs @@ -127,15 +127,6 @@ impl MagInterface { }; s.init_succeeded = false; unsafe { - if GetSystemMetrics(SM_CMONITORS) != 1 { - // Do not try to use the magnifier in multi-screen setup (where the API - // crashes sometimes). - return Err(Error::new( - ErrorKind::Other, - "Magnifier capturer cannot work on multi-screen system.", - )); - } - // load lib let lib_file_name = "Magnification.dll"; let lib_file_name_c = CString::new(lib_file_name).unwrap(); From fdeb38fee74ce8b27dda3def1ad3b9a99059c11c Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 6 Mar 2023 17:33:47 +0800 Subject: [PATCH 221/382] change timeout for waiting hwnd Signed-off-by: fufesou --- src/win_privacy.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win_privacy.rs b/src/win_privacy.rs index ad66c4639..9944bf262 100644 --- a/src/win_privacy.rs +++ b/src/win_privacy.rs @@ -245,7 +245,7 @@ pub fn start() -> ResultType<()> { wnd_handlers.hthread = proc_info.hThread as _; wnd_handlers.hprocess = proc_info.hProcess as _; - let hwnd = wait_find_privacy_hwnd(30_000)?; + let hwnd = wait_find_privacy_hwnd(1_000)?; if hwnd.is_null() { bail!("Failed to get hwnd after started"); } From fac4a966b2256a01d08f51bbf98b8c6415a4f2a8 Mon Sep 17 00:00:00 2001 From: mehdi-song Date: Mon, 6 Mar 2023 13:24:48 +0330 Subject: [PATCH 222/382] Update fa.rs --- 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 66ec011c4..99099bfd2 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -301,7 +301,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "موفقیت آمیز"), ("Someone turns on privacy mode, exit", "اگر شخصی حالت حریم خصوصی را روشن کرد، خارج شوید"), ("Unsupported", "پشتیبانی نشده"), - ("Please switch to Display 1 first", ""), + ("Please switch to Display 1 first", "لطفاً ابتدا به صفحه نمایش 1 بروید"), ("Peer denied", "توسط میزبان راه دور رد شد"), ("Please install plugins", "لطفا افزونه ها را نصب کنید"), ("Peer exit", "میزبان خارج شد"), From 6e21ddcc9c7ffc360964282801537619180b1956 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Mon, 6 Mar 2023 17:59:23 +0800 Subject: [PATCH 223/382] remove "Please switch to Display 1 first", which is temp used, don't bother contributors translate it --- 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/nl.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 - 33 files changed, 33 deletions(-) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 57787dead..89cc46920 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Aconseguit"), ("Someone turns on privacy mode, exit", "Algú ha activat el mode de privacitat, surti"), ("Unsupported", "No suportat"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Peer denegat"), ("Please install plugins", "Instal·li complements"), ("Peer exit", "El peer ha sortit"), diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 55e805848..3f4f6d25c 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "成功"), ("Someone turns on privacy mode, exit", "其他用户使用隐私模式,退出"), ("Unsupported", "不支持"), - ("Please switch to Display 1 first", "请先切换到第一个屏"), ("Peer denied", "被控端拒绝"), ("Please install plugins", "请安装插件"), ("Peer exit", "被控端退出"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 3ee9e5233..a2813815b 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Uspěl"), ("Someone turns on privacy mode, exit", "Někdo zapne režim soukromí, ukončete ho"), ("Unsupported", "Nepodporováno"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Peer popřel"), ("Please install plugins", "Nainstalujte si prosím pluginy"), ("Peer exit", "Peer exit"), diff --git a/src/lang/da.rs b/src/lang/da.rs index e3e5a4049..2760f94fb 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Vellykket"), ("Someone turns on privacy mode, exit", "Nogen aktiverede databeskyttelsestilstand, slut"), ("Unsupported", "Ikke understøttet"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Peer nægtet"), ("Please install plugins", "Venligst Installer plugins"), ("Peer exit", "Peer-Afslut"), diff --git a/src/lang/de.rs b/src/lang/de.rs index c562472be..36493f747 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Erfolgreich"), ("Someone turns on privacy mode, exit", "Jemand hat den Datenschutzmodus aktiviert, beende …"), ("Unsupported", "Nicht unterstützt"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Die Gegenstelle hat die Verbindung abgelehnt."), ("Please install plugins", "Bitte installieren Sie Plugins"), ("Peer exit", "Die Gegenstelle hat die Verbindung getrennt."), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index cbbeecc10..7a191f05d 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", ""), ("Someone turns on privacy mode, exit", ""), ("Unsupported", ""), - ("Please switch to Display 1 first", ""), ("Peer denied", ""), ("Please install plugins", ""), ("Peer exit", ""), diff --git a/src/lang/es.rs b/src/lang/es.rs index bd4df8e04..b290c7696 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Logrado"), ("Someone turns on privacy mode, exit", "Alguien active el modo privacidad, salga"), ("Unsupported", "No soportado"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Par denegado"), ("Please install plugins", "Instale complementos"), ("Peer exit", "Par salio"), diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 99099bfd2..7fe279a1b 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "موفقیت آمیز"), ("Someone turns on privacy mode, exit", "اگر شخصی حالت حریم خصوصی را روشن کرد، خارج شوید"), ("Unsupported", "پشتیبانی نشده"), - ("Please switch to Display 1 first", "لطفاً ابتدا به صفحه نمایش 1 بروید"), ("Peer denied", "توسط میزبان راه دور رد شد"), ("Please install plugins", "لطفا افزونه ها را نصب کنید"), ("Peer exit", "میزبان خارج شد"), diff --git a/src/lang/fr.rs b/src/lang/fr.rs index a343202e1..dd436831e 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Succès"), ("Someone turns on privacy mode, exit", "Quelqu'un active le mode de confidentialité, quittez"), ("Unsupported", "Non pris en charge"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Pair refusé"), ("Please install plugins", "Veuillez installer les plugins"), ("Peer exit", "Sortie des pairs"), diff --git a/src/lang/gr.rs b/src/lang/gr.rs index b38a96065..8629879ca 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Επιτυχής"), ("Someone turns on privacy mode, exit", "Κάποιος ενεργοποιεί τη λειτουργία απορρήτου, έξοδος"), ("Unsupported", "Δεν υποστηρίζεται"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Ο απομακρυσμένος σταθμός απέρριψε τη σύνδεση"), ("Please install plugins", "Παρακαλώ εγκαταστήστε τα πρόσθετα"), ("Peer exit", "Ο απομακρυσμένος σταθμός έχει αποσυνδεθεί"), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 2f6aafe95..8727c53c2 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Sikeres"), ("Someone turns on privacy mode, exit", "Valaki bekacsolta az inkognitó módot, lépjen ki"), ("Unsupported", "Nem támogatott"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Elutasítva a távoli fél álltal"), ("Please install plugins", "Kérem telepítse a bővítményeket"), ("Peer exit", "A távoli fél kilépett"), diff --git a/src/lang/id.rs b/src/lang/id.rs index 65f9f236e..b363a2ae8 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Berhasil"), ("Someone turns on privacy mode, exit", "Seseorang mengaktifkan mode privasi, keluar"), ("Unsupported", "Tidak didukung"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Rekan ditolak"), ("Please install plugins", "Silakan instal plugin"), ("Peer exit", "keluar rekan"), diff --git a/src/lang/it.rs b/src/lang/it.rs index b8a4af50e..340794ceb 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Successo"), ("Someone turns on privacy mode, exit", "Qualcuno attiva la modalità privacy, esci"), ("Unsupported", "Non supportato"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Peer negato"), ("Please install plugins", "Si prega di installare i plugin"), ("Peer exit", "Uscita tra pari"), diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 275b520c4..260c27607 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "成功"), ("Someone turns on privacy mode, exit", "プライバシーモードがオンになりました。終了します。"), ("Unsupported", "サポートされていません"), - ("Please switch to Display 1 first", ""), ("Peer denied", "相手が拒否しました"), ("Please install plugins", "プラグインをインストールしてください"), ("Peer exit", "相手が終了しました"), diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 2f303a2f4..f101ae20b 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "성공"), ("Someone turns on privacy mode, exit", "누군가가 개인정보 보호 모드를 활성화하여 종료됩니다"), ("Unsupported", "지원되지 않음"), - ("Please switch to Display 1 first", ""), ("Peer denied", "다른 사용자에 의해 거부됨"), ("Please install plugins", "플러그인을 설치해주세요"), ("Peer exit", "다른 사용자가 나감"), diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 9966bb3ae..fe0937a65 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Сәтті"), ("Someone turns on privacy mode, exit", "Біреу құпиялылық модасын қосты, шығу"), ("Unsupported", "Қолдаусыз"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Пир қабылдамады"), ("Please install plugins", "Плагиндерді орнатуды өтінеміз"), ("Peer exit", "Пирдің шығуы"), diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 769bd24d2..63d3cee7b 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Geslaagd"), ("Someone turns on privacy mode, exit", "Iemand schakelt privacymodus in, afsluiten"), ("Unsupported", "Niet Ondersteund"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Peer geweigerd"), ("Please install plugins", "Installeer plugins"), ("Peer exit", "Peer afgesloten"), diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 16e14ad3a..0c5f13659 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Udało się"), ("Someone turns on privacy mode, exit", "Ktoś włącza tryb prywatności, wyjdź"), ("Unsupported", "Niewspierane"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Odmowa dostępu"), ("Please install plugins", "Zainstaluj wtyczkę"), ("Peer exit", "Wyjście peer"), diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 90d832417..8eb4df2ad 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Conseguiu"), ("Someone turns on privacy mode, exit", "Alguém activou o modo de privacidade, desligue"), ("Unsupported", "Sem suporte"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Remoto negado"), ("Please install plugins", "Por favor instale plugins"), ("Peer exit", "Saída do Remoto"), diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 4dcf298aa..973048f3d 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Sucesso"), ("Someone turns on privacy mode, exit", "Alguém habilitou o modo de privacidade, sair"), ("Unsupported", "Não suportado"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Parceiro negou"), ("Please install plugins", "Por favor instale plugins"), ("Peer exit", "Parceiro saiu"), diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 69de05fd8..9e252aa8a 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Reușit"), ("Someone turns on privacy mode, exit", "Cineva activează modul privat, ieși din"), ("Unsupported", "Neacceptat"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Dispozitiv pereche refuzat"), ("Please install plugins", "Instalează pluginuri"), ("Peer exit", "Ieșire dispozitiv pereche"), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 8d3ea0e37..4c1f9ae34 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Выполнено"), ("Someone turns on privacy mode, exit", "Кто-то включает режим конфиденциальности, выход"), ("Unsupported", "Не поддерживается"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Отклонено удалённым узлом"), ("Please install plugins", "Установите плагины"), ("Peer exit", "Удалённый узел отключён"), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 24937438c..d60384286 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Podarilo sa"), ("Someone turns on privacy mode, exit", "Niekto zapne režim súkromia, ukončite ho"), ("Unsupported", "Nepodporované"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Peer poprel"), ("Please install plugins", "Nainštalujte si prosím pluginy"), ("Peer exit", "Peer exit"), diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 56dc7537b..bd07b1acb 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Uspelo"), ("Someone turns on privacy mode, exit", "Vklopljen je zasebni način, izhod"), ("Unsupported", "Ni podprto"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Odjemalec zavrnil"), ("Please install plugins", "Namestite vključke"), ("Peer exit", "Odjemalec se je zaprl"), diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 389f01dfc..b8f9203ca 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Sukses"), ("Someone turns on privacy mode, exit", "Dikush ka ndezur menyrën e privatësisë , largohu"), ("Unsupported", "Nuk mbështetet"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Peer mohohet"), ("Please install plugins", "Ju lutemi instaloni shtojcat"), ("Peer exit", "Dalje peer"), diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 15deabb30..4a9b73374 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Uspešno"), ("Someone turns on privacy mode, exit", "Neko je uključio mod privatnosti, izlaz."), ("Unsupported", "Nepodržano"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Klijent zabranjen"), ("Please install plugins", "Molimo instalirajte dodatke"), ("Peer exit", "Klijent izašao"), diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 2ba640b26..f73154e3e 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Lyckades"), ("Someone turns on privacy mode, exit", "Någon sätter på säkerhetesläge, avsluta"), ("Unsupported", "Stöds inte"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Klienten nekade"), ("Please install plugins", "Var god installera plugins"), ("Peer exit", "Avsluta klient"), diff --git a/src/lang/template.rs b/src/lang/template.rs index 4e4b20e41..e51a095c0 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", ""), ("Someone turns on privacy mode, exit", ""), ("Unsupported", ""), - ("Please switch to Display 1 first", ""), ("Peer denied", ""), ("Please install plugins", ""), ("Peer exit", ""), diff --git a/src/lang/th.rs b/src/lang/th.rs index 8fb653fd8..3214c3452 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "สำเร็จ"), ("Someone turns on privacy mode, exit", "มีใครบางคนเปิดใช้งานโหมดความเป็นส่วนตัว กำลังออก"), ("Unsupported", "ไม่รองรับ"), - ("Please switch to Display 1 first", ""), ("Peer denied", "ถูกปฏิเสธโดยอีกฝั่ง"), ("Please install plugins", "กรุณาติดตั้งปลั๊กอิน"), ("Peer exit", "อีกฝั่งออก"), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 424c18f14..82f95ef84 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "başarılı"), ("Someone turns on privacy mode, exit", "Birisi gizlilik modunu açarsa, çık"), ("Unsupported", "desteklenmiyor"), - ("Please switch to Display 1 first", ""), ("Peer denied", "eş reddedildi"), ("Please install plugins", "Lütfen eklentileri yükleyin"), ("Peer exit", "eş çıkışı"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 3ec448132..d0f12cdfa 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "成功"), ("Someone turns on privacy mode, exit", "其他用戶開啟隱私模式,退出"), ("Unsupported", "不支持"), - ("Please switch to Display 1 first", ""), ("Peer denied", "被控端拒絕"), ("Please install plugins", "請安裝插件"), ("Peer exit", "被控端退出"), diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 19b3aa355..793d1e147 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Успішно"), ("Someone turns on privacy mode, exit", "Хтось вмикає режим конфіденційності, вихід"), ("Unsupported", "Не підтримується"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Відхилено віддаленим комп'ютером"), ("Please install plugins", "Будь ласка, встановіть плагіни"), ("Peer exit", "Відключено віддаленим комп'ютером"), diff --git a/src/lang/vn.rs b/src/lang/vn.rs index f2a2bb748..fc665834d 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -301,7 +301,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Succeeded", "Thành công"), ("Someone turns on privacy mode, exit", "Ai đó đã bật chế độ riêng tư, thoát"), ("Unsupported", "Không hỗ trợ"), - ("Please switch to Display 1 first", ""), ("Peer denied", "Peer đã từ chối"), ("Please install plugins", "Hãy cài plugins"), ("Peer exit", "Peer đã thoát"), From 35e9815e9e5395d5c9ad341ee285651ffc186382 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Mon, 6 Mar 2023 18:02:47 +0800 Subject: [PATCH 224/382] temporary password -> one-time password --- src/lang/ca.rs | 2 +- src/lang/cn.rs | 2 +- src/lang/cs.rs | 2 +- src/lang/da.rs | 2 +- src/lang/de.rs | 2 +- src/lang/eo.rs | 2 +- src/lang/es.rs | 2 +- src/lang/fa.rs | 2 +- src/lang/fr.rs | 2 +- src/lang/gr.rs | 2 +- src/lang/hu.rs | 2 +- src/lang/id.rs | 2 +- src/lang/it.rs | 2 +- src/lang/ja.rs | 2 +- src/lang/ko.rs | 2 +- src/lang/kz.rs | 2 +- src/lang/nl.rs | 2 +- src/lang/pl.rs | 2 +- src/lang/pt_PT.rs | 2 +- src/lang/ptbr.rs | 2 +- src/lang/ro.rs | 2 +- src/lang/ru.rs | 2 +- src/lang/sk.rs | 2 +- src/lang/sl.rs | 2 +- src/lang/sq.rs | 2 +- src/lang/sr.rs | 2 +- src/lang/sv.rs | 2 +- src/lang/template.rs | 2 +- src/lang/th.rs | 2 +- src/lang/tr.rs | 2 +- src/lang/tw.rs | 2 +- src/lang/ua.rs | 2 +- src/lang/vn.rs | 2 +- 33 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index a8f5758ee..c4bc10bb4 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 03e253bfb..163c50e1b 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "编解码"), ("Resolution", "分辨率"), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index e85c95969..e3ddc5db8 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index f933972d9..f37f30a61 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 5ac7de62e..0829bc2b6 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Codec"), ("Resolution", "Auflösung"), ("No transfers in progress", "Keine Übertragungen im Gange"), - ("Set temporary password length", "Temporäre Passwortlänge festlegen"), + ("Set one-time password length", "Temporäre Passwortlänge festlegen"), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 667071e3f..ed64addf8 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index a93d0ccd9..1c780f842 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Códec"), ("Resolution", "Resolución"), ("No transfers in progress", "No hay transferencias en curso"), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index d20f321f3..a04103d0b 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "کدک"), ("Resolution", "وضوح"), ("No transfers in progress", "هیچ انتقالی در حال انجام نیست"), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index bc6a23d71..c0d739f91 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/gr.rs b/src/lang/gr.rs index 9158c37e2..819c257c3 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Κωδικοποίηση"), ("Resolution", "Ανάλυση"), ("No transfers in progress", "Δεν υπάρχει μεταφορά σε εξέλιξη"), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 62ec3b018..46750eb13 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 996fd3a3b..4133f136f 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 65e685f4c..17f066eef 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Codec"), ("Resolution", "Risoluzione"), ("No transfers in progress", "Nessun trasferimento in corso"), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 00b71c57b..b8031573a 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index f2cbc2ab0..fe6a0bfe9 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index d0b712ff5..4b1e92cad 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index fc4490aae..7888eed8e 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Codec"), ("Resolution", "Resolutie"), ("No transfers in progress", "Geen overdrachten in uitvoering"), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index b1cd7eb7c..b997267f1 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Kodek"), ("Resolution", "Rozdzielczość"), ("No transfers in progress", "Brak transferów w toku"), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 6f3504218..98b8035a4 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index cbb0651a9..18c9168c1 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 76a234aff..225fa7277 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index a8705d531..8a8b7f9c1 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Кодек"), ("Resolution", "Разрешение"), ("No transfers in progress", "Передача не осуществляется"), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 55bf55aff..cec9e5b3d 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 39e54b66d..295cd28a1 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 86f877aa0..ebbdf4a28 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 24ddb85be..67fb49799 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index a565be50e..9da1f1071 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 638bb4d21..cbbd65b4c 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 2f2c4fa31..97a8725e3 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index cf7e9997b..3b1137cb7 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index fc1576db7..72a38afcd 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "編解碼"), ("Resolution", "分辨率"), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 1eb6eea7a..4665d7c39 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 193408b0e..0130b11cf 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", ""), ("Resolution", ""), ("No transfers in progress", ""), - ("Set temporary password length", ""), + ("Set one-time password length", ""), ].iter().cloned().collect(); } From 8a083f40b0a560f18d673751c1ac54cd428aef25 Mon Sep 17 00:00:00 2001 From: csf Date: Mon, 6 Mar 2023 23:37:43 +0900 Subject: [PATCH 225/382] fix mobile change theme failure --- flutter/lib/common.dart | 2 +- src/lang/cn.rs | 2 +- src/lang/tw.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index dc91e9414..3d6f62efc 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -375,7 +375,7 @@ class MyTheme { static void changeDarkMode(ThemeMode mode) async { Get.changeThemeMode(mode); - if (desktopType == DesktopType.main) { + if (desktopType == DesktopType.main || isAndroid || isIOS) { if (mode == ThemeMode.system) { await bind.mainSetLocalOption(key: kCommConfKeyTheme, value: ''); } else { diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 3f4f6d25c..b5f71e588 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -349,7 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "安全"), ("Theme", "主题"), ("Dark Theme", "暗黑主题"), - ("Light Theme", ""), + ("Light Theme", "明亮主题"), ("Dark", "黑暗"), ("Light", "明亮"), ("Follow System", "跟随系统"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index d0f12cdfa..3fb2297e3 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -349,7 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "安全"), ("Theme", "主題"), ("Dark Theme", "暗黑主題"), - ("Light Theme", ""), + ("Light Theme", "明亮主題"), ("Dark", "黑暗"), ("Light", "明亮"), ("Follow System", "跟隨系統"), From c6fa97229918c1ff1bf3467d1f9720c63aeec1a5 Mon Sep 17 00:00:00 2001 From: dinger1986 Date: Mon, 6 Mar 2023 20:37:09 +0000 Subject: [PATCH 226/382] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3e0fb463f..45311c4b4 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,9 @@ Below are the servers you are using for free, they may change over time. If you | Seoul | AWS lightsail | 1 vCPU / 0.5GB RAM | | Germany | Hetzner | 2 vCPU / 4GB RAM | | Germany | Codext | 4 vCPU / 8GB RAM | -| Finland (Helsinki) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| Ukraine (Kyiv) | dc.volia (2VM) | 2 vCPU / 4GB RAM | +| Finland (Helsinki) | [Donated by Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| USA (Ashburn) | [Donated by Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| Ukraine (Kyiv) | [Donated by dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | ## Dev Container From 5a9e9e7f863dc793ab30e60820d0648aba2cb4d2 Mon Sep 17 00:00:00 2001 From: dinger1986 Date: Mon, 6 Mar 2023 20:38:35 +0000 Subject: [PATCH 227/382] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 45311c4b4..4e3b309c5 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,9 @@ Below are the servers you are using for free, they may change over time. If you | Seoul | AWS lightsail | 1 vCPU / 0.5GB RAM | | Germany | Hetzner | 2 vCPU / 4GB RAM | | Germany | Codext | 4 vCPU / 8GB RAM | -| Finland (Helsinki) | [Donated by Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | -| USA (Ashburn) | [Donated by Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | -| Ukraine (Kyiv) | [Donated by dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | +| Finland (Helsinki) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| USA (Ashburn) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| Ukraine (Kyiv) | [dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | ## Dev Container From f6eb7763ba8ae2b196cf445add9c442fed0a4e0f Mon Sep 17 00:00:00 2001 From: dinger1986 Date: Mon, 6 Mar 2023 20:38:59 +0000 Subject: [PATCH 228/382] Update README-NL.md --- docs/README-NL.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/README-NL.md b/docs/README-NL.md index 422890827..4a5372e67 100644 --- a/docs/README-NL.md +++ b/docs/README-NL.md @@ -27,8 +27,9 @@ Onderstaande servers zijn de servers die je gratis kunt gebruiken, ze kunnen op | Seoul | AWS lightsail | 1 vCPU / 0.5GB RAM | | Germany | Hetzner | 2 vCPU / 4GB RAM | | Germany | Codext | 4 vCPU / 8GB RAM | -| Finland (Helsinki) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | +| Finland (Helsinki) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| USA (Ashburn) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| Ukraine (Kyiv) | [dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | ## Afhankelijkheden From 0120663c8a4e6c1aff28190c6ebfecf4364b3a88 Mon Sep 17 00:00:00 2001 From: dinger1986 Date: Mon, 6 Mar 2023 20:39:41 +0000 Subject: [PATCH 229/382] Update README-UA.md --- docs/README-UA.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/README-UA.md b/docs/README-UA.md index 5d4a0a1ad..6e933cea9 100644 --- a/docs/README-UA.md +++ b/docs/README-UA.md @@ -35,8 +35,9 @@ RustDesk вітає внесок кожного. Дивіться [`docs/CONTRIB | Даллас | Vultr | 1 vCPU / 1GB RAM Німеччина | Hetzner | 2 vCPU / 4GB RAM | 2 VCPU / 4GB RAM | Німеччина | Hetzner | 2 VCPU / 4GB RAM | | Germany | Codext | 4 vCPU / 8GB RAM | -| Finland (Helsinki) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | +| Finland (Helsinki) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| USA (Ashburn) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| Ukraine (Kyiv) | [dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | ## Залежності From 7be24b7adb34707e655fe9d0296bad897aaeef86 Mon Sep 17 00:00:00 2001 From: dinger1986 Date: Mon, 6 Mar 2023 20:40:02 +0000 Subject: [PATCH 230/382] Update README-HU.md --- docs/README-HU.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/README-HU.md b/docs/README-HU.md index 62ba33482..9582cf1c6 100644 --- a/docs/README-HU.md +++ b/docs/README-HU.md @@ -35,8 +35,9 @@ Ezalatt az üzenet alatt találhatóak azok a publikus szerverek, amelyeket ingy | Seoul | AWS lightsail | 1 vCPU / 0.5GB RAM | | Germany | Hetzner | 2 vCPU / 4GB RAM | | Germany | Codext | 4 vCPU / 8GB RAM | -| Finland (Helsinki) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | +| Finland (Helsinki) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| USA (Ashburn) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| Ukraine (Kyiv) | [dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | ## Dependencies From ec1a02cae0fa21a87357b5600253166d14944209 Mon Sep 17 00:00:00 2001 From: dinger1986 Date: Mon, 6 Mar 2023 20:40:23 +0000 Subject: [PATCH 231/382] Update README-ES.md --- docs/README-ES.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/README-ES.md b/docs/README-ES.md index b7b828f13..66fc609fb 100644 --- a/docs/README-ES.md +++ b/docs/README-ES.md @@ -34,8 +34,9 @@ A continuación se muestran los servidores gratuitos, pueden cambiar a medida qu | Seoul | AWS lightsail | 1 vCPU / 0.5GB RAM | | Germany | Hetzner | 2 vCPU / 4GB RAM | | Germany | Codext | 4 vCPU / 8GB RAM | -| Finland (Helsinki) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | +| Finland (Helsinki) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| USA (Ashburn) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| Ukraine (Kyiv) | [dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | ## Dependencias From 55cd4ecd49e86720b8627003b4ef1dd88f33679c Mon Sep 17 00:00:00 2001 From: dinger1986 Date: Mon, 6 Mar 2023 20:40:43 +0000 Subject: [PATCH 232/382] Update README-PL.md --- docs/README-PL.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/README-PL.md b/docs/README-PL.md index 05e6d8da5..df8254f3d 100644 --- a/docs/README-PL.md +++ b/docs/README-PL.md @@ -27,8 +27,9 @@ Poniżej znajdują się serwery, z których można korzystać za darmo, może si | Seoul | AWS lightsail | 1 vCPU / 0.5GB RAM | | Germany | Hetzner | 2 vCPU / 4GB RAM | | Germany | Codext | 4 vCPU / 8GB RAM | -| Finland (Helsinki) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | +| Finland (Helsinki) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| USA (Ashburn) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| Ukraine (Kyiv) | [dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | ## Zależności From bf1a8a710d06dfa04dca7170f0412035b8124c31 Mon Sep 17 00:00:00 2001 From: dinger1986 Date: Mon, 6 Mar 2023 20:41:02 +0000 Subject: [PATCH 233/382] Update README-ID.md --- docs/README-ID.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/README-ID.md b/docs/README-ID.md index 2fdcd3646..702966566 100644 --- a/docs/README-ID.md +++ b/docs/README-ID.md @@ -27,8 +27,9 @@ Di bawah ini adalah server yang bisa Anda gunakan secara gratis, dapat berubah s | Seoul | AWS lightsail | 1 vCPU / 0.5GB RAM | | Germany | Hetzner | 2 vCPU / 4GB RAM | | Germany | Codext | 4 vCPU / 8GB RAM | -| Finland (Helsinki) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | +| Finland (Helsinki) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| USA (Ashburn) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| Ukraine (Kyiv) | [dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | ## Dependencies From d440831cda1eed494d6b13cf6d7f02f1d91d07c8 Mon Sep 17 00:00:00 2001 From: dinger1986 Date: Mon, 6 Mar 2023 20:41:24 +0000 Subject: [PATCH 234/382] Update README-FI.md --- docs/README-FI.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/README-FI.md b/docs/README-FI.md index d110e195a..8674bc1b3 100644 --- a/docs/README-FI.md +++ b/docs/README-FI.md @@ -27,8 +27,9 @@ Alla on palvelimia, joita voit käyttää ilmaiseksi, ne saattavat muuttua ajan | Seoul | AWS lightsail | 1 vCPU / 0.5GB RAM | | Germany | Hetzner | 2 vCPU / 4GB RAM | | Germany | Codext | 4 vCPU / 8GB RAM | -| Finland (Helsinki) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | +| Finland (Helsinki) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| USA (Ashburn) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| Ukraine (Kyiv) | [dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | ## Riippuvuudet From c2c801cd113bba04877b71f6f859a1faa7890e5d Mon Sep 17 00:00:00 2001 From: dinger1986 Date: Mon, 6 Mar 2023 20:41:48 +0000 Subject: [PATCH 235/382] Update README-IT.md --- docs/README-IT.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/README-IT.md b/docs/README-IT.md index 0b628f90d..2dec27e40 100644 --- a/docs/README-IT.md +++ b/docs/README-IT.md @@ -27,8 +27,9 @@ Qui sotto trovate i server che possono essere usati gratuitamente, la lista potr | Seoul | AWS lightsail | 1 vCPU / 0.5GB RAM | | Germany | Hetzner | 2 vCPU / 4GB RAM | | Germany | Codext | 4 vCPU / 8GB RAM | -| Finland (Helsinki) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | +| Finland (Helsinki) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| USA (Ashburn) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| Ukraine (Kyiv) | [dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | ## Dipendenze From 950dc493cdd269dc55cf1ab6540fdb7f0fdf8d78 Mon Sep 17 00:00:00 2001 From: dinger1986 Date: Mon, 6 Mar 2023 20:42:35 +0000 Subject: [PATCH 236/382] Update README-EO.md --- docs/README-EO.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/README-EO.md b/docs/README-EO.md index fdde88f11..4bca4a793 100644 --- a/docs/README-EO.md +++ b/docs/README-EO.md @@ -27,8 +27,9 @@ Malsupre estas la serviloj, kiuj vi uzas senpage, ĝi povas ŝanĝi laŭlonge de | Seoul | AWS lightsail | 1 vCPU / 0.5GB RAM | | Germany | Hetzner | 2 vCPU / 4GB RAM | | Germany | Codext | 4 vCPU / 8GB RAM | -| Finland (Helsinki) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | +| Finland (Helsinki) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| USA (Ashburn) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| Ukraine (Kyiv) | [dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | ## Dependantaĵoj From 1f63b6d2a733cfbecc3aeb7121f45ff63f3c628e Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Mon, 6 Mar 2023 23:19:35 +0100 Subject: [PATCH 237/382] Update com.rustdesk.RustDesk.policy --- res/com.rustdesk.RustDesk.policy | 1 + 1 file changed, 1 insertion(+) diff --git a/res/com.rustdesk.RustDesk.policy b/res/com.rustdesk.RustDesk.policy index a77223120..55f13629b 100644 --- a/res/com.rustdesk.RustDesk.policy +++ b/res/com.rustdesk.RustDesk.policy @@ -11,6 +11,7 @@ Authentication is required to change RustDesk options 要更改RustDesk选项, 需要您先通过身份验证 要變更RustDesk選項, 需要您先通過身份驗證 + Authentifizierung zum Ändern der RustDesk-Optionen /usr/share/rustdesk/files/polkit true From f4c80c599074d70742fd823d9c615b64854d1d28 Mon Sep 17 00:00:00 2001 From: "Miguel F. G" <116861809+flusheDData@users.noreply.github.com> Date: Tue, 7 Mar 2023 00:12:01 +0100 Subject: [PATCH 238/382] 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 1c780f842..3270ae26c 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Códec"), ("Resolution", "Resolución"), ("No transfers in progress", "No hay transferencias en curso"), - ("Set one-time password length", ""), + ("Set one-time password length", "Establecer contraseña de un solo uso"), ].iter().cloned().collect(); } From 9f69cf3d6edc76d15a7c82672c0c3245a35ce469 Mon Sep 17 00:00:00 2001 From: csf Date: Tue, 7 Mar 2023 11:08:41 +0900 Subject: [PATCH 239/382] fix mobile server event stream --- flutter/lib/consts.dart | 3 +++ src/flutter.rs | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 95e4d17e7..e2a3c6f0b 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -14,7 +14,10 @@ const String kPeerPlatformAndroid = "Android"; /// [kAppTypeMain] used by 'Desktop Main Page' , 'Mobile (Client and Server)', "Install Page" const String kAppTypeMain = "main"; + +/// [kAppTypeConnectionManager] only for 'Desktop CM Page' const String kAppTypeConnectionManager = "cm"; + const String kAppTypeDesktopRemote = "remote"; const String kAppTypeDesktopFileTransfer = "file transfer"; const String kAppTypeDesktopPortForward = "port forward"; diff --git a/src/flutter.rs b/src/flutter.rs index a39b992bf..354e418eb 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -26,8 +26,14 @@ use std::{ sync::{Arc, RwLock}, }; +/// tag "main" for [Desktop Main Page] and [Mobile (Client and Server)] (the mobile don't need multiple windows, only one global event stream is needed) +/// tag "cm" only for [Desktop CM Page] pub(super) const APP_TYPE_MAIN: &str = "main"; +#[cfg(not(any(target_os = "android", target_os = "ios")))] pub(super) const APP_TYPE_CM: &str = "cm"; +#[cfg(any(target_os = "android", target_os = "ios"))] +pub(super) const APP_TYPE_CM: &str = "main"; + pub(super) const APP_TYPE_DESKTOP_REMOTE: &str = "remote"; pub(super) const APP_TYPE_DESKTOP_FILE_TRANSFER: &str = "file transfer"; pub(super) const APP_TYPE_DESKTOP_PORT_FORWARD: &str = "port forward"; From 617872761c0655b3c7f41ee1db59104cfb252fb3 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Tue, 7 Mar 2023 10:56:35 +0800 Subject: [PATCH 240/382] fix: prevent call minimize when on mobile --- flutter/lib/models/server_model.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flutter/lib/models/server_model.dart b/flutter/lib/models/server_model.dart index 7ee23ec40..40aa68d20 100644 --- a/flutter/lib/models/server_model.dart +++ b/flutter/lib/models/server_model.dart @@ -456,7 +456,8 @@ class ServerModel with ChangeNotifier { Future.delayed(Duration.zero, () async { if (!hideCm) window_on_top(null); }); - if (client.authorized) { + // Only do the hidden task when on Desktop. + if (client.authorized && isDesktop) { cmHiddenTimer = Timer(const Duration(seconds: 3), () { if (!hideCm) windowManager.minimize(); cmHiddenTimer = null; From b5286b005ad80701e6703f197137a827a0cea4f0 Mon Sep 17 00:00:00 2001 From: mehdi-song Date: Tue, 7 Mar 2023 08:34:02 +0330 Subject: [PATCH 241/382] Update fa.rs --- 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 a04103d0b..e2a7e9516 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "کدک"), ("Resolution", "وضوح"), ("No transfers in progress", "هیچ انتقالی در حال انجام نیست"), - ("Set one-time password length", ""), + ("Set one-time password length", "طول رمز یکبار مصرف را تعیین کنید"), ].iter().cloned().collect(); } From f4551234ea741a2fd30c301ce641f4541b5984e1 Mon Sep 17 00:00:00 2001 From: solokot Date: Tue, 7 Mar 2023 11:38:08 +0300 Subject: [PATCH 242/382] Update ru.rs --- src/lang/ru.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 8a8b7f9c1..59957a2cd 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -349,7 +349,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Безопасность"), ("Theme", "Тема"), ("Dark Theme", "Тёмная тема"), - ("Light Theme", ""), + ("Light Theme", "Светлая тема"), ("Dark", "Тёмная"), ("Light", "Светлая"), ("Follow System", "Системная"), @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Кодек"), ("Resolution", "Разрешение"), ("No transfers in progress", "Передача не осуществляется"), - ("Set one-time password length", ""), + ("Set one-time password length", "Установить длину одноразового пароля"), ].iter().cloned().collect(); } From 93d196c2f89929e52c97c992375c459a434a7e45 Mon Sep 17 00:00:00 2001 From: csf Date: Tue, 7 Mar 2023 11:21:23 +0900 Subject: [PATCH 243/382] mobile save config when disable input --- flutter/lib/models/server_model.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flutter/lib/models/server_model.dart b/flutter/lib/models/server_model.dart index 7ee23ec40..90059e47f 100644 --- a/flutter/lib/models/server_model.dart +++ b/flutter/lib/models/server_model.dart @@ -263,8 +263,11 @@ class ServerModel with ChangeNotifier { toggleInput() { if (_inputOk) { parent.target?.invokeMethod("stop_input"); + bind.mainSetOption(key: "enable-keyboard", value: 'N'); } else { if (parent.target != null) { + /// the result of toggle-on depends on user actions in the settings page. + /// handle result, see [ServerModel.changeStatue] showInputWarnAlert(parent.target!); } } From d82cd0b1a724cca22956784183e4a6851987be04 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Tue, 7 Mar 2023 13:31:47 +0100 Subject: [PATCH 244/382] Update de.rs --- src/lang/de.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/lang/de.rs b/src/lang/de.rs index 0829bc2b6..7a935d299 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -125,7 +125,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Good image quality", "Hohe Bildqualität"), ("Balanced", "Ausgeglichen"), ("Optimize reaction time", "Geschwindigkeit"), - ("Custom", "Individuell"), + ("Custom", "Benutzerdefiniert"), ("Show remote cursor", "Entfernten Cursor anzeigen"), ("Show quality monitor", "Qualitätsüberwachung anzeigen"), ("Disable clipboard", "Zwischenablage deaktivieren"), @@ -152,7 +152,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Configure", "Konfigurieren"), ("config_acc", "Um Ihren PC aus der Ferne zu steuern, müssen Sie RustDesk Zugriffsrechte erteilen."), ("config_screen", "Um aus der Ferne auf Ihren PC zugreifen zu können, müssen Sie RustDesk die Berechtigung \"Bildschirmaufnahme\" erteilen."), - ("Installing ...", "Installiere …"), + ("Installing ...", " Wird installiert …"), ("Install", "Installieren"), ("Installation", "Installation"), ("Installation Path", "Installationspfad"), @@ -230,8 +230,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Add Tag", "Stichwort hinzufügen"), ("Unselect all tags", "Alle Stichworte abwählen"), ("Network error", "Netzwerkfehler"), - ("Username missed", "Benutzernamen vergessen"), - ("Password missed", "Passwort vergessen"), + ("Username missed", "Benutzername fehlt"), + ("Password missed", "Passwort fehlt"), ("Wrong credentials", "Falsche Anmeldedaten"), ("Edit Tag", "Schlagwort bearbeiten"), ("Unremember Password", "Gespeichertes Passwort löschen"), @@ -299,7 +299,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Help", "Hilfe"), ("Failed", "Fehlgeschlagen"), ("Succeeded", "Erfolgreich"), - ("Someone turns on privacy mode, exit", "Jemand hat den Datenschutzmodus aktiviert, beende …"), + ("Someone turns on privacy mode, exit", "Jemand hat den Datenschutzmodus aktiviert, wird beendet …"), ("Unsupported", "Nicht unterstützt"), ("Peer denied", "Die Gegenstelle hat die Verbindung abgelehnt."), ("Please install plugins", "Bitte installieren Sie Plugins"), @@ -407,7 +407,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("One-time Password", "Einmalpasswort"), ("Use one-time password", "Einmalpasswort verwenden"), ("One-time password length", "Länge des Einmalpassworts"), - ("Request access to your device", "Zugriff zu Ihrem Gerät erbitten"), + ("Request access to your device", "Zugriff auf Ihr Gerät anfordern"), ("Hide connection management window", "Fenster zur Verwaltung der Verbindung verstecken"), ("hide_cm_tip", "Dies ist nur möglich, wenn der Zugriff über ein permanentes Passwort erfolgt."), ("wayland_experiment_tip", "Die Unterstützung von Wayland ist nur experimentell. Bitte nutzen Sie X11, wenn Sie einen unbeaufsichtigten Zugriff benötigen."), @@ -442,7 +442,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Medium", "Mittel"), ("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."), + ("Please confirm if you want to share your desktop?", "Bitte bestätigen Sie, wenn Sie Ihren Desktop freigeben möchten."), ("Display", "Anzeige"), ("Default View Style", "Standard-Ansichtsstil"), ("Default Scroll Style", "Standard-Scroll-Stil"), @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Codec"), ("Resolution", "Auflösung"), ("No transfers in progress", "Keine Übertragungen im Gange"), - ("Set one-time password length", "Temporäre Passwortlänge festlegen"), + ("Set one-time password length", "Länge des Einmalpassworts festlegen"), ].iter().cloned().collect(); } From 2108e5ea960b91517dab44fb73257b14ddf6e446 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Tue, 7 Mar 2023 14:07:20 +0100 Subject: [PATCH 245/382] Update chat_page.dart Ellipsis removed because no windows or dialogs open. --- flutter/lib/common/widgets/chat_page.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/lib/common/widgets/chat_page.dart b/flutter/lib/common/widgets/chat_page.dart index c1991633a..9460f4f41 100644 --- a/flutter/lib/common/widgets/chat_page.dart +++ b/flutter/lib/common/widgets/chat_page.dart @@ -73,7 +73,7 @@ class ChatPage extends StatelessWidget implements PageShape { ? InputDecoration( isDense: true, hintText: - "${translate('Write a message')}...", + "${translate('Write a message')}", filled: true, fillColor: Theme.of(context).colorScheme.background, @@ -88,7 +88,7 @@ class ChatPage extends StatelessWidget implements PageShape { ) : defaultInputDecoration( hintText: - "${translate('Write a message')}...", + "${translate('Write a message')}", fillColor: Theme.of(context).colorScheme.background), sendButtonBuilder: defaultSendButton( From 56773b8d548098f52be37460a1b17eef4878552e Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Tue, 7 Mar 2023 14:55:26 +0100 Subject: [PATCH 246/382] Update README-DE.md --- docs/README-DE.md | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/README-DE.md b/docs/README-DE.md index ff3ec1d7f..2c159bd07 100644 --- a/docs/README-DE.md +++ b/docs/README-DE.md @@ -6,18 +6,18 @@ DateistrukturScreenshots
    [English] | [Українська] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Dansk] | [Ελληνικά]
    - Wir brauchen deine Hilfe, um dieses README, die RustDesk-Benutzeroberfläche und die Dokumentation in deine Muttersprache zu übersetzen. + Wir brauchen Ihre Hilfe, um dieses README, die RustDesk-Benutzeroberfläche und die Dokumentation in Ihre Muttersprache zu übersetzen.

    -Rede mit uns auf: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk) +Reden Sie mit uns auf: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk) [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09) -RustDesk ist eine in Rust geschriebene Remote-Desktop-Software, die out of the box ohne besondere Konfiguration funktioniert. Du hast die volle Kontrolle über deine Daten und musst dir keine Sorgen um die Sicherheit machen. Du kannst unseren Rendezvous/Relay-Server nutzen, [einen eigenen Server aufsetzen](https://rustdesk.com/server) oder [einen eigenen Server programmieren](https://github.com/rustdesk/rustdesk-server-demo). +RustDesk ist eine in Rust geschriebene Remote-Desktop-Software, die out of the box ohne besondere Konfiguration funktioniert. Sie haben die volle Kontrolle über Ihre Daten und müssen sich keine Sorgen um die Sicherheit machen. Sie können unseren Rendezvous/Relay-Server nutzen, [einen eigenen Server aufsetzen](https://rustdesk.com/server) oder [einen eigenen Server programmieren](https://github.com/rustdesk/rustdesk-server-demo). ![image](https://user-images.githubusercontent.com/71636191/171661982-430285f0-2e12-4b1d-9957-4a58e375304d.png) -RustDesk heißt jegliche Mitarbeit willkommen. Schau dir [CONTRIBUTING-DE.md](CONTRIBUTING-DE.md) an, wenn du Unterstützung beim Start brauchst. +RustDesk heißt jegliche Mitarbeit willkommen. Schauen Sie sich [CONTRIBUTING-DE.md](CONTRIBUTING-DE.md) an, wenn Sie Unterstützung beim Start brauchen. [**FAQ**](https://github.com/rustdesk/rustdesk/wiki/FAQ) @@ -31,29 +31,29 @@ RustDesk heißt jegliche Mitarbeit willkommen. Schau dir [CONTRIBUTING-DE.md](CO ## Freie öffentliche Server -Nachfolgend sind die Server gelistet, die du kostenlos nutzen kannst. Es kann sein, dass sich diese Liste immer mal wieder ändert. Falls du nicht in der Nähe einer dieser Server bist, kann es sein, dass deine Verbindung langsam sein wird. +Nachfolgend sind die Server gelistet, die Sie kostenlos nutzen können. Es kann sein, dass sich diese Liste immer mal wieder ändert. Falls Sie nicht in der Nähe einer dieser Server sind, kann es sein, dass Ihre Verbindung langsam sein wird. | Standort | Anbieter | Spezifikation | | --------- | ------------- | ------------------ | -| Südkorea (Seoul) | AWS lightsail | 1 vCPU / 0,5 GB RAM | -| Deutschland | Hetzner | 2 vCPU / 4 GB RAM | -| Deutschland | Codext | 4 vCPU / 8 GB RAM | -| Finnland (Helsinki) | 0x101 Cyber Security | 4 vCPU / 8 GB RAM | -| USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8 GB RAM | -| Ukraine (Kiew) | dc.volia (2VM) | 2 vCPU / 4 GB RAM | +| Südkorea (Seoul) | [AWS lightsail](https://aws.amazon.com/de/) | 1 vCPU / 0,5 GB RAM | +| Deutschland | [Hetzner](https://www.hetzner.com/de/) | 2 vCPU / 4 GB RAM | +| Deutschland | [Codext](https://codext.de/) | 4 vCPU / 8 GB RAM | +| Finnland (Helsinki) | [Netlock](https://netlockendpoint.com/de/index.html) | 4 vCPU / 8 GB RAM | +| USA (Ashburn) | [Netlock](https://netlockendpoint.com/de/index.html) | 4 vCPU / 8 GB RAM | +| Ukraine (Kiew) | [dc.volia](https://dc.volia.com) | 2 vCPU / 4 GB RAM | ## Dev-Container [![In Dev-Containern öffnen](https://img.shields.io/static/v1?label=Dev%20Container&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/rustdesk/rustdesk) -Wenn du VS Code und Docker bereits installiert hast, kannst du auf das Abzeichen oben klicken, um loszulegen. Wenn du darauf klickst, wird VS Code automatisch die Dev-Container-Erweiterung installieren, den Quellcode in ein Container-Volume klonen und einen Dev-Container für die Verwendung aufsetzen. +Wenn Sie VS Code und Docker bereits installiert haben, können Sie auf das Abzeichen oben klicken, um loszulegen. Wenn Sie darauf klicken, wird VS Code automatisch die Dev-Container-Erweiterung installieren, den Quellcode in ein Container-Volume klonen und einen Dev-Container für die Verwendung aufsetzen. -Weitere Informationen findest du in [DEVCONTAINER-DE.md](DEVCONTAINER-DE.md). +Weitere Informationen finden Sie in [DEVCONTAINER-DE.md](DEVCONTAINER-DE.md). ## Abhängigkeiten Desktop-Versionen verwenden [Sciter](https://sciter.com/) oder Flutter für die GUI, dieses Tutorial ist nur für Sciter. -Bitte lade die dynamische Bibliothek Sciter selbst herunter. +Bitte laden Sie die dynamische Bibliothek Sciter selbst herunter. [Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) | [Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) | @@ -61,14 +61,14 @@ Bitte lade die dynamische Bibliothek Sciter selbst herunter. ## Grobe Schritte zum Kompilieren -- Bereite deine Rust-Entwicklungsumgebung und C++-Build-Umgebung vor +- Bereiten Sie Ihre Rust-Entwicklungsumgebung und C++-Build-Umgebung vor -- Installiere [vcpkg](https://github.com/microsoft/vcpkg) und füge die Systemumgebungsvariable `VCPKG_ROOT` hinzu +- Installieren Sie [vcpkg](https://github.com/microsoft/vcpkg) und fügen Sie die Systemumgebungsvariable `VCPKG_ROOT` hinzu - Windows: `vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static` - Linux/macOS: `vcpkg install libvpx libyuv opus` -- Nutze `cargo run` +- Nutzen Sie `cargo run` ## [Erstellen](https://rustdesk.com/docs/de/dev/build/) @@ -167,7 +167,7 @@ method return time=1662544486.931020 sender=:1.54 -> destination=:1.139 serial=2 ## Auf Docker kompilieren -Beginne damit, das Repository zu klonen und den Docker-Container zu bauen: +Beginnen Sie damit, das Repository zu klonen und den Docker-Container zu bauen: ```sh git clone https://github.com/rustdesk/rustdesk @@ -175,25 +175,25 @@ cd rustdesk docker build -t "rustdesk-builder" . ``` -Führe jedes Mal, wenn du das Programm kompilieren musst, folgenden Befehl aus: +Führen Sie jedes Mal, wenn Sie das Programm kompilieren müssen, folgenden Befehl aus: ```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 ``` -Bedenke, dass das erste Kompilieren länger dauern kann, bis die Abhängigkeiten zwischengespeichert sind. Nachfolgende Kompiliervorgänge sind schneller. Wenn du verschiedene Argumente für den Kompilierbefehl angeben musst, kannst du dies am Ende des Befehls an der Position `` tun. Wenn du zum Beispiel eine optimierte Releaseversion kompilieren willst, kannst du `--release` am Ende des Befehls anhängen. Das daraus entstehende Programm findest du im Zielordner auf deinem System. Du kannst es mit folgendem Befehl ausführen: +Bedenken Sie, dass das erste Kompilieren länger dauern kann, bis die Abhängigkeiten zwischengespeichert sind. Nachfolgende Kompiliervorgänge sind schneller. Wenn Sie verschiedene Argumente für den Kompilierbefehl angeben müssen, können Sie dies am Ende des Befehls an der Position `` tun. Wenn Sie zum Beispiel eine optimierte Releaseversion kompilieren wollen, können Sie `--release` am Ende des Befehls anhängen. Das daraus entstehende Programm finden Sie im Zielordner auf Ihrem System. Sie können es mit folgendem Befehl ausführen: ```sh target/debug/rustdesk ``` -Oder, wenn du eine Releaseversion benutzt: +Oder, wenn Sie eine Releaseversion benutzen: ```sh target/release/rustdesk ``` -Bitte stelle sicher, dass du diese Befehle im Stammverzeichnis des RustDesk-Repositorys nutzt. Ansonsten kann es passieren, dass das Programm die Ressourcen nicht finden kann. Bitte bedenke auch, dass andere Cargo-Unterbefehle wie `install` oder `run` aktuell noch nicht unterstützt werden, da sie das Programm innerhalb des Containers starten oder installieren würden, anstatt auf deinem eigentlichen System. +Bitte stellen Sie sicher, dass Sie diese Befehle im Stammverzeichnis des RustDesk-Repositorys nutzen. Ansonsten kann es passieren, dass das Programm die Ressourcen nicht finden kann. Bitte bedenken Sie auch, dass andere Cargo-Unterbefehle wie `install` oder `run` aktuell noch nicht unterstützt werden, da sie das Programm innerhalb des Containers starten oder installieren würden, anstatt auf Ihrem eigentlichen System. ## Dateistruktur From 8b46639ef657a54b4d8724a1eb3a5daee6d9abeb Mon Sep 17 00:00:00 2001 From: csf Date: Wed, 8 Mar 2023 00:49:14 +0900 Subject: [PATCH 247/382] refactor file_manager --- .../lib/desktop/pages/file_manager_page.dart | 1276 ++++++++--------- flutter/lib/models/file_model.dart | 69 +- 2 files changed, 683 insertions(+), 662 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 8bb57145f..8d9cd0a5c 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -61,53 +61,15 @@ class FileManagerPage extends StatefulWidget { class _FileManagerPageState extends State with AutomaticKeepAliveClientMixin { - final _localSelectedItems = SelectedItems(); - final _remoteSelectedItems = SelectedItems(); - - final _locationStatusLocal = LocationStatus.bread.obs; - final _locationStatusRemote = LocationStatus.bread.obs; - final _locationNodeLocal = FocusNode(debugLabel: "locationNodeLocal"); - final _locationNodeRemote = FocusNode(debugLabel: "locationNodeRemote"); - final _locationBarKeyLocal = GlobalKey(debugLabel: "locationBarKeyLocal"); - final _locationBarKeyRemote = GlobalKey(debugLabel: "locationBarKeyRemote"); - final _searchTextLocal = "".obs; - final _searchTextRemote = "".obs; - final _breadCrumbScrollerLocal = ScrollController(); - final _breadCrumbScrollerRemote = ScrollController(); final _mouseFocusScope = Rx(MouseFocusScope.none); - final _keyboardNodeLocal = FocusNode(debugLabel: "keyboardNodeLocal"); - final _keyboardNodeRemote = FocusNode(debugLabel: "keyboardNodeRemote"); - final _listSearchBufferLocal = TimeoutStringBuffer(); - final _listSearchBufferRemote = TimeoutStringBuffer(); - final _nameColWidthLocal = kDesktopFileTransferNameColWidth.obs; - final _modifiedColWidthLocal = kDesktopFileTransferModifiedColWidth.obs; - final _nameColWidthRemote = kDesktopFileTransferNameColWidth.obs; - final _modifiedColWidthRemote = kDesktopFileTransferModifiedColWidth.obs; - - /// [_lastClickTime], [_lastClickEntry] help to handle double click - int _lastClickTime = - DateTime.now().millisecondsSinceEpoch - bind.getDoubleClickTime() - 1000; - Entry? _lastClickEntry; final _dropMaskVisible = false.obs; // TODO impl drop mask final _overlayKeyState = OverlayKeyState(); - ScrollController getBreadCrumbScrollController(bool isLocal) { - return isLocal ? _breadCrumbScrollerLocal : _breadCrumbScrollerRemote; - } - - GlobalKey getLocationBarKey(bool isLocal) { - return isLocal ? _locationBarKeyLocal : _locationBarKeyRemote; - } - late FFI _ffi; FileModel get model => _ffi.fileModel; - SelectedItems getSelectedItems(bool isLocal) { - return isLocal ? _localSelectedItems : _remoteSelectedItems; - } - @override void initState() { super.initState(); @@ -123,9 +85,6 @@ class _FileManagerPageState extends State } debugPrint("File manager page init success with id ${widget.id}"); model.onDirChanged = breadCrumbScrollToEnd; - // register location listener - _locationNodeLocal.addListener(onLocalLocationFocusChanged); - _locationNodeRemote.addListener(onRemoteLocationFocusChanged); _ffi.dialogManager.setOverlayState(_overlayKeyState); } @@ -138,17 +97,19 @@ class _FileManagerPageState extends State Wakelock.disable(); } Get.delete(tag: 'ft_${widget.id}'); - _locationNodeLocal.removeListener(onLocalLocationFocusChanged); - _locationNodeRemote.removeListener(onRemoteLocationFocusChanged); - _locationNodeLocal.dispose(); - _locationNodeRemote.dispose(); }); super.dispose(); } + @override + bool get wantKeepAlive => true; + @override Widget build(BuildContext context) { super.build(context); + // TODO + final localController = FileController(isLocal: true); + final remoteController = FileController(isLocal: false); return Overlay(key: _overlayKeyState.key, initialEntries: [ OverlayEntry(builder: (_) { return ChangeNotifierProvider.value( @@ -158,8 +119,14 @@ class _FileManagerPageState extends State backgroundColor: Theme.of(context).scaffoldBackgroundColor, body: Row( children: [ - Flexible(flex: 3, child: body(isLocal: true)), - Flexible(flex: 3, child: body(isLocal: false)), + Flexible( + flex: 3, + child: dropArea(FileManagerView( + localController, _ffi, _mouseFocusScope))), + Flexible( + flex: 3, + child: dropArea(FileManagerView( + remoteController, _ffi, _mouseFocusScope))), Flexible(flex: 2, child: statusList()) ], ), @@ -169,401 +136,17 @@ class _FileManagerPageState extends State ]); } - Widget menu({bool isLocal = false}) { - var menuPos = RelativeRect.fill; - - final List> items = [ - MenuEntrySwitch( - switchType: SwitchType.scheckbox, - text: translate("Show Hidden Files"), - getter: () async { - return model.getCurrentShowHidden(isLocal); - }, - setter: (bool v) async { - model.toggleShowHidden(local: isLocal); - }, - padding: kDesktopMenuPadding, - dismissOnClicked: true, - ), - MenuEntryButton( - childBuilder: (style) => Text(translate("Select All"), style: style), - proc: () => setState(() => getSelectedItems(isLocal) - .selectAll(model.getCurrentDir(isLocal).entries)), - padding: kDesktopMenuPadding, - dismissOnClicked: true), - MenuEntryButton( - childBuilder: (style) => - Text(translate("Unselect All"), style: style), - proc: () => setState(() => getSelectedItems(isLocal).clear()), - padding: kDesktopMenuPadding, - dismissOnClicked: true) - ]; - - return Listener( - onPointerDown: (e) { - final x = e.position.dx; - final y = e.position.dy; - menuPos = RelativeRect.fromLTRB(x, y, x, y); - }, - child: MenuButton( - onPressed: () => mod_menu.showMenu( - context: context, - position: menuPos, - items: items - .map( - (e) => e.build( - context, - MenuConfig( - commonColor: CustomPopupMenuTheme.commonColor, - height: CustomPopupMenuTheme.height, - dividerHeight: CustomPopupMenuTheme.dividerHeight), - ), - ) - .expand((i) => i) - .toList(), - elevation: 8, - ), - child: SvgPicture.asset( - "assets/dots.svg", - color: Theme.of(context).tabBarTheme.labelColor, - ), - color: Theme.of(context).cardColor, - hoverColor: Theme.of(context).hoverColor, - ), - ); - } - - Widget body({bool isLocal = false}) { - final scrollController = ScrollController(); - return Container( - margin: const EdgeInsets.all(16.0), - padding: const EdgeInsets.all(8.0), - child: DropTarget( - onDragDone: (detail) => handleDragDone(detail, isLocal), + Widget dropArea(FileManagerView fileView) { + return DropTarget( + onDragDone: (detail) => + handleDragDone(detail, fileView.controller.isLocal), onDragEntered: (enter) { _dropMaskVisible.value = true; }, onDragExited: (exit) { _dropMaskVisible.value = false; }, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - headTools(isLocal), - Expanded( - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: _buildFileList(context, isLocal, scrollController), - ) - ], - ), - ), - ], - ), - ), - ); - } - - Widget _buildFileList( - BuildContext context, bool isLocal, ScrollController scrollController) { - final fd = model.getCurrentDir(isLocal); - final entries = fd.entries; - final selectedEntries = getSelectedItems(isLocal); - - return MouseRegion( - onEnter: (evt) { - _mouseFocusScope.value = - isLocal ? MouseFocusScope.local : MouseFocusScope.remote; - if (isLocal) { - _keyboardNodeLocal.requestFocus(); - } else { - _keyboardNodeRemote.requestFocus(); - } - }, - onExit: (evt) { - _mouseFocusScope.value = MouseFocusScope.none; - }, - child: ListSearchActionListener( - node: isLocal ? _keyboardNodeLocal : _keyboardNodeRemote, - buffer: isLocal ? _listSearchBufferLocal : _listSearchBufferRemote, - onNext: (buffer) { - debugPrint("searching next for $buffer"); - assert(buffer.length == 1); - assert(selectedEntries.length <= 1); - var skipCount = 0; - if (selectedEntries.items.isNotEmpty) { - final index = entries.indexOf(selectedEntries.items.first); - if (index < 0) { - return; - } - skipCount = index + 1; - } - var searchResult = entries.skip(skipCount).where( - (element) => element.name.toLowerCase().startsWith(buffer)); - if (searchResult.isEmpty) { - // cannot find next, lets restart search from head - debugPrint("restart search from head"); - searchResult = entries.where( - (element) => element.name.toLowerCase().startsWith(buffer)); - } - if (searchResult.isEmpty) { - setState(() { - getSelectedItems(isLocal).clear(); - }); - return; - } - _jumpToEntry(isLocal, searchResult.first, scrollController, - kDesktopFileTransferRowHeight); - }, - onSearch: (buffer) { - debugPrint("searching for $buffer"); - final selectedEntries = getSelectedItems(isLocal); - final searchResult = entries.where( - (element) => element.name.toLowerCase().startsWith(buffer)); - selectedEntries.clear(); - if (searchResult.isEmpty) { - setState(() { - getSelectedItems(isLocal).clear(); - }); - return; - } - _jumpToEntry(isLocal, searchResult.first, scrollController, - kDesktopFileTransferRowHeight); - }, - child: ObxValue( - (searchText) { - final filteredEntries = searchText.isNotEmpty - ? entries.where((element) { - return element.name.contains(searchText.value); - }).toList(growable: false) - : entries; - final rows = filteredEntries.map((entry) { - final sizeStr = - entry.isFile ? readableFileSize(entry.size.toDouble()) : ""; - final lastModifiedStr = entry.isDrive - ? " " - : "${entry.lastModified().toString().replaceAll(".000", "")} "; - final isSelected = selectedEntries.contains(entry); - return Padding( - padding: EdgeInsets.symmetric(vertical: 1), - child: Container( - decoration: BoxDecoration( - color: isSelected - ? Theme.of(context).hoverColor - : Theme.of(context).cardColor, - borderRadius: BorderRadius.all( - Radius.circular(5.0), - ), - ), - key: ValueKey(entry.name), - height: kDesktopFileTransferRowHeight, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Expanded( - child: InkWell( - child: Row( - children: [ - GestureDetector( - child: Obx( - () => Container( - width: isLocal - ? _nameColWidthLocal.value - : _nameColWidthRemote.value, - child: Tooltip( - waitDuration: - Duration(milliseconds: 500), - message: entry.name, - child: Row(children: [ - entry.isDrive - ? Image( - image: iconHardDrive, - fit: BoxFit.scaleDown, - color: Theme.of(context) - .iconTheme - .color - ?.withOpacity(0.7)) - .paddingAll(4) - : SvgPicture.asset( - entry.isFile - ? "assets/file.svg" - : "assets/folder.svg", - color: Theme.of(context) - .tabBarTheme - .labelColor, - ), - Expanded( - child: Text( - entry.name.nonBreaking, - overflow: - TextOverflow.ellipsis)) - ]), - )), - ), - onTap: () { - final items = getSelectedItems(isLocal); - // handle double click - if (_checkDoubleClick(entry)) { - openDirectory(entry.path, - isLocal: isLocal); - items.clear(); - return; - } - _onSelectedChanged( - items, filteredEntries, entry, isLocal); - }, - ), - SizedBox( - width: 2.0, - ), - GestureDetector( - child: Obx( - () => SizedBox( - width: isLocal - ? _modifiedColWidthLocal.value - : _modifiedColWidthRemote.value, - child: Tooltip( - waitDuration: - Duration(milliseconds: 500), - message: lastModifiedStr, - child: Text( - lastModifiedStr, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, - ), - )), - ), - ), - ), - // Divider from header. - SizedBox( - width: 2.0, - ), - Expanded( - // width: 100, - child: GestureDetector( - child: Tooltip( - waitDuration: Duration(milliseconds: 500), - message: sizeStr, - child: Text( - sizeStr, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 10, - color: MyTheme.darkGray), - ), - ), - ), - ), - ], - ), - ), - ), - ], - )), - ); - }).toList(growable: false); - - return Column( - children: [ - // Header - Row( - children: [ - Expanded(child: _buildFileBrowserHeader(context, isLocal)), - ], - ), - // Body - Expanded( - child: ListView.builder( - controller: scrollController, - itemExtent: kDesktopFileTransferRowHeight, - itemBuilder: (context, index) { - return rows[index]; - }, - itemCount: rows.length, - ), - ), - ], - ); - }, - isLocal ? _searchTextLocal : _searchTextRemote, - ), - ), - ); - } - - void _jumpToEntry(bool isLocal, Entry entry, - ScrollController scrollController, double rowHeight) { - final entries = model.getCurrentDir(isLocal).entries; - final index = entries.indexOf(entry); - if (index == -1) { - debugPrint("entry is not valid: ${entry.path}"); - } - final selectedEntries = getSelectedItems(isLocal); - final searchResult = entries.where((element) => element == entry); - selectedEntries.clear(); - if (searchResult.isEmpty) { - return; - } - final offset = min( - max(scrollController.position.minScrollExtent, - entries.indexOf(searchResult.first) * rowHeight), - scrollController.position.maxScrollExtent); - scrollController.jumpTo(offset); - setState(() { - selectedEntries.add(isLocal, searchResult.first); - debugPrint("focused on ${searchResult.first.name}"); - }); - } - - void _onSelectedChanged(SelectedItems selectedItems, List entries, - Entry entry, bool isLocal) { - final isCtrlDown = RawKeyboard.instance.keysPressed - .contains(LogicalKeyboardKey.controlLeft); - final isShiftDown = - RawKeyboard.instance.keysPressed.contains(LogicalKeyboardKey.shiftLeft); - if (isCtrlDown) { - if (selectedItems.contains(entry)) { - selectedItems.remove(entry); - } else { - selectedItems.add(isLocal, entry); - } - } else if (isShiftDown) { - final List indexGroup = []; - for (var selected in selectedItems.items) { - indexGroup.add(entries.indexOf(selected)); - } - indexGroup.add(entries.indexOf(entry)); - indexGroup.removeWhere((e) => e == -1); - final maxIndex = indexGroup.reduce(max); - final minIndex = indexGroup.reduce(min); - selectedItems.clear(); - entries - .getRange(minIndex, maxIndex + 1) - .forEach((e) => selectedItems.add(isLocal, e)); - } else { - selectedItems.clear(); - selectedItems.add(isLocal, entry); - } - setState(() {}); - } - - bool _checkDoubleClick(Entry entry) { - final current = DateTime.now().millisecondsSinceEpoch; - final elapsed = current - _lastClickTime; - _lastClickTime = current; - if (_lastClickEntry == entry) { - if (elapsed < bind.getDoubleClickTime()) { - return true; - } - } else { - _lastClickEntry = entry; - } - return false; + child: fileView); } Widget generateCard(Widget child) { @@ -749,11 +332,123 @@ class _FileManagerPageState extends State ); } - Widget headTools(bool isLocal) { - final locationStatus = - isLocal ? _locationStatusLocal : _locationStatusRemote; - final locationFocus = isLocal ? _locationNodeLocal : _locationNodeRemote; - final selectedItems = getSelectedItems(isLocal); + void handleDragDone(DropDoneDetails details, bool isLocal) { + if (isLocal) { + // ignore local + return; + } + var items = SelectedItems(); + for (var file in details.files) { + final f = File(file.path); + items.add( + true, + Entry() + ..path = file.path + ..name = file.name + ..size = + FileSystemEntity.isDirectorySync(f.path) ? 0 : f.lengthSync()); + } + model.sendFiles(items, isRemote: false); + } +} + +class FileManagerView extends StatefulWidget { + final FileController controller; + final FFI _ffi; + final Rx _mouseFocusScope; + + FileManagerView(this.controller, this._ffi, this._mouseFocusScope); + + @override + State createState() => _FileManagerViewState(); +} + +class _FileManagerViewState extends State { + final _selectedItems = SelectedItems(); + final _locationStatus = LocationStatus.bread.obs; + final _locationNode = FocusNode(); + final _locationBarKey = GlobalKey(); + final _searchText = "".obs; + final _breadCrumbScroller = ScrollController(); + final _keyboardNode = FocusNode(); + final _listSearchBuffer = TimeoutStringBuffer(); + final _nameColWidth = kDesktopFileTransferNameColWidth.obs; + final _modifiedColWidth = kDesktopFileTransferModifiedColWidth.obs; + final _fileListScrollController = ScrollController(); + + /// [_lastClickTime], [_lastClickEntry] help to handle double click + var _lastClickTime = + DateTime.now().millisecondsSinceEpoch - bind.getDoubleClickTime() - 1000; + Entry? _lastClickEntry; + + FileController get controller => widget.controller; + bool get isLocal => widget.controller.isLocal; + FFI get _ffi => widget._ffi; + + @override + void initState() { + super.initState(); + // register location listener + _locationNode.addListener(onLocationFocusChanged); + } + + @override + void dispose() { + _locationNode.removeListener(onLocationFocusChanged); + _locationNode.dispose(); + _keyboardNode.dispose(); + _breadCrumbScroller.dispose(); + _fileListScrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.all(16.0), + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + headTools(), + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: MouseRegion( + onEnter: (evt) { + widget._mouseFocusScope.value = isLocal + ? MouseFocusScope.local + : MouseFocusScope.remote; + _keyboardNode.requestFocus(); + }, + onExit: (evt) => + widget._mouseFocusScope.value = MouseFocusScope.none, + child: _buildFileList( + context, isLocal, _fileListScrollController), + )) + ], + ), + ), + ], + ), + ); + } + + void onLocationFocusChanged() { + debugPrint("focus changed on local"); + if (_locationNode.hasFocus) { + // ignore + } else { + // lost focus, change to bread + if (_locationStatus.value != LocationStatus.fileSearchBar) { + _locationStatus.value = LocationStatus.bread; + } + } + } + + Widget headTools() { return Container( child: Column( children: [ @@ -812,7 +507,7 @@ class _FileManagerPageState extends State color: Theme.of(context).cardColor, hoverColor: Theme.of(context).hoverColor, onPressed: () { - selectedItems.clear(); + _selectedItems.clear(); model.goBack(isLocal: isLocal); }, ), @@ -827,7 +522,7 @@ class _FileManagerPageState extends State color: Theme.of(context).cardColor, hoverColor: Theme.of(context).hoverColor, onPressed: () { - selectedItems.clear(); + _selectedItems.clear(); model.goToParentDirectory(isLocal: isLocal); }, ), @@ -847,14 +542,14 @@ class _FileManagerPageState extends State padding: EdgeInsets.symmetric(vertical: 2.5), child: GestureDetector( onTap: () { - locationStatus.value = - locationStatus.value == LocationStatus.bread + _locationStatus.value = + _locationStatus.value == LocationStatus.bread ? LocationStatus.pathLocation : LocationStatus.bread; Future.delayed(Duration.zero, () { - if (locationStatus.value == + if (_locationStatus.value == LocationStatus.pathLocation) { - locationFocus.requestFocus(); + _locationNode.requestFocus(); } }); }, @@ -863,7 +558,7 @@ class _FileManagerPageState extends State child: Row( children: [ Expanded( - child: locationStatus.value == + child: _locationStatus.value == LocationStatus.bread ? buildBread(isLocal) : buildPathLocation(isLocal)), @@ -877,15 +572,13 @@ class _FileManagerPageState extends State ), ), Obx(() { - switch (locationStatus.value) { + switch (_locationStatus.value) { case LocationStatus.bread: return MenuButton( onPressed: () { - locationStatus.value = LocationStatus.fileSearchBar; - final focusNode = - isLocal ? _locationNodeLocal : _locationNodeRemote; + _locationStatus.value = LocationStatus.fileSearchBar; Future.delayed( - Duration.zero, () => focusNode.requestFocus()); + Duration.zero, () => _locationNode.requestFocus()); }, child: SvgPicture.asset( "assets/search.svg", @@ -908,7 +601,7 @@ class _FileManagerPageState extends State return MenuButton( onPressed: () { onSearchText("", isLocal); - locationStatus.value = LocationStatus.bread; + _locationStatus.value = LocationStatus.bread; }, child: SvgPicture.asset( "assets/close.svg", @@ -1027,11 +720,11 @@ class _FileManagerPageState extends State hoverColor: Theme.of(context).hoverColor, ), MenuButton( - onPressed: validItems(selectedItems) + onPressed: validItems(_selectedItems) ? () async { - await (model.removeAction(selectedItems, + await (model.removeAction(_selectedItems, isLocal: isLocal)); - selectedItems.clear(); + _selectedItems.clear(); } : null, child: SvgPicture.asset( @@ -1051,15 +744,15 @@ class _FileManagerPageState extends State ? EdgeInsets.only(left: 10) : EdgeInsets.only(right: 10)), backgroundColor: MaterialStateProperty.all( - selectedItems.length == 0 + _selectedItems.length == 0 ? MyTheme.accent80 : MyTheme.accent, ), ), - onPressed: validItems(selectedItems) + onPressed: validItems(_selectedItems) ? () { - model.sendFiles(selectedItems, isRemote: !isLocal); - selectedItems.clear(); + model.sendFiles(_selectedItems, isRemote: !isLocal); + _selectedItems.clear(); } : null, icon: isLocal @@ -1067,7 +760,7 @@ class _FileManagerPageState extends State translate('Send'), textAlign: TextAlign.right, style: TextStyle( - color: selectedItems.length == 0 + color: _selectedItems.length == 0 ? Theme.of(context).brightness == Brightness.light ? MyTheme.grayBg : MyTheme.darkGray @@ -1078,7 +771,7 @@ class _FileManagerPageState extends State quarterTurns: 2, child: SvgPicture.asset( "assets/arrow.svg", - color: selectedItems.length == 0 + color: _selectedItems.length == 0 ? Theme.of(context).brightness == Brightness.light ? MyTheme.grayBg : MyTheme.darkGray @@ -1089,7 +782,7 @@ class _FileManagerPageState extends State label: isLocal ? SvgPicture.asset( "assets/arrow.svg", - color: selectedItems.length == 0 + color: _selectedItems.length == 0 ? Theme.of(context).brightness == Brightness.light ? MyTheme.grayBg : MyTheme.darkGray @@ -1098,7 +791,7 @@ class _FileManagerPageState extends State : Text( translate('Receive'), style: TextStyle( - color: selectedItems.length == 0 + color: _selectedItems.length == 0 ? Theme.of(context).brightness == Brightness.light ? MyTheme.grayBg : MyTheme.darkGray @@ -1113,39 +806,440 @@ class _FileManagerPageState extends State ); } - bool validItems(SelectedItems items) { - if (items.length > 0) { - // exclude DirDrive type - return items.items.any((item) => !item.isDrive); + Widget menu({bool isLocal = false}) { + var menuPos = RelativeRect.fill; + + final List> items = [ + MenuEntrySwitch( + switchType: SwitchType.scheckbox, + text: translate("Show Hidden Files"), + getter: () async { + return model.getCurrentShowHidden(isLocal); + }, + setter: (bool v) async { + model.toggleShowHidden(local: isLocal); + }, + padding: kDesktopMenuPadding, + dismissOnClicked: true, + ), + MenuEntryButton( + childBuilder: (style) => Text(translate("Select All"), style: style), + proc: () => setState(() => + _selectedItems.selectAll(model.getCurrentDir(isLocal).entries)), + padding: kDesktopMenuPadding, + dismissOnClicked: true), + MenuEntryButton( + childBuilder: (style) => + Text(translate("Unselect All"), style: style), + proc: () => setState(() => _selectedItems.clear()), + padding: kDesktopMenuPadding, + dismissOnClicked: true) + ]; + + return Listener( + onPointerDown: (e) { + final x = e.position.dx; + final y = e.position.dy; + menuPos = RelativeRect.fromLTRB(x, y, x, y); + }, + child: MenuButton( + onPressed: () => mod_menu.showMenu( + context: context, + position: menuPos, + items: items + .map( + (e) => e.build( + context, + MenuConfig( + commonColor: CustomPopupMenuTheme.commonColor, + height: CustomPopupMenuTheme.height, + dividerHeight: CustomPopupMenuTheme.dividerHeight), + ), + ) + .expand((i) => i) + .toList(), + elevation: 8, + ), + child: SvgPicture.asset( + "assets/dots.svg", + color: Theme.of(context).tabBarTheme.labelColor, + ), + color: Theme.of(context).cardColor, + hoverColor: Theme.of(context).hoverColor, + ), + ); + } + + Widget _buildFileList( + BuildContext context, bool isLocal, ScrollController scrollController) { + final fd = model.getCurrentDir(isLocal); + final entries = fd.entries; + + return ListSearchActionListener( + node: _keyboardNode, + buffer: _listSearchBuffer, + onNext: (buffer) { + debugPrint("searching next for $buffer"); + assert(buffer.length == 1); + assert(_selectedItems.length <= 1); + var skipCount = 0; + if (_selectedItems.items.isNotEmpty) { + final index = entries.indexOf(_selectedItems.items.first); + if (index < 0) { + return; + } + skipCount = index + 1; + } + var searchResult = entries + .skip(skipCount) + .where((element) => element.name.toLowerCase().startsWith(buffer)); + if (searchResult.isEmpty) { + // cannot find next, lets restart search from head + debugPrint("restart search from head"); + searchResult = entries.where( + (element) => element.name.toLowerCase().startsWith(buffer)); + } + if (searchResult.isEmpty) { + setState(() => _selectedItems.clear()); + return; + } + _jumpToEntry(isLocal, searchResult.first, scrollController, + kDesktopFileTransferRowHeight); + }, + onSearch: (buffer) { + debugPrint("searching for $buffer"); + final selectedEntries = _selectedItems; + final searchResult = entries + .where((element) => element.name.toLowerCase().startsWith(buffer)); + selectedEntries.clear(); + if (searchResult.isEmpty) { + setState(() => _selectedItems.clear()); + return; + } + _jumpToEntry(isLocal, searchResult.first, scrollController, + kDesktopFileTransferRowHeight); + }, + child: ObxValue( + (searchText) { + final filteredEntries = searchText.isNotEmpty + ? entries.where((element) { + return element.name.contains(searchText.value); + }).toList(growable: false) + : entries; + final rows = filteredEntries.map((entry) { + final sizeStr = + entry.isFile ? readableFileSize(entry.size.toDouble()) : ""; + final lastModifiedStr = entry.isDrive + ? " " + : "${entry.lastModified().toString().replaceAll(".000", "")} "; + final isSelected = _selectedItems.contains(entry); + return Padding( + padding: EdgeInsets.symmetric(vertical: 1), + child: Container( + decoration: BoxDecoration( + color: isSelected + ? Theme.of(context).hoverColor + : Theme.of(context).cardColor, + borderRadius: BorderRadius.all( + Radius.circular(5.0), + ), + ), + key: ValueKey(entry.name), + height: kDesktopFileTransferRowHeight, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Expanded( + child: InkWell( + child: Row( + children: [ + GestureDetector( + child: Obx( + () => Container( + width: _nameColWidth.value, + child: Tooltip( + waitDuration: + Duration(milliseconds: 500), + message: entry.name, + child: Row(children: [ + entry.isDrive + ? Image( + image: iconHardDrive, + fit: BoxFit.scaleDown, + color: Theme.of(context) + .iconTheme + .color + ?.withOpacity(0.7)) + .paddingAll(4) + : SvgPicture.asset( + entry.isFile + ? "assets/file.svg" + : "assets/folder.svg", + color: Theme.of(context) + .tabBarTheme + .labelColor, + ), + Expanded( + child: Text( + entry.name.nonBreaking, + overflow: + TextOverflow.ellipsis)) + ]), + )), + ), + onTap: () { + final items = _selectedItems; + // handle double click + if (_checkDoubleClick(entry)) { + openDirectory(entry.path, isLocal: isLocal); + items.clear(); + return; + } + _onSelectedChanged( + items, filteredEntries, entry, isLocal); + }, + ), + SizedBox( + width: 2.0, + ), + GestureDetector( + child: Obx( + () => SizedBox( + width: _modifiedColWidth.value, + child: Tooltip( + waitDuration: + Duration(milliseconds: 500), + message: lastModifiedStr, + child: Text( + lastModifiedStr, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + )), + ), + ), + ), + // Divider from header. + SizedBox( + width: 2.0, + ), + Expanded( + // width: 100, + child: GestureDetector( + child: Tooltip( + waitDuration: Duration(milliseconds: 500), + message: sizeStr, + child: Text( + sizeStr, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 10, + color: MyTheme.darkGray), + ), + ), + ), + ), + ], + ), + ), + ), + ], + )), + ); + }).toList(growable: false); + + return Column( + children: [ + // Header + Row( + children: [ + Expanded(child: _buildFileBrowserHeader(context, isLocal)), + ], + ), + // Body + Expanded( + child: ListView.builder( + controller: scrollController, + itemExtent: kDesktopFileTransferRowHeight, + itemBuilder: (context, index) { + return rows[index]; + }, + itemCount: rows.length, + ), + ), + ], + ); + }, + _searchText, + ), + ); + } + + onSearchText(String searchText, bool isLocal) { + _selectedItems.clear(); + _searchText.value = searchText; + } + + void _jumpToEntry(bool isLocal, Entry entry, + ScrollController scrollController, double rowHeight) { + final entries = model.getCurrentDir(isLocal).entries; + final index = entries.indexOf(entry); + if (index == -1) { + debugPrint("entry is not valid: ${entry.path}"); + } + final selectedEntries = _selectedItems; + final searchResult = entries.where((element) => element == entry); + selectedEntries.clear(); + if (searchResult.isEmpty) { + return; + } + final offset = min( + max(scrollController.position.minScrollExtent, + entries.indexOf(searchResult.first) * rowHeight), + scrollController.position.maxScrollExtent); + scrollController.jumpTo(offset); + setState(() { + selectedEntries.add(isLocal, searchResult.first); + debugPrint("focused on ${searchResult.first.name}"); + }); + } + + void _onSelectedChanged(SelectedItems selectedItems, List entries, + Entry entry, bool isLocal) { + final isCtrlDown = RawKeyboard.instance.keysPressed + .contains(LogicalKeyboardKey.controlLeft); + final isShiftDown = + RawKeyboard.instance.keysPressed.contains(LogicalKeyboardKey.shiftLeft); + if (isCtrlDown) { + if (selectedItems.contains(entry)) { + selectedItems.remove(entry); + } else { + selectedItems.add(isLocal, entry); + } + } else if (isShiftDown) { + final List indexGroup = []; + for (var selected in selectedItems.items) { + indexGroup.add(entries.indexOf(selected)); + } + indexGroup.add(entries.indexOf(entry)); + indexGroup.removeWhere((e) => e == -1); + final maxIndex = indexGroup.reduce(max); + final minIndex = indexGroup.reduce(min); + selectedItems.clear(); + entries + .getRange(minIndex, maxIndex + 1) + .forEach((e) => selectedItems.add(isLocal, e)); + } else { + selectedItems.clear(); + selectedItems.add(isLocal, entry); + } + setState(() {}); + } + + bool _checkDoubleClick(Entry entry) { + final current = DateTime.now().millisecondsSinceEpoch; + final elapsed = current - _lastClickTime; + _lastClickTime = current; + if (_lastClickEntry == entry) { + if (elapsed < bind.getDoubleClickTime()) { + return true; + } + } else { + _lastClickEntry = entry; } return false; } - @override - bool get wantKeepAlive => true; - - void onLocalLocationFocusChanged() { - debugPrint("focus changed on local"); - if (_locationNodeLocal.hasFocus) { - // ignore - } else { - // lost focus, change to bread - if (_locationStatusLocal.value != LocationStatus.fileSearchBar) { - _locationStatusLocal.value = LocationStatus.bread; - } - } + Widget _buildFileBrowserHeader(BuildContext context, bool isLocal) { + final padding = EdgeInsets.all(1.0); + return SizedBox( + height: kDesktopFileTransferHeaderHeight, + child: Row( + children: [ + Obx( + () => headerItemFunc( + _nameColWidth.value, SortBy.name, translate("Name"), isLocal), + ), + DraggableDivider( + axis: Axis.vertical, + onPointerMove: (dx) { + _nameColWidth.value += dx; + _nameColWidth.value = min(kDesktopFileTransferMaximumWidth, + max(kDesktopFileTransferMinimumWidth, _nameColWidth.value)); + }, + padding: padding, + ), + Obx( + () => headerItemFunc(_modifiedColWidth.value, SortBy.modified, + translate("Modified"), isLocal), + ), + DraggableDivider( + axis: Axis.vertical, + onPointerMove: (dx) { + _modifiedColWidth.value += dx; + _modifiedColWidth.value = min( + kDesktopFileTransferMaximumWidth, + max(kDesktopFileTransferMinimumWidth, + _modifiedColWidth.value)); + }, + padding: padding), + Expanded( + child: + headerItemFunc(null, SortBy.size, translate("Size"), isLocal)) + ], + ), + ); } - void onRemoteLocationFocusChanged() { - debugPrint("focus changed on remote"); - if (_locationNodeRemote.hasFocus) { - // ignore - } else { - // lost focus, change to bread - if (_locationStatusRemote.value != LocationStatus.fileSearchBar) { - _locationStatusRemote.value = LocationStatus.bread; + Widget headerItemFunc( + double? width, SortBy sortBy, String name, bool isLocal) { + final headerTextStyle = + Theme.of(context).dataTableTheme.headingTextStyle ?? TextStyle(); + return ObxValue>( + (ascending) => InkWell( + onTap: () { + if (ascending.value == null) { + ascending.value = true; + } else { + ascending.value = !ascending.value!; + } + model.changeSortStyle(sortBy, + isLocal: isLocal, ascending: ascending.value!); + }, + child: SizedBox( + width: width, + height: kDesktopFileTransferHeaderHeight, + child: Row( + children: [ + Flexible( + flex: 2, + child: Text( + name, + style: headerTextStyle, + overflow: TextOverflow.ellipsis, + ).marginSymmetric(horizontal: 4), + ), + Flexible( + flex: 1, + child: ascending.value != null + ? Icon( + ascending.value! + ? Icons.keyboard_arrow_up_rounded + : Icons.keyboard_arrow_down_rounded, + ) + : const Offstage()) + ], + ), + ), + ), () { + if (model.getSortStyle(isLocal) == sortBy) { + return model.getSortAscending(isLocal).obs; + } else { + return Rx(null); } - } + }()); } Widget buildBread(bool isLocal) { @@ -1156,12 +1250,11 @@ class _FileManagerPageState extends State } openDirectory(path, isLocal: isLocal); }); - final locationBarKey = getLocationBarKey(isLocal); return items.isEmpty ? Offstage() : Row( - key: locationBarKey, + key: _locationBarKey, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( @@ -1169,7 +1262,7 @@ class _FileManagerPageState extends State // handle mouse wheel onPointerSignal: (e) { if (e is PointerScrollEvent) { - final sc = getBreadCrumbScrollController(isLocal); + final sc = _breadCrumbScroller; final scale = Platform.isWindows ? 2 : 4; sc.jumpTo(sc.offset + e.scrollDelta.dy / scale); } @@ -1178,7 +1271,7 @@ class _FileManagerPageState extends State items: items, divider: const Icon(Icons.keyboard_arrow_right_rounded), overflow: ScrollableOverflow( - controller: getBreadCrumbScrollController(isLocal), + controller: _breadCrumbScroller, ), ), ), @@ -1187,9 +1280,9 @@ class _FileManagerPageState extends State message: "", icon: Icons.keyboard_arrow_down_rounded, onTap: () async { - final renderBox = locationBarKey.currentContext + final renderBox = _locationBarKey.currentContext ?.findRenderObject() as RenderBox; - locationBarKey.currentContext?.size; + _locationBarKey.currentContext?.size; final size = renderBox.size; final offset = renderBox.localToGlobal(Offset.zero); @@ -1201,7 +1294,7 @@ class _FileManagerPageState extends State final List menuItems = [ MenuEntryButton( childBuilder: (TextStyle? style) => isPeerWindows - ? buildWindowsThisPC(style) + ? buildWindowsThisPC(context, style) : Text( '/', style: style, @@ -1274,15 +1367,6 @@ class _FileManagerPageState extends State ]); } - Widget buildWindowsThisPC([TextStyle? textStyle]) { - final color = Theme.of(context).iconTheme.color?.withOpacity(0.7); - return Row(children: [ - Icon(Icons.computer, size: 20, color: color), - SizedBox(width: 10), - Text(translate('This PC'), style: textStyle) - ]); - } - List getPathBreadCrumbItems( bool isLocal, void Function(List) onPressed) { final path = model.getCurrentDir(isLocal).path; @@ -1291,7 +1375,7 @@ class _FileManagerPageState extends State if (isWindows && path == '/') { breadCrumbList.add(BreadCrumbItem( content: TextButton( - child: buildWindowsThisPC(), + child: buildWindowsThisPC(context), style: ButtonStyle( minimumSize: MaterialStateProperty.all(Size(0, 0))), onPressed: () => onPressed(['/'])) @@ -1321,10 +1405,9 @@ class _FileManagerPageState extends State breadCrumbScrollToEnd(bool isLocal) { Future.delayed(Duration(milliseconds: 200), () { - final breadCrumbScroller = getBreadCrumbScrollController(isLocal); - if (breadCrumbScroller.hasClients) { - breadCrumbScroller.animateTo( - breadCrumbScroller.position.maxScrollExtent, + if (_breadCrumbScroller.hasClients) { + _breadCrumbScroller.animateTo( + _breadCrumbScroller.position.maxScrollExtent, duration: Duration(milliseconds: 200), curve: Curves.fastLinearToSlowEaseIn); } @@ -1332,26 +1415,22 @@ class _FileManagerPageState extends State } Widget buildPathLocation(bool isLocal) { - final searchTextObs = isLocal ? _searchTextLocal : _searchTextRemote; - final locationStatus = - isLocal ? _locationStatusLocal : _locationStatusRemote; - final focusNode = isLocal ? _locationNodeLocal : _locationNodeRemote; - final text = locationStatus.value == LocationStatus.pathLocation + final text = _locationStatus.value == LocationStatus.pathLocation ? model.getCurrentDir(isLocal).path - : searchTextObs.value; + : _searchText.value; final textController = TextEditingController(text: text) ..selection = TextSelection.collapsed(offset: text.length); return Row( children: [ SvgPicture.asset( - locationStatus.value == LocationStatus.pathLocation + _locationStatus.value == LocationStatus.pathLocation ? "assets/folder.svg" : "assets/search.svg", color: Theme.of(context).tabBarTheme.labelColor, ), Expanded( child: TextField( - focusNode: focusNode, + focusNode: _locationNode, decoration: InputDecoration( border: InputBorder.none, isDense: true, @@ -1363,7 +1442,7 @@ class _FileManagerPageState extends State onSubmitted: (path) { openDirectory(path, isLocal: isLocal); }, - onChanged: locationStatus.value == LocationStatus.fileSearchBar + onChanged: _locationStatus.value == LocationStatus.fileSearchBar ? (searchText) => onSearchText(searchText, isLocal) : null, ), @@ -1372,139 +1451,24 @@ class _FileManagerPageState extends State ); } - onSearchText(String searchText, bool isLocal) { - if (isLocal) { - _localSelectedItems.clear(); - _searchTextLocal.value = searchText; - } else { - _remoteSelectedItems.clear(); - _searchTextRemote.value = searchText; - } - } - - openDirectory(String path, {bool isLocal = false}) { - model.openDirectory(path, isLocal: isLocal); - } - - void handleDragDone(DropDoneDetails details, bool isLocal) { - if (isLocal) { - // ignore local - return; - } - var items = SelectedItems(); - for (var file in details.files) { - final f = File(file.path); - items.add( - true, - Entry() - ..path = file.path - ..name = file.name - ..size = - FileSystemEntity.isDirectorySync(f.path) ? 0 : f.lengthSync()); - } - model.sendFiles(items, isRemote: false); - } - - void refocusKeyboardListener(bool isLocal) { - Future.delayed(Duration.zero, () { - if (isLocal) { - _keyboardNodeLocal.requestFocus(); - } else { - _keyboardNodeRemote.requestFocus(); - } - }); - } - - Widget headerItemFunc( - double? width, SortBy sortBy, String name, bool isLocal) { - final headerTextStyle = - Theme.of(context).dataTableTheme.headingTextStyle ?? TextStyle(); - return ObxValue>( - (ascending) => InkWell( - onTap: () { - if (ascending.value == null) { - ascending.value = true; - } else { - ascending.value = !ascending.value!; - } - model.changeSortStyle(sortBy, - isLocal: isLocal, ascending: ascending.value!); - }, - child: SizedBox( - width: width, - height: kDesktopFileTransferHeaderHeight, - child: Row( - children: [ - Flexible( - flex: 2, - child: Text( - name, - style: headerTextStyle, - overflow: TextOverflow.ellipsis, - ).marginSymmetric(horizontal: 4), - ), - Flexible( - flex: 1, - child: ascending.value != null - ? Icon( - ascending.value! - ? Icons.keyboard_arrow_up_rounded - : Icons.keyboard_arrow_down_rounded, - ) - : const Offstage()) - ], - ), - ), - ), () { - if (model.getSortStyle(isLocal) == sortBy) { - return model.getSortAscending(isLocal).obs; - } else { - return Rx(null); - } - }()); - } - - Widget _buildFileBrowserHeader(BuildContext context, bool isLocal) { - final nameColWidth = isLocal ? _nameColWidthLocal : _nameColWidthRemote; - final modifiedColWidth = - isLocal ? _modifiedColWidthLocal : _modifiedColWidthRemote; - final padding = EdgeInsets.all(1.0); - return SizedBox( - height: kDesktopFileTransferHeaderHeight, - child: Row( - children: [ - Obx( - () => headerItemFunc( - nameColWidth.value, SortBy.name, translate("Name"), isLocal), - ), - DraggableDivider( - axis: Axis.vertical, - onPointerMove: (dx) { - nameColWidth.value += dx; - nameColWidth.value = min(kDesktopFileTransferMaximumWidth, - max(kDesktopFileTransferMinimumWidth, nameColWidth.value)); - }, - padding: padding, - ), - Obx( - () => headerItemFunc(modifiedColWidth.value, SortBy.modified, - translate("Modified"), isLocal), - ), - DraggableDivider( - axis: Axis.vertical, - onPointerMove: (dx) { - modifiedColWidth.value += dx; - modifiedColWidth.value = min( - kDesktopFileTransferMaximumWidth, - max(kDesktopFileTransferMinimumWidth, - modifiedColWidth.value)); - }, - padding: padding), - Expanded( - child: - headerItemFunc(null, SortBy.size, translate("Size"), isLocal)) - ], - ), - ); - } + // openDirectory(String path, {bool isLocal = false}) { + // model.openDirectory(path, isLocal: isLocal); + // } +} + +bool validItems(SelectedItems items) { + if (items.length > 0) { + // exclude DirDrive type + return items.items.any((item) => !item.isDrive); + } + return false; +} + +Widget buildWindowsThisPC(BuildContext context, [TextStyle? textStyle]) { + final color = Theme.of(context).iconTheme.color?.withOpacity(0.7); + return Row(children: [ + Icon(Icons.computer, size: 20, color: color), + SizedBox(width: 10), + Text(translate('This PC'), style: textStyle) + ]); } diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index feaecd356..e8f7cf15b 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -24,6 +24,63 @@ enum SortBy { } } +class JobID { + int _count = 0; + int next() { + _count++; + return _count; + } +} + +class SortStyle { + var by = SortBy.name; + var ascending = true; +} + +class FileModelNew { + static final JobID jobID = JobID(); + final jobTable = RxList.empty(growable: true); + final _jobResultListener = JobResultListener>(); + + final localController = FileController(isLocal: true); + final remoteController = FileController(isLocal: false); + + int getJob(int id) { + return jobTable.indexWhere((element) => element.id == id); + } +} + +class FileController extends FileState with FileAction, UIController { + FileController({required super.isLocal}); +} + +class FileState { + final bool isLocal; + final _fileFetcher = FileFetcher(); + + final options = DirectoryOptions().obs; + final directory = FileDirectory().obs; + + final history = RxList.empty(growable: true); + final sortStyle = SortStyle().obs; + + FileState({required this.isLocal}); +} + +mixin FileAction on FileState { + test() { + final a = _fileFetcher; + final b = isLocal; + } +} + +mixin UIController on FileState { + testUI() { + final a = _fileFetcher; + final b = isLocal; + } +} + class FileModel extends ChangeNotifier { /// mobile, current selected page show on mobile screen var _isSelectedLocal = false; @@ -31,8 +88,8 @@ class FileModel extends ChangeNotifier { /// mobile, select mode state var _selectMode = false; - final _localOption = DirectoryOption(); - final _remoteOption = DirectoryOption(); + final _localOption = DirectoryOptions(); + final _remoteOption = DirectoryOptions(); List localHistory = []; List remoteHistory = []; @@ -49,9 +106,9 @@ class FileModel extends ChangeNotifier { RxList get jobTable => _jobTable; - bool get isLocal => _isSelectedLocal; + bool get isLocal => _isSelectedLocal; // TODO parent - bool get selectMode => _selectMode; + bool get selectMode => _selectMode; // TODO parent JobProgress get jobProgress => _jobProgress; @@ -1179,12 +1236,12 @@ class PathUtil { } } -class DirectoryOption { +class DirectoryOptions { String home; bool showHidden; bool isWindows; - DirectoryOption( + DirectoryOptions( {this.home = "", this.showHidden = false, this.isWindows = false}); clear() { From 8f3f0d4cc4541b8ff3dfc2664f5658a7cc13726f Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Tue, 7 Mar 2023 19:58:03 +0200 Subject: [PATCH 248/382] Update and rename gr.rs to el.rs --- src/lang/{gr.rs => el.rs} | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) rename src/lang/{gr.rs => el.rs} (97%) diff --git a/src/lang/gr.rs b/src/lang/el.rs similarity index 97% rename from src/lang/gr.rs rename to src/lang/el.rs index 819c257c3..40cf36b91 100644 --- a/src/lang/gr.rs +++ b/src/lang/el.rs @@ -24,7 +24,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Refresh random password", "Νέος τυχαίος κωδικός πρόσβασης"), ("Set your own password", "Ορίστε τον δικό σας κωδικό πρόσβασης"), ("Enable Keyboard/Mouse", "Ενεργοποίηση πληκτρολογίου/ποντικιού"), - ("Enable Clipboard", "Ενεργοποίηση Προχείρου"), + ("Enable Clipboard", "Ενεργοποίηση προχείρου"), ("Enable File Transfer", "Ενεργοποίηση μεταφοράς αρχείων"), ("Enable TCP Tunneling", "Ενεργοποίηση TCP Tunneling"), ("IP Whitelisting", "Λίστα επιτρεπόμενων IP"), @@ -44,7 +44,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("id_change_tip", "Επιτρέπονται μόνο οι χαρακτήρες a-z, A-Z, 0-9 και _ (υπογράμμιση). Το πρώτο γράμμα πρέπει να είναι a-z, A-Z και το μήκος πρέπει να είναι μεταξύ 6 και 16 χαρακτήρων."), ("Website", "Ιστότοπος"), ("About", "Πληροφορίες"), - ("Slogan_tip", "Προγραμματισμένος με πάθος - σε έναν κόσμο που βυθίζεται στο χάος!"), + ("Slogan_tip", "Φτιαγμένο με πάθος - σε έναν κόσμο που βυθίζεται στο χάος!"), ("Privacy Statement", "Πολιτική απορρήτου"), ("Mute", "Σίγαση"), ("Build Date", "Ημερομηνία δημιουργίας"), @@ -120,12 +120,12 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Original", "Πρωτότυπο"), ("Shrink", "Συρρίκνωση"), ("Stretch", "Προσαρμογή"), - ("Scrollbar", "Γραμμή κύλισης"), + ("Scrollbar", "Μπάρα κύλισης"), ("ScrollAuto", "Αυτόματη κύλιση"), ("Good image quality", "Καλή ποιότητα εικόνας"), - ("Balanced", "Ισορροπημένο"), - ("Optimize reaction time", "Βελτιστοποίηση χρόνου αντίδρασης"), - ("Custom", "Προσαρμογή ποιότητας εικόνας"), + ("Balanced", "Ισορροπημένη"), + ("Optimize reaction time", "Βελτιστοποίηση απόκρισης"), + ("Custom", "Προσαρμοσμένη ποιότητας εικόνας"), ("Show remote cursor", "Εμφάνιση απομακρυσμένου κέρσορα"), ("Show quality monitor", "Εμφάνιση παρακολούθησης ποιότητας σύνδεσης"), ("Disable clipboard", "Απενεργοποίηση προχείρου"), @@ -146,9 +146,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Set Password", "Ορίστε κωδικό πρόσβασης"), ("OS Password", "Κωδικός πρόσβασης λειτουργικού συστήματος"), ("install_tip", "Λόγω UAC, το RustDesk ενδέχεται να μην λειτουργεί σωστά σε ορισμένες περιπτώσεις. Για να αποφύγετε το UAC, κάντε κλικ στο κουμπί παρακάτω για να εγκαταστήσετε το RustDesk στο σύστημα"), - ("Click to upgrade", "Κάντε κλικ για αναβάθμιση"), - ("Click to download", "Κάντε κλικ για λήψη"), - ("Click to update", "Κάντε κλικ για ενημέρωση"), + ("Click to upgrade", "Πιέστε για αναβάθμιση"), + ("Click to download", "Πιέστε για λήψη"), + ("Click to update", "Πιέστε για ενημέρωση"), ("Configure", "Διαμόρφωση"), ("config_acc", "Για τον απομακρυσμένο έλεγχο του υπολογιστή σας, πρέπει να εκχωρήσετε δικαιώματα πρόσβασης στο RustDesk."), ("config_screen", "Για να αποκτήσετε απομακρυσμένη πρόσβαση στον υπολογιστή σας, πρέπει να εκχωρήσετε το δικαίωμα RustDesk \"Screen Capture\"."), @@ -242,7 +242,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Invalid folder name", "Μη έγκυρο όνομα φακέλου"), ("Socks5 Proxy", "Διαμεσολαβητής Socks5"), ("Hostname", "Όνομα υπολογιστή"), - ("Discovered", "Ανακαλύφθηκε"), + ("Discovered", "Ανακαλύφθηκαν"), ("install_daemon_tip", "Για να ξεκινά με την εκκίνηση του υπολογιστή, πρέπει να εγκαταστήσετε την υπηρεσία συστήματος"), ("Remote ID", "Απομακρυσμένο ID"), ("Paste", "Επικόλληση"), @@ -344,7 +344,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Secure Connection", "Ασφαλής σύνδεση"), ("Insecure Connection", "Μη ασφαλής σύνδεση"), ("Scale original", "Κλιμάκωση πρωτότυπου"), - ("Scale adaptive", "Προσαρμοστική κλίμακα"), + ("Scale adaptive", "Προσαρμοσμένη κλίμακα"), ("General", "Γενικά"), ("Security", "Ασφάλεια"), ("Theme", "Θέμα"), @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Κωδικοποίηση"), ("Resolution", "Ανάλυση"), ("No transfers in progress", "Δεν υπάρχει μεταφορά σε εξέλιξη"), - ("Set one-time password length", ""), - ].iter().cloned().collect(); + ("Set one-time password length", "Μέγεθος κωδικού μιας χρήσης"), + ].iter().cloned().collect(); } From cd70da2e57dbe7eb46919f6ee9365640c7b0d632 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Tue, 7 Mar 2023 20:13:38 +0200 Subject: [PATCH 249/382] Update lang.rs the correct locale for the Greek language is el. (el, el_GR, el_CY all are the same Greek language) --- src/lang.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lang.rs b/src/lang.rs index 23ffa08d4..972510325 100644 --- a/src/lang.rs +++ b/src/lang.rs @@ -10,7 +10,7 @@ mod eo; mod es; mod fa; mod fr; -mod gr; +mod el; mod hu; mod id; mod it; @@ -59,7 +59,7 @@ pub const LANGS: &[(&str, &str)] = &[ ("ua", "Українська"), ("fa", "فارسی"), ("ca", "Català"), - ("gr", "Ελληνικά"), + ("el", "Ελληνικά"), ("sv", "Svenska"), ("sq", "Shqip"), ("sr", "Srpski"), @@ -122,7 +122,7 @@ pub fn translate_locale(name: String, locale: &str) -> String { "ua" => ua::T.deref(), "fa" => fa::T.deref(), "ca" => ca::T.deref(), - "gr" => gr::T.deref(), + "el" => el::T.deref(), "sv" => sv::T.deref(), "sq" => sq::T.deref(), "sr" => sr::T.deref(), From a4ef60a250bf5cc40f4d949e72160fbdc2867d5a Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Tue, 7 Mar 2023 19:27:39 +0100 Subject: [PATCH 250/382] reduced peer view type to one toggle, moved sorting button under peer view type --- flutter/lib/common/widgets/peer_tab_page.dart | 67 ++++++++++--------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index d0ab51058..b0ad4138a 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -113,14 +113,19 @@ class _PeerTabPageState extends State offstage: !isDesktop, child: _createPeerViewTypeSwitch(context) .marginOnly(left: 13)), - Offstage( - offstage: _hideSort, - child: PeerSortDropdown(), - ) ], ), ), ), + Row( + children: [ + Expanded(child: SizedBox()), + Offstage( + offstage: _hideSort, + child: PeerSortDropdown(), + ), + ], + ), _createPeersView(), ], ); @@ -240,32 +245,32 @@ class _PeerTabPageState extends State Widget _createPeerViewTypeSwitch(BuildContext context) { final textColor = Theme.of(context).textTheme.titleLarge?.color; - final activeDeco = - BoxDecoration(color: Theme.of(context).colorScheme.background); - return Row( - children: [PeerUiType.grid, PeerUiType.list] - .map((type) => Obx( - () => Container( - padding: EdgeInsets.all(4.0), - decoration: peerCardUiType.value == type ? activeDeco : null, - child: InkWell( - onTap: () async { - await bind.setLocalFlutterConfig( - k: 'peer-card-ui-type', v: type.index.toString()); - peerCardUiType.value = type; - }, - child: Icon( - type == PeerUiType.grid - ? Icons.grid_view_rounded - : Icons.list, - size: 18, - color: - peerCardUiType.value == type ? textColor : textColor - ?..withOpacity(0.5), - )), - ), - )) - .toList(), + final activeDeco = BoxDecoration( + color: Theme.of(context).colorScheme.background, + borderRadius: BorderRadius.circular(5), + ); + final types = [PeerUiType.grid, PeerUiType.list]; + + return Obx( + () => Container( + padding: EdgeInsets.all(4.0), + decoration: activeDeco, + child: InkWell( + onTap: () async { + final type = types.elementAt( + peerCardUiType.value == types.elementAt(0) ? 1 : 0); + await bind.setLocalFlutterConfig( + k: 'peer-card-ui-type', v: type.index.toString()); + peerCardUiType.value = type; + }, + child: Icon( + peerCardUiType.value == PeerUiType.grid + ? Icons.list_rounded + : Icons.grid_view_rounded, + size: 18, + color: textColor, + )), + ), ); } @@ -441,7 +446,7 @@ class _PeerSortDropdownState extends State { @override Widget build(BuildContext context) { return DropdownButton( - value: _sortType, + value: _sortType == "" ? 'id' : _sortType, elevation: 16, underline: SizedBox(), onChanged: (v) { From 43da91863045d0c6dcbab119827942e0c8b56723 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Tue, 7 Mar 2023 20:31:20 +0100 Subject: [PATCH 251/382] rounded tiles --- flutter/lib/common/widgets/peer_card.dart | 45 ++++++++++++------- flutter/lib/common/widgets/peer_tab_page.dart | 3 +- flutter/lib/common/widgets/peers_view.dart | 2 +- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/flutter/lib/common/widgets/peer_card.dart b/flutter/lib/common/widgets/peer_card.dart index 7d2d0cd2d..536d5e0c2 100644 --- a/flutter/lib/common/widgets/peer_card.dart +++ b/flutter/lib/common/widgets/peer_card.dart @@ -42,6 +42,7 @@ class _PeerCardState extends State<_PeerCard> with AutomaticKeepAliveClientMixin { var _menuPos = RelativeRect.fill; final double _cardRadius = 16; + final double _tileRadius = 5; final double _borderWidth = 2; @override @@ -116,27 +117,32 @@ class _PeerCardState extends State<_PeerCard> Widget _buildDesktop() { final peer = super.widget.peer; - var deco = Rx(BoxDecoration( + var deco = Rx( + BoxDecoration( border: Border.all(color: Colors.transparent, width: _borderWidth), - borderRadius: peerCardUiType.value == PeerUiType.grid - ? BorderRadius.circular(_cardRadius) - : null)); + borderRadius: BorderRadius.circular( + peerCardUiType.value == PeerUiType.grid ? _cardRadius : _tileRadius, + ), + ), + ); return MouseRegion( onEnter: (evt) { deco.value = BoxDecoration( - border: Border.all( - color: Theme.of(context).colorScheme.primary, - width: _borderWidth), - borderRadius: peerCardUiType.value == PeerUiType.grid - ? BorderRadius.circular(_cardRadius) - : null); + border: Border.all( + color: Theme.of(context).colorScheme.primary, + width: _borderWidth), + borderRadius: BorderRadius.circular( + peerCardUiType.value == PeerUiType.grid ? _cardRadius : _tileRadius, + ), + ); }, onExit: (evt) { deco.value = BoxDecoration( - border: Border.all(color: Colors.transparent, width: _borderWidth), - borderRadius: peerCardUiType.value == PeerUiType.grid - ? BorderRadius.circular(_cardRadius) - : null); + border: Border.all(color: Colors.transparent, width: _borderWidth), + borderRadius: BorderRadius.circular( + peerCardUiType.value == PeerUiType.grid ? _cardRadius : _tileRadius, + ), + ); }, child: GestureDetector( onDoubleTap: () => widget.connect(context, peer.id), @@ -163,6 +169,10 @@ class _PeerCardState extends State<_PeerCard> Container( decoration: BoxDecoration( color: str2color('${peer.id}${peer.platform}', 0x7f), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(_tileRadius), + bottomLeft: Radius.circular(_tileRadius), + ), ), alignment: Alignment.center, width: 42, @@ -171,7 +181,12 @@ class _PeerCardState extends State<_PeerCard> Expanded( child: Container( decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background), + color: Theme.of(context).colorScheme.background, + borderRadius: BorderRadius.only( + topRight: Radius.circular(_tileRadius), + bottomRight: Radius.circular(_tileRadius), + ), + ), child: Row( children: [ Expanded( diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index b0ad4138a..cbc3b1370 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -12,7 +12,6 @@ import 'package:flutter_hbb/desktop/widgets/popup_menu.dart'; import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; import 'package:flutter_hbb/desktop/widgets/material_mod_popup_menu.dart' as mod_menu; -import 'package:flutter_hbb/models/file_model.dart'; import 'package:flutter_hbb/models/peer_tab_model.dart'; import 'package:get/get.dart'; import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart'; @@ -446,7 +445,7 @@ class _PeerSortDropdownState extends State { @override Widget build(BuildContext context) { return DropdownButton( - value: _sortType == "" ? 'id' : _sortType, + value: _sortType.isEmpty ? 'id' : _sortType, elevation: 16, underline: SizedBox(), onChanged: (v) { diff --git a/flutter/lib/common/widgets/peers_view.dart b/flutter/lib/common/widgets/peers_view.dart index 88e05238e..2bc0f6fbb 100644 --- a/flutter/lib/common/widgets/peers_view.dart +++ b/flutter/lib/common/widgets/peers_view.dart @@ -211,7 +211,7 @@ class _PeersViewState extends State<_PeersView> with WindowListener { p1.username.toLowerCase().compareTo(p2.username.toLowerCase())); break; case 'status': - peers.sort((p1, p2) => p1.online ? 1 : -1); + peers.sort((p1, p2) => p1.online ? -1 : 1); break; } } From 39dba0c7afcf3c5f32737d28714771cd1239041a Mon Sep 17 00:00:00 2001 From: grummbeer Date: Tue, 7 Mar 2023 21:20:30 +0100 Subject: [PATCH 252/382] Android. Remove exclamation mark from notification. --- .../src/main/kotlin/com/carriez/flutter_hbb/MainService.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt index fa7440c8d..1c3fbce6c 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt @@ -623,7 +623,7 @@ class MainService : Service() { .setAutoCancel(true) .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setContentTitle(DEFAULT_NOTIFY_TITLE) - .setContentText(translate(DEFAULT_NOTIFY_TEXT) + '!') + .setContentText(translate(DEFAULT_NOTIFY_TEXT)) .setOnlyAlertOnce(true) .setContentIntent(pendingIntent) .setColor(ContextCompat.getColor(this, R.color.primary)) @@ -689,7 +689,7 @@ class MainService : Service() { private fun setTextNotification(_title: String?, _text: String?) { val title = _title ?: DEFAULT_NOTIFY_TITLE - val text = _text ?: translate(DEFAULT_NOTIFY_TEXT) + '!' + val text = _text ?: translate(DEFAULT_NOTIFY_TEXT) val notification = notificationBuilder .clearActions() .setStyle(null) From d1e0ae7815870c34f04cff5b8e896d38d91e9437 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Wed, 8 Mar 2023 11:28:00 +0800 Subject: [PATCH 253/382] never show empty display server, use x11 instead, #3541 --- libs/hbb_common/src/platform/linux.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/hbb_common/src/platform/linux.rs b/libs/hbb_common/src/platform/linux.rs index 191ea2e6f..f6133415a 100644 --- a/libs/hbb_common/src/platform/linux.rs +++ b/libs/hbb_common/src/platform/linux.rs @@ -81,8 +81,10 @@ fn get_display_server_of_session(session: &str) -> String { display_server = sestype; } } - // If the session is not a tty, then just return the type as usual - display_server + if display_server == "" { + display_server = "x11".to_owned(); + } + display_server.to_lowercase() } pub fn get_values_of_seat0(indices: Vec) -> Vec { From 2689688da5a8bc49ef0af31cfb45c060a71c510a Mon Sep 17 00:00:00 2001 From: rustdesk Date: Wed, 8 Mar 2023 11:44:41 +0800 Subject: [PATCH 254/382] chore: remove extra empty --- src/lang/ca.rs | 2 +- src/lang/cn.rs | 2 +- src/lang/cs.rs | 2 +- src/lang/da.rs | 2 +- src/lang/de.rs | 2 +- src/lang/el.rs | 2 +- src/lang/eo.rs | 2 +- src/lang/es.rs | 2 +- src/lang/fa.rs | 2 +- src/lang/fr.rs | 2 +- src/lang/hu.rs | 2 +- src/lang/id.rs | 2 +- src/lang/it.rs | 2 +- src/lang/ja.rs | 2 +- src/lang/ko.rs | 2 +- src/lang/kz.rs | 2 +- src/lang/nl.rs | 2 +- src/lang/pl.rs | 2 +- src/lang/pt_PT.rs | 2 +- src/lang/ptbr.rs | 2 +- src/lang/ro.rs | 2 +- src/lang/ru.rs | 2 +- src/lang/sk.rs | 2 +- src/lang/sl.rs | 2 +- src/lang/sq.rs | 2 +- src/lang/sr.rs | 2 +- src/lang/sv.rs | 2 +- src/lang/template.rs | 2 +- src/lang/th.rs | 2 +- src/lang/tr.rs | 2 +- src/lang/tw.rs | 2 +- src/lang/ua.rs | 2 +- src/lang/vn.rs | 2 +- src/ui_interface.rs | 2 +- 34 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index c4bc10bb4..1e3b4930d 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Avís"), ("Login screen using Wayland is not supported", "La pantalla d'inici de sessió amb Wayland no és compatible"), ("Reboot required", "Cal reiniciar"), - ("Unsupported display server ", "Servidor de visualització no compatible"), + ("Unsupported display server", "Servidor de visualització no compatible"), ("x11 expected", "x11 necessari"), ("Port", ""), ("Settings", "Ajustaments"), diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 9a8f176a2..94f0cd2d6 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "警告"), ("Login screen using Wayland is not supported", "不支持使用 Wayland 登录界面"), ("Reboot required", "重启后才能生效"), - ("Unsupported display server ", "不支持当前显示服务器"), + ("Unsupported display server", "不支持当前显示服务器"), ("x11 expected", "请切换到 x11"), ("Port", "端口"), ("Settings", "设置"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index e3ddc5db8..e7fb7684f 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Upozornení"), ("Login screen using Wayland is not supported", "Přihlašovací obrazovka prostřednictvím Wayland není podporována"), ("Reboot required", "Je třeba restartovat"), - ("Unsupported display server ", "Nepodporovaný zobrazovací server"), + ("Unsupported display server", "Nepodporovaný zobrazovací server"), ("x11 expected", "očekávány x11"), ("Port", ""), ("Settings", "Nastavení"), diff --git a/src/lang/da.rs b/src/lang/da.rs index f37f30a61..08758d7d1 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Advarsel"), ("Login screen using Wayland is not supported", "Registreringsskærm med Wayland understøttes ikke"), ("Reboot required", "Genstart krævet"), - ("Unsupported display server ", "Ikke-understøttet displayserver"), + ("Unsupported display server", "Ikke-understøttet displayserver"), ("x11 expected", "X11 Forventet"), ("Port", "Port"), ("Settings", "Indstillinger"), diff --git a/src/lang/de.rs b/src/lang/de.rs index 7a935d299..78d6d6c15 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -204,7 +204,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 Anzeigeserver"), + ("Unsupported display server", "Nicht unterstützter Anzeigeserver"), ("x11 expected", "X11 erwartet"), ("Port", "Port"), ("Settings", "Einstellungen"), diff --git a/src/lang/el.rs b/src/lang/el.rs index 40cf36b91..89458bec6 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Προειδοποίηση"), ("Login screen using Wayland is not supported", "Η οθόνη εισόδου με χρήση του Wayland δεν υποστηρίζεται"), ("Reboot required", "Απαιτείται επανεκκίνηση"), - ("Unsupported display server ", "Μη υποστηριζόμενος διακομιστής εμφάνισης "), + ("Unsupported display server", "Μη υποστηριζόμενος διακομιστής εμφάνισης "), ("x11 expected", "απαιτείται X11"), ("Port", "Θύρα"), ("Settings", "Ρυθμίσεις"), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index ed64addf8..63995a918 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Averto"), ("Login screen using Wayland is not supported", "Konektajn ekranojn uzantajn Wayland ne estas subtenitaj"), ("Reboot required", "Restarto deviga"), - ("Unsupported display server ", "La aktuala bilda servilo ne estas subtenita"), + ("Unsupported display server", "La aktuala bilda servilo ne estas subtenita"), ("x11 expected", "Bonvolu uzi x11"), ("Port", ""), ("Settings", "Agordoj"), diff --git a/src/lang/es.rs b/src/lang/es.rs index 3270ae26c..fb45ddcd0 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Aviso"), ("Login screen using Wayland is not supported", "La pantalla de inicio de sesión con Wayland no es compatible"), ("Reboot required", "Reinicio requerido"), - ("Unsupported display server ", "Servidor de visualización no compatible"), + ("Unsupported display server", "Servidor de visualización no compatible"), ("x11 expected", "x11 necesario"), ("Port", "Puerto"), ("Settings", "Ajustes"), diff --git a/src/lang/fa.rs b/src/lang/fa.rs index e2a7e9516..9c24ca6c3 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "هشدار"), ("Login screen using Wayland is not supported", "پشتیبانی نمی شود Wayland ورود به سیستم با استفاده از "), ("Reboot required", "راه اندازی مجدد مورد نیاز است"), - ("Unsupported display server ", "سرور تصویر پشتیبانی نشده است"), + ("Unsupported display server", "سرور تصویر پشتیبانی نشده است"), ("x11 expected", ""), ("Port", "پورت"), ("Settings", "تنظیمات"), diff --git a/src/lang/fr.rs b/src/lang/fr.rs index c0d739f91..7cb6d1239 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Avertissement"), ("Login screen using Wayland is not supported", "L'écran de connexion utilisant Wayland n'est pas pris en charge"), ("Reboot required", "Redémarrage requis"), - ("Unsupported display server ", "Le serveur d'affichage actuel n'est pas pris en charge"), + ("Unsupported display server", "Le serveur d'affichage actuel n'est pas pris en charge"), ("x11 expected", "x11 requis"), ("Port", "Port"), ("Settings", "Paramètres"), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 46750eb13..f9ff3bd0f 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Figyelmeztetés"), ("Login screen using Wayland is not supported", "Bejelentkezéskori Wayland használata nem támogatott"), ("Reboot required", "Újraindítás szükséges"), - ("Unsupported display server ", "Nem támogatott megjelenítő szerver"), + ("Unsupported display server", "Nem támogatott megjelenítő szerver"), ("x11 expected", "x11-re számítottt"), ("Port", "Port"), ("Settings", "Beállítások"), diff --git a/src/lang/id.rs b/src/lang/id.rs index 4133f136f..e210432c0 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Peringatan"), ("Login screen using Wayland is not supported", "Layar masuk menggunakan Wayland tidak didukung"), ("Reboot required", "Diperlukan boot ulang"), - ("Unsupported display server ", "Server tampilan tidak didukung "), + ("Unsupported display server", "Server tampilan tidak didukung "), ("x11 expected", "x11 diharapkan"), ("Port", "Port"), ("Settings", "Pengaturan"), diff --git a/src/lang/it.rs b/src/lang/it.rs index 17f066eef..7dfc67f29 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Avviso"), ("Login screen using Wayland is not supported", "La schermata di accesso non è supportata utilizzando Wayland"), ("Reboot required", "Riavvio necessario"), - ("Unsupported display server ", "Display server non supportato"), + ("Unsupported display server", "Display server non supportato"), ("x11 expected", "x11 necessario"), ("Port", "Porta"), ("Settings", "Impostazioni"), diff --git a/src/lang/ja.rs b/src/lang/ja.rs index b8031573a..48391d8f2 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "注意"), ("Login screen using Wayland is not supported", "Waylandを使用したログインスクリーンはサポートされていません"), ("Reboot required", "再起動が必要"), - ("Unsupported display server ", "サポートされていないディスプレイサーバー"), + ("Unsupported display server", "サポートされていないディスプレイサーバー"), ("x11 expected", "X11 が必要です"), ("Port", ""), ("Settings", "設定"), diff --git a/src/lang/ko.rs b/src/lang/ko.rs index fe6a0bfe9..91b73fc45 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "경고"), ("Login screen using Wayland is not supported", "Wayland를 사용한 로그인 화면이 지원되지 않습니다"), ("Reboot required", "재부팅이 필요합니다"), - ("Unsupported display server ", "지원하지 않는 디스플레이 서버"), + ("Unsupported display server", "지원하지 않는 디스플레이 서버"), ("x11 expected", "x11 예상됨"), ("Port", ""), ("Settings", "설정"), diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 4b1e92cad..9d7cf3971 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Ескерту"), ("Login screen using Wayland is not supported", "Wayland қолданған Кіру екіреніне қолдау көрсетілмейді"), ("Reboot required", "Қайта-қосу қажет"), - ("Unsupported display server ", "Қолдаусыз дисплей сербері"), + ("Unsupported display server", "Қолдаусыз дисплей сербері"), ("x11 expected", "x11 күтілген"), ("Port", "Порт"), ("Settings", "Орнатпалар"), diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 7888eed8e..5b959a353 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Waarschuwing"), ("Login screen using Wayland is not supported", "Aanmeldingsscherm via Wayland wordt niet ondersteund"), ("Reboot required", "Opnieuw opstarten vereist"), - ("Unsupported display server ", "Niet-ondersteunde weergaveserver"), + ("Unsupported display server", "Niet-ondersteunde weergaveserver"), ("x11 expected", "x11 verwacht"), ("Port", "Poort"), ("Settings", "Instellingen"), diff --git a/src/lang/pl.rs b/src/lang/pl.rs index b997267f1..4d99f3be2 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Ostrzeżenie"), ("Login screen using Wayland is not supported", "Ekran logowania korzystający z Wayland nie jest obsługiwany"), ("Reboot required", "Wymagany ponowne uruchomienie"), - ("Unsupported display server ", "Nieobsługiwany serwer wyświetlania"), + ("Unsupported display server", "Nieobsługiwany serwer wyświetlania"), ("x11 expected", "Wymagany jest X11"), ("Port", "Port"), ("Settings", "Ustawienia"), diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 98b8035a4..e568daeb5 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Aviso"), ("Login screen using Wayland is not supported", "Tela de Login com Wayland não é suportada"), ("Reboot required", "Reinicialização necessária"), - ("Unsupported display server ", "Servidor de display não suportado"), + ("Unsupported display server", "Servidor de display não suportado"), ("x11 expected", "x11 em falha"), ("Port", ""), ("Settings", "Configurações"), diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 18c9168c1..54389652c 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Aviso"), ("Login screen using Wayland is not supported", "Tela de Login utilizando Wayland não é suportada"), ("Reboot required", "Reinicialização necessária"), - ("Unsupported display server ", "Servidor de display não suportado"), + ("Unsupported display server", "Servidor de display não suportado"), ("x11 expected", "x11 esperado"), ("Port", "Porta"), ("Settings", "Configurações"), diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 225fa7277..14675762c 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Avertisment"), ("Login screen using Wayland is not supported", "Ecranele de conectare care folosesc Wayland nu sunt acceptate"), ("Reboot required", "Repornire necesară"), - ("Unsupported display server ", "Tipul de server de afișaj nu este acceptat"), + ("Unsupported display server", "Tipul de server de afișaj nu este acceptat"), ("x11 expected", "E necesar X11"), ("Port", "Port"), ("Settings", "Setări"), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 59957a2cd..adc5872a3 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Предупреждение"), ("Login screen using Wayland is not supported", "Вход в систему с использованием Wayland не поддерживается"), ("Reboot required", "Требуется перезагрузка"), - ("Unsupported display server ", "Неподдерживаемый сервер отображения"), + ("Unsupported display server", "Неподдерживаемый сервер отображения"), ("x11 expected", "Ожидается X11"), ("Port", "Порт"), ("Settings", "Настройки"), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index cec9e5b3d..1031fb9d2 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Upozornenie"), ("Login screen using Wayland is not supported", "Prihlasovacia obrazovka prostredníctvom Wayland nie je podporovaná"), ("Reboot required", "Vyžaduje sa reštart"), - ("Unsupported display server ", "Nepodporovaný zobrazovací (display) server"), + ("Unsupported display server", "Nepodporovaný zobrazovací (display) server"), ("x11 expected", "očakáva sa x11"), ("Port", ""), ("Settings", "Nastavenia"), diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 295cd28a1..b1b5dbeb0 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Opozorilo"), ("Login screen using Wayland is not supported", "Prijava z Waylandom ni podprta"), ("Reboot required", "Potreben je ponovni zagon"), - ("Unsupported display server ", "Nepodprt zaslonski strežnik"), + ("Unsupported display server", "Nepodprt zaslonski strežnik"), ("x11 expected", "Pričakovan X11"), ("Port", "Vrata"), ("Settings", "Nastavitve"), diff --git a/src/lang/sq.rs b/src/lang/sq.rs index ebbdf4a28..a73a5f10c 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Dicka po shkon keq"), ("Login screen using Wayland is not supported", "Hyrja në ekran duke përdorur Wayland muk suportohet"), ("Reboot required", "Kërkohet rinisja"), - ("Unsupported display server ", "Nuk supurtohet severi ekranit"), + ("Unsupported display server", "Nuk supurtohet severi ekranit"), ("x11 expected", "Pritet x11"), ("Port", "Port"), ("Settings", "Cilësimet"), diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 67fb49799..c4e70bd85 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Upozorenje"), ("Login screen using Wayland is not supported", "Ekran za prijavu koji koristi Wayland nije podržan"), ("Reboot required", "Potreban je restart"), - ("Unsupported display server ", "Nepodržan server za prikaz"), + ("Unsupported display server", "Nepodržan server za prikaz"), ("x11 expected", "x11 očekivan"), ("Port", "Port"), ("Settings", "Postavke"), diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 9da1f1071..88db1e931 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Varning"), ("Login screen using Wayland is not supported", "Login med Wayland stöds inte"), ("Reboot required", "Omstart krävs"), - ("Unsupported display server ", "Displayserver stöds inte "), + ("Unsupported display server", "Displayserver stöds inte "), ("x11 expected", "x11 förväntades"), ("Port", "Port"), ("Settings", "Inställningar"), diff --git a/src/lang/template.rs b/src/lang/template.rs index cbbd65b4c..2255d8aa5 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", ""), ("Login screen using Wayland is not supported", ""), ("Reboot required", ""), - ("Unsupported display server ", ""), + ("Unsupported display server", ""), ("x11 expected", ""), ("Port", ""), ("Settings", ""), diff --git a/src/lang/th.rs b/src/lang/th.rs index 97a8725e3..e0bfe8846 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "คำเตือน"), ("Login screen using Wayland is not supported", "หน้าจอการเข้าสู่ระบบโดยใช้ Wayland ยังไม่ถูกรองรับ"), ("Reboot required", "จำเป็นต้องเริ่มต้นระบบใหม่"), - ("Unsupported display server ", "เซิร์ฟเวอร์การแสดงผลที่ไม่รองรับ"), + ("Unsupported display server", "เซิร์ฟเวอร์การแสดงผลที่ไม่รองรับ"), ("x11 expected", "ต้องใช้งาน x11"), ("Port", "พอร์ท"), ("Settings", "ตั้งค่า"), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 3b1137cb7..e0d1d5777 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Uyarı"), ("Login screen using Wayland is not supported", "Wayland kullanan giriş ekranı desteklenmiyor"), ("Reboot required", "Yeniden başlatma gerekli"), - ("Unsupported display server ", "Desteklenmeyen görüntü sunucusu"), + ("Unsupported display server", "Desteklenmeyen görüntü sunucusu"), ("x11 expected", "x11 bekleniyor"), ("Port", "Port"), ("Settings", "Ayarlar"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 3cf05689a..6bf0b0fa8 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "警告"), ("Login screen using Wayland is not supported", "不支援使用 Wayland 的登入畫面"), ("Reboot required", "需要重新啟動"), - ("Unsupported display server ", "不支援顯示伺服器"), + ("Unsupported display server", "不支援顯示伺服器"), ("x11 expected", "預期 x11"), ("Port", "端口"), ("Settings", "設定"), diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 4665d7c39..d5142452e 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Попередження"), ("Login screen using Wayland is not supported", "Вхід у систему з використанням Wayland не підтримується"), ("Reboot required", "Потрібне перезавантаження"), - ("Unsupported display server ", "Графічний сервер не підтримується"), + ("Unsupported display server", "Графічний сервер не підтримується"), ("x11 expected", "Очікується X11"), ("Port", "Порт"), ("Settings", "Налаштування"), diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 0130b11cf..c71d12d16 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -204,7 +204,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Warning", "Cảnh báo"), ("Login screen using Wayland is not supported", "Màn hình đăng nhập sử dụng Wayland không đựoc hỗ trợ"), ("Reboot required", "Yêu cầu khởi động lại"), - ("Unsupported display server ", "Máy chủ hiển thị không đuợc hỗ trọ"), + ("Unsupported display server", "Máy chủ hiển thị không đuợc hỗ trọ"), ("x11 expected", "Cần x11"), ("Port", ""), ("Settings", "Cài đặt"), diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 1d4bd5cf4..ec570b42c 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -511,7 +511,7 @@ pub fn get_error() -> String { if dtype != "x11" { return format!( "{} {}, {}", - crate::client::translate("Unsupported display server ".to_owned()), + crate::client::translate("Unsupported display server".to_owned()), dtype, crate::client::translate("x11 expected".to_owned()), ); From e00eaee4b56b7c00bfb00b316089b360099b587d Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 7 Mar 2023 19:10:37 +0800 Subject: [PATCH 255/382] win, install cert Signed-off-by: fufesou --- Cargo.lock | 1 + Cargo.toml | 3 +- flutter/lib/desktop/pages/install_page.dart | 18 +++ src/platform/windows.rs | 164 ++++++++++++++++++++ 4 files changed, 185 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index d0f22a0ab..1029bfed4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4943,6 +4943,7 @@ dependencies = [ "flutter_rust_bridge_codegen", "fruitbasket", "hbb_common", + "hex", "hound", "image 0.24.5", "impersonate_system", diff --git a/Cargo.toml b/Cargo.toml index ba92733ca..47c2bb0e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,7 @@ errno = "0.2.8" rdev = { git = "https://github.com/fufesou/rdev" } url = { version = "2.1", features = ["serde"] } dlopen = "0.1" +hex = "0.4.3" reqwest = { version = "0.11", features = ["blocking", "json", "rustls-tls"], default-features=false } chrono = "0.4.23" @@ -87,7 +88,7 @@ system_shutdown = "3.0.0" [target.'cfg(target_os = "windows")'.dependencies] trayicon = { git = "https://github.com/open-trade/trayicon-rs", features = ["winit"] } winit = "0.26" -winapi = { version = "0.3", features = ["winuser"] } +winapi = { version = "0.3", features = ["winuser", "wincrypt"] } winreg = "0.10" windows-service = "0.4" virtual_display = { path = "libs/virtual_display" } diff --git a/flutter/lib/desktop/pages/install_page.dart b/flutter/lib/desktop/pages/install_page.dart index 00ca2bb23..856430dc6 100644 --- a/flutter/lib/desktop/pages/install_page.dart +++ b/flutter/lib/desktop/pages/install_page.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; @@ -63,6 +65,7 @@ class _InstallPageBodyState extends State<_InstallPageBody> late final TextEditingController controller; final RxBool startmenu = true.obs; final RxBool desktopicon = true.obs; + final RxBool driverCert = false.obs; final RxBool showProgress = false.obs; final RxBool btnEnabled = true.obs; @@ -165,6 +168,20 @@ class _InstallPageBodyState extends State<_InstallPageBody> Text(translate('Create desktop icon')) ], ), + Offstage( + offstage: !Platform.isWindows, + child: Row( + children: [ + Obx(() => Checkbox( + value: driverCert.value, + onChanged: (b) { + if (b != null) driverCert.value = b; + })), + Text( + '${translate('Install driver cert')} ${translate('Virtual display requirement')}') + ], + ), + ), GestureDetector( onTap: () => launchUrlString('http://rustdesk.com/privacy'), child: Row( @@ -230,6 +247,7 @@ class _InstallPageBodyState extends State<_InstallPageBody> String args = ''; if (startmenu.value) args += ' startmenu'; if (desktopicon.value) args += ' desktopicon'; + if (driverCert.value) args += ' driverCert'; bind.installInstallMe(options: args, path: controller.text); } diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 3d8b415b5..fe91b618e 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1084,6 +1084,9 @@ copy /Y \"{tmp_path}\\Uninstall {app_name}.lnk\" \"{start_menu}\\\" app_name = crate::get_app_name(), ); } + if options.contains("driverCert") { + allow_err!(cert::install_cert("IddSampleDriver.cer")); + } let meta = std::fs::symlink_metadata(std::env::current_exe()?)?; let size = meta.len() / 1024; @@ -1236,6 +1239,7 @@ fn get_uninstall(kill_self: bool) -> String { } pub fn uninstall_me(kill_self: bool) -> ResultType<()> { + allow_err!(cert::uninstall_certs()); run_cmds(get_uninstall(kill_self), true, "uninstall") } @@ -1902,3 +1906,163 @@ pub fn user_accessible_folder() -> ResultType { } Ok(dir) } + +mod cert { + use hbb_common::{bail, log, ResultType}; + use std::{path::Path, str::from_utf8}; + use winapi::shared::{ + minwindef::{BYTE, DWORD, TRUE}, + ntdef::NULL, + }; + use winapi::um::{ + errhandlingapi::GetLastError, + wincrypt::{ + CertCloseStore, CertEnumCertificatesInStore, CertNameToStrA, CertOpenSystemStoreA, + CryptHashCertificate, ALG_ID, CALG_SHA1, CERT_ID_SHA1_HASH, CERT_X500_NAME_STR, + PCCERT_CONTEXT, + }, + winreg::HKEY_LOCAL_MACHINE, + }; + use winreg::{ + enums::{KEY_WRITE, REG_BINARY}, + RegKey, + }; + + const ROOT_CERT_STORE_PATH: &str = "SOFTWARE\\Microsoft\\SystemCertificates\\ROOT\\Certificates\\"; + const THUMBPRINT_ALG: ALG_ID = CALG_SHA1; + const THUMBPRINT_LEN: DWORD = 20; + + #[inline] + unsafe fn compute_thumbprint(pb_encoded: *const BYTE, cb_encoded: DWORD) -> (Vec, String) { + let mut size = THUMBPRINT_LEN; + let mut thumbprint = [0u8; THUMBPRINT_LEN as usize]; + if CryptHashCertificate( + 0, + THUMBPRINT_ALG, + 0, + pb_encoded, + cb_encoded, + thumbprint.as_mut_ptr(), + &mut size, + ) == TRUE + { + (thumbprint.to_vec(), hex::encode(thumbprint)) + } else { + (thumbprint.to_vec(), "".to_owned()) + } + } + + #[inline] + unsafe fn open_reg_cert_store() -> ResultType { + let hklm = winreg::RegKey::predef(HKEY_LOCAL_MACHINE); + Ok(hklm.open_subkey_with_flags(ROOT_CERT_STORE_PATH, KEY_WRITE)?) + } + + // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gpef/6a9e35fa-2ac7-4c10-81e1-eabe8d2472f1 + fn create_cert_blob(thumbprint: Vec, encoded: Vec) -> Vec { + let mut blob = Vec::new(); + + let mut property_id = (CERT_ID_SHA1_HASH as u32).to_le_bytes().to_vec(); + let mut pro_reserved = [0x01, 0x00, 0x00, 0x00].to_vec(); + let mut pro_length = (THUMBPRINT_LEN as u32).to_le_bytes().to_vec(); + let mut pro_val = thumbprint; + blob.append(&mut property_id); + blob.append(&mut pro_reserved); + blob.append(&mut pro_length); + blob.append(&mut pro_val); + + let mut blob_reserved = [0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00].to_vec(); + let mut blob_length = (encoded.len() as u32).to_le_bytes().to_vec(); + let mut blob_val = encoded; + blob.append(&mut blob_reserved); + blob.append(&mut blob_length); + blob.append(&mut blob_val); + + blob + } + + pub fn install_cert>(path: P) -> ResultType<()> { + let mut cert_bytes = std::fs::read(path)?; + unsafe { + let thumbprint = compute_thumbprint(cert_bytes.as_mut_ptr(), cert_bytes.len() as _); + log::debug!("Thumbprint of cert {}", &thumbprint.1); + + let reg_cert_key = open_reg_cert_store()?; + let (cert_key, _) = reg_cert_key.create_subkey(&thumbprint.1.to_ascii_uppercase())?; + let data = winreg::RegValue { + vtype: REG_BINARY, + bytes: create_cert_blob(thumbprint.0, cert_bytes), + }; + cert_key.set_raw_value("Blob", &data)?; + } + Ok(()) + } + + fn get_thumbprints_to_rm() -> ResultType> { + let issuers_to_rm = ["CN=\"WDKTestCert admin,133225435702113567\""]; + + let mut thumbprints = Vec::new(); + let mut buf = [0u8; 1024]; + + unsafe { + let store_handle = CertOpenSystemStoreA(0 as _, "ROOT\0".as_ptr() as _); + if store_handle.is_null() { + bail!("Error opening certificate store: {}", GetLastError()); + } + + let mut cert_ctx: PCCERT_CONTEXT = CertEnumCertificatesInStore(store_handle, NULL as _); + while !cert_ctx.is_null() { + // https://stackoverflow.com/a/66432736 + let cb_size = CertNameToStrA( + (*cert_ctx).dwCertEncodingType, + &mut ((*(*cert_ctx).pCertInfo).Issuer) as _, + CERT_X500_NAME_STR, + buf.as_mut_ptr() as _, + buf.len() as _, + ); + if cb_size != 1 { + if let Ok(issuer) = from_utf8(&buf) { + for iss in issuers_to_rm.iter() { + if issuer.contains(iss) { + let (_, thumbprint) = compute_thumbprint( + (*cert_ctx).pbCertEncoded, + (*cert_ctx).cbCertEncoded, + ); + if !thumbprint.is_empty() { + thumbprints.push(thumbprint); + } + } + } + } + } + cert_ctx = CertEnumCertificatesInStore(store_handle, cert_ctx); + } + CertCloseStore(store_handle, 0); + } + + Ok(thumbprints) + } + + pub fn uninstall_certs() -> ResultType<()> { + let thumbprints = get_thumbprints_to_rm()?; + let reg_cert_key = unsafe { open_reg_cert_store()? }; + for thumbprint in thumbprints.iter() { + reg_cert_key.delete_subkey(&hex::encode(thumbprint)).ok(); + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_install_cert() { + println!("install driver cert: {:?}", cert::install_cert("RustDeskIddDriver.cer")); + } + + #[test] + fn test_uninstall_cert() { + println!("uninstall driver certs: {:?}", cert::uninstall_certs()); + } +} From 9bb9a749798ac6d3953a5e8313db20ef8d91b4c4 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 7 Mar 2023 19:43:39 +0800 Subject: [PATCH 256/382] win, install cert Signed-off-by: fufesou --- flutter/lib/desktop/pages/install_page.dart | 2 +- src/lang/ca.rs | 2 ++ src/lang/cn.rs | 2 ++ src/lang/cs.rs | 2 ++ src/lang/da.rs | 2 ++ src/lang/eo.rs | 2 ++ src/lang/es.rs | 2 ++ src/lang/fr.rs | 2 ++ src/lang/hu.rs | 2 ++ src/lang/id.rs | 2 ++ src/lang/it.rs | 2 ++ src/lang/ja.rs | 2 ++ src/lang/ko.rs | 2 ++ src/lang/kz.rs | 2 ++ src/lang/nl.rs | 2 ++ src/lang/pl.rs | 2 ++ src/lang/pt_PT.rs | 2 ++ src/lang/ptbr.rs | 2 ++ src/lang/ro.rs | 2 ++ src/lang/sk.rs | 2 ++ src/lang/sl.rs | 2 ++ src/lang/sq.rs | 2 ++ src/lang/sr.rs | 2 ++ src/lang/sv.rs | 2 ++ src/lang/template.rs | 2 ++ src/lang/th.rs | 2 ++ src/lang/tr.rs | 2 ++ src/lang/tw.rs | 2 ++ src/lang/ua.rs | 2 ++ src/lang/vn.rs | 2 ++ src/platform/windows.rs | 6 +++--- 31 files changed, 62 insertions(+), 4 deletions(-) diff --git a/flutter/lib/desktop/pages/install_page.dart b/flutter/lib/desktop/pages/install_page.dart index 856430dc6..5dbba39d7 100644 --- a/flutter/lib/desktop/pages/install_page.dart +++ b/flutter/lib/desktop/pages/install_page.dart @@ -178,7 +178,7 @@ class _InstallPageBodyState extends State<_InstallPageBody> if (b != null) driverCert.value = b; })), Text( - '${translate('Install driver cert')} ${translate('Virtual display requirement')}') + '${translate('Install driver cert(test cert)')} ${translate('Virtual display requirement')}') ], ), ), diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 1e3b4930d..8ce7c59ef 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 94f0cd2d6..4ae8cbd70 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "分辨率"), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", "安装驱动证书(测试证书)"), + ("Virtual display requirement", "虚拟显示器要求") ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index e7fb7684f..a835825db 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 08758d7d1..afa86e2d1 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 63995a918..c07f34bea 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index fb45ddcd0..ca486a753 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Resolución"), ("No transfers in progress", "No hay transferencias en curso"), ("Set one-time password length", "Establecer contraseña de un solo uso"), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 7cb6d1239..4f39d295d 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index f9ff3bd0f..32cf282e8 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index e210432c0..1da76479d 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 7dfc67f29..41d3000dc 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Risoluzione"), ("No transfers in progress", "Nessun trasferimento in corso"), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 48391d8f2..24dc25b08 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 91b73fc45..fc92d9642 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 9d7cf3971..cb74d04bb 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 5b959a353..900a1c4b9 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Resolutie"), ("No transfers in progress", "Geen overdrachten in uitvoering"), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 4d99f3be2..3665b00c7 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Rozdzielczość"), ("No transfers in progress", "Brak transferów w toku"), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index e568daeb5..4f9074f02 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 54389652c..a7e831fb2 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 14675762c..0b2b1407a 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 1031fb9d2..086ef00e6 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index b1b5dbeb0..7db2a9d2f 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index a73a5f10c..c18080d98 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index c4e70bd85..30e2e7a00 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 88db1e931..6284a346f 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 2255d8aa5..19474fc19 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index e0bfe8846..06b6731a6 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index e0d1d5777..80938a70b 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 6bf0b0fa8..882a779a9 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "分辨率"), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index d5142452e..70512a713 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index c71d12d16..c7e6e8f4b 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/platform/windows.rs b/src/platform/windows.rs index fe91b618e..11a8ee53f 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1084,9 +1084,6 @@ copy /Y \"{tmp_path}\\Uninstall {app_name}.lnk\" \"{start_menu}\\\" app_name = crate::get_app_name(), ); } - if options.contains("driverCert") { - allow_err!(cert::install_cert("IddSampleDriver.cer")); - } let meta = std::fs::symlink_metadata(std::env::current_exe()?)?; let size = meta.len() / 1024; @@ -1177,6 +1174,9 @@ sc delete {app_name} ); run_cmds(cmds, debug, "install")?; std::thread::sleep(std::time::Duration::from_millis(2000)); + if options.contains("driverCert") { + allow_err!(cert::install_cert(std::path::Path::new(&path).join("IddSampleDriver.cer"))); + } if !silent { std::process::Command::new(&exe).spawn()?; std::process::Command::new(&exe).arg("--tray").spawn()?; From ea44eb5380996b58c6b9745855e8611869ba9288 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 7 Mar 2023 19:52:29 +0800 Subject: [PATCH 257/382] win, add idd-driver build option Signed-off-by: fufesou --- .github/workflows/flutter-nightly.yml | 2 +- build.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/flutter-nightly.yml b/.github/workflows/flutter-nightly.yml index 4ae281583..c9aa01a83 100644 --- a/.github/workflows/flutter-nightly.yml +++ b/.github/workflows/flutter-nightly.yml @@ -86,7 +86,7 @@ jobs: shell: bash - name: Build rustdesk - run: python3 .\build.py --portable --hwcodec --flutter + run: python3 .\build.py --portable --hwcodec --flutter --idd-driver - name: Sign rustdesk files uses: GermanBluefox/code-sign-action@v7 diff --git a/build.py b/build.py index 45fe1b132..d7e6e0edf 100755 --- a/build.py +++ b/build.py @@ -106,6 +106,12 @@ def make_parser(): action='store_true', help='Skip cargo build process, only flutter version + Linux supported currently' ) + if windows: + parser.add_argument( + '--idd-driver', + action='store_true', + help='Build idd driver for virtual display.' + ) return parser From 4f60dc952268789814010468df5e3355904e3d03 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 7 Mar 2023 20:29:44 +0800 Subject: [PATCH 258/382] win,debug Signed-off-by: fufesou --- .github/workflows/flutter-nightly.yml | 2 +- build.py | 6 ------ src/platform/windows.rs | 10 +++++----- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/.github/workflows/flutter-nightly.yml b/.github/workflows/flutter-nightly.yml index c9aa01a83..2a1254e23 100644 --- a/.github/workflows/flutter-nightly.yml +++ b/.github/workflows/flutter-nightly.yml @@ -86,7 +86,7 @@ jobs: shell: bash - name: Build rustdesk - run: python3 .\build.py --portable --hwcodec --flutter --idd-driver + run: python3 .\build.py --portable --hwcodec --flutter --feature IddDriver - name: Sign rustdesk files uses: GermanBluefox/code-sign-action@v7 diff --git a/build.py b/build.py index d7e6e0edf..45fe1b132 100755 --- a/build.py +++ b/build.py @@ -106,12 +106,6 @@ def make_parser(): action='store_true', help='Skip cargo build process, only flutter version + Linux supported currently' ) - if windows: - parser.add_argument( - '--idd-driver', - action='store_true', - help='Build idd driver for virtual display.' - ) return parser diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 11a8ee53f..22896e65b 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1908,7 +1908,7 @@ pub fn user_accessible_folder() -> ResultType { } mod cert { - use hbb_common::{bail, log, ResultType}; + use hbb_common::{allow_err, bail, log, ResultType}; use std::{path::Path, str::from_utf8}; use winapi::shared::{ minwindef::{BYTE, DWORD, TRUE}, @@ -1946,7 +1946,7 @@ mod cert { &mut size, ) == TRUE { - (thumbprint.to_vec(), hex::encode(thumbprint)) + (thumbprint.to_vec(), hex::encode(thumbprint).to_ascii_uppercase()) } else { (thumbprint.to_vec(), "".to_owned()) } @@ -1988,7 +1988,7 @@ mod cert { log::debug!("Thumbprint of cert {}", &thumbprint.1); let reg_cert_key = open_reg_cert_store()?; - let (cert_key, _) = reg_cert_key.create_subkey(&thumbprint.1.to_ascii_uppercase())?; + let (cert_key, _) = reg_cert_key.create_subkey(&thumbprint.1)?; let data = winreg::RegValue { vtype: REG_BINARY, bytes: create_cert_blob(thumbprint.0, cert_bytes), @@ -2021,7 +2021,7 @@ mod cert { buf.len() as _, ); if cb_size != 1 { - if let Ok(issuer) = from_utf8(&buf) { + if let Ok(issuer) = from_utf8(&buf[..cb_size as _]) { for iss in issuers_to_rm.iter() { if issuer.contains(iss) { let (_, thumbprint) = compute_thumbprint( @@ -2047,7 +2047,7 @@ mod cert { let thumbprints = get_thumbprints_to_rm()?; let reg_cert_key = unsafe { open_reg_cert_store()? }; for thumbprint in thumbprints.iter() { - reg_cert_key.delete_subkey(&hex::encode(thumbprint)).ok(); + allow_err!(reg_cert_key.delete_subkey(thumbprint)); } Ok(()) } From cf676df976e7ed751ee8151ac663be5e7d6d79e4 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 7 Mar 2023 20:34:06 +0800 Subject: [PATCH 259/382] remove unused file Signed-off-by: fufesou --- build.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.py b/build.py index 45fe1b132..0f511fc51 100755 --- a/build.py +++ b/build.py @@ -37,7 +37,7 @@ def parse_rc_features(feature): 'IddDriver': { 'zip_url': 'https://github.com/fufesou/RustDeskIddDriver/releases/download/v0.1/RustDeskIddDriver_x64.zip', 'checksum_url': 'https://github.com/fufesou/RustDeskIddDriver/releases/download/v0.1/checksum_md5', - 'exclude': ['README.md'], + 'exclude': ['README.md', 'certmgr.exe', 'install_cert_runas_admin.bat'], }, 'PrivacyMode': { 'zip_url': 'https://github.com/fufesou/RustDeskTempTopMostWindow/releases/download/v0.1' @@ -386,7 +386,7 @@ def main(): os.chdir('libs/virtual_display/dylib') system2('cargo build --release') os.chdir('../../..') - + return if flutter: build_flutter_windows(version, features) return From 28e95c0552171fad8484ac0157308473e86af24d Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 7 Mar 2023 20:42:40 +0800 Subject: [PATCH 260/382] debug Signed-off-by: fufesou --- build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.py b/build.py index 0f511fc51..4a39f596d 100755 --- a/build.py +++ b/build.py @@ -386,7 +386,7 @@ def main(): os.chdir('libs/virtual_display/dylib') system2('cargo build --release') os.chdir('../../..') - return + if flutter: build_flutter_windows(version, features) return From 79934d006b3a2b83badc972a3f98a4bf5490133b Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 7 Mar 2023 21:01:28 +0800 Subject: [PATCH 261/382] fix error cert file Signed-off-by: fufesou --- src/lang/cn.rs | 2 +- src/platform/windows.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 4ae8cbd70..7f579ecdd 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -462,6 +462,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", "安装驱动证书(测试证书)"), - ("Virtual display requirement", "虚拟显示器要求") + ("Virtual display requirement", "虚拟显示器需要") ].iter().cloned().collect(); } diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 22896e65b..dbf30311c 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1175,7 +1175,7 @@ sc delete {app_name} run_cmds(cmds, debug, "install")?; std::thread::sleep(std::time::Duration::from_millis(2000)); if options.contains("driverCert") { - allow_err!(cert::install_cert(std::path::Path::new(&path).join("IddSampleDriver.cer"))); + allow_err!(cert::install_cert(std::path::Path::new(&path).join("RustDeskIddDriver.cer"))); } if !silent { std::process::Command::new(&exe).spawn()?; From c0257bff525b57935f77fdad9bff2fa49122af01 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 7 Mar 2023 22:38:01 +0800 Subject: [PATCH 262/382] win, install cert Signed-off-by: fufesou --- src/core_main.rs | 4 ++++ src/lang/de.rs | 2 ++ src/lang/fa.rs | 2 ++ src/lang/ru.rs | 2 ++ src/platform/windows.rs | 25 ++++++++++++++++++++++--- 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/core_main.rs b/src/core_main.rs index 60a7d9c9c..76b630f88 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -143,6 +143,10 @@ pub fn core_main() -> Option> { #[cfg(feature = "with_rc")] hbb_common::allow_err!(crate::rc::extract_resources(&args[1])); return None; + } else if args[0] == "--install-cert" { + #[cfg(windows)] + hbb_common::allow_err!(crate::platform::windows::install_cert(&args[1])); + return None; } else if args[0] == "--portable-service" { crate::platform::elevate_or_run_as_system( click_setup, diff --git a/src/lang/de.rs b/src/lang/de.rs index 78d6d6c15..26fb727c5 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Auflösung"), ("No transfers in progress", "Keine Übertragungen im Gange"), ("Set one-time password length", "Länge des Einmalpassworts festlegen"), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 9c24ca6c3..a45768701 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "وضوح"), ("No transfers in progress", "هیچ انتقالی در حال انجام نیست"), ("Set one-time password length", "طول رمز یکبار مصرف را تعیین کنید"), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index adc5872a3..145700c0d 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -461,5 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Разрешение"), ("No transfers in progress", "Передача не осуществляется"), ("Set one-time password length", "Установить длину одноразового пароля"), + ("Install driver cert(test cert)", ""), + ("Virtual display requirement", "") ].iter().cloned().collect(); } diff --git a/src/platform/windows.rs b/src/platform/windows.rs index dbf30311c..696a18ab9 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1108,6 +1108,12 @@ if exist \"{tmp_path}\\{app_name} Tray.lnk\" del /f /q \"{tmp_path}\\{app_name} ); let src_exe = std::env::current_exe()?.to_str().unwrap_or("").to_string(); + let install_cert = if options.contains("driverCert") { + format!("\"{}\" --install-cert \"RustDeskIddDriver.cer\"", src_exe) + } else { + "".to_owned() + }; + let cmds = format!( " {uninstall_str} @@ -1139,6 +1145,7 @@ sc create {app_name} binpath= \"\\\"{exe}\\\" --import-config \\\"{config_path}\ sc start {app_name} sc stop {app_name} sc delete {app_name} +{install_cert} {after_install} {sleep} ", @@ -1159,6 +1166,7 @@ sc delete {app_name} shortcuts=shortcuts, config_path=Config::file().to_str().unwrap_or(""), lic=register_licence(), + install_cert=install_cert, after_install=get_after_install(&exe), sleep=if debug { "timeout 300" @@ -1174,9 +1182,6 @@ sc delete {app_name} ); run_cmds(cmds, debug, "install")?; std::thread::sleep(std::time::Duration::from_millis(2000)); - if options.contains("driverCert") { - allow_err!(cert::install_cert(std::path::Path::new(&path).join("RustDeskIddDriver.cer"))); - } if !silent { std::process::Command::new(&exe).spawn()?; std::process::Command::new(&exe).arg("--tray").spawn()?; @@ -1907,6 +1912,20 @@ pub fn user_accessible_folder() -> ResultType { Ok(dir) } +#[inline] +pub fn install_cert(cert_file: &str) -> ResultType<()> { + let exe_file = std::env::current_exe()?; + if let Some(cur_dir) = exe_file.parent() { + allow_err!(cert::install_cert(cur_dir.join(cert_file))); + } else { + bail!( + "Invalid exe parent for {}", + exe_file.to_string_lossy().as_ref() + ); + } + Ok(()) +} + mod cert { use hbb_common::{allow_err, bail, log, ResultType}; use std::{path::Path, str::from_utf8}; From ad32eec879c135ee2eb0e7d3d8da61d2e25745bd Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 8 Mar 2023 11:14:29 +0800 Subject: [PATCH 263/382] better install prompt Signed-off-by: fufesou --- flutter/lib/common.dart | 1 - flutter/lib/desktop/pages/install_page.dart | 50 +++++++++++++++++---- 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/hu.rs | 3 +- src/lang/id.rs | 3 +- src/lang/it.rs | 3 +- src/lang/ja.rs | 3 +- src/lang/ko.rs | 3 +- src/lang/kz.rs | 3 +- src/lang/nl.rs | 3 +- src/lang/pl.rs | 3 +- src/lang/pt_PT.rs | 3 +- src/lang/ptbr.rs | 3 +- src/lang/ro.rs | 3 +- src/lang/ru.rs | 3 +- src/lang/sk.rs | 3 +- src/lang/sl.rs | 3 +- src/lang/sq.rs | 3 +- src/lang/sr.rs | 3 +- src/lang/sv.rs | 3 +- src/lang/template.rs | 3 +- src/lang/th.rs | 3 +- src/lang/tr.rs | 3 +- src/lang/tw.rs | 3 +- src/lang/ua.rs | 3 +- src/lang/vn.rs | 3 +- 34 files changed, 106 insertions(+), 41 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index fce2c852f..666eab0ba 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -946,7 +946,6 @@ Widget msgboxContent(String type, String title, String text) { void msgBoxCommon(OverlayDialogManager dialogManager, String title, Widget content, List buttons, {bool hasCancel = true}) { - dialogManager.dismissAll(); dialogManager.show((setState, close) => CustomAlertDialog( title: Text( translate(title), diff --git a/flutter/lib/desktop/pages/install_page.dart b/flutter/lib/desktop/pages/install_page.dart index 5dbba39d7..96a090b17 100644 --- a/flutter/lib/desktop/pages/install_page.dart +++ b/flutter/lib/desktop/pages/install_page.dart @@ -65,7 +65,7 @@ class _InstallPageBodyState extends State<_InstallPageBody> late final TextEditingController controller; final RxBool startmenu = true.obs; final RxBool desktopicon = true.obs; - final RxBool driverCert = false.obs; + final RxBool driverCert = true.obs; final RxBool showProgress = false.obs; final RxBool btnEnabled = true.obs; @@ -242,13 +242,47 @@ class _InstallPageBodyState extends State<_InstallPageBody> } void install() { - btnEnabled.value = false; - showProgress.value = true; - String args = ''; - if (startmenu.value) args += ' startmenu'; - if (desktopicon.value) args += ' desktopicon'; - if (driverCert.value) args += ' driverCert'; - bind.installInstallMe(options: args, path: controller.text); + do_install() { + btnEnabled.value = false; + showProgress.value = true; + String args = ''; + if (startmenu.value) args += ' startmenu'; + if (desktopicon.value) args += ' desktopicon'; + if (driverCert.value) args += ' driverCert'; + bind.installInstallMe(options: args, path: controller.text); + } + + if (driverCert.isTrue) { + final tag = 'install-info-install-cert-confirm'; + final btns = [ + dialogButton( + 'Cancel', + onPressed: () => gFFI.dialogManager.dismissByTag(tag), + isOutline: true, + ), + dialogButton( + 'OK', + onPressed: () { + gFFI.dialogManager.dismissByTag(tag); + do_install(); + }, + isOutline: false, + ), + ]; + gFFI.dialogManager.show( + (setState, close) => CustomAlertDialog( + title: null, + content: SelectionArea( + child: msgboxContent( + 'info', '', 'Continue with installing cert is checked.')), + actions: btns, + onCancel: close, + ), + tag: tag, + ); + } else { + do_install(); + } } void selectInstallPath() async { diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 8ce7c59ef..7f0d902d5 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 7f579ecdd..2dad9d63e 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", "安装驱动证书(测试证书)"), - ("Virtual display requirement", "虚拟显示器需要") + ("Virtual display requirement", "虚拟显示器需"), + ("Continue with installing cert is checked.", "安装证书已选择,是否继续") ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index a835825db..d6a27eed2 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index afa86e2d1..082e0ec06 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 26fb727c5..563925391 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "Keine Übertragungen im Gange"), ("Set one-time password length", "Länge des Einmalpassworts festlegen"), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index c07f34bea..631d66a23 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index ca486a753..bbfce42c6 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "No hay transferencias en curso"), ("Set one-time password length", "Establecer contraseña de un solo uso"), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index a45768701..f7b609bdf 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "هیچ انتقالی در حال انجام نیست"), ("Set one-time password length", "طول رمز یکبار مصرف را تعیین کنید"), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 4f39d295d..933944fae 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 32cf282e8..557ce9439 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 1da76479d..40483bc6a 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 41d3000dc..afbf862c2 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "Nessun trasferimento in corso"), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 24dc25b08..f64e95c62 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index fc92d9642..e43df3cc1 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index cb74d04bb..636dcaf70 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 900a1c4b9..912eaec33 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "Geen overdrachten in uitvoering"), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 3665b00c7..b89f2fb25 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "Brak transferów w toku"), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 4f9074f02..dad48c821 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index a7e831fb2..c5d32b192 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 0b2b1407a..1a9ecd78e 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 145700c0d..f8603a44d 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "Передача не осуществляется"), ("Set one-time password length", "Установить длину одноразового пароля"), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 086ef00e6..3a9383497 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 7db2a9d2f..8ae15250c 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index c18080d98..77af8b5c8 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 30e2e7a00..2fb24a223 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 6284a346f..18259f32e 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 19474fc19..f0bb91f38 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 06b6731a6..b0b31829d 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 80938a70b..81ac5cbb6 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 882a779a9..3d394307e 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 70512a713..c40452778 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index c7e6e8f4b..6ecf025a4 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("Install driver cert(test cert)", ""), - ("Virtual display requirement", "") + ("Virtual display requirement", ""), + ("Continue with installing cert is checked.", "") ].iter().cloned().collect(); } From 1d85d87b402b025e9702cc92d13889a153107a95 Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 8 Mar 2023 12:51:04 +0800 Subject: [PATCH 264/382] translate changes Signed-off-by: fufesou --- flutter/lib/desktop/pages/install_page.dart | 5 ++--- src/lang/ca.rs | 6 +++--- src/lang/cn.rs | 6 +++--- src/lang/cs.rs | 6 +++--- src/lang/da.rs | 6 +++--- src/lang/de.rs | 6 +++--- src/lang/el.rs | 7 +++++-- src/lang/en.rs | 1 + src/lang/eo.rs | 6 +++--- src/lang/es.rs | 6 +++--- src/lang/fa.rs | 6 +++--- src/lang/fr.rs | 6 +++--- src/lang/hu.rs | 6 +++--- src/lang/id.rs | 6 +++--- src/lang/it.rs | 6 +++--- src/lang/ja.rs | 6 +++--- src/lang/ko.rs | 6 +++--- src/lang/kz.rs | 6 +++--- src/lang/nl.rs | 6 +++--- src/lang/pl.rs | 6 +++--- src/lang/pt_PT.rs | 6 +++--- src/lang/ptbr.rs | 6 +++--- src/lang/ro.rs | 6 +++--- src/lang/ru.rs | 6 +++--- src/lang/sk.rs | 6 +++--- src/lang/sl.rs | 6 +++--- src/lang/sq.rs | 6 +++--- src/lang/sr.rs | 6 +++--- src/lang/sv.rs | 6 +++--- src/lang/template.rs | 6 +++--- src/lang/th.rs | 6 +++--- src/lang/tr.rs | 6 +++--- src/lang/tw.rs | 6 +++--- src/lang/ua.rs | 6 +++--- src/lang/vn.rs | 6 +++--- 35 files changed, 104 insertions(+), 101 deletions(-) diff --git a/flutter/lib/desktop/pages/install_page.dart b/flutter/lib/desktop/pages/install_page.dart index 96a090b17..2334d633f 100644 --- a/flutter/lib/desktop/pages/install_page.dart +++ b/flutter/lib/desktop/pages/install_page.dart @@ -178,7 +178,7 @@ class _InstallPageBodyState extends State<_InstallPageBody> if (b != null) driverCert.value = b; })), Text( - '${translate('Install driver cert(test cert)')} ${translate('Virtual display requirement')}') + '${translate('Install driver cert (test cert)')} ${translate('Virtual display need')}') ], ), ), @@ -273,8 +273,7 @@ class _InstallPageBodyState extends State<_InstallPageBody> (setState, close) => CustomAlertDialog( title: null, content: SelectionArea( - child: msgboxContent( - 'info', '', 'Continue with installing cert is checked.')), + child: msgboxContent('info', '', 'instsall_cert_tip')), actions: btns, onCancel: close, ), diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 7f0d902d5..7c238c818 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 2dad9d63e..d12071186 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "分辨率"), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", "安装驱动证书(测试证书)"), - ("Virtual display requirement", "虚拟显示器需"), - ("Continue with installing cert is checked.", "安装证书已选择,是否继续") + ("Install driver cert (test cert)", "安装驱动证书 (测试证书)"), + ("Virtual display need", "虚拟显示器需要"), + ("instsall_cert_tip", "已选择安装驱动,是否继续?") ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index d6a27eed2..622730d93 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 082e0ec06..ce84b4805 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 563925391..37de302bd 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Auflösung"), ("No transfers in progress", "Keine Übertragungen im Gange"), ("Set one-time password length", "Länge des Einmalpassworts festlegen"), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index 89458bec6..162218edd 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -460,6 +460,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Κωδικοποίηση"), ("Resolution", "Ανάλυση"), ("No transfers in progress", "Δεν υπάρχει μεταφορά σε εξέλιξη"), - ("Set one-time password length", "Μέγεθος κωδικού μιας χρήσης"), - ].iter().cloned().collect(); + ("Set one-time password length", "Μέγεθος κωδικού μιας χρήσης"), + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") + ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index 250530013..01a4c843e 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -45,5 +45,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("config_microphone", "In order to speak remotely, you need to grant RustDesk \"Record Audio\" permissions."), ("relay_hint_tip", "It may not be possible to connect directly, you can try to connect via relay. \nIn addition, if you want to use relay on your first try, you can add the \"/r\" suffix to the ID, or select the option \"Always connect via relay\" in the peer card."), ("No transfers in progress", ""), + ("instsall_cert_tip", "\"Install driver cert\" is checked, continue?") ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 631d66a23..5c6c92783 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index bbfce42c6..fefa8b74e 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Resolución"), ("No transfers in progress", "No hay transferencias en curso"), ("Set one-time password length", "Establecer contraseña de un solo uso"), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index f7b609bdf..f6be0e01b 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "وضوح"), ("No transfers in progress", "هیچ انتقالی در حال انجام نیست"), ("Set one-time password length", "طول رمز یکبار مصرف را تعیین کنید"), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 933944fae..1e438bba6 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 557ce9439..1c243e2f6 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 40483bc6a..8edc78e1d 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index afbf862c2..400e0ad98 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Risoluzione"), ("No transfers in progress", "Nessun trasferimento in corso"), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index f64e95c62..e87a232f9 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index e43df3cc1..06d10d018 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 636dcaf70..ede87875b 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 912eaec33..55ad9504d 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Resolutie"), ("No transfers in progress", "Geen overdrachten in uitvoering"), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index b89f2fb25..08106782d 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Rozdzielczość"), ("No transfers in progress", "Brak transferów w toku"), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index dad48c821..11583b265 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index c5d32b192..7aa014682 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 1a9ecd78e..49b3b3585 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index f8603a44d..243ffda40 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Разрешение"), ("No transfers in progress", "Передача не осуществляется"), ("Set one-time password length", "Установить длину одноразового пароля"), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 3a9383497..1a5b9207d 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 8ae15250c..1efc4de47 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 77af8b5c8..ffe3c9edd 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 2fb24a223..fe7e0bae6 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 18259f32e..98ceed9ad 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index f0bb91f38..e0d7929af 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index b0b31829d..615c15508 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 81ac5cbb6..5bbddde5e 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 3d394307e..a056d6b81 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "分辨率"), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index c40452778..1bab4a553 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 6ecf025a4..f5b8052ef 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert(test cert)", ""), - ("Virtual display requirement", ""), - ("Continue with installing cert is checked.", "") + ("Install driver cert (test cert)", ""), + ("Virtual display need", ""), + ("instsall_cert_tip", "") ].iter().cloned().collect(); } From 18ca4273bef7fc4b8815f62d504b71e2eb771550 Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 8 Mar 2023 15:57:33 +0800 Subject: [PATCH 265/382] better prompt Signed-off-by: fufesou --- flutter/lib/desktop/pages/install_page.dart | 78 ++++++++++++++------- src/lang/ca.rs | 5 +- src/lang/cn.rs | 5 +- src/lang/cs.rs | 5 +- src/lang/da.rs | 5 +- src/lang/de.rs | 5 +- src/lang/el.rs | 5 +- src/lang/en.rs | 3 +- src/lang/eo.rs | 5 +- src/lang/es.rs | 5 +- src/lang/fa.rs | 5 +- src/lang/fr.rs | 5 +- src/lang/hu.rs | 5 +- src/lang/id.rs | 5 +- src/lang/it.rs | 5 +- src/lang/ja.rs | 5 +- src/lang/ko.rs | 5 +- src/lang/kz.rs | 5 +- src/lang/nl.rs | 5 +- src/lang/pl.rs | 5 +- src/lang/pt_PT.rs | 5 +- src/lang/ptbr.rs | 5 +- src/lang/ro.rs | 5 +- src/lang/ru.rs | 5 +- src/lang/sk.rs | 5 +- src/lang/sl.rs | 5 +- src/lang/sq.rs | 5 +- src/lang/sr.rs | 5 +- src/lang/sv.rs | 5 +- src/lang/template.rs | 5 +- src/lang/th.rs | 5 +- src/lang/tr.rs | 5 +- src/lang/tw.rs | 5 +- src/lang/ua.rs | 5 +- src/lang/vn.rs | 5 +- 35 files changed, 119 insertions(+), 127 deletions(-) diff --git a/flutter/lib/desktop/pages/install_page.dart b/flutter/lib/desktop/pages/install_page.dart index 2334d633f..adc0df138 100644 --- a/flutter/lib/desktop/pages/install_page.dart +++ b/flutter/lib/desktop/pages/install_page.dart @@ -148,40 +148,63 @@ class _InstallPageBodyState extends State<_InstallPageBody> .marginOnly(left: em)) ], ).marginSymmetric(vertical: 2 * em), - Row( - children: [ - Obx(() => Checkbox( - value: startmenu.value, - onChanged: (b) { - if (b != null) startmenu.value = b; - })), - Text(translate('Create start menu shortcuts')) - ], - ), - Row( - children: [ - Obx(() => Checkbox( - value: desktopicon.value, - onChanged: (b) { - if (b != null) desktopicon.value = b; - })), - Text(translate('Create desktop icon')) - ], - ), - Offstage( - offstage: !Platform.isWindows, + TextButton( + onPressed: () => startmenu.value = !startmenu.value, child: Row( children: [ Obx(() => Checkbox( - value: driverCert.value, + value: startmenu.value, onChanged: (b) { - if (b != null) driverCert.value = b; + if (b != null) startmenu.value = b; })), - Text( - '${translate('Install driver cert (test cert)')} ${translate('Virtual display need')}') + RichText( + text: TextSpan( + text: translate('Create start menu shortcuts'), + style: DefaultTextStyle.of(context).style, + ), + ), ], ), ), + TextButton( + onPressed: () => desktopicon.value = !desktopicon.value, + child: Row( + children: [ + Obx(() => Checkbox( + value: desktopicon.value, + onChanged: (b) { + if (b != null) desktopicon.value = b; + })), + RichText( + text: TextSpan( + text: translate('Create desktop icon'), + style: DefaultTextStyle.of(context).style, + ), + ), + ], + ), + ), + Offstage( + offstage: !Platform.isWindows, + child: TextButton( + onPressed: () => driverCert.value = !driverCert.value, + child: Row( + children: [ + Obx(() => Checkbox( + value: driverCert.value, + onChanged: (b) { + if (b != null) driverCert.value = b; + })), + RichText( + text: TextSpan( + text: translate('idd_driver_tip'), + style: DefaultTextStyle.of(context).style, + ), + ), + ], + ), + ), + ), GestureDetector( onTap: () => launchUrlString('http://rustdesk.com/privacy'), child: Row( @@ -273,7 +296,8 @@ class _InstallPageBodyState extends State<_InstallPageBody> (setState, close) => CustomAlertDialog( title: null, content: SelectionArea( - child: msgboxContent('info', '', 'instsall_cert_tip')), + child: + msgboxContent('info', 'Warning', 'confirm_idd_driver_tip')), actions: btns, onCancel: close, ), diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 7c238c818..3cea5e60e 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index d12071186..161fa0358 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "分辨率"), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", "安装驱动证书 (测试证书)"), - ("Virtual display need", "虚拟显示器需要"), - ("instsall_cert_tip", "已选择安装驱动,是否继续?") + ("idd_driver_tip", "安装虚拟显示器驱动,以便在没有连接显示器的情况下启动虚拟显示器进行控制。"), + ("confirm_idd_driver_tip", "安装虚拟显示器驱动的选项已勾选。请注意,测试证书将被安装以信任虚拟显示器驱动。测试证书仅会用于信任Rustdesk的驱动。") ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 622730d93..86e9c47c7 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index ce84b4805..d262c08cf 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 37de302bd..21e57701c 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Auflösung"), ("No transfers in progress", "Keine Übertragungen im Gange"), ("Set one-time password length", "Länge des Einmalpassworts festlegen"), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index 162218edd..b0e629ba7 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Ανάλυση"), ("No transfers in progress", "Δεν υπάρχει μεταφορά σε εξέλιξη"), ("Set one-time password length", "Μέγεθος κωδικού μιας χρήσης"), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index 01a4c843e..100788f6e 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -45,6 +45,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("config_microphone", "In order to speak remotely, you need to grant RustDesk \"Record Audio\" permissions."), ("relay_hint_tip", "It may not be possible to connect directly, you can try to connect via relay. \nIn addition, if you want to use relay on your first try, you can add the \"/r\" suffix to the ID, or select the option \"Always connect via relay\" in the peer card."), ("No transfers in progress", ""), - ("instsall_cert_tip", "\"Install driver cert\" is checked, continue?") + ("idd_driver_tip", "Install virtual display driver which is used when you have no physical displays."), + ("confirm_idd_driver_tip", "The option to install the virtual display driver is checked. Note that a test certificate will be installed to trust the virtual display driver. This test certificate will only be used to trust Rustdesk drivers.") ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 5c6c92783..f36afedcb 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index fefa8b74e..2b38ecd1e 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Resolución"), ("No transfers in progress", "No hay transferencias en curso"), ("Set one-time password length", "Establecer contraseña de un solo uso"), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index f6be0e01b..0cc8188b2 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "وضوح"), ("No transfers in progress", "هیچ انتقالی در حال انجام نیست"), ("Set one-time password length", "طول رمز یکبار مصرف را تعیین کنید"), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 1e438bba6..ef74b0666 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 1c243e2f6..f984afcdd 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 8edc78e1d..53f718e82 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 400e0ad98..c3b77ddf7 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Risoluzione"), ("No transfers in progress", "Nessun trasferimento in corso"), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index e87a232f9..4a0fc3abb 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 06d10d018..a3aef55cc 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index ede87875b..8b7582af3 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 55ad9504d..6fb537119 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Resolutie"), ("No transfers in progress", "Geen overdrachten in uitvoering"), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 08106782d..d60fe2d30 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Rozdzielczość"), ("No transfers in progress", "Brak transferów w toku"), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 11583b265..2747a0ca7 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 7aa014682..e8fca4b80 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 49b3b3585..e4521305f 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 243ffda40..473ec402f 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Разрешение"), ("No transfers in progress", "Передача не осуществляется"), ("Set one-time password length", "Установить длину одноразового пароля"), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 1a5b9207d..aeed03fcd 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 1efc4de47..eaa8b1b50 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index ffe3c9edd..46f14c738 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index fe7e0bae6..ee48beb32 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 98ceed9ad..b099acc9d 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index e0d7929af..bfab1a33a 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 615c15508..d77eb5fc1 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 5bbddde5e..d4d0b942d 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index a056d6b81..e1119b12c 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "分辨率"), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 1bab4a553..216f764c1 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index f5b8052ef..c7fbc5b9b 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -461,8 +461,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("Install driver cert (test cert)", ""), - ("Virtual display need", ""), - ("instsall_cert_tip", "") + ("idd_driver_tip", ""), + ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); } From ceda7320b4577e58615a45334a0d57b55830da6b Mon Sep 17 00:00:00 2001 From: ilGigioVr88 Date: Wed, 8 Mar 2023 09:18:15 +0100 Subject: [PATCH 266/382] Update it.rs --- src/lang/it.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/it.rs b/src/lang/it.rs index 7dfc67f29..00974b43e 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -460,6 +460,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Codec"), ("Resolution", "Risoluzione"), ("No transfers in progress", "Nessun trasferimento in corso"), - ("Set one-time password length", ""), + ("Set one-time password length", "Imposta la lunghezza della password monouso"), ].iter().cloned().collect(); } From 3da68377ae9b0194bfa5a0377a01e4213f2b64c6 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Wed, 8 Mar 2023 17:03:13 +0800 Subject: [PATCH 267/382] fix it --- src/lang/it.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lang/it.rs b/src/lang/it.rs index cd7e20a9c..0cab57203 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -461,7 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Risoluzione"), ("No transfers in progress", "Nessun trasferimento in corso"), ("Set one-time password length", "Imposta la lunghezza della password monouso"), - ("Set one-time password length", ""), ("idd_driver_tip", ""), ("confirm_idd_driver_tip", "") ].iter().cloned().collect(); From 513feca03f19916152249136de56f604ed963ad5 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Tue, 7 Mar 2023 22:03:52 +0100 Subject: [PATCH 268/382] Translations. Add "RDP Settings" --- flutter/lib/common/widgets/peer_card.dart | 2 +- src/lang/ca.rs | 3 ++- src/lang/cn.rs | 3 ++- src/lang/cs.rs | 3 ++- src/lang/da.rs | 3 ++- src/lang/de.rs | 3 ++- src/lang/el.rs | 3 ++- src/lang/eo.rs | 3 ++- src/lang/es.rs | 3 ++- src/lang/fa.rs | 3 ++- src/lang/fr.rs | 3 ++- src/lang/hu.rs | 3 ++- src/lang/id.rs | 3 ++- src/lang/it.rs | 3 ++- src/lang/ja.rs | 3 ++- src/lang/ko.rs | 3 ++- src/lang/kz.rs | 3 ++- src/lang/nl.rs | 3 ++- src/lang/pl.rs | 3 ++- src/lang/pt_PT.rs | 3 ++- src/lang/ptbr.rs | 3 ++- src/lang/ro.rs | 3 ++- src/lang/ru.rs | 3 ++- src/lang/sk.rs | 3 ++- src/lang/sl.rs | 3 ++- src/lang/sq.rs | 3 ++- src/lang/sr.rs | 3 ++- src/lang/sv.rs | 3 ++- src/lang/template.rs | 3 ++- src/lang/th.rs | 3 ++- src/lang/tr.rs | 3 ++- src/lang/tw.rs | 3 ++- src/lang/ua.rs | 3 ++- src/lang/vn.rs | 3 ++- 34 files changed, 67 insertions(+), 34 deletions(-) diff --git a/flutter/lib/common/widgets/peer_card.dart b/flutter/lib/common/widgets/peer_card.dart index 7d2d0cd2d..51ab3066d 100644 --- a/flutter/lib/common/widgets/peer_card.dart +++ b/flutter/lib/common/widgets/peer_card.dart @@ -1115,7 +1115,7 @@ void _rdpDialog(String id) async { } return CustomAlertDialog( - title: Text('RDP ${translate('Settings')}'), + title: Text(translate('RDP Settings')), content: ConstrainedBox( constraints: const BoxConstraints(minWidth: 500), child: Column( diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 3cea5e60e..9507ffc25 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 161fa0358..e5ba70aa6 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", "安装虚拟显示器驱动,以便在没有连接显示器的情况下启动虚拟显示器进行控制。"), - ("confirm_idd_driver_tip", "安装虚拟显示器驱动的选项已勾选。请注意,测试证书将被安装以信任虚拟显示器驱动。测试证书仅会用于信任Rustdesk的驱动。") + ("confirm_idd_driver_tip", "安装虚拟显示器驱动的选项已勾选。请注意,测试证书将被安装以信任虚拟显示器驱动。测试证书仅会用于信任Rustdesk的驱动。"), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 86e9c47c7..5920e002c 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index d262c08cf..6e7394d79 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 21e57701c..26925a9fb 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "Keine Übertragungen im Gange"), ("Set one-time password length", "Länge des Einmalpassworts festlegen"), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", "RDP Einstellungen"), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index b0e629ba7..4c3698194 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "Δεν υπάρχει μεταφορά σε εξέλιξη"), ("Set one-time password length", "Μέγεθος κωδικού μιας χρήσης"), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index f36afedcb..457fbea02 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 2b38ecd1e..7443f8640 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "No hay transferencias en curso"), ("Set one-time password length", "Establecer contraseña de un solo uso"), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 0cc8188b2..f1503a83e 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "هیچ انتقالی در حال انجام نیست"), ("Set one-time password length", "طول رمز یکبار مصرف را تعیین کنید"), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index ef74b0666..63d1ce317 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index f984afcdd..4789ba55d 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 53f718e82..e2a969a88 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 0cab57203..1c531c59f 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "Nessun trasferimento in corso"), ("Set one-time password length", "Imposta la lunghezza della password monouso"), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 4a0fc3abb..a2d3446bb 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index a3aef55cc..9c2076d63 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 8b7582af3..b8a415e48 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 6fb537119..595e0710e 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "Geen overdrachten in uitvoering"), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index d60fe2d30..08f6ca905 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "Brak transferów w toku"), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 2747a0ca7..1eb5fc6e7 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index e8fca4b80..df0f5a26e 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index e4521305f..7515ccbf1 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 473ec402f..afeb8d17d 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", "Передача не осуществляется"), ("Set one-time password length", "Установить длину одноразового пароля"), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index aeed03fcd..1d8c6c626 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index eaa8b1b50..07bb2b543 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 46f14c738..a7cdfa8e7 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index ee48beb32..bcdedef59 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index b099acc9d..63167ed82 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index bfab1a33a..3fb6d17a9 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index d77eb5fc1..808f69f8d 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index d4d0b942d..34949aa4c 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index e1119b12c..17ef4b7ed 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 216f764c1..cc44d86d0 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index c7fbc5b9b..b774e094f 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -462,6 +462,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("No transfers in progress", ""), ("Set one-time password length", ""), ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", "") + ("confirm_idd_driver_tip", ""), + ("RDP Settings", ""), ].iter().cloned().collect(); } From c28238542ae97a61b3250d207b9748539758ec53 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 8 Mar 2023 02:13:55 +0100 Subject: [PATCH 269/382] Fix. Mobile. Remove left label in RDP dialog --- flutter/lib/common/widgets/peer_card.dart | 63 +++++++++++++---------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/flutter/lib/common/widgets/peer_card.dart b/flutter/lib/common/widgets/peer_card.dart index 51ab3066d..73660cc3a 100644 --- a/flutter/lib/common/widgets/peer_card.dart +++ b/flutter/lib/common/widgets/peer_card.dart @@ -1126,56 +1126,67 @@ void _rdpDialog(String id) async { ), Row( children: [ - ConstrainedBox( - constraints: const BoxConstraints(minWidth: 140), - child: Text( - "${translate('Port')}:", - textAlign: TextAlign.right, - ).marginOnly(right: 10)), + isDesktop + ? ConstrainedBox( + constraints: const BoxConstraints(minWidth: 140), + child: Text( + "${translate('Port')}:", + textAlign: TextAlign.right, + ).marginOnly(right: 10)) + : SizedBox.shrink(), Expanded( child: TextField( inputFormatters: [ FilteringTextInputFormatter.allow(RegExp( r'^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$')) ], - decoration: const InputDecoration( - border: OutlineInputBorder(), hintText: '3389'), + decoration: InputDecoration( + labelText: isDesktop ? null : translate('Port'), + border: isDesktop ? const OutlineInputBorder() : null, + hintText: '3389'), controller: portController, autofocus: true, ), ), ], - ).marginOnly(bottom: 8), + ).marginOnly(bottom: isDesktop ? 8 : 0), Row( children: [ - ConstrainedBox( - constraints: const BoxConstraints(minWidth: 140), - child: Text( - "${translate('Username')}:", - textAlign: TextAlign.right, - ).marginOnly(right: 10)), + isDesktop + ? ConstrainedBox( + constraints: const BoxConstraints(minWidth: 140), + child: Text( + "${translate('Username')}:", + textAlign: TextAlign.right, + ).marginOnly(right: 10)) + : SizedBox.shrink(), Expanded( child: TextField( - decoration: - const InputDecoration(border: OutlineInputBorder()), + decoration: InputDecoration( + labelText: isDesktop ? null : translate('Username'), + border: isDesktop ? const OutlineInputBorder() : null), controller: userController, ), ), ], - ).marginOnly(bottom: 8), + ).marginOnly(bottom: isDesktop ? 8 : 0), Row( children: [ - ConstrainedBox( - constraints: const BoxConstraints(minWidth: 140), - child: Text( - "${translate('Password')}:", - textAlign: TextAlign.right, - ).marginOnly(right: 10)), + isDesktop + ? ConstrainedBox( + constraints: const BoxConstraints(minWidth: 140), + child: Text( + "${translate('Password')}:", + textAlign: TextAlign.right, + ).marginOnly(right: 10)) + : SizedBox.shrink(), Expanded( child: Obx(() => TextField( obscureText: secure.value, decoration: InputDecoration( - border: const OutlineInputBorder(), + labelText: isDesktop ? null : translate('Password'), + border: + isDesktop ? const OutlineInputBorder() : null, suffixIcon: IconButton( onPressed: () => secure.value = !secure.value, icon: Icon(secure.value @@ -1185,7 +1196,7 @@ void _rdpDialog(String id) async { )), ), ], - ).marginOnly(bottom: 8), + ).marginOnly(bottom: isDesktop ? 8 : 0), ], ), ), From 2dd4545be0ad1a3ac3e7de1a3ef0afd3e5183c7b Mon Sep 17 00:00:00 2001 From: csf Date: Wed, 8 Mar 2023 21:05:55 +0900 Subject: [PATCH 270/382] refactor file_model.dart --- .../lib/desktop/pages/file_manager_page.dart | 2 +- .../lib/mobile/pages/file_manager_page.dart | 2 +- flutter/lib/models/file_model.dart | 1347 +++++++---------- flutter/lib/models/model.dart | 14 +- 4 files changed, 560 insertions(+), 805 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 8d9cd0a5c..0a8ebdd33 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -90,7 +90,7 @@ class _FileManagerPageState extends State @override void dispose() { - model.onClose().whenComplete(() { + model.close().whenComplete(() { _ffi.close(); _ffi.dialogManager.dismissAll(); if (!Platform.isLinux) { diff --git a/flutter/lib/mobile/pages/file_manager_page.dart b/flutter/lib/mobile/pages/file_manager_page.dart index 7aa9a0005..26e024ca4 100644 --- a/flutter/lib/mobile/pages/file_manager_page.dart +++ b/flutter/lib/mobile/pages/file_manager_page.dart @@ -38,7 +38,7 @@ class _FileManagerPageState extends State { @override void dispose() { - model.onClose().whenComplete(() { + model.close().whenComplete(() { gFFI.close(); gFFI.dialogManager.dismissAll(); Wakelock.disable(); diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index e8f7cf15b..621df4d69 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -37,341 +37,64 @@ class SortStyle { var ascending = true; } -class FileModelNew { - static final JobID jobID = JobID(); - final jobTable = RxList.empty(growable: true); - final _jobResultListener = JobResultListener>(); - - final localController = FileController(isLocal: true); - final remoteController = FileController(isLocal: false); - - int getJob(int id) { - return jobTable.indexWhere((element) => element.id == id); - } -} - -class FileController extends FileState with FileAction, UIController { - FileController({required super.isLocal}); -} - -class FileState { - final bool isLocal; - final _fileFetcher = FileFetcher(); - - final options = DirectoryOptions().obs; - final directory = FileDirectory().obs; - - final history = RxList.empty(growable: true); - final sortStyle = SortStyle().obs; - - FileState({required this.isLocal}); -} - -mixin FileAction on FileState { - test() { - final a = _fileFetcher; - final b = isLocal; - } -} - -mixin UIController on FileState { - testUI() { - final a = _fileFetcher; - final b = isLocal; - } -} - -class FileModel extends ChangeNotifier { - /// mobile, current selected page show on mobile screen - var _isSelectedLocal = false; - - /// mobile, select mode state - var _selectMode = false; - - final _localOption = DirectoryOptions(); - final _remoteOption = DirectoryOptions(); - - List localHistory = []; - List remoteHistory = []; - - var _jobId = 0; - - final _jobProgress = JobProgress(); // from rust update - - /// JobTable - final _jobTable = List.empty(growable: true).obs; - - /// `isLocal` bool - Function(bool)? onDirChanged; - - RxList get jobTable => _jobTable; - - bool get isLocal => _isSelectedLocal; // TODO parent - - bool get selectMode => _selectMode; // TODO parent - - JobProgress get jobProgress => _jobProgress; - - JobState get jobState => _jobProgress.state; - - SortBy _sortStyle = SortBy.name; - - SortBy get sortStyle => _sortStyle; - - SortBy _localSortStyle = SortBy.name; - - bool _localSortAscending = true; - - bool _remoteSortAscending = true; - - SortBy _remoteSortStyle = SortBy.name; - - bool get localSortAscending => _localSortAscending; - - SortBy getSortStyle(bool isLocal) { - return isLocal ? _localSortStyle : _remoteSortStyle; - } - - bool getSortAscending(bool isLocal) { - return isLocal ? _localSortAscending : _remoteSortAscending; - } - - FileDirectory _currentLocalDir = FileDirectory(); - - FileDirectory get currentLocalDir => _currentLocalDir; - - FileDirectory _currentRemoteDir = FileDirectory(); - - FileDirectory get currentRemoteDir => _currentRemoteDir; - - FileDirectory get currentDir => - _isSelectedLocal ? currentLocalDir : currentRemoteDir; - - FileDirectory getCurrentDir(bool isLocal) { - return isLocal ? currentLocalDir : currentRemoteDir; - } - - String getCurrentShortPath(bool isLocal) { - final currentDir = getCurrentDir(isLocal); - final currentHome = getCurrentHome(isLocal); - if (currentDir.path.startsWith(currentHome)) { - var path = currentDir.path.replaceFirst(currentHome, ""); - if (path.isEmpty) return ""; - if (path[0] == "/" || path[0] == "\\") { - // remove more '/' or '\' - path = path.replaceFirst(path[0], ""); - } - return path; - } else { - return currentDir.path.replaceFirst(currentHome, ""); - } - } - - String get currentHome => - _isSelectedLocal ? _localOption.home : _remoteOption.home; - - String getCurrentHome(bool isLocal) { - return isLocal ? _localOption.home : _remoteOption.home; - } - - int getJob(int id) { - return jobTable.indexWhere((element) => element.id == id); - } - - String get currentShortPath { - if (currentDir.path.startsWith(currentHome)) { - var path = currentDir.path.replaceFirst(currentHome, ""); - if (path.isEmpty) return ""; - if (path[0] == "/" || path[0] == "\\") { - // remove more '/' or '\' - path = path.replaceFirst(path[0], ""); - } - return path; - } else { - return currentDir.path.replaceFirst(currentHome, ""); - } - } - - String shortPath(bool isLocal) { - final dir = isLocal ? currentLocalDir : currentRemoteDir; - if (dir.path.startsWith(currentHome)) { - var path = dir.path.replaceFirst(currentHome, ""); - if (path.isEmpty) return ""; - if (path[0] == "/" || path[0] == "\\") { - // remove more '/' or '\' - path = path.replaceFirst(path[0], ""); - } - return path; - } else { - return dir.path.replaceFirst(currentHome, ""); - } - } - - bool getCurrentShowHidden([bool? isLocal]) { - final isLocal_ = isLocal ?? _isSelectedLocal; - return isLocal_ ? _localOption.showHidden : _remoteOption.showHidden; - } - - bool getCurrentIsWindows([bool? isLocal]) { - final isLocal_ = isLocal ?? _isSelectedLocal; - return isLocal_ ? _localOption.isWindows : _remoteOption.isWindows; - } - - final _fileFetcher = FileFetcher(); - - final _jobResultListener = JobResultListener>(); - +class FileModel { final WeakReference parent; - - FileModel(this.parent); - - toggleSelectMode() { - if (jobState == JobState.inProgress) { - return; - } - _selectMode = !_selectMode; - notifyListeners(); + late final String sessionID; + FileModel(this.parent) { + sessionID = parent.target?.id ?? ""; } - togglePage() { - _isSelectedLocal = !_isSelectedLocal; - notifyListeners(); + late final fileFetcher = FileFetcher(sessionID); + late final jobController = JobController(sessionID); + + late final localController = FileController( + isLocal: true, + sessionID: sessionID, + dialogManager: parent.target?.dialogManager, + jobController: jobController, + fileFetcher: fileFetcher); + + late final remoteController = FileController( + isLocal: false, + sessionID: sessionID, + dialogManager: parent.target?.dialogManager, + jobController: jobController, + fileFetcher: fileFetcher); + + Future onReady() async { + await localController.onReady(); + await remoteController.onReady(); } - toggleShowHidden({bool? showHidden, bool? local}) { - final isLocal = local ?? _isSelectedLocal; - if (isLocal) { - _localOption.showHidden = showHidden ?? !_localOption.showHidden; - } else { - _remoteOption.showHidden = showHidden ?? !_remoteOption.showHidden; - } - refresh(isLocal: local); + Future close() async { + parent.target?.dialogManager.dismissAll(); + jobController.close(); + await localController.close(); + await remoteController.close(); } - tryUpdateJobProgress(Map evt) { - try { - int id = int.parse(evt['id']); - if (!isDesktop) { - _jobProgress.id = id; - _jobProgress.fileNum = int.parse(evt['file_num']); - _jobProgress.speed = double.parse(evt['speed']); - _jobProgress.finishedSize = int.parse(evt['finished_size']); - } else { - // Desktop uses jobTable - // id = index + 1 - final jobIndex = getJob(id); - if (jobIndex >= 0 && _jobTable.length > jobIndex) { - final job = _jobTable[jobIndex]; - job.fileNum = int.parse(evt['file_num']); - job.speed = double.parse(evt['speed']); - job.finishedSize = int.parse(evt['finished_size']); - debugPrint("update job $id with $evt"); - } - } - notifyListeners(); - } catch (e) { - debugPrint("Failed to tryUpdateJobProgress,evt:${evt.toString()}"); - } + Future refreshAll() async { + await localController.refresh(); + await remoteController.refresh(); } - receiveFileDir(Map evt) { + void receiveFileDir(Map evt) { if (evt['is_local'] == "false") { - // init remote home, the connection will automatic read remote home when established, - try { - final fd = FileDirectory.fromJson(jsonDecode(evt['value'])); - fd.format(_remoteOption.isWindows, sort: _sortStyle); - if (fd.id > 0) { - final jobIndex = getJob(fd.id); - if (jobIndex != -1) { - final job = jobTable[jobIndex]; - var totalSize = 0; - var fileCount = fd.entries.length; - for (var element in fd.entries) { - totalSize += element.size; - } - job.totalSize = totalSize; - job.fileCount = fileCount; - debugPrint("update receive details:${fd.path}"); - } - } else if (_remoteOption.home.isEmpty) { - _remoteOption.home = fd.path; - debugPrint("init remote home:${fd.path}"); - _currentRemoteDir = fd; - } - } catch (e) { - debugPrint("receiveFileDir err=$e"); - } + // init remote home, the remote connection will send one dir event when established. TODO opt + remoteController.initDirAndHome(evt); } - _fileFetcher.tryCompleteTask(evt['value'], evt['is_local']); - notifyListeners(); + fileFetcher.tryCompleteTask(evt['value'], evt['is_local']); } - jobDone(Map evt) async { - if (_jobResultListener.isListening) { - _jobResultListener.complete(evt); - return; - } - if (!isDesktop) { - _selectMode = false; - _jobProgress.state = JobState.done; - } else { - int id = int.parse(evt['id']); - final jobIndex = getJob(id); - if (jobIndex != -1) { - final job = jobTable[jobIndex]; - job.finishedSize = job.totalSize; - job.state = JobState.done; - job.fileNum = int.parse(evt['file_num']); - } - } - await Future.wait([ - refresh(isLocal: false), - refresh(isLocal: true), - ]); - } - - jobError(Map evt) { - final err = evt['err'].toString(); - if (!isDesktop) { - if (_jobResultListener.isListening) { - _jobResultListener.complete(evt); - return; - } - _selectMode = false; - _jobProgress.clear(); - _jobProgress.err = err; - _jobProgress.state = JobState.error; - _jobProgress.fileNum = int.parse(evt['file_num']); - if (err == "skipped") { - _jobProgress.state = JobState.done; - _jobProgress.finishedSize = _jobProgress.totalSize; - } - } else { - int jobIndex = getJob(int.parse(evt['id'])); - if (jobIndex != -1) { - final job = jobTable[jobIndex]; - job.state = JobState.error; - job.err = err; - job.fileNum = int.parse(evt['file_num']); - if (err == "skipped") { - job.state = JobState.done; - job.finishedSize = job.totalSize; - } - } - } - debugPrint("jobError $evt"); - notifyListeners(); - } - - overrideFileConfirm(Map evt) async { + void overrideFileConfirm(Map evt) async { final resp = await showFileConfirmDialog( translate("Overwrite"), "${evt['read_path']}", true); final id = int.tryParse(evt['id']) ?? 0; if (false == resp) { - final jobIndex = getJob(id); + final jobIndex = jobController.getJob(id); if (jobIndex != -1) { - cancelJob(id); - final job = jobTable[jobIndex]; + jobController.cancelJob(id); + final job = jobController.jobTable[jobIndex]; job.state = JobState.done; } } else { @@ -384,7 +107,7 @@ class FileModel extends ChangeNotifier { need_override = true; } bind.sessionSetConfirmOverrideFile( - id: parent.target?.id ?? "", + id: sessionID, actId: id, fileNum: int.parse(evt['file_num']), needOverride: need_override, @@ -393,367 +116,6 @@ class FileModel extends ChangeNotifier { } } - jobReset() { - _jobProgress.clear(); - notifyListeners(); - } - - onReady() async { - _localOption.home = await bind.mainGetHomeDir(); - _localOption.showHidden = (await bind.sessionGetPeerOption( - id: parent.target?.id ?? "", name: "local_show_hidden")) - .isNotEmpty; - _localOption.isWindows = Platform.isWindows; - - _remoteOption.showHidden = (await bind.sessionGetPeerOption( - id: parent.target?.id ?? "", name: "remote_show_hidden")) - .isNotEmpty; - _remoteOption.isWindows = - parent.target?.ffiModel.pi.platform == kPeerPlatformWindows; - - await Future.delayed(Duration(milliseconds: 100)); - - final local = (await bind.sessionGetPeerOption( - id: parent.target?.id ?? "", name: "local_dir")); - final remote = (await bind.sessionGetPeerOption( - id: parent.target?.id ?? "", name: "remote_dir")); - openDirectory(local.isEmpty ? _localOption.home : local, isLocal: true); - openDirectory(remote.isEmpty ? _remoteOption.home : remote, isLocal: false); - await Future.delayed(Duration(seconds: 1)); - if (_currentLocalDir.path.isEmpty) { - openDirectory(_localOption.home, isLocal: true); - } - if (_currentRemoteDir.path.isEmpty) { - openDirectory(_remoteOption.home, isLocal: false); - } - } - - Future onClose() async { - parent.target?.dialogManager.dismissAll(); - jobReset(); - - onDirChanged = null; - - // save config - Map msgMap = {}; - - msgMap["local_dir"] = _currentLocalDir.path; - msgMap["local_show_hidden"] = _localOption.showHidden ? "Y" : ""; - msgMap["remote_dir"] = _currentRemoteDir.path; - msgMap["remote_show_hidden"] = _remoteOption.showHidden ? "Y" : ""; - final id = parent.target?.id ?? ""; - for (final msg in msgMap.entries) { - await bind.sessionPeerOption(id: id, name: msg.key, value: msg.value); - } - _currentLocalDir.clear(); - _currentRemoteDir.clear(); - _localOption.clear(); - _remoteOption.clear(); - } - - Future refresh({bool? isLocal}) async { - if (isDesktop) { - isLocal = isLocal ?? _isSelectedLocal; - isLocal - ? await openDirectory(currentLocalDir.path, isLocal: isLocal) - : await openDirectory(currentRemoteDir.path, isLocal: isLocal); - } else { - await openDirectory(currentDir.path); - } - } - - openDirectory(String path, {bool? isLocal, bool isBack = false}) async { - isLocal = isLocal ?? _isSelectedLocal; - if (path == ".") { - refresh(isLocal: isLocal); - return; - } - if (path == "..") { - goToParentDirectory(isLocal: isLocal); - return; - } - if (!isBack) { - pushHistory(isLocal); - } - final showHidden = getCurrentShowHidden(isLocal); - final isWindows = getCurrentIsWindows(isLocal); - // process /C:\ -> C:\ on Windows - if (isWindows && path.length > 1 && path[0] == '/') { - path = path.substring(1); - if (path[path.length - 1] != '\\') { - path = "$path\\"; - } - } - try { - final fd = await _fileFetcher.fetchDirectory(path, isLocal, showHidden); - fd.format(isWindows, sort: _sortStyle); - if (isLocal) { - _currentLocalDir = fd; - } else { - _currentRemoteDir = fd; - } - notifyListeners(); - onDirChanged?.call(isLocal); - } catch (e) { - debugPrint("Failed to openDirectory $path: $e"); - } - } - - Future fetchDirectory(path, isLocal, showHidden) async { - return await _fileFetcher.fetchDirectory(path, isLocal, showHidden); - } - - void pushHistory(bool isLocal) { - final history = isLocal ? localHistory : remoteHistory; - final currPath = isLocal ? currentLocalDir.path : currentRemoteDir.path; - if (history.isNotEmpty && history.last == currPath) { - return; - } - history.add(currPath); - } - - goHome({bool? isLocal}) { - isLocal = isLocal ?? _isSelectedLocal; - openDirectory(getCurrentHome(isLocal), isLocal: isLocal); - } - - goBack({bool? isLocal}) { - isLocal = isLocal ?? _isSelectedLocal; - final history = isLocal ? localHistory : remoteHistory; - if (history.isEmpty) return; - final path = history.removeAt(history.length - 1); - if (path.isEmpty) return; - final currPath = isLocal ? currentLocalDir.path : currentRemoteDir.path; - if (currPath == path) { - goBack(isLocal: isLocal); - return; - } - openDirectory(path, isLocal: isLocal, isBack: true); - } - - goToParentDirectory({bool? isLocal}) { - isLocal = isLocal ?? _isSelectedLocal; - final isWindows = - isLocal ? _localOption.isWindows : _remoteOption.isWindows; - final currDir = isLocal ? currentLocalDir : currentRemoteDir; - var parent = PathUtil.dirname(currDir.path, isWindows); - // specially for C:\, D:\, goto '/' - if (parent == currDir.path && isWindows) { - openDirectory('/', isLocal: isLocal); - return; - } - openDirectory(parent, isLocal: isLocal); - } - - /// isRemote only for desktop now, [isRemote == true] means [remote -> local] - sendFiles(SelectedItems items, {bool isRemote = false}) { - if (isDesktop) { - // desktop sendFiles - final toPath = isRemote ? currentLocalDir.path : currentRemoteDir.path; - final isWindows = - isRemote ? _localOption.isWindows : _remoteOption.isWindows; - final showHidden = - isRemote ? _localOption.showHidden : _remoteOption.showHidden; - for (var from in items.items) { - final jobId = ++_jobId; - _jobTable.add(JobProgress() - ..fileName = path.basename(from.path) - ..jobName = from.path - ..totalSize = from.size - ..state = JobState.inProgress - ..id = jobId - ..isRemote = isRemote); - bind.sessionSendFiles( - id: '${parent.target?.id}', - actId: _jobId, - path: from.path, - to: PathUtil.join(toPath, from.name, isWindows), - fileNum: 0, - includeHidden: showHidden, - isRemote: isRemote); - debugPrint( - "path:${from.path}, toPath:$toPath, to:${PathUtil.join(toPath, from.name, isWindows)}"); - } - } else { - if (items.isLocal == null) { - debugPrint("Failed to sendFiles ,wrong path state"); - return; - } - _jobProgress.state = JobState.inProgress; - final toPath = - items.isLocal! ? currentRemoteDir.path : currentLocalDir.path; - final isWindows = - items.isLocal! ? _localOption.isWindows : _remoteOption.isWindows; - final showHidden = - items.isLocal! ? _localOption.showHidden : _remoteOption.showHidden; - items.items.forEach((from) async { - _jobId++; - await bind.sessionSendFiles( - id: '${parent.target?.id}', - actId: _jobId, - path: from.path, - to: PathUtil.join(toPath, from.name, isWindows), - fileNum: 0, - includeHidden: showHidden, - isRemote: !(items.isLocal!)); - }); - } - } - - bool removeCheckboxRemember = false; - - removeAction(SelectedItems items, {bool? isLocal}) async { - isLocal = isLocal ?? _isSelectedLocal; - removeCheckboxRemember = false; - if (items.isLocal == null) { - debugPrint("Failed to removeFile, wrong path state"); - return; - } - final isWindows = - items.isLocal! ? _localOption.isWindows : _remoteOption.isWindows; - await Future.forEach(items.items, (Entry item) async { - _jobId++; - var title = ""; - var content = ""; - late final List entries; - if (item.isFile) { - title = translate("Are you sure you want to delete this file?"); - content = item.name; - entries = [item]; - } else if (item.isDirectory) { - title = translate("Not an empty directory"); - parent.target?.dialogManager.showLoading(translate("Waiting")); - final fd = await _fileFetcher.fetchDirectoryRecursive( - _jobId, item.path, items.isLocal!, true); - if (fd.path.isEmpty) { - fd.path = item.path; - } - fd.format(isWindows); - parent.target?.dialogManager.dismissAll(); - if (fd.entries.isEmpty) { - final confirm = await showRemoveDialog( - translate( - "Are you sure you want to delete this empty directory?"), - item.name, - false); - if (confirm == true) { - sendRemoveEmptyDir(item.path, 0, items.isLocal!); - } - return; - } - entries = fd.entries; - } else { - entries = []; - } - - for (var i = 0; i < entries.length; i++) { - final dirShow = item.isDirectory - ? "${translate("Are you sure you want to delete the file of this directory?")}\n" - : ""; - final count = entries.length > 1 ? "${i + 1}/${entries.length}" : ""; - content = "$dirShow\n\n${entries[i].path}".trim(); - final confirm = await showRemoveDialog( - count.isEmpty ? title : "$title ($count)", - content, - item.isDirectory, - ); - try { - if (confirm == true) { - sendRemoveFile(entries[i].path, i, items.isLocal!); - final res = await _jobResultListener.start(); - // handle remove res; - if (item.isDirectory && - res['file_num'] == (entries.length - 1).toString()) { - sendRemoveEmptyDir(item.path, i, items.isLocal!); - } - } - if (removeCheckboxRemember) { - if (confirm == true) { - for (var j = i + 1; j < entries.length; j++) { - sendRemoveFile(entries[j].path, j, items.isLocal!); - final res = await _jobResultListener.start(); - if (item.isDirectory && - res['file_num'] == (entries.length - 1).toString()) { - sendRemoveEmptyDir(item.path, i, items.isLocal!); - } - } - } - break; - } - } catch (e) { - print("remove error: $e"); - } - } - }); - _selectMode = false; - refresh(isLocal: isLocal); - } - - Future showRemoveDialog( - String title, String content, bool showCheckbox) async { - return await parent.target?.dialogManager.show( - (setState, Function(bool v) close) { - cancel() => close(false); - submit() => close(true); - return CustomAlertDialog( - title: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Icons.warning_rounded, color: Colors.red), - Text(title).paddingOnly( - left: 10, - ), - ], - ), - contentBoxConstraints: - BoxConstraints(minHeight: 100, minWidth: 400, maxWidth: 400), - content: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(content), - Text( - translate("This is irreversible!"), - style: const TextStyle( - fontWeight: FontWeight.bold, - color: Colors.red, - ), - ).paddingOnly(top: 20), - showCheckbox - ? CheckboxListTile( - contentPadding: const EdgeInsets.all(0), - dense: true, - controlAffinity: ListTileControlAffinity.leading, - title: Text( - translate("Do this for all conflicts"), - ), - value: removeCheckboxRemember, - onChanged: (v) { - if (v == null) return; - setState(() => removeCheckboxRemember = v); - }, - ) - : const SizedBox.shrink() - ], - ), - actions: [ - dialogButton( - "Cancel", - icon: Icon(Icons.close_rounded), - onPressed: cancel, - isOutline: true, - ), - dialogButton( - "OK", - icon: Icon(Icons.done_rounded), - onPressed: submit, - ), - ], - onSubmit: submit, - onCancel: cancel, - ); - }, useAnimation: false); - } - bool fileConfirmCheckboxRemember = false; Future showFileConfirmDialog( @@ -822,65 +184,523 @@ class FileModel extends ChangeNotifier { ); }, useAnimation: false); } +} - sendRemoveFile(String path, int fileNum, bool isLocal) { +class FileController { + final bool isLocal; + final String sessionID; + + final FileFetcher fileFetcher; + + final options = DirectoryOptions().obs; + final directory = FileDirectory().obs; + + final history = RxList.empty(growable: true); + final sortStyle = SortStyle().obs; + final JobController jobController; + final OverlayDialogManager? dialogManager; + + FileController( + {required this.isLocal, + required this.sessionID, + required this.dialogManager, + required this.jobController, + required this.fileFetcher}); + + String get homePath => options.value.home; + + String get shortPath { + final dirPath = directory.value.path; + if (dirPath.startsWith(homePath)) { + var path = dirPath.replaceFirst(homePath, ""); + if (path.isEmpty) return ""; + if (path[0] == "/" || path[0] == "\\") { + // remove more '/' or '\' + path = path.replaceFirst(path[0], ""); + } + return path; + } else { + return dirPath.replaceFirst(homePath, ""); + } + } + + Future onReady() async { + options.value.home = await bind.mainGetHomeDir(); + options.value.showHidden = (await bind.sessionGetPeerOption( + id: sessionID, + name: isLocal ? "local_show_hidden" : "remote_show_hidden")) + .isNotEmpty; + options.value.isWindows = Platform.isWindows; + + await Future.delayed(Duration(milliseconds: 100)); + + final dir = (await bind.sessionGetPeerOption( + id: sessionID, name: isLocal ? "local_dir" : "remote_dir")); + openDirectory(dir.isEmpty ? options.value.home : dir); + + await Future.delayed(Duration(seconds: 1)); + + if (directory.value.path.isEmpty) { + openDirectory(options.value.home); + } + } + + Future close() async { + // save config + Map msgMap = {}; + msgMap[isLocal ? "local_dir" : "remote_dir"] = directory.value.path; + msgMap[isLocal ? "local_show_hidden" : "remote_show_hidden"] = + options.value.showHidden ? "Y" : ""; + for (final msg in msgMap.entries) { + await bind.sessionPeerOption( + id: sessionID, name: msg.key, value: msg.value); + } + directory.value.clear(); + options.value.clear(); + } + + void toggleShowHidden({bool? showHidden}) { + options.value.showHidden = showHidden ?? !options.value.showHidden; + refresh(); + } + + void changeSortStyle(SortBy sort, {bool? isLocal, bool ascending = true}) { + sortStyle.value.by = sort; + sortStyle.value.ascending = ascending; + directory.value.changeSortStyle(sort, ascending: ascending); + } + + Future refresh() async { + await openDirectory(directory.value.path); + } + + Future openDirectory(String path, {bool isBack = false}) async { + if (path == ".") { + refresh(); + return; + } + if (path == "..") { + goToParentDirectory(); + return; + } + if (!isBack) { + pushHistory(); + } + final showHidden = options.value.showHidden; + final isWindows = options.value.isWindows; + // process /C:\ -> C:\ on Windows + if (isWindows && path.length > 1 && path[0] == '/') { + path = path.substring(1); + if (path[path.length - 1] != '\\') { + path = "$path\\"; + } + } + try { + final fd = await fileFetcher.fetchDirectory(path, isLocal, showHidden); + fd.format(isWindows, sort: sortStyle.value.by); + directory.value = fd; + } catch (e) { + debugPrint("Failed to openDirectory $path: $e"); + } + } + + void pushHistory() { + if (history.isNotEmpty && history.last == directory.value.path) { + return; + } + history.add(directory.value.path); + } + + void goToHomeDirectory() { + openDirectory(homePath); + } + + void goBack() { + if (history.isEmpty) return; + final path = history.removeAt(history.length - 1); + if (path.isEmpty) return; + if (directory.value.path == path) { + goBack(); + return; + } + openDirectory(path, isBack: true); + } + + void goToParentDirectory() { + final isWindows = options.value.isWindows; + final dirPath = directory.value.path; + var parent = PathUtil.dirname(dirPath, isWindows); + // specially for C:\, D:\, goto '/' + if (parent == dirPath && isWindows) { + openDirectory('/'); + return; + } + openDirectory(parent); + } + + // TODO deprecated this + void initDirAndHome(Map evt) { + try { + final fd = FileDirectory.fromJson(jsonDecode(evt['value'])); + fd.format(options.value.isWindows, sort: sortStyle.value.by); + if (fd.id > 0) { + final jobIndex = jobController.getJob(fd.id); + if (jobIndex != -1) { + final job = jobController.jobTable[jobIndex]; + var totalSize = 0; + var fileCount = fd.entries.length; + for (var element in fd.entries) { + totalSize += element.size; + } + job.totalSize = totalSize; + job.fileCount = fileCount; + debugPrint("update receive details:${fd.path}"); + } + } else if (options.value.home.isEmpty) { + options.value.home = fd.path; + debugPrint("init remote home:${fd.path}"); + directory.value = fd; + } + } catch (e) { + debugPrint("initDirAndHome err=$e"); + } + } + + /// sendFiles from other side (SelectedItems) to current side (FileController.isLocal). + void sendFiles(SelectedItems items) { + /// ignore same side + if (items.isLocal == isLocal) { + return; + } + + // alias + final isRemoteToLocal = isLocal; + + final toPath = directory.value.path; + final isWindows = options.value.isWindows; + final showHidden = options.value.showHidden; + for (var from in items.items) { + final jobID = jobController.add(from, isRemoteToLocal); + bind.sessionSendFiles( + id: sessionID, + actId: jobID, + path: from.path, + to: PathUtil.join(toPath, from.name, isWindows), + fileNum: 0, + includeHidden: showHidden, + isRemote: isRemoteToLocal); + debugPrint( + "path:${from.path}, toPath:$toPath, to:${PathUtil.join(toPath, from.name, isWindows)}"); + } + } + + bool _removeCheckboxRemember = false; + + Future removeAction(SelectedItems items) async { + _removeCheckboxRemember = false; + if (items.isLocal == isLocal) { + debugPrint("Failed to removeFile, wrong files"); + return; + } + final isWindows = options.value.isWindows; + await Future.forEach(items.items, (Entry item) async { + final jobID = JobController.jobID.next(); + var title = ""; + var content = ""; + late final List entries; + if (item.isFile) { + title = translate("Are you sure you want to delete this file?"); + content = item.name; + entries = [item]; + } else if (item.isDirectory) { + title = translate("Not an empty directory"); + dialogManager?.showLoading(translate("Waiting")); + final fd = await fileFetcher.fetchDirectoryRecursive( + jobID, item.path, items.isLocal!, true); + if (fd.path.isEmpty) { + fd.path = item.path; + } + fd.format(isWindows); + dialogManager?.dismissAll(); + if (fd.entries.isEmpty) { + final confirm = await showRemoveDialog( + translate( + "Are you sure you want to delete this empty directory?"), + item.name, + false); + if (confirm == true) { + sendRemoveEmptyDir(item.path, 0); + } + return; + } + entries = fd.entries; + } else { + entries = []; + } + + for (var i = 0; i < entries.length; i++) { + final dirShow = item.isDirectory + ? "${translate("Are you sure you want to delete the file of this directory?")}\n" + : ""; + final count = entries.length > 1 ? "${i + 1}/${entries.length}" : ""; + content = "$dirShow\n\n${entries[i].path}".trim(); + final confirm = await showRemoveDialog( + count.isEmpty ? title : "$title ($count)", + content, + item.isDirectory, + ); + try { + if (confirm == true) { + sendRemoveFile(entries[i].path, i); + final res = await jobController.jobResultListener.start(); + // handle remove res; + if (item.isDirectory && + res['file_num'] == (entries.length - 1).toString()) { + sendRemoveEmptyDir(item.path, i); + } + } + if (_removeCheckboxRemember) { + if (confirm == true) { + for (var j = i + 1; j < entries.length; j++) { + sendRemoveFile(entries[j].path, j); + final res = await jobController.jobResultListener.start(); + if (item.isDirectory && + res['file_num'] == (entries.length - 1).toString()) { + sendRemoveEmptyDir(item.path, i); + } + } + } + break; + } + } catch (e) { + print("remove error: $e"); + } + } + }); + refresh(); + } + + Future showRemoveDialog( + String title, String content, bool showCheckbox) async { + return await dialogManager?.show((setState, Function(bool v) close) { + cancel() => close(false); + submit() => close(true); + return CustomAlertDialog( + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon(Icons.warning_rounded, color: Colors.red), + Text(title).paddingOnly( + left: 10, + ), + ], + ), + contentBoxConstraints: + BoxConstraints(minHeight: 100, minWidth: 400, maxWidth: 400), + content: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(content), + Text( + translate("This is irreversible!"), + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.red, + ), + ).paddingOnly(top: 20), + showCheckbox + ? CheckboxListTile( + contentPadding: const EdgeInsets.all(0), + dense: true, + controlAffinity: ListTileControlAffinity.leading, + title: Text( + translate("Do this for all conflicts"), + ), + value: _removeCheckboxRemember, + onChanged: (v) { + if (v == null) return; + setState(() => _removeCheckboxRemember = v); + }, + ) + : const SizedBox.shrink() + ], + ), + actions: [ + dialogButton( + "Cancel", + icon: Icon(Icons.close_rounded), + onPressed: cancel, + isOutline: true, + ), + dialogButton( + "OK", + icon: Icon(Icons.done_rounded), + onPressed: submit, + ), + ], + onSubmit: submit, + onCancel: cancel, + ); + }, useAnimation: false); + } + + void sendRemoveFile(String path, int fileNum) { bind.sessionRemoveFile( - id: '${parent.target?.id}', - actId: _jobId, + id: sessionID, + actId: JobController.jobID.next(), path: path, isRemote: !isLocal, fileNum: fileNum); } - sendRemoveEmptyDir(String path, int fileNum, bool isLocal) { - final history = isLocal ? localHistory : remoteHistory; + void sendRemoveEmptyDir(String path, int fileNum) { history.removeWhere((element) => element.contains(path)); bind.sessionRemoveAllEmptyDirs( - id: '${parent.target?.id}', - actId: _jobId, + id: sessionID, + actId: JobController.jobID.next(), path: path, isRemote: !isLocal); } - createDir(String path, {bool? isLocal}) async { - isLocal = isLocal ?? this.isLocal; - _jobId++; + Future createDir(String path) async { bind.sessionCreateDir( - id: '${parent.target?.id}', - actId: _jobId, + id: sessionID, + actId: JobController.jobID.next(), path: path, isRemote: !isLocal); } +} - cancelJob(int id) async { - bind.sessionCancelJob(id: '${parent.target?.id}', actId: id); - jobReset(); +class JobController { + static final JobID jobID = JobID(); + final jobTable = RxList.empty(growable: true); + final jobResultListener = JobResultListener>(); + final String sessionID; + + JobController(this.sessionID); + + int getJob(int id) { + return jobTable.indexWhere((element) => element.id == id); } - changeSortStyle(SortBy sort, {bool? isLocal, bool ascending = true}) { - _sortStyle = sort; - if (isLocal == null) { - // compatible for mobile logic - _currentLocalDir.changeSortStyle(sort, ascending: ascending); - _currentRemoteDir.changeSortStyle(sort, ascending: ascending); - _localSortStyle = sort; - _localSortAscending = ascending; - _remoteSortStyle = sort; - _remoteSortAscending = ascending; - } else if (isLocal) { - _currentLocalDir.changeSortStyle(sort, ascending: ascending); - _localSortStyle = sort; - _localSortAscending = ascending; - } else { - _currentRemoteDir.changeSortStyle(sort, ascending: ascending); - _remoteSortStyle = sort; - _remoteSortAscending = ascending; + // JobProgress? getJob(int id) { + // return jobTable.firstWhere((element) => element.id == id); + // } + + void close() { + jobTable.close(); + jobTable.clear(); + } + + // return jobID + int add(Entry from, bool isRemoteToLocal) { + final jobID = JobController.jobID.next(); + jobTable.add(JobProgress() + ..fileName = path.basename(from.path) + ..jobName = from.path + ..totalSize = from.size + ..state = JobState.inProgress + ..id = jobID + ..isRemoteToLocal = isRemoteToLocal); + return jobID; + } + + void tryUpdateJobProgress(Map evt) { + try { + int id = int.parse(evt['id']); + // id = index + 1 + final jobIndex = getJob(id); + if (jobIndex >= 0 && jobTable.length > jobIndex) { + final job = jobTable[jobIndex]; + job.fileNum = int.parse(evt['file_num']); + job.speed = double.parse(evt['speed']); + job.finishedSize = int.parse(evt['finished_size']); + debugPrint("update job $id with $evt"); + } + } catch (e) { + debugPrint("Failed to tryUpdateJobProgress,evt:${evt.toString()}"); } - notifyListeners(); } - initFileFetcher() { - _fileFetcher.id = parent.target?.id; + void jobDone(Map evt) async { + if (jobResultListener.isListening) { + jobResultListener.complete(evt); + return; + } + + int id = int.parse(evt['id']); + final jobIndex = getJob(id); + if (jobIndex != -1) { + final job = jobTable[jobIndex]; + job.finishedSize = job.totalSize; + job.state = JobState.done; + job.fileNum = int.parse(evt['file_num']); + } + } + + void jobError(Map evt) { + final err = evt['err'].toString(); + int jobIndex = getJob(int.parse(evt['id'])); + if (jobIndex != -1) { + final job = jobTable[jobIndex]; + job.state = JobState.error; + job.err = err; + job.fileNum = int.parse(evt['file_num']); + if (err == "skipped") { + job.state = JobState.done; + job.finishedSize = job.totalSize; + } + } + debugPrint("jobError $evt"); + } + + void cancelJob(int id) async { + bind.sessionCancelJob(id: sessionID, actId: id); + } + + void loadLastJob(Map evt) { + debugPrint("load last job: $evt"); + Map jobDetail = json.decode(evt['value']); + // int id = int.parse(jobDetail['id']); + String remote = jobDetail['remote']; + String to = jobDetail['to']; + bool showHidden = jobDetail['show_hidden']; + int fileNum = jobDetail['file_num']; + bool isRemote = jobDetail['is_remote']; + final currJobId = JobController.jobID.next(); + String fileName = path.basename(isRemote ? remote : to); + var jobProgress = JobProgress() + ..fileName = fileName + ..jobName = isRemote ? remote : to + ..id = currJobId + ..isRemoteToLocal = isRemote + ..fileNum = fileNum + ..remote = remote + ..to = to + ..showHidden = showHidden + ..state = JobState.paused; + jobTable.add(jobProgress); + bind.sessionAddJob( + id: sessionID, + isRemote: isRemote, + includeHidden: showHidden, + actId: currJobId, + path: isRemote ? remote : to, + to: isRemote ? to : remote, + fileNum: fileNum, + ); + } + + void resumeJob(int jobId) { + final jobIndex = getJob(jobId); + if (jobIndex != -1) { + final job = jobTable[jobIndex]; + bind.sessionResumeJob( + id: sessionID, actId: job.id, isRemote: job.isRemoteToLocal); + job.state = JobState.inProgress; + } else { + debugPrint("jobId $jobId is not exists"); + } } void updateFolderFiles(Map evt) { @@ -896,55 +716,6 @@ class FileModel extends ChangeNotifier { job.totalSize = total_size.toInt(); } debugPrint("update folder files: $info"); - notifyListeners(); - } - - bool get remoteSortAscending => _remoteSortAscending; - - void loadLastJob(Map evt) { - debugPrint("load last job: $evt"); - Map jobDetail = json.decode(evt['value']); - // int id = int.parse(jobDetail['id']); - String remote = jobDetail['remote']; - String to = jobDetail['to']; - bool showHidden = jobDetail['show_hidden']; - int fileNum = jobDetail['file_num']; - bool isRemote = jobDetail['is_remote']; - final currJobId = _jobId++; - String fileName = path.basename(isRemote ? remote : to); - var jobProgress = JobProgress() - ..fileName = fileName - ..jobName = isRemote ? remote : to - ..id = currJobId - ..isRemote = isRemote - ..fileNum = fileNum - ..remote = remote - ..to = to - ..showHidden = showHidden - ..state = JobState.paused; - jobTable.add(jobProgress); - bind.sessionAddJob( - id: '${parent.target?.id}', - isRemote: isRemote, - includeHidden: showHidden, - actId: currJobId, - path: isRemote ? remote : to, - to: isRemote ? to : remote, - fileNum: fileNum, - ); - } - - resumeJob(int jobId) { - final jobIndex = getJob(jobId); - if (jobIndex != -1) { - final job = jobTable[jobIndex]; - bind.sessionResumeJob( - id: '${parent.target?.id}', actId: job.id, isRemote: job.isRemote); - job.state = JobState.inProgress; - } else { - debugPrint("jobId $jobId is not exists"); - } - notifyListeners(); } } @@ -993,10 +764,9 @@ class FileFetcher { Map> remoteTasks = {}; Map> readRecursiveTasks = {}; - String? id; + String id; - // if id == null, means to fetch global FFI - FFI get _ffi => ffi(id ?? ""); + FileFetcher(this.id); Future registerReadTask(bool isLocal, String path) { // final jobs = isLocal?localJobs:remoteJobs; // maybe we will use read local dir async later @@ -1015,16 +785,16 @@ class FileFetcher { return c.future; } - Future registerReadRecursiveTask(int id) { + Future registerReadRecursiveTask(int actID) { final tasks = readRecursiveTasks; - if (tasks.containsKey(id)) { + if (tasks.containsKey(actID)) { throw "Failed to registerRemoveTask, already have same ReadRecursive job"; } final c = Completer(); - tasks[id] = c; + tasks[actID] = c; Timer(Duration(seconds: 2), () { - tasks.remove(id); + tasks.remove(actID); if (c.isCompleted) return; c.completeError("Failed to read dir,timeout"); }); @@ -1073,16 +843,16 @@ class FileFetcher { } Future fetchDirectoryRecursive( - int id, String path, bool isLocal, bool showHidden) async { + int actID, String path, bool isLocal, bool showHidden) async { // TODO test Recursive is show hidden default? try { await bind.sessionReadDirRecursive( - id: _ffi.id, - actId: id, + id: id, + actId: actID, path: path, isRemote: !isLocal, showHidden: showHidden); - return registerReadRecursiveTask(id); + return registerReadRecursiveTask(actID); } catch (e) { return Future.error(e); } @@ -1179,7 +949,10 @@ class JobProgress { var finishedSize = 0; var totalSize = 0; var fileCount = 0; - var isRemote = false; + // [isRemote == true] means [remote -> local] + // var isRemote = false; + // to-do use enum + var isRemoteToLocal = false; var jobName = ""; var fileName = ""; var remote = ""; @@ -1252,21 +1025,17 @@ class DirectoryOptions { } class SelectedItems { - bool? _isLocal; + final bool isLocal; final List _items = []; List get items => _items; int get length => _items.length; - bool? get isLocal => _isLocal; + SelectedItems(this.isLocal); - add(bool isLocal, Entry e) { + add(Entry e) { if (e.isDrive) return; - _isLocal ??= isLocal; - if (_isLocal != null && _isLocal != isLocal) { - return; - } if (!_items.contains(e)) { _items.add(e); } @@ -1278,22 +1047,10 @@ class SelectedItems { remove(Entry e) { _items.remove(e); - if (_items.isEmpty) { - _isLocal = null; - } - } - - bool isOtherPage(bool currentIsLocal) { - if (_isLocal == null) { - return false; - } else { - return _isLocal != currentIsLocal; - } } clear() { _items.clear(); - _isLocal = null; } void selectAll(List entries) { diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 802a18a52..0b2ae9dd4 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -166,17 +166,18 @@ class FfiModel with ChangeNotifier { } else if (name == 'file_dir') { parent.target?.fileModel.receiveFileDir(evt); } else if (name == 'job_progress') { - parent.target?.fileModel.tryUpdateJobProgress(evt); + parent.target?.fileModel.jobController.tryUpdateJobProgress(evt); } else if (name == 'job_done') { - parent.target?.fileModel.jobDone(evt); + parent.target?.fileModel.jobController.jobDone(evt); + parent.target?.fileModel.refreshAll(); } else if (name == 'job_error') { - parent.target?.fileModel.jobError(evt); + parent.target?.fileModel.jobController.jobError(evt); } else if (name == 'override_file_confirm') { parent.target?.fileModel.overrideFileConfirm(evt); } else if (name == 'load_last_job') { - parent.target?.fileModel.loadLastJob(evt); + parent.target?.fileModel.jobController.loadLastJob(evt); } else if (name == 'update_folder_files') { - parent.target?.fileModel.updateFolderFiles(evt); + parent.target?.fileModel.jobController.updateFolderFiles(evt); } else if (name == 'add_connection') { parent.target?.serverModel.addConnection(evt); } else if (name == 'on_client_remove') { @@ -1571,9 +1572,6 @@ class FFI { }(); // every instance will bind a stream this.id = id; - if (isFileTransfer) { - fileModel.initFileFetcher(); - } } /// Login with [password], choose if the client should [remember] it. From de27f3613450e6dde022ec9798dbcc754749dda5 Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 8 Mar 2023 21:00:56 +0800 Subject: [PATCH 271/382] set KEYBOARD_ONLY for rdev Signed-off-by: fufesou --- src/keyboard.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/keyboard.rs b/src/keyboard.rs index 3f7ed6779..bfff9ff86 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -215,6 +215,7 @@ static mut IS_0X021D_DOWN: bool = false; static mut IS_LEFT_OPTION_DOWN: bool = false; pub fn start_grab_loop() { + std::env::set_var("KEYBOARD_ONLY", "y"); #[cfg(any(target_os = "windows", target_os = "macos"))] std::thread::spawn(move || { let try_handle_keyboard = move |event: Event, key: Key, is_press: bool| -> Option { From acae095541cc3da02708ba8c5b6cd55bff5ff2b4 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Wed, 8 Mar 2023 14:11:11 +0100 Subject: [PATCH 272/382] Update de.rs --- src/lang/de.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lang/de.rs b/src/lang/de.rs index 26925a9fb..f753265f8 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -152,7 +152,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Configure", "Konfigurieren"), ("config_acc", "Um Ihren PC aus der Ferne zu steuern, müssen Sie RustDesk Zugriffsrechte erteilen."), ("config_screen", "Um aus der Ferne auf Ihren PC zugreifen zu können, müssen Sie RustDesk die Berechtigung \"Bildschirmaufnahme\" erteilen."), - ("Installing ...", " Wird installiert …"), + ("Installing ...", "Wird installiert …"), ("Install", "Installieren"), ("Installation", "Installation"), ("Installation Path", "Installationspfad"), @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Auflösung"), ("No transfers in progress", "Keine Übertragungen im Gange"), ("Set one-time password length", "Länge des Einmalpassworts festlegen"), - ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", ""), - ("RDP Settings", "RDP Einstellungen"), + ("idd_driver_tip", "Installieren Sie den virtuellen Anzeigetreiber, der verwendet wird, wenn Sie keine physischen Anzeigen haben."), + ("confirm_idd_driver_tip", "Die Option zur Installation des virtuellen Anzeigetreibers ist aktiviert. Beachten Sie, dass ein Testzertifikat installiert wird, um dem virtuellen Anzeigetreiber zu vertrauen. Dieses Testzertifikat wird nur verwendet, um Rustdesk-Treibern zu vertrauen."), + ("RDP Settings", "RDP-Einstellungen"), ].iter().cloned().collect(); } From d867decd9891771bfc8b02dd1d6afcf3b08fdd9f Mon Sep 17 00:00:00 2001 From: csf Date: Wed, 8 Mar 2023 22:32:55 +0900 Subject: [PATCH 273/382] refactor Desktop file_manager_page.dart --- .../lib/desktop/pages/file_manager_page.dart | 440 +++++++++--------- flutter/lib/models/file_model.dart | 83 ++-- 2 files changed, 257 insertions(+), 266 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 0a8ebdd33..99b873cdc 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -69,6 +69,7 @@ class _FileManagerPageState extends State late FFI _ffi; FileModel get model => _ffi.fileModel; + JobController get jobController => model.jobController; @override void initState() { @@ -84,7 +85,6 @@ class _FileManagerPageState extends State Wakelock.enable(); } debugPrint("File manager page init success with id ${widget.id}"); - model.onDirChanged = breadCrumbScrollToEnd; _ffi.dialogManager.setOverlayState(_overlayKeyState); } @@ -107,31 +107,24 @@ class _FileManagerPageState extends State @override Widget build(BuildContext context) { super.build(context); - // TODO - final localController = FileController(isLocal: true); - final remoteController = FileController(isLocal: false); return Overlay(key: _overlayKeyState.key, initialEntries: [ OverlayEntry(builder: (_) { - return ChangeNotifierProvider.value( - value: _ffi.fileModel, - child: Consumer(builder: (context, model, child) { - return Scaffold( - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - body: Row( - children: [ - Flexible( - flex: 3, - child: dropArea(FileManagerView( - localController, _ffi, _mouseFocusScope))), - Flexible( - flex: 3, - child: dropArea(FileManagerView( - remoteController, _ffi, _mouseFocusScope))), - Flexible(flex: 2, child: statusList()) - ], - ), - ); - })); + return Scaffold( + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + body: Row( + children: [ + Flexible( + flex: 3, + child: dropArea(FileManagerView( + model.localController, _ffi, _mouseFocusScope))), + Flexible( + flex: 3, + child: dropArea(FileManagerView( + model.remoteController, _ffi, _mouseFocusScope))), + Flexible(flex: 2, child: statusList()) + ], + ), + ); }) ]); } @@ -169,7 +162,7 @@ class _FileManagerPageState extends State child: Container( margin: const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0), padding: const EdgeInsets.all(8.0), - child: model.jobTable.isEmpty + child: jobController.jobTable.isEmpty ? generateCard( Center( child: Column( @@ -195,7 +188,7 @@ class _FileManagerPageState extends State () => ListView.builder( controller: ScrollController(), itemBuilder: (BuildContext context, int index) { - final item = model.jobTable[index]; + final item = jobController.jobTable[index]; return Padding( padding: const EdgeInsets.only(bottom: 5), child: generateCard( @@ -206,7 +199,7 @@ class _FileManagerPageState extends State crossAxisAlignment: CrossAxisAlignment.center, children: [ Transform.rotate( - angle: item.isRemote ? pi : 0, + angle: item.isRemoteToLocal ? pi : 0, child: SvgPicture.asset( "assets/arrow.svg", color: Theme.of(context) @@ -293,7 +286,7 @@ class _FileManagerPageState extends State offstage: item.state != JobState.paused, child: MenuButton( onPressed: () { - model.resumeJob(item.id); + jobController.resumeJob(item.id); }, child: SvgPicture.asset( "assets/refresh.svg", @@ -310,8 +303,8 @@ class _FileManagerPageState extends State color: Colors.white, ), onPressed: () { - model.jobTable.removeAt(index); - model.cancelJob(item.id); + jobController.jobTable.removeAt(index); + jobController.cancelJob(item.id); }, color: MyTheme.accent, hoverColor: MyTheme.accent80, @@ -325,7 +318,7 @@ class _FileManagerPageState extends State ), ); }, - itemCount: model.jobTable.length, + itemCount: jobController.jobTable.length, ), ), ), @@ -337,18 +330,15 @@ class _FileManagerPageState extends State // ignore local return; } - var items = SelectedItems(); + final items = SelectedItems(isLocal: false); for (var file in details.files) { final f = File(file.path); - items.add( - true, - Entry() - ..path = file.path - ..name = file.name - ..size = - FileSystemEntity.isDirectorySync(f.path) ? 0 : f.lengthSync()); + items.add(Entry() + ..path = file.path + ..name = file.name + ..size = FileSystemEntity.isDirectorySync(f.path) ? 0 : f.lengthSync()); } - model.sendFiles(items, isRemote: false); + model.remoteController.sendFiles(items); } } @@ -364,7 +354,6 @@ class FileManagerView extends StatefulWidget { } class _FileManagerViewState extends State { - final _selectedItems = SelectedItems(); final _locationStatus = LocationStatus.bread.obs; final _locationNode = FocusNode(); final _locationBarKey = GlobalKey(); @@ -376,6 +365,8 @@ class _FileManagerViewState extends State { final _modifiedColWidth = kDesktopFileTransferModifiedColWidth.obs; final _fileListScrollController = ScrollController(); + late final _selectedItems = SelectedItems(isLocal: isLocal); + /// [_lastClickTime], [_lastClickEntry] help to handle double click var _lastClickTime = DateTime.now().millisecondsSinceEpoch - bind.getDoubleClickTime() - 1000; @@ -390,6 +381,7 @@ class _FileManagerViewState extends State { super.initState(); // register location listener _locationNode.addListener(onLocationFocusChanged); + controller.directory.listen((e) => breadCrumbScrollToEnd()); } @override @@ -508,7 +500,7 @@ class _FileManagerViewState extends State { hoverColor: Theme.of(context).hoverColor, onPressed: () { _selectedItems.clear(); - model.goBack(isLocal: isLocal); + controller.goBack(); }, ), MenuButton( @@ -523,7 +515,7 @@ class _FileManagerViewState extends State { hoverColor: Theme.of(context).hoverColor, onPressed: () { _selectedItems.clear(); - model.goToParentDirectory(isLocal: isLocal); + controller.goToParentDirectory(); }, ), ], @@ -560,8 +552,8 @@ class _FileManagerViewState extends State { Expanded( child: _locationStatus.value == LocationStatus.bread - ? buildBread(isLocal) - : buildPathLocation(isLocal)), + ? buildBread() + : buildPathLocation()), ], ), ), @@ -617,7 +609,7 @@ class _FileManagerViewState extends State { left: 3, ), onPressed: () { - model.refresh(isLocal: isLocal); + controller.refresh(); }, child: SvgPicture.asset( "assets/refresh.svg", @@ -641,7 +633,7 @@ class _FileManagerViewState extends State { right: 3, ), onPressed: () { - model.goHome(isLocal: isLocal); + controller.goToHomeDirectory(); }, child: SvgPicture.asset( "assets/home.svg", @@ -656,12 +648,11 @@ class _FileManagerViewState extends State { _ffi.dialogManager.show((setState, close) { submit() { if (name.value.text.isNotEmpty) { - model.createDir( - PathUtil.join( - model.getCurrentDir(isLocal).path, - name.value.text, - model.getCurrentIsWindows(isLocal)), - isLocal: isLocal); + controller.createDir(PathUtil.join( + controller.directory.value.path, + name.value.text, + controller.options.value.isWindows, + )); close(); } } @@ -722,8 +713,7 @@ class _FileManagerViewState extends State { MenuButton( onPressed: validItems(_selectedItems) ? () async { - await (model.removeAction(_selectedItems, - isLocal: isLocal)); + await (controller.removeAction(_selectedItems)); _selectedItems.clear(); } : null, @@ -751,7 +741,7 @@ class _FileManagerViewState extends State { ), onPressed: validItems(_selectedItems) ? () { - model.sendFiles(_selectedItems, isRemote: !isLocal); + controller.sendFiles(_selectedItems); _selectedItems.clear(); } : null, @@ -814,10 +804,10 @@ class _FileManagerViewState extends State { switchType: SwitchType.scheckbox, text: translate("Show Hidden Files"), getter: () async { - return model.getCurrentShowHidden(isLocal); + return controller.options.value.isWindows; }, setter: (bool v) async { - model.toggleShowHidden(local: isLocal); + controller.toggleShowHidden(); }, padding: kDesktopMenuPadding, dismissOnClicked: true, @@ -825,7 +815,7 @@ class _FileManagerViewState extends State { MenuEntryButton( childBuilder: (style) => Text(translate("Select All"), style: style), proc: () => setState(() => - _selectedItems.selectAll(model.getCurrentDir(isLocal).entries)), + _selectedItems.selectAll(controller.directory.value.entries)), padding: kDesktopMenuPadding, dismissOnClicked: true), MenuEntryButton( @@ -872,7 +862,7 @@ class _FileManagerViewState extends State { Widget _buildFileList( BuildContext context, bool isLocal, ScrollController scrollController) { - final fd = model.getCurrentDir(isLocal); + final fd = controller.directory.value; final entries = fd.entries; return ListSearchActionListener( @@ -919,161 +909,155 @@ class _FileManagerViewState extends State { _jumpToEntry(isLocal, searchResult.first, scrollController, kDesktopFileTransferRowHeight); }, - child: ObxValue( - (searchText) { - final filteredEntries = searchText.isNotEmpty - ? entries.where((element) { - return element.name.contains(searchText.value); - }).toList(growable: false) - : entries; - final rows = filteredEntries.map((entry) { - final sizeStr = - entry.isFile ? readableFileSize(entry.size.toDouble()) : ""; - final lastModifiedStr = entry.isDrive - ? " " - : "${entry.lastModified().toString().replaceAll(".000", "")} "; - final isSelected = _selectedItems.contains(entry); - return Padding( - padding: EdgeInsets.symmetric(vertical: 1), - child: Container( - decoration: BoxDecoration( - color: isSelected - ? Theme.of(context).hoverColor - : Theme.of(context).cardColor, - borderRadius: BorderRadius.all( - Radius.circular(5.0), - ), + child: Obx(() { + final entries = controller.directory.value.entries; + final filteredEntries = _searchText.isNotEmpty + ? entries.where((element) { + return element.name.contains(_searchText.value); + }).toList(growable: false) + : entries; + final rows = filteredEntries.map((entry) { + final sizeStr = + entry.isFile ? readableFileSize(entry.size.toDouble()) : ""; + final lastModifiedStr = entry.isDrive + ? " " + : "${entry.lastModified().toString().replaceAll(".000", "")} "; + final isSelected = _selectedItems.contains(entry); + return Padding( + padding: EdgeInsets.symmetric(vertical: 1), + child: Container( + decoration: BoxDecoration( + color: isSelected + ? Theme.of(context).hoverColor + : Theme.of(context).cardColor, + borderRadius: BorderRadius.all( + Radius.circular(5.0), ), - key: ValueKey(entry.name), - height: kDesktopFileTransferRowHeight, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Expanded( - child: InkWell( - child: Row( - children: [ - GestureDetector( - child: Obx( - () => Container( - width: _nameColWidth.value, - child: Tooltip( - waitDuration: - Duration(milliseconds: 500), - message: entry.name, - child: Row(children: [ - entry.isDrive - ? Image( - image: iconHardDrive, - fit: BoxFit.scaleDown, - color: Theme.of(context) - .iconTheme - .color - ?.withOpacity(0.7)) - .paddingAll(4) - : SvgPicture.asset( - entry.isFile - ? "assets/file.svg" - : "assets/folder.svg", - color: Theme.of(context) - .tabBarTheme - .labelColor, - ), - Expanded( - child: Text( - entry.name.nonBreaking, - overflow: - TextOverflow.ellipsis)) - ]), + ), + key: ValueKey(entry.name), + height: kDesktopFileTransferRowHeight, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Expanded( + child: InkWell( + child: Row( + children: [ + GestureDetector( + child: Obx( + () => Container( + width: _nameColWidth.value, + child: Tooltip( + waitDuration: Duration(milliseconds: 500), + message: entry.name, + child: Row(children: [ + entry.isDrive + ? Image( + image: iconHardDrive, + fit: BoxFit.scaleDown, + color: Theme.of(context) + .iconTheme + .color + ?.withOpacity(0.7)) + .paddingAll(4) + : SvgPicture.asset( + entry.isFile + ? "assets/file.svg" + : "assets/folder.svg", + color: Theme.of(context) + .tabBarTheme + .labelColor, + ), + Expanded( + child: Text(entry.name.nonBreaking, + overflow: + TextOverflow.ellipsis)) + ]), + )), + ), + onTap: () { + final items = _selectedItems; + // handle double click + if (_checkDoubleClick(entry)) { + controller.openDirectory(entry.path); + items.clear(); + return; + } + _onSelectedChanged( + items, filteredEntries, entry, isLocal); + }, + ), + SizedBox( + width: 2.0, + ), + GestureDetector( + child: Obx( + () => SizedBox( + width: _modifiedColWidth.value, + child: Tooltip( + waitDuration: Duration(milliseconds: 500), + message: lastModifiedStr, + child: Text( + lastModifiedStr, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), )), ), - onTap: () { - final items = _selectedItems; - // handle double click - if (_checkDoubleClick(entry)) { - openDirectory(entry.path, isLocal: isLocal); - items.clear(); - return; - } - _onSelectedChanged( - items, filteredEntries, entry, isLocal); - }, ), - SizedBox( - width: 2.0, - ), - GestureDetector( - child: Obx( - () => SizedBox( - width: _modifiedColWidth.value, - child: Tooltip( - waitDuration: - Duration(milliseconds: 500), - message: lastModifiedStr, - child: Text( - lastModifiedStr, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, - ), - )), + ), + // Divider from header. + SizedBox( + width: 2.0, + ), + Expanded( + // width: 100, + child: GestureDetector( + child: Tooltip( + waitDuration: Duration(milliseconds: 500), + message: sizeStr, + child: Text( + sizeStr, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 10, color: MyTheme.darkGray), ), ), ), - // Divider from header. - SizedBox( - width: 2.0, - ), - Expanded( - // width: 100, - child: GestureDetector( - child: Tooltip( - waitDuration: Duration(milliseconds: 500), - message: sizeStr, - child: Text( - sizeStr, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 10, - color: MyTheme.darkGray), - ), - ), - ), - ), - ], - ), + ), + ], ), ), - ], - )), - ); - }).toList(growable: false); - - return Column( - children: [ - // Header - Row( - children: [ - Expanded(child: _buildFileBrowserHeader(context, isLocal)), - ], - ), - // Body - Expanded( - child: ListView.builder( - controller: scrollController, - itemExtent: kDesktopFileTransferRowHeight, - itemBuilder: (context, index) { - return rows[index]; - }, - itemCount: rows.length, - ), - ), - ], + ), + ], + )), ); - }, - _searchText, - ), + }).toList(growable: false); + + return Column( + children: [ + // Header + Row( + children: [ + Expanded(child: _buildFileBrowserHeader(context, isLocal)), + ], + ), + // Body + Expanded( + child: ListView.builder( + controller: scrollController, + itemExtent: kDesktopFileTransferRowHeight, + itemBuilder: (context, index) { + return rows[index]; + }, + itemCount: rows.length, + ), + ), + ], + ); + }), ); } @@ -1084,7 +1068,7 @@ class _FileManagerViewState extends State { void _jumpToEntry(bool isLocal, Entry entry, ScrollController scrollController, double rowHeight) { - final entries = model.getCurrentDir(isLocal).entries; + final entries = controller.directory.value.entries; final index = entries.indexOf(entry); if (index == -1) { debugPrint("entry is not valid: ${entry.path}"); @@ -1101,7 +1085,7 @@ class _FileManagerViewState extends State { scrollController.position.maxScrollExtent); scrollController.jumpTo(offset); setState(() { - selectedEntries.add(isLocal, searchResult.first); + selectedEntries.add(searchResult.first); debugPrint("focused on ${searchResult.first.name}"); }); } @@ -1116,7 +1100,7 @@ class _FileManagerViewState extends State { if (selectedItems.contains(entry)) { selectedItems.remove(entry); } else { - selectedItems.add(isLocal, entry); + selectedItems.add(entry); } } else if (isShiftDown) { final List indexGroup = []; @@ -1130,10 +1114,10 @@ class _FileManagerViewState extends State { selectedItems.clear(); entries .getRange(minIndex, maxIndex + 1) - .forEach((e) => selectedItems.add(isLocal, e)); + .forEach((e) => selectedItems.add(e)); } else { selectedItems.clear(); - selectedItems.add(isLocal, entry); + selectedItems.add(entry); } setState(() {}); } @@ -1205,7 +1189,7 @@ class _FileManagerViewState extends State { } else { ascending.value = !ascending.value!; } - model.changeSortStyle(sortBy, + controller.changeSortStyle(sortBy, isLocal: isLocal, ascending: ascending.value!); }, child: SizedBox( @@ -1234,21 +1218,21 @@ class _FileManagerViewState extends State { ), ), ), () { - if (model.getSortStyle(isLocal) == sortBy) { - return model.getSortAscending(isLocal).obs; + if (controller.sortBy.value == sortBy) { + return controller.sortAscending; } else { return Rx(null); } }()); } - Widget buildBread(bool isLocal) { + Widget buildBread() { final items = getPathBreadCrumbItems(isLocal, (list) { var path = ""; for (var item in list) { - path = PathUtil.join(path, item, model.getCurrentIsWindows(isLocal)); + path = PathUtil.join(path, item, controller.options.value.isWindows); } - openDirectory(path, isLocal: isLocal); + controller.openDirectory(path); }); return items.isEmpty @@ -1290,7 +1274,7 @@ class _FileManagerViewState extends State { final x = offset.dx; final y = offset.dy + size.height + 1; - final isPeerWindows = model.getCurrentIsWindows(isLocal); + final isPeerWindows = controller.options.value.isWindows; final List menuItems = [ MenuEntryButton( childBuilder: (TextStyle? style) => isPeerWindows @@ -1300,7 +1284,7 @@ class _FileManagerViewState extends State { style: style, ), proc: () { - openDirectory('/', isLocal: isLocal); + controller.openDirectory('/'); }, dismissOnClicked: true), MenuEntryDivider() @@ -1311,8 +1295,9 @@ class _FileManagerViewState extends State { loadingTag = _ffi.dialogManager.showLoading("Waiting"); } try { - final fd = - await model.fetchDirectory("/", isLocal, isLocal); + final showHidden = controller.options.value.showHidden; + final fd = await controller.fileFetcher + .fetchDirectory("/", isLocal, showHidden); for (var entry in fd.entries) { menuItems.add(MenuEntryButton( childBuilder: (TextStyle? style) => @@ -1331,8 +1316,7 @@ class _FileManagerViewState extends State { ) ]), proc: () { - openDirectory('${entry.name}\\', - isLocal: isLocal); + controller.openDirectory('${entry.name}\\'); }, dismissOnClicked: true)); } @@ -1369,9 +1353,9 @@ class _FileManagerViewState extends State { List getPathBreadCrumbItems( bool isLocal, void Function(List) onPressed) { - final path = model.getCurrentDir(isLocal).path; + final path = controller.directory.value.path; final breadCrumbList = List.empty(growable: true); - final isWindows = model.getCurrentIsWindows(isLocal); + final isWindows = controller.options.value.isWindows; if (isWindows && path == '/') { breadCrumbList.add(BreadCrumbItem( content: TextButton( @@ -1403,7 +1387,7 @@ class _FileManagerViewState extends State { return breadCrumbList; } - breadCrumbScrollToEnd(bool isLocal) { + breadCrumbScrollToEnd() { Future.delayed(Duration(milliseconds: 200), () { if (_breadCrumbScroller.hasClients) { _breadCrumbScroller.animateTo( @@ -1414,9 +1398,9 @@ class _FileManagerViewState extends State { }); } - Widget buildPathLocation(bool isLocal) { + Widget buildPathLocation() { final text = _locationStatus.value == LocationStatus.pathLocation - ? model.getCurrentDir(isLocal).path + ? controller.directory.value.path : _searchText.value; final textController = TextEditingController(text: text) ..selection = TextSelection.collapsed(offset: text.length); @@ -1440,7 +1424,7 @@ class _FileManagerViewState extends State { ), controller: textController, onSubmitted: (path) { - openDirectory(path, isLocal: isLocal); + controller.openDirectory(path); }, onChanged: _locationStatus.value == LocationStatus.fileSearchBar ? (searchText) => onSearchText(searchText, isLocal) diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index 621df4d69..aa4b6253f 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -32,35 +32,38 @@ class JobID { } } -class SortStyle { - var by = SortBy.name; - var ascending = true; -} +typedef GetSessionID = String Function(); class FileModel { final WeakReference parent; - late final String sessionID; + // late final String sessionID; + late final FileFetcher fileFetcher; + late final JobController jobController; + + late final FileController localController; + late final FileController remoteController; + + late final GetSessionID getSessionID; + String get sessionID => getSessionID(); + FileModel(this.parent) { - sessionID = parent.target?.id ?? ""; + getSessionID = () => parent.target?.id ?? ""; + fileFetcher = FileFetcher(getSessionID); + jobController = JobController(getSessionID); + localController = FileController( + isLocal: true, + getSessionID: getSessionID, + dialogManager: parent.target?.dialogManager, + jobController: jobController, + fileFetcher: fileFetcher); + remoteController = FileController( + isLocal: false, + getSessionID: getSessionID, + dialogManager: parent.target?.dialogManager, + jobController: jobController, + fileFetcher: fileFetcher); } - late final fileFetcher = FileFetcher(sessionID); - late final jobController = JobController(sessionID); - - late final localController = FileController( - isLocal: true, - sessionID: sessionID, - dialogManager: parent.target?.dialogManager, - jobController: jobController, - fileFetcher: fileFetcher); - - late final remoteController = FileController( - isLocal: false, - sessionID: sessionID, - dialogManager: parent.target?.dialogManager, - jobController: jobController, - fileFetcher: fileFetcher); - Future onReady() async { await localController.onReady(); await remoteController.onReady(); @@ -188,7 +191,8 @@ class FileModel { class FileController { final bool isLocal; - final String sessionID; + final GetSessionID getSessionID; + String get sessionID => getSessionID(); final FileFetcher fileFetcher; @@ -196,13 +200,14 @@ class FileController { final directory = FileDirectory().obs; final history = RxList.empty(growable: true); - final sortStyle = SortStyle().obs; + final sortBy = SortBy.name.obs; + final sortAscending = true.obs; final JobController jobController; final OverlayDialogManager? dialogManager; FileController( {required this.isLocal, - required this.sessionID, + required this.getSessionID, required this.dialogManager, required this.jobController, required this.fileFetcher}); @@ -265,8 +270,8 @@ class FileController { } void changeSortStyle(SortBy sort, {bool? isLocal, bool ascending = true}) { - sortStyle.value.by = sort; - sortStyle.value.ascending = ascending; + sortBy.value = sort; + sortAscending.value = ascending; directory.value.changeSortStyle(sort, ascending: ascending); } @@ -297,7 +302,7 @@ class FileController { } try { final fd = await fileFetcher.fetchDirectory(path, isLocal, showHidden); - fd.format(isWindows, sort: sortStyle.value.by); + fd.format(isWindows, sort: sortBy.value); directory.value = fd; } catch (e) { debugPrint("Failed to openDirectory $path: $e"); @@ -342,7 +347,7 @@ class FileController { void initDirAndHome(Map evt) { try { final fd = FileDirectory.fromJson(jsonDecode(evt['value'])); - fd.format(options.value.isWindows, sort: sortStyle.value.by); + fd.format(options.value.isWindows, sort: sortBy.value); if (fd.id > 0) { final jobIndex = jobController.getJob(fd.id); if (jobIndex != -1) { @@ -575,9 +580,10 @@ class JobController { static final JobID jobID = JobID(); final jobTable = RxList.empty(growable: true); final jobResultListener = JobResultListener>(); - final String sessionID; + final GetSessionID getSessionID; + String get sessionID => getSessionID(); - JobController(this.sessionID); + JobController(this.getSessionID); int getJob(int id) { return jobTable.indexWhere((element) => element.id == id); @@ -764,9 +770,10 @@ class FileFetcher { Map> remoteTasks = {}; Map> readRecursiveTasks = {}; - String id; + final GetSessionID getSessionID; + String get sessionID => getSessionID(); - FileFetcher(this.id); + FileFetcher(this.getSessionID); Future registerReadTask(bool isLocal, String path) { // final jobs = isLocal?localJobs:remoteJobs; // maybe we will use read local dir async later @@ -829,12 +836,12 @@ class FileFetcher { try { if (isLocal) { final res = await bind.sessionReadLocalDirSync( - id: id ?? "", path: path, showHidden: showHidden); + id: sessionID ?? "", path: path, showHidden: showHidden); final fd = FileDirectory.fromJson(jsonDecode(res)); return fd; } else { await bind.sessionReadRemoteDir( - id: id ?? "", path: path, includeHidden: showHidden); + id: sessionID ?? "", path: path, includeHidden: showHidden); return registerReadTask(isLocal, path); } } catch (e) { @@ -847,7 +854,7 @@ class FileFetcher { // TODO test Recursive is show hidden default? try { await bind.sessionReadDirRecursive( - id: id, + id: sessionID, actId: actID, path: path, isRemote: !isLocal, @@ -1032,7 +1039,7 @@ class SelectedItems { int get length => _items.length; - SelectedItems(this.isLocal); + SelectedItems({required this.isLocal}); add(Entry e) { if (e.isDrive) return; From a962e068f811391cb46aeb4ad5e2463409d9fc8e Mon Sep 17 00:00:00 2001 From: csf Date: Wed, 8 Mar 2023 23:06:34 +0900 Subject: [PATCH 274/382] fix sendFiles wrong direction --- .../lib/desktop/pages/file_manager_page.dart | 7 +++- flutter/lib/models/file_model.dart | 37 +++++++++++++------ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 99b873cdc..1010d56c4 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -338,7 +338,8 @@ class _FileManagerPageState extends State ..name = file.name ..size = FileSystemEntity.isDirectorySync(f.path) ? 0 : f.lengthSync()); } - model.remoteController.sendFiles(items); + final otherSideData = model.localController.directoryData(); + model.remoteController.sendFiles(items, otherSideData); } } @@ -741,7 +742,9 @@ class _FileManagerViewState extends State { ), onPressed: validItems(_selectedItems) ? () { - controller.sendFiles(_selectedItems); + final otherSideData = + controller.getOtherSideDirectoryData(); + controller.sendFiles(_selectedItems, otherSideData); _selectedItems.clear(); } : null, diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index aa4b6253f..2073991ef 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -55,13 +55,15 @@ class FileModel { getSessionID: getSessionID, dialogManager: parent.target?.dialogManager, jobController: jobController, - fileFetcher: fileFetcher); + fileFetcher: fileFetcher, + getOtherSideDirectoryData: () => remoteController.directoryData()); remoteController = FileController( isLocal: false, getSessionID: getSessionID, dialogManager: parent.target?.dialogManager, jobController: jobController, - fileFetcher: fileFetcher); + fileFetcher: fileFetcher, + getOtherSideDirectoryData: () => localController.directoryData()); } Future onReady() async { @@ -189,6 +191,12 @@ class FileModel { } } +class DirectoryData { + final DirectoryOptions options; + final FileDirectory directory; + DirectoryData(this.directory, this.options); +} + class FileController { final bool isLocal; final GetSessionID getSessionID; @@ -205,12 +213,15 @@ class FileController { final JobController jobController; final OverlayDialogManager? dialogManager; + final DirectoryData Function() getOtherSideDirectoryData; + FileController( {required this.isLocal, required this.getSessionID, required this.dialogManager, required this.jobController, - required this.fileFetcher}); + required this.fileFetcher, + required this.getOtherSideDirectoryData}); String get homePath => options.value.home; @@ -229,6 +240,10 @@ class FileController { } } + DirectoryData directoryData() { + return DirectoryData(directory.value, options.value); + } + Future onReady() async { options.value.home = await bind.mainGetHomeDir(); options.value.showHidden = (await bind.sessionGetPeerOption( @@ -372,18 +387,18 @@ class FileController { } /// sendFiles from other side (SelectedItems) to current side (FileController.isLocal). - void sendFiles(SelectedItems items) { - /// ignore same side - if (items.isLocal == isLocal) { + void sendFiles(SelectedItems items, DirectoryData otherSideData) { + /// ignore wrong items side status + if (items.isLocal != isLocal) { return; } // alias - final isRemoteToLocal = isLocal; + final isRemoteToLocal = !isLocal; - final toPath = directory.value.path; - final isWindows = options.value.isWindows; - final showHidden = options.value.showHidden; + final toPath = otherSideData.directory.path; + final isWindows = otherSideData.options.isWindows; + final showHidden = otherSideData.options.showHidden; for (var from in items.items) { final jobID = jobController.add(from, isRemoteToLocal); bind.sessionSendFiles( @@ -403,7 +418,7 @@ class FileController { Future removeAction(SelectedItems items) async { _removeCheckboxRemember = false; - if (items.isLocal == isLocal) { + if (items.isLocal != isLocal) { debugPrint("Failed to removeFile, wrong files"); return; } From b7a0436aa34501a57c49c3f6a5b209b6e961c4a3 Mon Sep 17 00:00:00 2001 From: csf Date: Wed, 8 Mar 2023 23:14:52 +0900 Subject: [PATCH 275/382] fix close error --- flutter/lib/models/file_model.dart | 6 ------ 1 file changed, 6 deletions(-) diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index 2073991ef..6670677d6 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -73,7 +73,6 @@ class FileModel { Future close() async { parent.target?.dialogManager.dismissAll(); - jobController.close(); await localController.close(); await remoteController.close(); } @@ -608,11 +607,6 @@ class JobController { // return jobTable.firstWhere((element) => element.id == id); // } - void close() { - jobTable.close(); - jobTable.clear(); - } - // return jobID int add(Entry from, bool isRemoteToLocal) { final jobID = JobController.jobID.next(); From a2f82b6ea6b5cd20e72de585e067363aabbff046 Mon Sep 17 00:00:00 2001 From: csf Date: Thu, 9 Mar 2023 00:06:24 +0900 Subject: [PATCH 276/382] restore jobTable state mode --- .../lib/desktop/pages/file_manager_page.dart | 336 +++++++++--------- flutter/lib/models/file_model.dart | 6 +- 2 files changed, 165 insertions(+), 177 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 1010d56c4..59dff5518 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -157,171 +157,163 @@ class _FileManagerPageState extends State /// transfer status list /// watch transfer status Widget statusList() { + statusListView() => Obx(() => ListView.builder( + controller: ScrollController(), + itemBuilder: (BuildContext context, int index) { + final item = jobController.jobTable[index]; + return Padding( + padding: const EdgeInsets.only(bottom: 5), + child: generateCard( + Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Transform.rotate( + angle: item.isRemoteToLocal ? pi : 0, + child: SvgPicture.asset( + "assets/arrow.svg", + color: Theme.of(context).tabBarTheme.labelColor, + ), + ).paddingOnly(left: 15), + const SizedBox( + width: 16.0, + ), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Tooltip( + waitDuration: Duration(milliseconds: 500), + message: item.jobName, + child: Text( + item.fileName, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ).paddingSymmetric(vertical: 10), + ), + Text( + '${translate("Total")} ${readableFileSize(item.totalSize.toDouble())}', + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + Offstage( + offstage: item.state != JobState.inProgress, + child: Text( + '${translate("Speed")} ${readableFileSize(item.speed)}/s', + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + ), + Offstage( + offstage: item.state == JobState.inProgress, + child: Text( + translate( + item.display(), + ), + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + ), + Offstage( + offstage: item.state != JobState.inProgress, + child: LinearPercentIndicator( + padding: EdgeInsets.only(right: 15), + animateFromLastPercent: true, + center: Text( + '${(item.finishedSize / item.totalSize * 100).toStringAsFixed(0)}%', + ), + barRadius: Radius.circular(15), + percent: item.finishedSize / item.totalSize, + progressColor: MyTheme.accent, + backgroundColor: Theme.of(context).hoverColor, + lineHeight: kDesktopFileTransferRowHeight, + ).paddingSymmetric(vertical: 15), + ), + ], + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Offstage( + offstage: item.state != JobState.paused, + child: MenuButton( + onPressed: () { + jobController.resumeJob(item.id); + }, + child: SvgPicture.asset( + "assets/refresh.svg", + color: Colors.white, + ), + color: MyTheme.accent, + hoverColor: MyTheme.accent80, + ), + ), + MenuButton( + padding: EdgeInsets.only(right: 15), + child: SvgPicture.asset( + "assets/close.svg", + color: Colors.white, + ), + onPressed: () { + jobController.jobTable.removeAt(index); + jobController.cancelJob(item.id); + }, + color: MyTheme.accent, + hoverColor: MyTheme.accent80, + ), + ], + ), + ], + ), + ], + ).paddingSymmetric(vertical: 10), + ), + ); + }, + itemCount: jobController.jobTable.length, + )); + return PreferredSize( preferredSize: const Size(200, double.infinity), child: Container( - margin: const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0), - padding: const EdgeInsets.all(8.0), - child: jobController.jobTable.isEmpty - ? generateCard( - Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SvgPicture.asset( - "assets/transfer.svg", - color: Theme.of(context).tabBarTheme.labelColor, - height: 40, - ).paddingOnly(bottom: 10), - Text( - translate("No transfers in progress"), - textAlign: TextAlign.center, - textScaleFactor: 1.20, - style: TextStyle( - color: Theme.of(context).tabBarTheme.labelColor), + margin: const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0), + padding: const EdgeInsets.all(8.0), + child: Obx( + () => jobController.jobTable.isEmpty + ? generateCard( + Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + "assets/transfer.svg", + color: Theme.of(context).tabBarTheme.labelColor, + height: 40, + ).paddingOnly(bottom: 10), + Text( + translate("No transfers in progress"), + textAlign: TextAlign.center, + textScaleFactor: 1.20, + style: TextStyle( + color: + Theme.of(context).tabBarTheme.labelColor), + ), + ], ), - ], - ), - ), - ) - : Obx( - () => ListView.builder( - controller: ScrollController(), - itemBuilder: (BuildContext context, int index) { - final item = jobController.jobTable[index]; - return Padding( - padding: const EdgeInsets.only(bottom: 5), - child: generateCard( - Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Transform.rotate( - angle: item.isRemoteToLocal ? pi : 0, - child: SvgPicture.asset( - "assets/arrow.svg", - color: Theme.of(context) - .tabBarTheme - .labelColor, - ), - ).paddingOnly(left: 15), - const SizedBox( - width: 16.0, - ), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Tooltip( - waitDuration: - Duration(milliseconds: 500), - message: item.jobName, - child: Text( - item.fileName, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ).paddingSymmetric(vertical: 10), - ), - Text( - '${translate("Total")} ${readableFileSize(item.totalSize.toDouble())}', - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, - ), - ), - Offstage( - offstage: - item.state != JobState.inProgress, - child: Text( - '${translate("Speed")} ${readableFileSize(item.speed)}/s', - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, - ), - ), - ), - Offstage( - offstage: - item.state == JobState.inProgress, - child: Text( - translate( - item.display(), - ), - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, - ), - ), - ), - Offstage( - offstage: - item.state != JobState.inProgress, - child: LinearPercentIndicator( - padding: EdgeInsets.only(right: 15), - animateFromLastPercent: true, - center: Text( - '${(item.finishedSize / item.totalSize * 100).toStringAsFixed(0)}%', - ), - barRadius: Radius.circular(15), - percent: item.finishedSize / - item.totalSize, - progressColor: MyTheme.accent, - backgroundColor: - Theme.of(context).hoverColor, - lineHeight: - kDesktopFileTransferRowHeight, - ).paddingSymmetric(vertical: 15), - ), - ], - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Offstage( - offstage: item.state != JobState.paused, - child: MenuButton( - onPressed: () { - jobController.resumeJob(item.id); - }, - child: SvgPicture.asset( - "assets/refresh.svg", - color: Colors.white, - ), - color: MyTheme.accent, - hoverColor: MyTheme.accent80, - ), - ), - MenuButton( - padding: EdgeInsets.only(right: 15), - child: SvgPicture.asset( - "assets/close.svg", - color: Colors.white, - ), - onPressed: () { - jobController.jobTable.removeAt(index); - jobController.cancelJob(item.id); - }, - color: MyTheme.accent, - hoverColor: MyTheme.accent80, - ), - ], - ), - ], - ), - ], - ).paddingSymmetric(vertical: 10), - ), - ); - }, - itemCount: jobController.jobTable.length, - ), - ), - ), + ), + ) + : statusListView(), + )), ); } @@ -418,8 +410,7 @@ class _FileManagerViewState extends State { }, onExit: (evt) => widget._mouseFocusScope.value = MouseFocusScope.none, - child: _buildFileList( - context, isLocal, _fileListScrollController), + child: _buildFileList(context, _fileListScrollController), )) ], ), @@ -864,7 +855,7 @@ class _FileManagerViewState extends State { } Widget _buildFileList( - BuildContext context, bool isLocal, ScrollController scrollController) { + BuildContext context, ScrollController scrollController) { final fd = controller.directory.value; final entries = fd.entries; @@ -1044,7 +1035,7 @@ class _FileManagerViewState extends State { // Header Row( children: [ - Expanded(child: _buildFileBrowserHeader(context, isLocal)), + Expanded(child: _buildFileBrowserHeader(context)), ], ), // Body @@ -1139,7 +1130,7 @@ class _FileManagerViewState extends State { return false; } - Widget _buildFileBrowserHeader(BuildContext context, bool isLocal) { + Widget _buildFileBrowserHeader(BuildContext context) { final padding = EdgeInsets.all(1.0); return SizedBox( height: kDesktopFileTransferHeaderHeight, @@ -1147,7 +1138,7 @@ class _FileManagerViewState extends State { children: [ Obx( () => headerItemFunc( - _nameColWidth.value, SortBy.name, translate("Name"), isLocal), + _nameColWidth.value, SortBy.name, translate("Name")), ), DraggableDivider( axis: Axis.vertical, @@ -1160,7 +1151,7 @@ class _FileManagerViewState extends State { ), Obx( () => headerItemFunc(_modifiedColWidth.value, SortBy.modified, - translate("Modified"), isLocal), + translate("Modified")), ), DraggableDivider( axis: Axis.vertical, @@ -1172,16 +1163,13 @@ class _FileManagerViewState extends State { _modifiedColWidth.value)); }, padding: padding), - Expanded( - child: - headerItemFunc(null, SortBy.size, translate("Size"), isLocal)) + Expanded(child: headerItemFunc(null, SortBy.size, translate("Size"))) ], ), ); } - Widget headerItemFunc( - double? width, SortBy sortBy, String name, bool isLocal) { + Widget headerItemFunc(double? width, SortBy sortBy, String name) { final headerTextStyle = Theme.of(context).dataTableTheme.headingTextStyle ?? TextStyle(); return ObxValue>( @@ -1222,7 +1210,7 @@ class _FileManagerViewState extends State { ), ), () { if (controller.sortBy.value == sortBy) { - return controller.sortAscending; + return controller.sortAscending.obs; } else { return Rx(null); } diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index 6670677d6..11720ad56 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -208,7 +208,7 @@ class FileController { final history = RxList.empty(growable: true); final sortBy = SortBy.name.obs; - final sortAscending = true.obs; + var sortAscending = true; final JobController jobController; final OverlayDialogManager? dialogManager; @@ -285,7 +285,7 @@ class FileController { void changeSortStyle(SortBy sort, {bool? isLocal, bool ascending = true}) { sortBy.value = sort; - sortAscending.value = ascending; + sortAscending = ascending; directory.value.changeSortStyle(sort, ascending: ascending); } @@ -592,7 +592,7 @@ class FileController { class JobController { static final JobID jobID = JobID(); - final jobTable = RxList.empty(growable: true); + final jobTable = List.empty(growable: true).obs; final jobResultListener = JobResultListener>(); final GetSessionID getSessionID; String get sessionID => getSessionID(); From 8cb0cc0a5df641e156067ecbe303aad06482b6c2 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Wed, 8 Mar 2023 16:35:33 +0100 Subject: [PATCH 277/382] added "Sort by" translations --- 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 | 5 +++-- src/lang/ja.rs | 1 + src/lang/ko.rs | 1 + src/lang/kz.rs | 1 + src/lang/nl.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 + 33 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index c4bc10bb4..9cb09cef7 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 163c50e1b..408013eae 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "分辨率"), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index e3ddc5db8..ddc29cbc2 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index f37f30a61..be49f5c21 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 7a935d299..35c1b58da 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Auflösung"), ("No transfers in progress", "Keine Übertragungen im Gange"), ("Set one-time password length", "Länge des Einmalpassworts festlegen"), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index ed64addf8..02b65adcb 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 3270ae26c..a8b616994 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Resolución"), ("No transfers in progress", "No hay transferencias en curso"), ("Set one-time password length", "Establecer contraseña de un solo uso"), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index e2a7e9516..741149b97 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "وضوح"), ("No transfers in progress", "هیچ انتقالی در حال انجام نیست"), ("Set one-time password length", "طول رمز یکبار مصرف را تعیین کنید"), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index c0d739f91..be39c42d2 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/gr.rs b/src/lang/gr.rs index 819c257c3..139315099 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Ανάλυση"), ("No transfers in progress", "Δεν υπάρχει μεταφορά σε εξέλιξη"), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 46750eb13..192126892 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 4133f136f..ed4167d9d 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 17f066eef..c4d2236c9 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -208,7 +208,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("x11 expected", "x11 necessario"), ("Port", "Porta"), ("Settings", "Impostazioni"), - ("Username", " Nome utente"), + ("Username", "Nome utente"), ("Invalid port", "Numero di porta non valido"), ("Closed manually by the peer", "Chiuso manualmente dal peer"), ("Enable remote configuration modification", "Abilita la modifica remota della configurazione"), @@ -460,6 +460,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Codec"), ("Resolution", "Risoluzione"), ("No transfers in progress", "Nessun trasferimento in corso"), - ("Set one-time password length", ""), + ("Set one-time password length", "Imposta lunghezza password monouso"), + ("Sort by", "Ordina per"), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index b8031573a..6b98b4a17 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index fe6a0bfe9..237b27382 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 4b1e92cad..c0adba507 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 7888eed8e..f749d45f6 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Resolutie"), ("No transfers in progress", "Geen overdrachten in uitvoering"), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index b997267f1..95f145a2e 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Rozdzielczość"), ("No transfers in progress", "Brak transferów w toku"), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 98b8035a4..7fff174fd 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 18c9168c1..1efcaf6c2 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 225fa7277..6ad0c2974 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 59957a2cd..1bb44608f 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Разрешение"), ("No transfers in progress", "Передача не осуществляется"), ("Set one-time password length", "Установить длину одноразового пароля"), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index cec9e5b3d..3c19b9cfc 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 295cd28a1..78e2e8504 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index ebbdf4a28..9aa5a38c8 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 67fb49799..fccb383a9 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 9da1f1071..ef93478ca 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index cbbd65b4c..005e1cf0d 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 97a8725e3..68dc955da 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 3b1137cb7..717c79bd4 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 72a38afcd..3bfcfaf2c 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "分辨率"), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 4665d7c39..fa8c40cb0 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 0130b11cf..33007597c 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -461,5 +461,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), + ("Sort by", ""), ].iter().cloned().collect(); } From 2724c16e3422643d29518f7bc298aef99d6cdd28 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Wed, 8 Mar 2023 16:40:35 +0100 Subject: [PATCH 278/382] improved design and moved sort button --- flutter/lib/common/widgets/peer_tab_page.dart | 109 +++++++++++------- flutter/pubspec.lock | 8 ++ flutter/pubspec.yaml | 1 + 3 files changed, 79 insertions(+), 39 deletions(-) diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index cbc3b1370..cdafbc4f1 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -17,6 +17,7 @@ import 'package:get/get.dart'; import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart'; import 'package:provider/provider.dart'; import 'package:visibility_detector/visibility_detector.dart'; +import 'package:dropdown_button2/dropdown_button2.dart'; import '../../common.dart'; import '../../models/platform_model.dart'; @@ -112,19 +113,14 @@ class _PeerTabPageState extends State offstage: !isDesktop, child: _createPeerViewTypeSwitch(context) .marginOnly(left: 13)), + Offstage( + offstage: _hideSort, + child: PeerSortDropdown().marginOnly(left: 8), + ), ], ), ), ), - Row( - children: [ - Expanded(child: SizedBox()), - Offstage( - offstage: _hideSort, - child: PeerSortDropdown(), - ), - ], - ), _createPeersView(), ], ); @@ -244,7 +240,7 @@ class _PeerTabPageState extends State Widget _createPeerViewTypeSwitch(BuildContext context) { final textColor = Theme.of(context).textTheme.titleLarge?.color; - final activeDeco = BoxDecoration( + final deco = BoxDecoration( color: Theme.of(context).colorScheme.background, borderRadius: BorderRadius.circular(5), ); @@ -253,7 +249,7 @@ class _PeerTabPageState extends State return Obx( () => Container( padding: EdgeInsets.all(4.0), - decoration: activeDeco, + decoration: deco, child: InkWell( onTap: () async { final type = types.elementAt( @@ -439,39 +435,74 @@ class PeerSortDropdown extends StatefulWidget { } class _PeerSortDropdownState extends State { - final List sort_names = ['id', 'username', "status"]; + final List sort_names = ['Remote ID', 'Username', "Status"]; String _sortType = peerSort.value; @override Widget build(BuildContext context) { - return DropdownButton( - value: _sortType.isEmpty ? 'id' : _sortType, - elevation: 16, - underline: SizedBox(), - onChanged: (v) { - if (v != null) { - setState(() { - _sortType = v; - bind.setLocalFlutterConfig( - k: "peer-sorting", - v: _sortType, - ); - }); - peerSort.value = _sortType; - } - }, - dropdownColor: Theme.of(context).cardColor, - items: sort_names - .map>( - (String value) => DropdownMenuItem( - value: value, - child: Text( - value, - overflow: TextOverflow.ellipsis, - ), + final deco = BoxDecoration( + color: Theme.of(context).colorScheme.background, + borderRadius: BorderRadius.circular(5), + ); + return Container( + padding: EdgeInsets.all(4.0), + decoration: deco, + child: DropdownButtonHideUnderline( + child: DropdownButton2( + value: sort_names.contains(_sortType) ? _sortType : sort_names[0], + onChanged: (v) async { + if (v != null) { + setState(() => _sortType = v); + await bind.setLocalFlutterConfig( + k: "peer-sorting", + v: _sortType, + ); + peerSort.value = _sortType; + } + }, + customButton: Icon( + Icons.sort, + size: 18, ), - ) - .toList(), + dropdownStyleData: DropdownStyleData( + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.circular(10), + ), + width: 160, + ), + items: [ + DropdownMenuItem( + alignment: Alignment.center, + child: Text( + translate("Sort by"), + style: TextStyle(fontWeight: FontWeight.bold), + ), + enabled: false, + ), + ...sort_names + .map>( + (String value) => DropdownMenuItem( + value: value, + child: Row( + children: [ + Icon( + value == _sortType + ? Icons.radio_button_checked_rounded + : Icons.radio_button_off_rounded, + size: 18, + ).paddingOnly(right: 12), + Text( + translate(value), + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ) + .toList(), + ]), + ), ); } } diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index 63f6c804c..f3db95378 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -386,6 +386,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.0.2" + dropdown_button2: + dependency: "direct main" + description: + name: dropdown_button2 + sha256: "4458d81bfd24207f3d58f66f78097064e02f810f94cf1bc80bf20fe7685ebc80" + url: "https://pub.dev" + source: hosted + version: "2.0.0" event_bus: dependency: transitive description: diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index ccb53cc9c..a212a5093 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -94,6 +94,7 @@ dependencies: flutter_keyboard_visibility: ^5.4.0 texture_rgba_renderer: ^0.0.12 percent_indicator: ^4.2.2 + dropdown_button2: ^2.0.0 dev_dependencies: icons_launcher: ^2.0.4 From f042ed44bd17bb6bea0489a791c336a5bf0c2978 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Wed, 8 Mar 2023 20:10:08 +0100 Subject: [PATCH 279/382] refactor strings in a separate class, added alias and remote host sort types --- flutter/lib/common/widgets/peer_tab_page.dart | 7 ++-- flutter/lib/common/widgets/peers_view.dart | 34 ++++++++++++++++--- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index cdafbc4f1..e3bb3a5be 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -435,7 +435,6 @@ class PeerSortDropdown extends StatefulWidget { } class _PeerSortDropdownState extends State { - final List sort_names = ['Remote ID', 'Username', "Status"]; String _sortType = peerSort.value; @override @@ -449,7 +448,9 @@ class _PeerSortDropdownState extends State { decoration: deco, child: DropdownButtonHideUnderline( child: DropdownButton2( - value: sort_names.contains(_sortType) ? _sortType : sort_names[0], + value: PeerSortType.values.contains(_sortType) + ? _sortType + : PeerSortType.remoteId, onChanged: (v) async { if (v != null) { setState(() => _sortType = v); @@ -480,7 +481,7 @@ class _PeerSortDropdownState extends State { ), enabled: false, ), - ...sort_names + ...PeerSortType.values .map>( (String value) => DropdownMenuItem( value: value, diff --git a/flutter/lib/common/widgets/peers_view.dart b/flutter/lib/common/widgets/peers_view.dart index 2bc0f6fbb..640f7d085 100644 --- a/flutter/lib/common/widgets/peers_view.dart +++ b/flutter/lib/common/widgets/peers_view.dart @@ -16,6 +16,22 @@ import 'peer_card.dart'; typedef PeerFilter = bool Function(Peer peer); typedef PeerCardBuilder = Widget Function(Peer peer); +class PeerSortType { + static const String remoteId = 'Remote ID'; + static const String remoteHost = 'Remote Host'; + static const String alias = 'Alias'; + static const String username = 'Username'; + static const String status = 'Status'; + + static List values = [ + PeerSortType.remoteId, + PeerSortType.remoteHost, + PeerSortType.alias, + PeerSortType.username, + PeerSortType.status + ]; +} + /// for peer search text, global obs value final peerSearchText = "".obs; @@ -193,8 +209,8 @@ class _PeersViewState extends State<_PeersView> with WindowListener { } // fallback to id sorting - if (sortedBy.isEmpty) { - sortedBy = 'id'; + if (!PeerSortType.values.contains(sortedBy)) { + sortedBy = PeerSortType.remoteId; bind.setLocalFlutterConfig( k: "peer-sorting", v: sortedBy, @@ -203,14 +219,22 @@ class _PeersViewState extends State<_PeersView> with WindowListener { if (widget.peers.loadEvent != 'load_recent_peers') { switch (sortedBy) { - case 'id': + case PeerSortType.remoteId: peers.sort((p1, p2) => p1.id.compareTo(p2.id)); break; - case 'username': + case PeerSortType.remoteHost: + peers.sort((p1, p2) => + p1.hostname.toLowerCase().compareTo(p2.hostname.toLowerCase())); + break; + case PeerSortType.alias: + peers.sort((p1, p2) => + p1.alias.toLowerCase().compareTo(p2.alias.toLowerCase())); + break; + case PeerSortType.username: peers.sort((p1, p2) => p1.username.toLowerCase().compareTo(p2.username.toLowerCase())); break; - case 'status': + case PeerSortType.status: peers.sort((p1, p2) => p1.online ? -1 : 1); break; } From c307013325fe9b074f40b8147467dc3ba413def3 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Wed, 8 Mar 2023 21:04:03 +0100 Subject: [PATCH 280/382] fix bug fallback peer sort setting --- flutter/lib/common/widgets/peer_tab_page.dart | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index e3bb3a5be..869bd5fd9 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -435,7 +435,17 @@ class PeerSortDropdown extends StatefulWidget { } class _PeerSortDropdownState extends State { - String _sortType = peerSort.value; + @override + void initState() { + if (!PeerSortType.values.contains(peerSort.value)) { + peerSort.value = PeerSortType.remoteId; + bind.setLocalFlutterConfig( + k: "peer-sorting", + v: peerSort.value, + ); + } + super.initState(); + } @override Widget build(BuildContext context) { @@ -448,17 +458,13 @@ class _PeerSortDropdownState extends State { decoration: deco, child: DropdownButtonHideUnderline( child: DropdownButton2( - value: PeerSortType.values.contains(_sortType) - ? _sortType - : PeerSortType.remoteId, onChanged: (v) async { if (v != null) { - setState(() => _sortType = v); + setState(() => peerSort.value = v); await bind.setLocalFlutterConfig( k: "peer-sorting", - v: _sortType, + v: peerSort.value, ); - peerSort.value = _sortType; } }, customButton: Icon( @@ -488,7 +494,7 @@ class _PeerSortDropdownState extends State { child: Row( children: [ Icon( - value == _sortType + value == peerSort.value ? Icons.radio_button_checked_rounded : Icons.radio_button_off_rounded, size: 18, From 0b254aae045321570b75abcb8e12d5f2c66d55a1 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Wed, 8 Mar 2023 21:45:43 +0100 Subject: [PATCH 281/382] translations --- src/lang/it.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lang/it.rs b/src/lang/it.rs index 2ada1e208..4d2da35fa 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -461,9 +461,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Risoluzione"), ("No transfers in progress", "Nessun trasferimento in corso"), ("Set one-time password length", "Imposta la lunghezza della password monouso"), - ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", ""), - ("RDP Settings", "Imposta lunghezza password monouso"), + ("idd_driver_tip", "Installa il driver per lo schermo virtuale che sarà utilizzato quando non si dispone di schermi fisici."), + ("confirm_idd_driver_tip", "L'opzione per installare il driver per lo schermo virtuale è selezionata. Nota che un certificato di test sarà installato per l'attendibilità del driver dello schermo virtuale. Questo certificato di test verrà utilizzato solo per l'attendibilità dei driver di RustDesk."), + ("RDP Settings", "Impostazioni RDP"), ("Sort by", "Ordina per"), ].iter().cloned().collect(); } From 08f9b3760f643de642fd3b81df4cb7e3092185fe Mon Sep 17 00:00:00 2001 From: rustdesk Date: Thu, 9 Mar 2023 06:30:39 +0800 Subject: [PATCH 282/382] fix #3562 set en as default language and add es for built-in Flutter context menu text --- flutter/lib/common.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 666eab0ba..d9c052723 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -430,7 +430,7 @@ final ButtonStyle flatButtonStyle = TextButton.styleFrom( ); List supportedLocales = const [ - // specify CN/TW to fix CJK issue in flutter + Locale('en', 'US'), Locale('zh', 'CN'), Locale('zh', 'TW'), Locale('zh', 'SG'), @@ -452,7 +452,7 @@ List supportedLocales = const [ Locale('vi'), Locale('pl'), Locale('kz'), - Locale('en', 'US'), + Locale('es'), ]; String formatDurationToTime(Duration duration) { From 970dfa3c88e42d6b54e18d3b4742d8e2bfa8fbec Mon Sep 17 00:00:00 2001 From: csf Date: Thu, 9 Mar 2023 11:40:06 +0900 Subject: [PATCH 283/382] fix jobTable state can't update --- flutter/lib/desktop/pages/file_manager_page.dart | 8 ++++---- flutter/lib/models/file_model.dart | 11 ++++++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 59dff5518..a1a686afe 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -157,10 +157,10 @@ class _FileManagerPageState extends State /// transfer status list /// watch transfer status Widget statusList() { - statusListView() => Obx(() => ListView.builder( + statusListView(List jobs) => ListView.builder( controller: ScrollController(), itemBuilder: (BuildContext context, int index) { - final item = jobController.jobTable[index]; + final item = jobs[index]; return Padding( padding: const EdgeInsets.only(bottom: 5), child: generateCard( @@ -281,7 +281,7 @@ class _FileManagerPageState extends State ); }, itemCount: jobController.jobTable.length, - )); + ); return PreferredSize( preferredSize: const Size(200, double.infinity), @@ -312,7 +312,7 @@ class _FileManagerPageState extends State ), ), ) - : statusListView(), + : statusListView(jobController.jobTable), )), ); } diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index 11720ad56..1b5afd956 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -100,6 +100,7 @@ class FileModel { jobController.cancelJob(id); final job = jobController.jobTable[jobIndex]; job.state = JobState.done; + jobController.jobTable.refresh(); } } else { var need_override = false; @@ -286,7 +287,9 @@ class FileController { void changeSortStyle(SortBy sort, {bool? isLocal, bool ascending = true}) { sortBy.value = sort; sortAscending = ascending; - directory.value.changeSortStyle(sort, ascending: ascending); + directory.update((dir) { + dir?.changeSortStyle(sort, ascending: ascending); + }); } Future refresh() async { @@ -374,6 +377,7 @@ class FileController { job.totalSize = totalSize; job.fileCount = fileCount; debugPrint("update receive details:${fd.path}"); + jobController.jobTable.refresh(); } } else if (options.value.home.isEmpty) { options.value.home = fd.path; @@ -631,6 +635,7 @@ class JobController { job.speed = double.parse(evt['speed']); job.finishedSize = int.parse(evt['finished_size']); debugPrint("update job $id with $evt"); + jobTable.refresh(); } } catch (e) { debugPrint("Failed to tryUpdateJobProgress,evt:${evt.toString()}"); @@ -650,6 +655,7 @@ class JobController { job.finishedSize = job.totalSize; job.state = JobState.done; job.fileNum = int.parse(evt['file_num']); + jobTable.refresh(); } } @@ -665,6 +671,7 @@ class JobController { job.state = JobState.done; job.finishedSize = job.totalSize; } + jobTable.refresh(); } debugPrint("jobError $evt"); } @@ -713,6 +720,7 @@ class JobController { bind.sessionResumeJob( id: sessionID, actId: job.id, isRemote: job.isRemoteToLocal); job.state = JobState.inProgress; + jobTable.refresh(); } else { debugPrint("jobId $jobId is not exists"); } @@ -729,6 +737,7 @@ class JobController { final job = jobTable[jobIndex]; job.fileCount = num_entries; job.totalSize = total_size.toInt(); + jobTable.refresh(); } debugPrint("update folder files: $info"); } From 812c0c7fe109f9660a61845fe88f4e3acc3f06fc Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 9 Mar 2023 11:54:17 +0800 Subject: [PATCH 284/382] better interval Signed-off-by: fufesou --- flutter/lib/common/widgets/peers_view.dart | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/flutter/lib/common/widgets/peers_view.dart b/flutter/lib/common/widgets/peers_view.dart index 9c98f24b8..695266fb9 100644 --- a/flutter/lib/common/widgets/peers_view.dart +++ b/flutter/lib/common/widgets/peers_view.dart @@ -45,7 +45,7 @@ class _PeersViewState extends State<_PeersView> with WindowListener { var _lastChangeTime = DateTime.now(); var _lastQueryPeers = {}; var _lastQueryTime = DateTime.now().subtract(const Duration(hours: 1)); - var _queryCoun = 0; + var _queryCount = 0; var _exit = false; late final mobileWidth = () { @@ -78,12 +78,12 @@ class _PeersViewState extends State<_PeersView> with WindowListener { @override void onWindowFocus() { - _queryCoun = 0; + _queryCount = 0; } @override void onWindowMinimize() { - _queryCoun = _maxQueryCount; + _queryCount = _maxQueryCount; } @override @@ -149,6 +149,7 @@ class _PeersViewState extends State<_PeersView> with WindowListener { // ignore: todo // TODO: variables walk through async tasks? void _startCheckOnlines() { + final queryInterval = const Duration(seconds: 20); () async { while (!_exit) { final now = DateTime.now(); @@ -158,18 +159,18 @@ class _PeersViewState extends State<_PeersView> with WindowListener { platformFFI.ffiBind .queryOnlines(ids: _curPeers.toList(growable: false)); _lastQueryPeers = {..._curPeers}; - _lastQueryTime = DateTime.now(); - _queryCoun = 0; + _lastQueryTime = DateTime.now().subtract(queryInterval); + _queryCount = 0; } } } else { - if (_queryCoun < _maxQueryCount) { - if (now.difference(_lastQueryTime) > const Duration(seconds: 20)) { + if (_queryCount < _maxQueryCount) { + if (now.difference(_lastQueryTime) > queryInterval) { if (_curPeers.isNotEmpty) { platformFFI.ffiBind .queryOnlines(ids: _curPeers.toList(growable: false)); _lastQueryTime = DateTime.now(); - _queryCoun += 1; + _queryCount += 1; } } } From b566251986c567f91cc0c4c90099b83f101da9ee Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 9 Mar 2023 13:07:56 +0800 Subject: [PATCH 285/382] fix peer online state Signed-off-by: fufesou --- flutter/lib/common/widgets/peers_view.dart | 27 +++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/flutter/lib/common/widgets/peers_view.dart b/flutter/lib/common/widgets/peers_view.dart index 695266fb9..720e6727c 100644 --- a/flutter/lib/common/widgets/peers_view.dart +++ b/flutter/lib/common/widgets/peers_view.dart @@ -100,6 +100,19 @@ class _PeersViewState extends State<_PeersView> with WindowListener { ); } + onVisibilityChanged(VisibilityInfo info) { + final peerId = _peerId((info.key as ValueKey).value); + if (info.visibleFraction > 0.00001) { + _curPeers.add(peerId); + } else { + _curPeers.remove(peerId); + } + _lastChangeTime = DateTime.now(); + } + + String _cardId(String id) => widget.peers.name + id; + String _peerId(String cardId) => cardId.replaceAll(widget.peers.name, ''); + Widget _buildPeersView(Peers peers) { final body = ObxValue((searchText) { return FutureBuilder>( @@ -109,16 +122,8 @@ class _PeersViewState extends State<_PeersView> with WindowListener { final cards = []; for (final peer in peers) { final visibilityChild = VisibilityDetector( - key: ValueKey(peer.id), - onVisibilityChanged: (info) { - final peerId = (info.key as ValueKey).value; - if (info.visibleFraction > 0.00001) { - _curPeers.add(peerId); - } else { - _curPeers.remove(peerId); - } - _lastChangeTime = DateTime.now(); - }, + key: ValueKey(_cardId(peer.id)), + onVisibilityChanged: onVisibilityChanged, child: widget.peerCardBuilder(peer), ); cards.add(isDesktop @@ -165,7 +170,7 @@ class _PeersViewState extends State<_PeersView> with WindowListener { } } else { if (_queryCount < _maxQueryCount) { - if (now.difference(_lastQueryTime) > queryInterval) { + if (now.difference(_lastQueryTime) >= queryInterval) { if (_curPeers.isNotEmpty) { platformFFI.ffiBind .queryOnlines(ids: _curPeers.toList(growable: false)); From 265b865fbb9102c5213b8d44a873ce20d83f779c Mon Sep 17 00:00:00 2001 From: solokot Date: Thu, 9 Mar 2023 11:01:42 +0300 Subject: [PATCH 286/382] Update ru.rs --- src/lang/ru.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lang/ru.rs b/src/lang/ru.rs index afeb8d17d..a11828431 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Разрешение"), ("No transfers in progress", "Передача не осуществляется"), ("Set one-time password length", "Установить длину одноразового пароля"), - ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", ""), - ("RDP Settings", ""), + ("idd_driver_tip", "Установите драйвер виртуального дисплея, который используется при отсутствии физических дисплеев."), + ("confirm_idd_driver_tip", "Включена функция установки драйвера виртуального дисплея. Обратите внимание, что для доверия к драйверу будет установлен тестовый сертификат. Этот сертификат будет использоваться только для подтверждения доверия драйверам Rustdesk."), + ("RDP Settings", "Настройки RDP"), ].iter().cloned().collect(); } From 5ae3d33f3c9aef4672d484a9306f1071165f0dab Mon Sep 17 00:00:00 2001 From: csf Date: Thu, 9 Mar 2023 18:05:09 +0900 Subject: [PATCH 287/382] move selectedItems to file controller model --- .../lib/desktop/pages/file_manager_page.dart | 61 ++++++++----------- flutter/lib/models/file_model.dart | 15 ++++- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index a1a686afe..da88405a9 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -358,8 +358,6 @@ class _FileManagerViewState extends State { final _modifiedColWidth = kDesktopFileTransferModifiedColWidth.obs; final _fileListScrollController = ScrollController(); - late final _selectedItems = SelectedItems(isLocal: isLocal); - /// [_lastClickTime], [_lastClickEntry] help to handle double click var _lastClickTime = DateTime.now().millisecondsSinceEpoch - bind.getDoubleClickTime() - 1000; @@ -368,6 +366,7 @@ class _FileManagerViewState extends State { FileController get controller => widget.controller; bool get isLocal => widget.controller.isLocal; FFI get _ffi => widget._ffi; + SelectedItems get selectedItems => controller.selectedItems; @override void initState() { @@ -491,7 +490,7 @@ class _FileManagerViewState extends State { color: Theme.of(context).cardColor, hoverColor: Theme.of(context).hoverColor, onPressed: () { - _selectedItems.clear(); + selectedItems.clear(); controller.goBack(); }, ), @@ -506,7 +505,7 @@ class _FileManagerViewState extends State { color: Theme.of(context).cardColor, hoverColor: Theme.of(context).hoverColor, onPressed: () { - _selectedItems.clear(); + selectedItems.clear(); controller.goToParentDirectory(); }, ), @@ -703,10 +702,10 @@ class _FileManagerViewState extends State { hoverColor: Theme.of(context).hoverColor, ), MenuButton( - onPressed: validItems(_selectedItems) + onPressed: selectedItems.valid() ? () async { - await (controller.removeAction(_selectedItems)); - _selectedItems.clear(); + await (controller.removeAction(selectedItems)); + selectedItems.clear(); } : null, child: SvgPicture.asset( @@ -726,17 +725,17 @@ class _FileManagerViewState extends State { ? EdgeInsets.only(left: 10) : EdgeInsets.only(right: 10)), backgroundColor: MaterialStateProperty.all( - _selectedItems.length == 0 + selectedItems.length == 0 ? MyTheme.accent80 : MyTheme.accent, ), ), - onPressed: validItems(_selectedItems) + onPressed: selectedItems.valid() ? () { final otherSideData = controller.getOtherSideDirectoryData(); - controller.sendFiles(_selectedItems, otherSideData); - _selectedItems.clear(); + controller.sendFiles(selectedItems, otherSideData); + selectedItems.clear(); } : null, icon: isLocal @@ -744,7 +743,7 @@ class _FileManagerViewState extends State { translate('Send'), textAlign: TextAlign.right, style: TextStyle( - color: _selectedItems.length == 0 + color: selectedItems.length == 0 ? Theme.of(context).brightness == Brightness.light ? MyTheme.grayBg : MyTheme.darkGray @@ -755,7 +754,7 @@ class _FileManagerViewState extends State { quarterTurns: 2, child: SvgPicture.asset( "assets/arrow.svg", - color: _selectedItems.length == 0 + color: selectedItems.length == 0 ? Theme.of(context).brightness == Brightness.light ? MyTheme.grayBg : MyTheme.darkGray @@ -766,7 +765,7 @@ class _FileManagerViewState extends State { label: isLocal ? SvgPicture.asset( "assets/arrow.svg", - color: _selectedItems.length == 0 + color: selectedItems.length == 0 ? Theme.of(context).brightness == Brightness.light ? MyTheme.grayBg : MyTheme.darkGray @@ -775,7 +774,7 @@ class _FileManagerViewState extends State { : Text( translate('Receive'), style: TextStyle( - color: _selectedItems.length == 0 + color: selectedItems.length == 0 ? Theme.of(context).brightness == Brightness.light ? MyTheme.grayBg : MyTheme.darkGray @@ -809,13 +808,13 @@ class _FileManagerViewState extends State { MenuEntryButton( childBuilder: (style) => Text(translate("Select All"), style: style), proc: () => setState(() => - _selectedItems.selectAll(controller.directory.value.entries)), + selectedItems.selectAll(controller.directory.value.entries)), padding: kDesktopMenuPadding, dismissOnClicked: true), MenuEntryButton( childBuilder: (style) => Text(translate("Unselect All"), style: style), - proc: () => setState(() => _selectedItems.clear()), + proc: () => setState(() => selectedItems.clear()), padding: kDesktopMenuPadding, dismissOnClicked: true) ]; @@ -865,10 +864,10 @@ class _FileManagerViewState extends State { onNext: (buffer) { debugPrint("searching next for $buffer"); assert(buffer.length == 1); - assert(_selectedItems.length <= 1); + assert(selectedItems.length <= 1); var skipCount = 0; - if (_selectedItems.items.isNotEmpty) { - final index = entries.indexOf(_selectedItems.items.first); + if (selectedItems.items.isNotEmpty) { + final index = entries.indexOf(selectedItems.items.first); if (index < 0) { return; } @@ -884,7 +883,7 @@ class _FileManagerViewState extends State { (element) => element.name.toLowerCase().startsWith(buffer)); } if (searchResult.isEmpty) { - setState(() => _selectedItems.clear()); + setState(() => selectedItems.clear()); return; } _jumpToEntry(isLocal, searchResult.first, scrollController, @@ -892,12 +891,12 @@ class _FileManagerViewState extends State { }, onSearch: (buffer) { debugPrint("searching for $buffer"); - final selectedEntries = _selectedItems; + final selectedEntries = selectedItems; final searchResult = entries .where((element) => element.name.toLowerCase().startsWith(buffer)); selectedEntries.clear(); if (searchResult.isEmpty) { - setState(() => _selectedItems.clear()); + setState(() => selectedItems.clear()); return; } _jumpToEntry(isLocal, searchResult.first, scrollController, @@ -916,7 +915,7 @@ class _FileManagerViewState extends State { final lastModifiedStr = entry.isDrive ? " " : "${entry.lastModified().toString().replaceAll(".000", "")} "; - final isSelected = _selectedItems.contains(entry); + final isSelected = selectedItems.contains(entry); return Padding( padding: EdgeInsets.symmetric(vertical: 1), child: Container( @@ -970,7 +969,7 @@ class _FileManagerViewState extends State { )), ), onTap: () { - final items = _selectedItems; + final items = selectedItems; // handle double click if (_checkDoubleClick(entry)) { controller.openDirectory(entry.path); @@ -1056,7 +1055,7 @@ class _FileManagerViewState extends State { } onSearchText(String searchText, bool isLocal) { - _selectedItems.clear(); + selectedItems.clear(); _searchText.value = searchText; } @@ -1067,7 +1066,7 @@ class _FileManagerViewState extends State { if (index == -1) { debugPrint("entry is not valid: ${entry.path}"); } - final selectedEntries = _selectedItems; + final selectedEntries = selectedItems; final searchResult = entries.where((element) => element == entry); selectedEntries.clear(); if (searchResult.isEmpty) { @@ -1431,14 +1430,6 @@ class _FileManagerViewState extends State { // } } -bool validItems(SelectedItems items) { - if (items.length > 0) { - // exclude DirDrive type - return items.items.any((item) => !item.isDrive); - } - return false; -} - Widget buildWindowsThisPC(BuildContext context, [TextStyle? textStyle]) { final color = Theme.of(context).iconTheme.color?.withOpacity(0.7); return Row(children: [ diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index 1b5afd956..30a897a56 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -214,6 +214,7 @@ class FileController { final OverlayDialogManager? dialogManager; final DirectoryData Function() getOtherSideDirectoryData; + late final SelectedItems selectedItems = SelectedItems(isLocal: isLocal); FileController( {required this.isLocal, @@ -1059,7 +1060,7 @@ class SelectedItems { SelectedItems({required this.isLocal}); - add(Entry e) { + void add(Entry e) { if (e.isDrive) return; if (!_items.contains(e)) { _items.add(e); @@ -1070,11 +1071,11 @@ class SelectedItems { return _items.contains(e); } - remove(Entry e) { + void remove(Entry e) { _items.remove(e); } - clear() { + void clear() { _items.clear(); } @@ -1082,6 +1083,14 @@ class SelectedItems { _items.clear(); _items.addAll(entries); } + + bool valid() { + if (length > 0) { + // exclude DirDrive type + return items.any((item) => !item.isDrive); + } + return false; + } } // edited from [https://github.com/DevsOnFlutter/file_manager/blob/c1bf7f0225b15bcb86eba602c60acd5c4da90dd8/lib/file_manager.dart#L22] From 61679a107265a826de2066f77853b7640429c239 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Thu, 9 Mar 2023 17:22:14 +0800 Subject: [PATCH 288/382] upgrade some crates, fix scrap benchmark on mac, fix compile issue on osx10.14 --- Cargo.lock | 1939 +++++++++++++++++-------------- Cargo.toml | 17 +- build.rs | 9 +- libs/hbb_common/Cargo.toml | 12 +- libs/scrap/Cargo.toml | 2 +- libs/scrap/src/common/quartz.rs | 2 +- src/client.rs | 2 +- src/common.rs | 12 + src/license.rs | 3 +- src/naming.rs | 3 +- src/platform/macos.mm | 4 + src/server/connection.rs | 6 +- src/ui_interface.rs | 4 +- 13 files changed, 1108 insertions(+), 907 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1029bfed4..c48a69e8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ "gimli", ] @@ -17,12 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "adler32" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" - [[package]] name = "ahash" version = "0.7.6" @@ -111,12 +105,12 @@ dependencies = [ [[package]] name = "android_logger" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e9dd62f37dea550caf48c77591dc50bd1a378ce08855be1a0c42a97b7550fb" +checksum = "8619b80c242aa7bd638b5c7ddd952addeecb71f69c75e33f1d47b2804f8f883a" dependencies = [ "android_log-sys", - "env_logger 0.9.3", + "env_logger 0.10.0", "log", "once_cell", ] @@ -141,23 +135,24 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" [[package]] name = "arboard" -version = "2.1.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc120354d1b5ec6d7aaf4876b602def75595937b5e15d356eb554ab5177e08bb" +checksum = "d6041616acea41d67c4a984709ddab1587fd0b10efe5cc563fee954d2f011854" dependencies = [ "clipboard-win", "core-graphics 0.22.3", - "image 0.23.14", + "image", "log", "objc", "objc-foundation", "objc_id", + "once_cell", "parking_lot 0.12.1", "thiserror", "winapi 0.3.9", @@ -166,13 +161,12 @@ dependencies = [ [[package]] name = "async-broadcast" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d26004fe83b2d1cd3a97609b21e39f9a31535822210fe83205d2ce48866ea61" +checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" dependencies = [ "event-listener", "futures-core", - "parking_lot 0.12.1", ] [[package]] @@ -200,6 +194,18 @@ dependencies = [ "slab", ] +[[package]] +name = "async-fs" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" +dependencies = [ + "async-lock", + "autocfg 1.1.0", + "blocking", + "futures-lite", +] + [[package]] name = "async-io" version = "1.12.0" @@ -215,19 +221,18 @@ dependencies = [ "parking", "polling", "slab", - "socket2 0.4.7", + "socket2 0.4.9", "waker-fn", "windows-sys 0.42.0", ] [[package]] name = "async-lock" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" +checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" dependencies = [ "event-listener", - "futures-lite", ] [[package]] @@ -250,13 +255,13 @@ dependencies = [ [[package]] name = "async-recursion" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea" +checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -267,13 +272,13 @@ checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" [[package]] name = "async-trait" -version = "0.1.59" +version = "0.1.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364" +checksum = "b84f9ebcc6c1f5b8cb160f6990096a5c127f423fcb6e1ccc46c370cbdfb75dfc" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -284,7 +289,7 @@ checksum = "39991bc421ddf72f70159011b323ff49b0f783cc676a7287c59453da2e2531cf" dependencies = [ "atk-sys", "bitflags", - "glib 0.16.5", + "glib 0.16.7", "libc", ] @@ -311,9 +316,9 @@ dependencies = [ [[package]] name = "atomic-waker" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" +checksum = "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599" [[package]] name = "atty" @@ -321,7 +326,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi 0.3.9", ] @@ -343,24 +348,30 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ "addr2line", "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide 0.5.4", + "miniz_oxide", "object", "rustc-demangle", ] [[package]] -name = "base64" -version = "0.13.1" +name = "base-x" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" + +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "bindgen" @@ -377,12 +388,12 @@ dependencies = [ "lazycell", "log", "peeking_take_while", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2 1.0.51", + "quote 1.0.23", "regex", "rustc-hash", "shlex", - "which 4.3.0", + "which", ] [[package]] @@ -397,19 +408,41 @@ dependencies = [ "lazy_static", "lazycell", "peeking_take_while", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2 1.0.51", + "quote 1.0.23", "regex", "rustc-hash", "shlex", - "syn 1.0.105", + "syn 1.0.109", +] + +[[package]] +name = "bindgen" +version = "0.64.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2 1.0.51", + "quote 1.0.23", + "regex", + "rustc-hash", + "shlex", + "syn 1.0.109", + "which", ] [[package]] name = "bit_field" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" [[package]] name = "bitflags" @@ -437,9 +470,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "block-buffer" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] @@ -471,9 +504,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "2.3.2" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80" +checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -487,15 +520,15 @@ checksum = "832133bbabbbaa9fbdba793456a2827627a7d2b8fb96032fa1e7666d7895832b" [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "bytemuck" -version = "1.12.3" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" [[package]] name = "byteorder" @@ -505,11 +538,11 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" dependencies = [ - "serde 1.0.149", + "serde 1.0.154", ] [[package]] @@ -520,7 +553,7 @@ checksum = "f3125b15ec28b84c238f6f476c6034016a5f6cc0221cb514ca46c532139fc97d" dependencies = [ "bitflags", "cairo-sys-rs", - "glib 0.16.5", + "glib 0.16.7", "libc", "once_cell", "thiserror", @@ -549,11 +582,11 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e" +checksum = "6031a462f977dd38968b6f23378356512feeace69cef817e1a4475108093cec3" dependencies = [ - "serde 1.0.149", + "serde 1.0.154", ] [[package]] @@ -562,7 +595,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" dependencies = [ - "serde 1.0.149", + "serde 1.0.154", ] [[package]] @@ -573,9 +606,9 @@ checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", "cargo-platform", - "semver 1.0.14", - "serde 1.0.149", - "serde_json 1.0.89", + "semver 1.0.16", + "serde 1.0.154", + "serde_json 1.0.94", ] [[package]] @@ -585,23 +618,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6358dedf60f4d9b8db43ad187391afe959746101346fe51bb978126bec61dfb" dependencies = [ "clap 3.2.23", - "heck 0.4.0", + "heck 0.4.1", "indexmap", "log", - "proc-macro2 1.0.47", - "quote 1.0.21", - "serde 1.0.149", - "serde_json 1.0.89", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "serde 1.0.154", + "serde_json 1.0.94", + "syn 1.0.109", "tempfile", - "toml", + "toml 0.5.11", ] [[package]] name = "cc" -version = "1.0.77" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] @@ -659,9 +692,9 @@ dependencies = [ [[package]] name = "cidr-utils" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "355d5b5df67e58b523953d0c1a8d3d2c05f5af51f1332b0199b9c92263614ed0" +checksum = "fdfa36f04861d39453affe1cf084ce2d6554021a84eb6f31ebdeafb6fb92a01c" dependencies = [ "debug-helper", "num-bigint", @@ -672,9 +705,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.4.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" +checksum = "77ed9a53e5d4d9c573ae844bfac6872b159cb1d1585a83b29e7a64b7eef7332a" dependencies = [ "glob", "libc", @@ -705,7 +738,7 @@ dependencies = [ "atty", "bitflags", "clap_derive", - "clap_lex", + "clap_lex 0.2.4", "indexmap", "once_cell", "strsim 0.10.0", @@ -713,17 +746,30 @@ dependencies = [ "textwrap 0.16.0", ] +[[package]] +name = "clap" +version = "4.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d7ae14b20b94cb02149ed21a86c423859cbe18dc7ed69845cace50e52b40a5" +dependencies = [ + "bitflags", + "clap_lex 0.3.2", + "is-terminal", + "strsim 0.10.0", + "termcolor", +] + [[package]] name = "clap_derive" version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ - "heck 0.4.0", + "heck 0.4.1", "proc-macro-error", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -735,6 +781,15 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clap_lex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "clipboard" version = "0.1.0" @@ -742,16 +797,16 @@ dependencies = [ "cc", "hbb_common", "lazy_static", - "serde 1.0.149", + "serde 1.0.154", "serde_derive", "thiserror", ] [[package]] name = "clipboard-win" -version = "4.4.2" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4ab1b92798304eedc095b53942963240037c0516452cb11aeba709d420b2219" +checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" dependencies = [ "error-code", "str-buf", @@ -823,6 +878,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "colored" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" +dependencies = [ + "atty", + "lazy_static", + "winapi 0.3.9", +] + [[package]] name = "combine" version = "4.6.6" @@ -835,9 +901,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b" +checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" dependencies = [ "crossbeam-utils", ] @@ -848,9 +914,9 @@ version = "0.4.0" source = "git+https://github.com/open-trade/confy#630cc28a396cb7d01eefdd9f3824486fe4d8554b" dependencies = [ "directories-next", - "serde 1.0.149", + "serde 1.0.154", "thiserror", - "toml", + "toml 0.5.11", ] [[package]] @@ -972,27 +1038,26 @@ dependencies = [ [[package]] name = "cpal" -version = "0.13.5" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74117836a5124f3629e4b474eed03e479abaf98988b4bb317e29f08cfe0e4116" +checksum = "f342c1b63e185e9953584ff2199726bf53850d96610a310e3aca09e9405a2d0b" dependencies = [ "alsa", "core-foundation-sys 0.8.3", "coreaudio-rs", "jni 0.19.0", "js-sys", - "lazy_static", "libc", "mach", - "ndk 0.6.0", - "ndk-glue 0.6.2", - "nix 0.23.2", + "ndk 0.7.0", + "ndk-context", "oboe", - "parking_lot 0.11.2", + "once_cell", + "parking_lot 0.12.1", "stdweb", "thiserror", "web-sys", - "winapi 0.3.9", + "windows 0.37.0", ] [[package]] @@ -1015,9 +1080,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1025,9 +1090,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", @@ -1036,14 +1101,14 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.13" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset 0.7.1", + "memoffset 0.8.0", "scopeguard", ] @@ -1059,9 +1124,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ "cfg-if 1.0.0", ] @@ -1084,12 +1149,12 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.2.4" +version = "3.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1631ca6e3c59112501a9d87fd86f21591ff77acd31331e8a73f8d80a65bbdd71" +checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639" dependencies = [ - "nix 0.26.1", - "windows-sys 0.42.0", + "nix 0.26.2", + "windows-sys 0.45.0", ] [[package]] @@ -1100,9 +1165,9 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" [[package]] name = "cxx" -version = "1.0.83" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf07d07d6531bfcdbe9b8b739b104610c6508dcc4d63b410585faf338241daf" +checksum = "9a140f260e6f3f79013b8bfc65e7ce630c9ab4388c6a89c71e07226f49487b72" dependencies = [ "cc", "cxxbridge-flags", @@ -1112,34 +1177,34 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.83" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2eb5b96ecdc99f72657332953d4d9c50135af1bac34277801cc3937906ebd39" +checksum = "da6383f459341ea689374bf0a42979739dc421874f112ff26f829b8040b8e613" dependencies = [ "cc", "codespan-reporting", "once_cell", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2 1.0.51", + "quote 1.0.23", "scratch", - "syn 1.0.105", + "syn 1.0.109", ] [[package]] name = "cxxbridge-flags" -version = "1.0.83" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac040a39517fd1674e0f32177648334b0f4074625b5588a64519804ba0553b12" +checksum = "90201c1a650e95ccff1c8c0bb5a343213bdd317c6e600a93075bca2eff54ec97" [[package]] name = "cxxbridge-macro" -version = "1.0.83" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1362b0ddcfc4eb0a1f57b68bd77dd99f0e826958a96abd0ae9bd092e114ffed6" +checksum = "0b75aed41bb2e6367cae39e6326ef817a851db13c13e4f3263714ca3cfb8de56" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -1187,10 +1252,10 @@ checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2 1.0.51", + "quote 1.0.23", "strsim 0.9.3", - "syn 1.0.105", + "syn 1.0.109", ] [[package]] @@ -1201,10 +1266,10 @@ checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2 1.0.51", + "quote 1.0.23", "strsim 0.10.0", - "syn 1.0.105", + "syn 1.0.109", ] [[package]] @@ -1214,8 +1279,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" dependencies = [ "darling_core 0.10.2", - "quote 1.0.21", - "syn 1.0.105", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -1225,8 +1290,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core 0.13.4", - "quote 1.0.21", - "syn 1.0.105", + "quote 1.0.23", + "syn 1.0.109", +] + +[[package]] +name = "dart-sys" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d8b5680b5c2cc52f50acb2457d9b3a3b58adcca785db13a0e3655626f601de6" +dependencies = [ + "cc", ] [[package]] @@ -1350,9 +1424,9 @@ dependencies = [ [[package]] name = "dbus" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8bcdd56d2e5c4ed26a529c5a9029f5db8290d433497506f958eae3be148eb6" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" dependencies = [ "libc", "libdbus-sys", @@ -1361,9 +1435,9 @@ dependencies = [ [[package]] name = "dbus-crossroads" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "554114296d012b33fdaf362a733db6dc5f73c4c9348b8b620ddd42e61b406e30" +checksum = "3a4c83437187544ba5142427746835061b330446ca8902eabd70e4afb8f76de0" dependencies = [ "dbus", ] @@ -1392,25 +1466,15 @@ dependencies = [ "windows 0.30.0", ] -[[package]] -name = "deflate" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" -dependencies = [ - "adler32", - "byteorder", -] - [[package]] name = "delegate" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "082a24a9967533dc5d743c602157637116fc1b52806d694a5a45e6f32567fcdd" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -1419,9 +1483,9 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -1431,9 +1495,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1cf41b4580a37cca5ef2ada2cc43cf5d6be3983f4522e83010d67ab6925e84b" dependencies = [ "darling 0.10.2", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -1513,6 +1577,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "discard" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" + [[package]] name = "dispatch" version = "0.2.0" @@ -1565,7 +1635,7 @@ checksum = "7f3f119846c823f9eafcf953a8f6ffb6ed69bf6240883261a7f13b634579a51f" dependencies = [ "lazy_static", "regex", - "serde 1.0.149", + "serde 1.0.154", "strsim 0.10.0", ] @@ -1588,25 +1658,25 @@ dependencies = [ "cc", "hbb_common", "lazy_static", - "serde 1.0.149", + "serde 1.0.154", "serde_derive", "thiserror", ] [[package]] name = "ed25519" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" dependencies = [ "signature", ] [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "embed-resource" @@ -1616,16 +1686,16 @@ checksum = "e62abb876c07e4754fae5c14cafa77937841f01740637e17d78dc04352f32a5e" dependencies = [ "cc", "rustc_version 0.4.0", - "toml", + "toml 0.5.11", "vswhom", "winreg 0.10.1", ] [[package]] name = "encoding_rs" -version = "0.8.31" +version = "0.8.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" dependencies = [ "cfg-if 1.0.0", ] @@ -1640,7 +1710,7 @@ dependencies = [ "objc", "pkg-config", "rdev", - "serde 1.0.149", + "serde 1.0.154", "serde_derive", "tfc", "unicode-segmentation", @@ -1649,34 +1719,34 @@ dependencies = [ [[package]] name = "enum-map" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5a56d54c8dd9b3ad34752ed197a4eb2a6601bc010808eb097a04a58ae4c43e1" +checksum = "50c25992259941eb7e57b936157961b217a4fc8597829ddef0596d6c3cd86e1a" dependencies = [ "enum-map-derive", ] [[package]] name = "enum-map-derive" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9045e2676cd5af83c3b167d917b0a5c90a4d8e266e2683d6631b235c457fc27" +checksum = "2a4da76b3b6116d758c7ba93f7ec6a35d2e2cf24feda76c6e38a375f4d5c59f2" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] name = "enum_dispatch" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eb359f1476bf611266ac1f5355bc14aeca37b299d0ebccc038ee7058891c9cb" +checksum = "11f36e95862220b211a6e2aa5eca09b4fa391b13cd52ceb8035a24bf65a79de2" dependencies = [ "once_cell", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -1686,7 +1756,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb" dependencies = [ "enumflags2_derive", - "serde 1.0.149", + "serde 1.0.154", ] [[package]] @@ -1695,9 +1765,9 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -1723,6 +1793,19 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "epoll" version = "4.3.1" @@ -1740,10 +1823,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34a887c8df3ed90498c1c437ce21f211c8e27672921a8ffa293cb8d6d4caa9e" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2 1.0.51", + "quote 1.0.23", "rustversion", - "syn 1.0.105", + "syn 1.0.109", "synstructure", ] @@ -1758,6 +1841,17 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "errno" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.45.0", +] + [[package]] name = "errno-dragonfly" version = "0.1.2" @@ -1804,62 +1898,52 @@ dependencies = [ "flume", "half", "lebe", - "miniz_oxide 0.6.2", + "miniz_oxide", "smallvec", "threadpool", "zune-inflate", ] -[[package]] -name = "extend" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5216e387a76eebaaf11f6d871ec8a4aae0b25f05456ee21f228e024b1b3610" -dependencies = [ - "proc-macro-error", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", -] - -[[package]] -name = "failure" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" -dependencies = [ - "backtrace", -] - [[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] [[package]] -name = "field-offset" -version = "0.3.4" +name = "fern" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92" +checksum = "3bdd7b0849075e79ee9a1836df22c717d1eba30451796fdc631b04565dd11e2a" dependencies = [ - "memoffset 0.6.5", - "rustc_version 0.3.3", + "chrono", + "colored", + "log", +] + +[[package]] +name = "field-offset" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3cf3a800ff6e860c863ca6d4b16fd999db8b752819c1606884047b73e468535" +dependencies = [ + "memoffset 0.8.0", + "rustc_version 0.4.0", ] [[package]] name = "filetime" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -1869,27 +1953,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", - "miniz_oxide 0.6.2", + "miniz_oxide", ] [[package]] name = "flexi_logger" -version = "0.22.6" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c76a80dd14a27fc3d8bc696502132cb52b3f227256fd8601166c3a35e45f409" +checksum = "6eae57842a8221ef13f1f207632d786a175dd13bd8fbdc8be9d852f7c9cf1046" dependencies = [ - "ansi_term", - "atty", "chrono", "crossbeam-channel", "crossbeam-queue", "glob", + "is-terminal", "lazy_static", "log", + "nu-ansi-term", "regex", - "rustversion", "thiserror", - "time 0.3.9", ] [[package]] @@ -1907,9 +1989,9 @@ dependencies = [ [[package]] name = "flutter_rust_bridge" -version = "1.61.1" +version = "1.68.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8079119bbe8fb63d7ebb731fa2aa68c6c8375f4ac95ca26d5868e64c0f4b9244" +checksum = "54f0d71ff30fc2ae7c18508b517488a89051d81e3bfc4d48d4a6cf54b5dab789" dependencies = [ "allo-isolate", "anyhow", @@ -1918,6 +2000,7 @@ dependencies = [ "cc", "chrono", "console_error_panic_hook", + "dart-sys", "flutter_rust_bridge_macros", "js-sys", "lazy_static", @@ -1931,39 +2014,41 @@ dependencies = [ [[package]] name = "flutter_rust_bridge_codegen" -version = "1.61.1" +version = "1.68.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd7396bc479eae8aa24243e4c0e3d3dbda1909134f8de6bde4f080d262c9a0d" +checksum = "2a2a75a72411f0c5b480e4671417f52780172053128cf87d5614a9757d7680a0" dependencies = [ "anyhow", + "atty", "cargo_metadata", "cbindgen", + "chrono", "clap 3.2.23", "convert_case", "delegate", "enum_dispatch", - "env_logger 0.9.3", - "extend", + "fern", "itertools 0.10.5", "lazy_static", "log", "pathdiff", - "quote 1.0.21", + "quote 1.0.23", "regex", - "serde 1.0.149", + "serde 1.0.154", "serde_yaml", - "syn 1.0.105", + "strum_macros 0.24.3", + "syn 1.0.109", "tempfile", "thiserror", - "toml", + "toml 0.5.11", "topological-sort", ] [[package]] name = "flutter_rust_bridge_macros" -version = "1.61.1" +version = "1.68.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d5cd827645690ef378be57a890d0581e17c28d07b712872af7d744f454fd27d" +checksum = "f6187d1635afede47c23a9979f85c3dc57e3391eb9c690b7fe95715bf945da72" [[package]] name = "fnv" @@ -2038,9 +2123,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -2053,9 +2138,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -2063,15 +2148,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -2080,9 +2165,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-lite" @@ -2101,32 +2186,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -2140,15 +2225,6 @@ dependencies = [ "slab", ] -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - [[package]] name = "gdk" version = "0.16.2" @@ -2160,7 +2236,7 @@ dependencies = [ "gdk-pixbuf", "gdk-sys", "gio", - "glib 0.16.5", + "glib 0.16.7", "libc", "pango", ] @@ -2174,7 +2250,7 @@ dependencies = [ "bitflags", "gdk-pixbuf-sys", "gio", - "glib 0.16.5", + "glib 0.16.7", "libc", ] @@ -2232,7 +2308,7 @@ dependencies = [ "glib-sys 0.16.3", "libc", "system-deps 6.0.3", - "x11 2.20.1", + "x11 2.21.0", ] [[package]] @@ -2280,9 +2356,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.2" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "gio" @@ -2296,7 +2372,7 @@ dependencies = [ "futures-io", "futures-util", "gio-sys", - "glib 0.16.5", + "glib 0.16.7", "libc", "once_cell", "pin-project-lite", @@ -2338,9 +2414,9 @@ dependencies = [ [[package]] name = "glib" -version = "0.16.5" +version = "0.16.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cd04d150a2c63e6779f43aec7e04f5374252479b7bed5f45146d9c0e821f161" +checksum = "ddd4df61a866ed7259d6189b8bcb1464989a77f1d85d25d002279bbe9dd38b2f" dependencies = [ "bitflags", "futures-channel", @@ -2369,9 +2445,9 @@ dependencies = [ "itertools 0.9.0", "proc-macro-crate 0.1.5", "proc-macro-error", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -2381,12 +2457,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e084807350b01348b6d9dbabb724d1a0bb987f47a2c85de200e98e12e30733bf" dependencies = [ "anyhow", - "heck 0.4.0", - "proc-macro-crate 1.2.1", + "heck 0.4.1", + "proc-macro-crate 1.3.1", "proc-macro-error", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -2411,9 +2487,9 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "gobject-sys" @@ -2584,7 +2660,7 @@ dependencies = [ "gdk", "gdk-pixbuf", "gio", - "glib 0.16.5", + "glib 0.16.7", "gtk-sys", "gtk3-macros", "libc", @@ -2618,18 +2694,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cfd6557b1018b773e43c8de9d0d13581d6b36190d0501916cbec4731db5ccff" dependencies = [ "anyhow", - "proc-macro-crate 1.2.1", + "proc-macro-crate 1.3.1", "proc-macro-error", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] name = "h2" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" +checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" dependencies = [ "bytes", "fnv", @@ -2673,7 +2749,7 @@ dependencies = [ "confy", "directories-next", "dirs-next", - "env_logger 0.9.3", + "env_logger 0.10.0", "filetime", "flexi_logger", "futures", @@ -2689,16 +2765,16 @@ dependencies = [ "quinn", "rand 0.8.5", "regex", - "serde 1.0.149", + "serde 1.0.154", "serde_derive", - "serde_json 1.0.89", + "serde_json 1.0.94", "socket2 0.3.19", "sodiumoxide", "sysinfo", "tokio", "tokio-socks", "tokio-util", - "toml", + "toml 0.7.2", "winapi 0.3.9", "zstd", ] @@ -2714,9 +2790,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -2727,6 +2803,21 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "hex" version = "0.4.3" @@ -2741,13 +2832,13 @@ checksum = "4d13cdbd5dbb29f9c88095bbdc2590c9cba0d0a1269b983fef6b2cdd7e9f4db1" [[package]] name = "http" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ "bytes", "fnv", - "itoa 1.0.4", + "itoa 1.0.6", ] [[package]] @@ -2782,21 +2873,21 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hwcodec" version = "0.1.0" -source = "git+https://github.com/21pages/hwcodec#64f885b3787694b16dfcff08256750b0376b2eba" +source = "git+https://github.com/21pages/hwcodec#d55f7761ef692fae738259d8c14506d901eb824c" dependencies = [ "bindgen 0.59.2", "cc", "log", - "serde 1.0.149", + "serde 1.0.154", "serde_derive", - "serde_json 1.0.89", + "serde_json 1.0.94", ] [[package]] name = "hyper" -version = "0.14.23" +version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ "bytes", "futures-channel", @@ -2807,9 +2898,9 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.4", + "itoa 1.0.6", "pin-project-lite", - "socket2 0.4.7", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -2869,22 +2960,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "image" -version = "0.23.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "num-iter", - "num-rational 0.3.2", - "num-traits 0.2.15", - "png 0.16.8", - "tiff 0.6.1", -] - [[package]] name = "image" version = "0.24.5" @@ -2896,12 +2971,12 @@ dependencies = [ "color_quant", "exr", "gif", - "jpeg-decoder 0.3.0", + "jpeg-decoder", "num-rational 0.4.1", "num-traits 0.2.15", - "png 0.17.7", + "png", "scoped_threadpool", - "tiff 0.8.1", + "tiff", ] [[package]] @@ -2927,8 +3002,8 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2 1.0.51", + "quote 1.0.23", ] [[package]] @@ -2973,6 +3048,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "io-lifetimes" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3" +dependencies = [ + "libc", + "windows-sys 0.45.0", +] + [[package]] name = "iovec" version = "0.1.4" @@ -2984,9 +3069,21 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec947b7a4ce12e3b87e353abae7ce124d025b6c7d6c5aea5cc0bcf92e9510ded" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" + +[[package]] +name = "is-terminal" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.45.0", +] [[package]] name = "itertools" @@ -3014,9 +3111,9 @@ checksum = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" [[package]] name = "itoa" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "jni" @@ -3054,19 +3151,13 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" dependencies = [ "libc", ] -[[package]] -name = "jpeg-decoder" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" - [[package]] name = "jpeg-decoder" version = "0.3.0" @@ -3078,9 +3169,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -3102,7 +3193,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7668b7cff6a51fe61cdde64cd27c8a220786f399501b57ebe36f7d8112fd68" dependencies = [ "bitflags", - "serde 1.0.149", + "serde 1.0.154", "unicode-segmentation", ] @@ -3130,7 +3221,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89e1edfdc9b0853358306c6dfb4b77c79c779174256fe93d80c0b5ebca451a2f" dependencies = [ - "glib 0.16.5", + "glib 0.16.7", "gtk", "gtk-sys", "libappindicator-sys", @@ -3150,15 +3241,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.138" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libdbus-sys" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c185b5b7ad900923ef3a8ff594083d4d9b5aea80bb4f32b8342363138c0d456b" +checksum = "9f8d7ae751e1cb825c840ae5e682f59b098cdfd213c350ac268b61449a5f58a0" dependencies = [ "pkg-config", ] @@ -3175,9 +3266,9 @@ dependencies = [ [[package]] name = "libpulse-binding" -version = "2.26.0" +version = "2.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17be42160017e0ae993c03bfdab4ecb6f82ce3f8d515bd8da8fdf18d10703663" +checksum = "1745b20bfc194ac12ef828f144f0ec2d4a7fe993281fa3567a0bd4969aee6890" dependencies = [ "bitflags", "libc", @@ -3189,9 +3280,9 @@ dependencies = [ [[package]] name = "libpulse-simple-binding" -version = "2.25.0" +version = "2.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cbf1a1dfd69a48cb60906399fa1d17f1b75029ef51c0789597be792dfd0bcd5" +checksum = "5ced94199e6e44133431374e4043f34e1f0697ebfb7b7d6c244a65bfaedf0e31" dependencies = [ "libpulse-binding", "libpulse-simple-sys", @@ -3200,9 +3291,9 @@ dependencies = [ [[package]] name = "libpulse-simple-sys" -version = "1.19.2" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c73f96f9ca34809692c4760cfe421225860aa000de50edab68a16221fd27cc1" +checksum = "84e423d9c619c908ce9b4916080e65ab586ca55b8c4939379f15e6e72fb43842" dependencies = [ "libpulse-sys", "pkg-config", @@ -3210,9 +3301,9 @@ dependencies = [ [[package]] name = "libpulse-sys" -version = "1.19.3" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "991e6bd0efe2a36e6534e136e7996925e4c1a8e35b7807fe533f2beffff27c30" +checksum = "2191e6880818d1df4cf72eac8e91dce7a5a52ba0da4b2a5cdafabc22b937eadb" dependencies = [ "libc", "num-derive", @@ -3258,14 +3349,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db23b9e7e2b7831bbd8aac0bbeeeb7b68cbebc162b227e7052e8e55829a09212" dependencies = [ "libc", - "x11 2.20.1", + "x11 2.21.0", +] + +[[package]] +name = "line-wrap" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" +dependencies = [ + "safemem", ] [[package]] name = "link-cplusplus" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" dependencies = [ "cc", ] @@ -3276,6 +3376,12 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + [[package]] name = "lock_api" version = "0.4.9" @@ -3386,6 +3492,15 @@ dependencies = [ "autocfg 1.1.0", ] +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg 1.1.0", +] + [[package]] name = "mime" version = "0.3.16" @@ -3398,34 +3513,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" -dependencies = [ - "adler32", -] - -[[package]] -name = "miniz_oxide" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg 1.1.0", -] - -[[package]] -name = "miniz_oxide" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.6.2" @@ -3456,14 +3543,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -3518,9 +3605,9 @@ dependencies = [ [[package]] name = "muda" -version = "0.4.1" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66365a21dc5e322c6b6ba25c735d00153c57dd2eb377926aa50e3caf547b6f6" +checksum = "0ee091608fe840d80c6b25e8f838964b264ee8e02e82ae0a38b2d900464d1582" dependencies = [ "cocoa", "crossbeam-channel", @@ -3531,7 +3618,7 @@ dependencies = [ "libxdo", "objc", "once_cell", - "png 0.17.7", + "png", "thiserror", "windows-sys 0.45.0", ] @@ -3587,7 +3674,7 @@ dependencies = [ "jni-sys", "ndk-sys 0.4.1+23.1.7779620", "num_enum", - "raw-window-handle 0.5.0", + "raw-window-handle 0.5.1", "thiserror", ] @@ -3612,21 +3699,6 @@ dependencies = [ "ndk-sys 0.2.2", ] -[[package]] -name = "ndk-glue" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d0c4a7b83860226e6b4183edac21851f05d5a51756e97a1144b7f5a6b63e65f" -dependencies = [ - "lazy_static", - "libc", - "log", - "ndk 0.6.0", - "ndk-context", - "ndk-macro", - "ndk-sys 0.3.0", -] - [[package]] name = "ndk-macro" version = "0.3.0" @@ -3634,10 +3706,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" dependencies = [ "darling 0.13.4", - "proc-macro-crate 1.2.1", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro-crate 1.3.1", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -3715,35 +3787,23 @@ dependencies = [ [[package]] name = "nix" -version = "0.25.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ - "autocfg 1.1.0", "bitflags", "cfg-if 1.0.0", "libc", - "memoffset 0.6.5", + "memoffset 0.7.1", "pin-utils", -] - -[[package]] -name = "nix" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a58d1d356c6597d08cde02c2f09d785b09e28711837b1ed667dc652c08a694" -dependencies = [ - "bitflags", - "cfg-if 1.0.0", - "libc", "static_assertions", ] [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", @@ -3751,13 +3811,23 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.3.7" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +checksum = "bc51db7b362b205941f71232e56c625156eb9a929f8cf74a428fd5bc094a4afc" dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi 0.3.9", +] + [[package]] name = "num-bigint" version = "0.4.3" @@ -3771,9 +3841,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" +checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" dependencies = [ "num-traits 0.2.15", ] @@ -3784,9 +3854,9 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -3799,17 +3869,6 @@ dependencies = [ "num-traits 0.2.15", ] -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg 1.1.0", - "num-integer", - "num-traits 0.2.15", -] - [[package]] name = "num-rational" version = "0.3.2" @@ -3852,42 +3911,33 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] [[package]] name = "num_enum" -version = "0.5.7" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.5.7" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" dependencies = [ - "proc-macro-crate 1.2.1", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", -] - -[[package]] -name = "num_threads" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" -dependencies = [ - "libc", + "proc-macro-crate 1.3.1", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -3931,9 +3981,9 @@ dependencies = [ [[package]] name = "object" -version = "0.29.0" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "memchr", ] @@ -3963,9 +4013,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "openssl-probe" @@ -3985,14 +4035,26 @@ dependencies = [ [[package]] name = "ordered-stream" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ca8c99d73c6e92ac1358f9f692c22c0bfd9c4701fa086f5d365c0d4ea818ea" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" dependencies = [ "futures-core", "pin-project-lite", ] +[[package]] +name = "os-version" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a8a1fed76ac765e39058ca106b6229a93c5a60292a1bd4b602ce2be11e1c020" +dependencies = [ + "anyhow", + "plist", + "uname", + "winapi 0.3.9", +] + [[package]] name = "os_str_bytes" version = "6.4.1" @@ -4005,11 +4067,17 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38731fa859ef679f1aec66ca9562165926b442f298467f76f5990f431efe87dc" dependencies = [ - "serde 1.0.149", + "serde 1.0.154", "serde_derive", - "serde_json 1.0.89", + "serde_json 1.0.94", ] +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "pango" version = "0.16.5" @@ -4018,7 +4086,7 @@ checksum = "cdff66b271861037b89d028656184059e03b0b6ccb36003820be19f7200b1e94" dependencies = [ "bitflags", "gio", - "glib 0.16.5", + "glib 0.16.7", "libc", "once_cell", "pango-sys", @@ -4065,7 +4133,7 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core 0.8.5", + "parking_lot_core 0.8.6", ] [[package]] @@ -4075,14 +4143,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.5", + "parking_lot_core 0.9.7", ] [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ "cfg-if 1.0.0", "instant", @@ -4094,22 +4162,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.5" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] name = "paste" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" [[package]] name = "pathdiff" @@ -4129,16 +4197,6 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" -[[package]] -name = "pest" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0" -dependencies = [ - "thiserror", - "ucd-trie", -] - [[package]] name = "phf" version = "0.7.24" @@ -4192,9 +4250,9 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -4216,15 +4274,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] -name = "png" -version = "0.16.8" +name = "plist" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" +checksum = "ffac6a51110e97610dd3ac73e34a65b27e56a1e305df41bad1f616d8e1cb22f4" dependencies = [ - "bitflags", - "crc32fast", - "deflate", - "miniz_oxide 0.3.7", + "base64", + "indexmap", + "line-wrap", + "quick-xml", + "serde 1.0.154", + "time 0.3.20", ] [[package]] @@ -4236,21 +4296,23 @@ dependencies = [ "bitflags", "crc32fast", "flate2", - "miniz_oxide 0.6.2", + "miniz_oxide", ] [[package]] name = "polling" -version = "2.5.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "166ca89eb77fd403230b9c156612965a81e094ec6ec3aa13663d4c8b113fa748" +checksum = "7e1f879b2998099c2d69ab9605d145d5b661195627eccc680002c4918a7fb6fa" dependencies = [ "autocfg 1.1.0", + "bitflags", "cfg-if 1.0.0", + "concurrent-queue", "libc", "log", - "wepoll-ffi", - "windows-sys 0.42.0", + "pin-project-lite", + "windows-sys 0.45.0", ] [[package]] @@ -4280,18 +4342,17 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" dependencies = [ - "toml", + "toml 0.5.11", ] [[package]] name = "proc-macro-crate" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "thiserror", - "toml", + "toml_edit", ] [[package]] @@ -4301,9 +4362,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", "version_check", ] @@ -4313,8 +4374,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2 1.0.51", + "quote 1.0.23", "version_check", ] @@ -4329,9 +4390,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -4376,7 +4437,7 @@ dependencies = [ "protobuf-support", "tempfile", "thiserror", - "which 4.3.0", + "which", ] [[package]] @@ -4402,17 +4463,25 @@ dependencies = [ ] [[package]] -name = "quinn" -version = "0.8.5" +name = "quick-xml" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b435e71d9bfa0d8889927231970c51fb89c58fa63bffcab117c9c7a41e5ef8f" +checksum = "ffc053f057dd768a56f62cd7e434c42c831d296968997e9ac1f76ea7c2d14c41" +dependencies = [ + "memchr", +] + +[[package]] +name = "quinn" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445cbfe2382fa023c4f2f3c7e1c95c03dcc1df2bf23cebcb2b13e1402c4394d1" dependencies = [ "bytes", - "futures-channel", - "futures-util", - "fxhash", + "pin-project-lite", "quinn-proto", "quinn-udp", + "rustc-hash", "rustls", "thiserror", "tokio", @@ -4422,17 +4491,16 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.8.4" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fce546b9688f767a57530652488420d419a8b1f44a478b451c3d1ab6d992a55" +checksum = "72ef4ced82a24bb281af338b9e8f94429b6eca01b4e66d899f40031f074e74c9" dependencies = [ "bytes", - "fxhash", "rand 0.8.5", "ring", + "rustc-hash", "rustls", "rustls-native-certs", - "rustls-pemfile 0.2.1", "slab", "thiserror", "tinyvec", @@ -4442,16 +4510,15 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.1.4" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b07946277141531aea269befd949ed16b2c85a780ba1043244eda0969e538e54" +checksum = "641538578b21f5e5c8ea733b736895576d0fe329bb883b937db6f4d163dbaaf4" dependencies = [ - "futures-util", "libc", "quinn-proto", - "socket2 0.4.7", - "tokio", + "socket2 0.4.9", "tracing", + "windows-sys 0.42.0", ] [[package]] @@ -4465,11 +4532,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ - "proc-macro2 1.0.47", + "proc-macro2 1.0.51", ] [[package]] @@ -4625,18 +4692,15 @@ dependencies = [ [[package]] name = "raw-window-handle" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7e3d950b66e19e0c372f3fa3fbbcf85b1746b571f74e0c2af6042a5c93420a" -dependencies = [ - "cty", -] +checksum = "4f851a03551ceefd30132e447f07f96cb7011d6b658374f3aed847333adb5559" [[package]] name = "rayon" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" dependencies = [ "either", "rayon-core", @@ -4644,9 +4708,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -4670,12 +4734,12 @@ dependencies = [ "lazy_static", "libc", "log", - "mio 0.8.5", + "mio 0.8.6", "strum 0.24.1", "strum_macros 0.24.3", "widestring 1.0.2", "winapi 0.3.9", - "x11 2.20.1", + "x11 2.21.0", ] [[package]] @@ -4718,9 +4782,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", @@ -4733,15 +4797,6 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "repng" version = "0.2.2" @@ -4754,9 +4809,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" +checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" dependencies = [ "base64", "bytes", @@ -4776,9 +4831,9 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustls", - "rustls-pemfile 1.0.1", - "serde 1.0.149", - "serde_json 1.0.89", + "rustls-pemfile", + "serde 1.0.154", + "serde_json 1.0.94", "serde_urlencoded", "tokio", "tokio-rustls", @@ -4852,12 +4907,12 @@ dependencies = [ [[package]] name = "runas" -version = "0.2.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a620b0994a180cdfa25c0439e6d58c0628272571501880d626ffff58e96a0799" +checksum = "ed87390fefd18965ff20baae5aeb9913bcf82d2b59dc04c0f6d8f17f7be56ff2" dependencies = [ "cc", - "which 3.1.1", + "which", ] [[package]] @@ -4892,11 +4947,11 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" -version = "0.3.3" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver 0.11.0", + "semver 0.9.0", ] [[package]] @@ -4905,14 +4960,14 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.14", + "semver 1.0.16", ] [[package]] name = "rustdesk" version = "1.2.0" dependencies = [ - "android_logger 0.11.1", + "android_logger 0.11.3", "arboard", "async-process", "async-trait", @@ -4922,7 +4977,7 @@ dependencies = [ "cfg-if 1.0.0", "chrono", "cidr-utils", - "clap 3.2.23", + "clap 4.1.8", "clipboard", "cocoa", "core-foundation 0.9.3", @@ -4937,7 +4992,7 @@ dependencies = [ "dispatch", "dlopen", "enigo", - "errno", + "errno 0.3.0", "evdev", "flutter_rust_bridge", "flutter_rust_bridge_codegen", @@ -4945,7 +5000,7 @@ dependencies = [ "hbb_common", "hex", "hound", - "image 0.24.5", + "image", "impersonate_system", "include_dir", "jni 0.19.0", @@ -4959,6 +5014,7 @@ dependencies = [ "num_cpus", "objc", "objc_id", + "os-version", "parity-tokio-ipc", "rdev", "repng", @@ -4970,9 +5026,9 @@ dependencies = [ "samplerate", "sciter-rs", "scrap", - "serde 1.0.149", + "serde 1.0.154", "serde_derive", - "serde_json 1.0.89", + "serde_json 1.0.94", "sha2", "shared_memory", "shutdown_hooks", @@ -5021,10 +5077,24 @@ dependencies = [ ] [[package]] -name = "rustls" -version = "0.20.7" +name = "rustix" +version = "0.36.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c" +checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc" +dependencies = [ + "bitflags", + "errno 0.2.8", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + +[[package]] +name = "rustls" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" dependencies = [ "log", "ring", @@ -5039,40 +5109,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" dependencies = [ "openssl-probe", - "rustls-pemfile 1.0.1", + "rustls-pemfile", "schannel", "security-framework", ] [[package]] name = "rustls-pemfile" -version = "0.2.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" -dependencies = [ - "base64", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" dependencies = [ "base64", ] [[package]] name = "rustversion" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" [[package]] name = "same-file" @@ -5094,12 +5161,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "lazy_static", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] @@ -5136,7 +5202,7 @@ name = "scrap" version = "0.5.0" dependencies = [ "android_logger 0.10.1", - "bindgen 0.59.2", + "bindgen 0.64.0", "block", "cfg-if 1.0.0", "dbus", @@ -5153,8 +5219,8 @@ dependencies = [ "num_cpus", "quest", "repng", - "serde 1.0.149", - "serde_json 1.0.89", + "serde 1.0.154", + "serde_json 1.0.94", "target_build_utils", "tracing", "webm", @@ -5163,9 +5229,9 @@ dependencies = [ [[package]] name = "scratch" -version = "1.0.2" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" +checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" [[package]] name = "sct" @@ -5179,9 +5245,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.7.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ "bitflags", "core-foundation 0.9.3", @@ -5192,9 +5258,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.6.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" dependencies = [ "core-foundation-sys 0.8.3", "libc", @@ -5202,30 +5268,27 @@ dependencies = [ [[package]] name = "semver" -version = "0.11.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ "semver-parser", ] [[package]] name = "semver" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" dependencies = [ - "serde 1.0.149", + "serde 1.0.154", ] [[package]] name = "semver-parser" -version = "0.10.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" @@ -5235,22 +5298,22 @@ checksum = "34b623917345a631dc9608d5194cc206b3fe6c3554cd1c75b937e55e285254af" [[package]] name = "serde" -version = "1.0.149" +version = "1.0.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055" +checksum = "8cdd151213925e7f1ab45a9bbfb129316bd00799784b174b7cc7bcd16961c49e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.149" +version = "1.0.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4" +checksum = "4fc80d722935453bcafdc2c9a73cd6fac4dc1938f0346035d84bf99fa9e33217" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -5267,24 +5330,33 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.89" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" dependencies = [ - "itoa 1.0.4", + "itoa 1.0.6", "ryu", - "serde 1.0.149", + "serde 1.0.154", ] [[package]] name = "serde_repr" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca" +checksum = "395627de918015623b32e7669714206363a7fc00382bf477e72c1f7533e8eafc" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", +] + +[[package]] +name = "serde_spanned" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +dependencies = [ + "serde 1.0.154", ] [[package]] @@ -5294,9 +5366,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.4", + "itoa 1.0.6", "ryu", - "serde 1.0.149", + "serde 1.0.154", ] [[package]] @@ -5307,10 +5379,19 @@ checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ "indexmap", "ryu", - "serde 1.0.149", + "serde 1.0.154", "yaml-rust", ] +[[package]] +name = "sha1" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + [[package]] name = "sha1" version = "0.10.5" @@ -5322,6 +5403,12 @@ dependencies = [ "digest", ] +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + [[package]] name = "sha2" version = "0.10.6" @@ -5360,9 +5447,9 @@ checksum = "6057adedbec913419c92996f395ba69931acbd50b7d56955394cd3f7bedbfa45" [[package]] name = "signal-hook" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" dependencies = [ "libc", "signal-hook-registry", @@ -5370,9 +5457,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] @@ -5395,7 +5482,7 @@ version = "0.1.0" dependencies = [ "confy", "hbb_common", - "serde 1.0.149", + "serde 1.0.154", "serde_derive", "walkdir", ] @@ -5408,9 +5495,9 @@ checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg 1.1.0", ] @@ -5453,9 +5540,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ "libc", "winapi 0.3.9", @@ -5470,7 +5557,7 @@ dependencies = [ "ed25519", "libc", "libsodium-sys", - "serde 1.0.149", + "serde 1.0.154", ] [[package]] @@ -5496,9 +5583,52 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stdweb" -version = "0.1.3" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" +checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" +dependencies = [ + "discard", + "rustc_version 0.2.3", + "stdweb-derive", + "stdweb-internal-macros", + "stdweb-internal-runtime", + "wasm-bindgen", +] + +[[package]] +name = "stdweb-derive" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" +dependencies = [ + "proc-macro2 1.0.51", + "quote 1.0.23", + "serde 1.0.154", + "serde_derive", + "syn 1.0.109", +] + +[[package]] +name = "stdweb-internal-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" +dependencies = [ + "base-x", + "proc-macro2 1.0.51", + "quote 1.0.23", + "serde 1.0.154", + "serde_derive", + "serde_json 1.0.94", + "sha1 0.6.1", + "syn 1.0.109", +] + +[[package]] +name = "stdweb-internal-runtime" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" [[package]] name = "str-buf" @@ -5549,9 +5679,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" dependencies = [ "heck 0.3.3", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -5560,11 +5690,11 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "heck 0.4.0", - "proc-macro2 1.0.47", - "quote 1.0.21", + "heck 0.4.1", + "proc-macro2 1.0.51", + "quote 1.0.23", "rustversion", - "syn 1.0.105", + "syn 1.0.109", ] [[package]] @@ -5580,12 +5710,12 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.105" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2 1.0.51", + "quote 1.0.23", "unicode-ident", ] @@ -5595,30 +5725,30 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", "unicode-xid 0.2.4", ] [[package]] name = "sys-locale" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3358acbb4acd4146138b9bda219e904a6bb5aaaa237f8eed06f4d6bc1580ecee" +checksum = "f8a11bd9c338fdba09f7881ab41551932ad42e405f61d01e8406baea71c07aee" dependencies = [ "js-sys", "libc", "wasm-bindgen", "web-sys", - "winapi 0.3.9", + "windows-sys 0.45.0", ] [[package]] name = "sysinfo" -version = "0.24.7" +version = "0.26.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54cb4ebf3d49308b99e6e9dc95e989e2fdbdc210e4f67c39db0bb89ba927001c" +checksum = "5c18a6156d1f27a9592ee18c1a846ca8dd5c258b7179fc193ae87c74ebb666f5" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys 0.8.3", @@ -5661,7 +5791,7 @@ dependencies = [ "strum 0.18.0", "strum_macros 0.18.0", "thiserror", - "toml", + "toml 0.5.11", "version-compare 0.0.10", ] @@ -5672,19 +5802,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2955b1fe31e1fa2fbd1976b71cc69a606d7d4da16f6de3333d0c92d51419aeff" dependencies = [ "cfg-expr", - "heck 0.4.0", + "heck 0.4.1", "pkg-config", - "toml", + "toml 0.5.11", "version-compare 0.1.1", ] [[package]] name = "system_shutdown" -version = "3.0.0" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "035e081d603551d8d78db27d2232913269c749ea67648c369100049820406a14" +checksum = "7567f71160af5e9abfb4f5a21532cf2174cefe91ac5c336419295685a695cc66" dependencies = [ - "winapi 0.3.9", + "windows 0.44.0", + "zbus", ] [[package]] @@ -5706,10 +5837,10 @@ dependencies = [ "gdkwayland-sys", "gdkx11-sys", "gio", - "glib 0.16.5", + "glib 0.16.7", "glib-sys 0.16.3", "gtk", - "image 0.24.5", + "image", "instant", "jni 0.20.0", "lazy_static", @@ -5721,8 +5852,8 @@ dependencies = [ "objc", "once_cell", "parking_lot 0.12.1", - "png 0.17.7", - "raw-window-handle 0.5.0", + "png", + "raw-window-handle 0.5.1", "scopeguard", "tao-macros", "unicode-segmentation", @@ -5737,9 +5868,9 @@ name = "tao-macros" version = "0.1.0" source = "git+https://github.com/tauri-apps/tao?branch=muda#676bd90a80286b893d8850cc4e3813a0c4a27dcf" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -5761,23 +5892,22 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" dependencies = [ "cfg-if 1.0.0", "fastrand", - "libc", "redox_syscall", - "remove_dir_all", - "winapi 0.3.9", + "rustix", + "windows-sys 0.42.0", ] [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] @@ -5809,8 +5939,9 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "tfc" version = "0.6.1" -source = "git+https://github.com/fufesou/The-Fat-Controller#a5f13e6ef80327eb8d860aeb26b0af93eb5aee2b" +source = "git+https://github.com/fufesou/The-Fat-Controller#102f2ec2cb2bbbd64413d20d28323e5e77e0fe71" dependencies = [ + "anyhow", "core-graphics 0.22.3", "unicode-segmentation", "winapi 0.3.9", @@ -5819,22 +5950,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -5846,17 +5977,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "tiff" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437" -dependencies = [ - "jpeg-decoder 0.1.22", - "miniz_oxide 0.4.4", - "weezl", -] - [[package]] name = "tiff" version = "0.8.1" @@ -5864,7 +5984,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7449334f9ff2baf290d55d73983a7d6fa15e01198faef72af07e2a8db851e471" dependencies = [ "flate2", - "jpeg-decoder 0.3.0", + "jpeg-decoder", "weezl", ] @@ -5881,21 +6001,30 @@ dependencies = [ [[package]] name = "time" -version = "0.3.9" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" dependencies = [ - "itoa 1.0.4", - "libc", - "num_threads", + "itoa 1.0.6", + "serde 1.0.154", + "time-core", "time-macros", ] [[package]] -name = "time-macros" -version = "0.2.4" +name = "time-core" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +dependencies = [ + "time-core", +] [[package]] name = "tinyvec" @@ -5908,28 +6037,28 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.23.0" +version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" +checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" dependencies = [ "autocfg 1.1.0", "bytes", "libc", "memchr", - "mio 0.8.5", + "mio 0.8.6", "num_cpus", "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", - "socket2 0.4.7", + "socket2 0.4.9", "tokio-macros", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -5938,9 +6067,9 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -5972,9 +6101,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.4" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ "bytes", "futures-core", @@ -5990,11 +6119,45 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ - "serde 1.0.149", + "serde 1.0.154", +] + +[[package]] +name = "toml" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6" +dependencies = [ + "serde 1.0.154", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +dependencies = [ + "serde 1.0.154", +] + +[[package]] +name = "toml_edit" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825" +dependencies = [ + "indexmap", + "serde 1.0.154", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] @@ -6027,9 +6190,9 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -6053,9 +6216,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d62801a4da61bb100b8d3174a5a46fed7b6ea03cc2ae93ee7340793b09a94ce3" +checksum = "f87445e3a107818c17d87e8369db30a6fc25539bface8351efe2132b22e47dbc" dependencies = [ "cocoa", "core-graphics 0.22.3", @@ -6065,7 +6228,7 @@ dependencies = [ "muda", "objc", "once_cell", - "png 0.17.7", + "png", "thiserror", "windows-sys 0.45.0", ] @@ -6081,9 +6244,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "typenum" @@ -6091,12 +6254,6 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" -[[package]] -name = "ucd-trie" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" - [[package]] name = "uds_windows" version = "1.0.2" @@ -6108,16 +6265,25 @@ dependencies = [ ] [[package]] -name = "unicode-bidi" -version = "0.3.8" +name = "uname" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8" +dependencies = [ + "libc", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524b68aca1d05e03fdf03fcdce2c6c94b6daf6d16861ddaa7e4f2b6638a9052c" [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "unicode-normalization" @@ -6130,9 +6296,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" @@ -6167,7 +6333,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", - "serde 1.0.149", + "serde 1.0.154", ] [[package]] @@ -6273,9 +6439,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -6283,24 +6449,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -6310,32 +6476,32 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ - "quote 1.0.21", + "quote 1.0.23", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "wayland-client" @@ -6394,8 +6560,8 @@ version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2 1.0.51", + "quote 1.0.23", "xml-rs", ] @@ -6412,9 +6578,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -6463,30 +6629,11 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" -[[package]] -name = "wepoll-ffi" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" -dependencies = [ - "cc", -] - [[package]] name = "which" -version = "3.1.1" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" -dependencies = [ - "failure", - "libc", -] - -[[package]] -name = "which" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" dependencies = [ "either", "libc", @@ -6495,11 +6642,10 @@ dependencies = [ [[package]] name = "whoami" -version = "1.2.3" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6631b6a2fd59b1841b622e8f1a7ad241ef0a46f2d580464ce8140ac94cbd571" +checksum = "45dbc71f0cdca27dc261a9bd37ddec174e4a0af2b900b890f378460f745426e3" dependencies = [ - "bumpalo", "wasm-bindgen", "web-sys", ] @@ -6603,6 +6749,19 @@ dependencies = [ "windows_x86_64_msvc 0.34.0", ] +[[package]] +name = "windows" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647" +dependencies = [ + "windows_aarch64_msvc 0.37.0", + "windows_i686_gnu 0.37.0", + "windows_i686_msvc 0.37.0", + "windows_x86_64_gnu 0.37.0", + "windows_x86_64_msvc 0.37.0", +] + [[package]] name = "windows" version = "0.44.0" @@ -6620,9 +6779,9 @@ version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce87ca8e3417b02dc2a8a22769306658670ec92d78f1bd420d6310a67c245c6" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -6631,9 +6790,9 @@ version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "853f69a591ecd4f810d29f17e902d40e349fb05b0b11fff63b08b826bfe39c7f" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] [[package]] @@ -6661,19 +6820,6 @@ dependencies = [ "windows_x86_64_msvc 0.28.0", ] -[[package]] -name = "windows-sys" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", -] - [[package]] name = "windows-sys" version = "0.42.0" @@ -6739,9 +6885,9 @@ checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a" [[package]] name = "windows_aarch64_msvc" @@ -6769,9 +6915,9 @@ checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1" [[package]] name = "windows_i686_gnu" @@ -6799,9 +6945,9 @@ checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c" [[package]] name = "windows_i686_msvc" @@ -6829,9 +6975,9 @@ checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d" [[package]] name = "windows_x86_64_gnu" @@ -6865,9 +7011,9 @@ checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d" [[package]] name = "windows_x86_64_msvc" @@ -6891,9 +7037,9 @@ dependencies = [ "lazy_static", "libc", "log", - "mio 0.8.5", + "mio 0.8.6", "ndk 0.5.0", - "ndk-glue 0.5.2", + "ndk-glue", "ndk-sys 0.2.2", "objc", "parking_lot 0.11.2", @@ -6908,6 +7054,15 @@ dependencies = [ "x11-dl", ] +[[package]] +name = "winnow" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee7b2c67f962bf5042bfd8b6a916178df33a26eec343ae064cb8e069f638fa6f" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.6.2" @@ -6932,17 +7087,14 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c" dependencies = [ - "toml", + "toml 0.5.11", ] [[package]] name = "wol-rs" -version = "0.9.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f97e69b28b256ccfb02472c25057132e234aa8368fea3bb0268def564ce1f2" -dependencies = [ - "clap 3.2.23", -] +checksum = "48dc5e486e34a31515518d370cdd8bf59ec696323fe8f92b858e43942e84a765" [[package]] name = "ws2_32-sys" @@ -6974,9 +7126,9 @@ dependencies = [ [[package]] name = "x11" -version = "2.20.1" +version = "2.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2638d5b9c17ac40575fb54bb461a4b1d2a8d1b4ffcc4ff237d254ec59ddeb82" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" dependencies = [ "libc", "pkg-config", @@ -6995,14 +7147,24 @@ dependencies = [ [[package]] name = "x11rb" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e99be55648b3ae2a52342f9a870c0e138709a3493261ce9b469afe6e4df6d8a" +checksum = "592b4883219f345e712b3209c62654ebda0bb50887f330cbd018d0f654bfd507" dependencies = [ "gethostname", - "nix 0.22.3", + "nix 0.24.3", "winapi 0.3.9", "winapi-wsapoll", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56b245751c0ac9db0e006dc812031482784e434630205a93c73cfefcaabeac67" +dependencies = [ + "nix 0.24.3", ] [[package]] @@ -7027,7 +7189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5af43ba661cee58bd86b9f81a899e45a15ac7f42fa4401340f73c0c2950030c1" dependencies = [ "derive_setters", - "serde 1.0.149", + "serde 1.0.154", ] [[package]] @@ -7041,13 +7203,13 @@ dependencies = [ [[package]] name = "zbus" -version = "3.6.2" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938ea6da98c75c2c37a86007bd17fd8e208cbec24e086108c87ece98e9edec0d" +checksum = "20aae5dd5b051971cd2f49f9f3b860e57b2b495ba5ba254eaec42d34ede57e97" dependencies = [ "async-broadcast", - "async-channel", "async-executor", + "async-fs", "async-io", "async-lock", "async-recursion", @@ -7062,13 +7224,13 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix 0.25.1", + "nix 0.26.2", "once_cell", "ordered-stream", "rand 0.8.5", - "serde 1.0.149", + "serde 1.0.154", "serde_repr", - "sha1", + "sha1 0.10.5", "static_assertions", "tracing", "uds_windows", @@ -7080,24 +7242,25 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "3.6.2" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45066039ebf3330820e495e854f8b312abb68f0a39e97972d092bd72e8bb3e8e" +checksum = "9264b3a1bcf5503d4e0348b6e7efe1da58d4f92a913c15ed9e63b52de85faaa1" dependencies = [ - "proc-macro-crate 1.2.1", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro-crate 1.3.1", + "proc-macro2 1.0.51", + "quote 1.0.23", "regex", - "syn 1.0.105", + "syn 1.0.109", + "zvariant_utils", ] [[package]] name = "zbus_names" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c737644108627748a660d038974160e0cbb62605536091bdfa28fd7f64d43c8" +checksum = "f34f314916bd89bdb9934154627fab152f4f28acdda03e7c4c68181b214fe7e3" dependencies = [ - "serde 1.0.149", + "serde 1.0.154", "static_assertions", "zvariant", ] @@ -7133,35 +7296,47 @@ dependencies = [ [[package]] name = "zune-inflate" -version = "0.2.42" +version = "0.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c473377c11c4a3ac6a2758f944cd336678e9c977aa0abf54f6450cf77e902d6d" +checksum = "a01728b79fb9b7e28a8c11f715e1cd8dc2cda7416a007d66cac55cebb3a8ac6b" dependencies = [ "simd-adler32", ] [[package]] name = "zvariant" -version = "3.9.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f8c89c183461e11867ded456db252eae90874bc6769b7adbea464caa777e51" +checksum = "46fe4914a985446d6fd287019b5fceccce38303d71407d9e6e711d44954a05d8" dependencies = [ "byteorder", "enumflags2", "libc", - "serde 1.0.149", + "serde 1.0.154", "static_assertions", "zvariant_derive", ] [[package]] name = "zvariant_derive" -version = "3.9.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "155247a5d1ab55e335421c104ccd95d64f17cebbd02f50cdbc1c33385f9c4d81" +checksum = "34c20260af4b28b3275d6676c7e2a6be0d4332e8e0aba4616d34007fd84e462a" dependencies = [ - "proc-macro-crate 1.2.1", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.105", + "proc-macro-crate 1.3.1", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b22993dbc4d128a17a3b6c92f1c63872dd67198537ee728d8b5d7c40640a8b" +dependencies = [ + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.109", ] diff --git a/Cargo.toml b/Cargo.toml index 47c2bb0e7..7ad979f8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,22 +45,22 @@ lazy_static = "1.4" sha2 = "0.10" repng = "0.2" parity-tokio-ipc = { git = "https://github.com/open-trade/parity-tokio-ipc" } -runas = "0.2" +runas = "1.0" magnum-opus = { git = "https://github.com/rustdesk/magnum-opus" } dasp = { version = "0.11", features = ["signal", "interpolate-linear", "interpolate"], optional = true } rubato = { version = "0.12", optional = true } samplerate = { version = "0.2", optional = true } async-trait = "0.1" uuid = { version = "1.0", features = ["v4"] } -clap = "3.0" +clap = "4.1" rpassword = "7.0" -base64 = "0.13" +base64 = "0.21" num_cpus = "1.13" bytes = { version = "1.2", features = ["serde"] } default-net = "0.12.0" -wol-rs = "0.9.1" +wol-rs = "1.0" flutter_rust_bridge = { version = "1.61.1", optional = true } -errno = "0.2.8" +errno = "0.3" rdev = { git = "https://github.com/fufesou/rdev" } url = { version = "2.1", features = ["serde"] } dlopen = "0.1" @@ -71,7 +71,7 @@ chrono = "0.4.23" cidr-utils = "0.5.9" [target.'cfg(not(any(target_os = "android", target_os = "linux")))'.dependencies] -cpal = "0.13.5" +cpal = "0.14" [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] machine-uid = "0.2" @@ -81,9 +81,9 @@ sys-locale = "0.2" enigo = { path = "libs/enigo", features = [ "with_serde" ] } clipboard = { path = "libs/clipboard" } ctrlc = "3.2" -arboard = "2.0" +arboard = "3.2" #minreq = { version = "2.4", features = ["punycode", "https-native"] } -system_shutdown = "3.0.0" +system_shutdown = "4.0" [target.'cfg(target_os = "windows")'.dependencies] trayicon = { git = "https://github.com/open-trade/trayicon-rs", features = ["winit"] } @@ -148,6 +148,7 @@ cc = "1.0" hbb_common = { path = "libs/hbb_common" } simple_rc = { path = "libs/simple_rc", optional = true } flutter_rust_bridge_codegen = "1.61.1" +os-version = "0.2" [dev-dependencies] hound = "3.5" diff --git a/build.rs b/build.rs index d15f27424..bf141e539 100644 --- a/build.rs +++ b/build.rs @@ -9,7 +9,14 @@ fn build_windows() { #[cfg(target_os = "macos")] fn build_mac() { let file = "src/platform/macos.mm"; - cc::Build::new().file(file).compile("macos"); + let mut b = cc::Build::new(); + if let Ok(os_version::OsVersion::MacOS(v)) = os_version::detect() { + let v = v.version; + if v.contains("10.14") { + b.flag("-DNO_InputMonitoringAuthStatus=1"); + } + } + b.file(file).compile("macos"); println!("cargo:rerun-if-changed={}", file); } diff --git a/libs/hbb_common/Cargo.toml b/libs/hbb_common/Cargo.toml index c77f11eb5..fd02639ed 100644 --- a/libs/hbb_common/Cargo.toml +++ b/libs/hbb_common/Cargo.toml @@ -7,17 +7,17 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -flexi_logger = { version = "0.22", features = ["async", "use_chrono_for_offset"] } +flexi_logger = { version = "0.25", features = ["async"] } protobuf = { version = "3.1", features = ["with-bytes"] } tokio = { version = "1.20", features = ["full"] } tokio-util = { version = "0.7", features = ["full"] } futures = "0.3" bytes = { version = "1.2", features = ["serde"] } log = "0.4" -env_logger = "0.9" +env_logger = "0.10" socket2 = { version = "0.3", features = ["reuseport"] } zstd = "0.9" -quinn = {version = "0.8", optional = true } +quinn = {version = "0.9", optional = true } anyhow = "1.0" futures-util = "0.3" directories-next = "2.0" @@ -34,7 +34,7 @@ tokio-socks = { git = "https://github.com/open-trade/tokio-socks" } chrono = "0.4" backtrace = "0.3" libc = "0.2" -sysinfo = "0.24" +sysinfo = "0.26" [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] mac_address = "1.1" @@ -54,5 +54,5 @@ winapi = { version = "0.3", features = ["winuser"] } osascript = "0.3.0" [dev-dependencies] -toml = "0.5" -serde_json = "1.0" +toml = "0.7" +serde_json = "1.0" \ No newline at end of file diff --git a/libs/scrap/Cargo.toml b/libs/scrap/Cargo.toml index 82cb88faf..99e15aeef 100644 --- a/libs/scrap/Cargo.toml +++ b/libs/scrap/Cargo.toml @@ -42,7 +42,7 @@ quest = "0.3" [build-dependencies] target_build_utils = "0.3" -bindgen = "0.59" +bindgen = "0.64" [target.'cfg(target_os = "linux")'.dependencies] dbus = { version = "0.9", optional = true } diff --git a/libs/scrap/src/common/quartz.rs b/libs/scrap/src/common/quartz.rs index a02d55ebb..dc59edac1 100644 --- a/libs/scrap/src/common/quartz.rs +++ b/libs/scrap/src/common/quartz.rs @@ -83,7 +83,7 @@ impl crate::TraitCapturer for Capturer { } } -pub struct Frame<'a>(quartz::Frame, PhantomData<&'a [u8]>); +pub struct Frame<'a>(pub quartz::Frame, PhantomData<&'a [u8]>); impl<'a> ops::Deref for Frame<'a> { type Target = [u8]; diff --git a/src/client.rs b/src/client.rs index ab27c0185..9202a34ba 100644 --- a/src/client.rs +++ b/src/client.rs @@ -2233,7 +2233,7 @@ fn get_pk(pk: &[u8]) -> Option<[u8; 32]> { #[inline] fn get_rs_pk(str_base64: &str) -> Option { - if let Ok(pk) = base64::decode(str_base64) { + if let Ok(pk) = crate::decode64(str_base64) { get_pk(&pk).map(|x| sign::PublicKey(x)) } else { None diff --git a/src/common.rs b/src/common.rs index 28d8dddc4..0b475805d 100644 --- a/src/common.rs +++ b/src/common.rs @@ -787,3 +787,15 @@ pub fn handle_url_scheme(url: String) { let _ = crate::run_me(vec![url]); } } + +#[inline] +pub fn encode64>(input: T) -> String { + #[allow(deprecated)] + base64::encode(input) +} + +#[inline] +pub fn decode64>(input: T) -> Result, base64::DecodeError> { + #[allow(deprecated)] + base64::decode(input) +} diff --git a/src/license.rs b/src/license.rs index f8f5d27d5..8875d2b64 100644 --- a/src/license.rs +++ b/src/license.rs @@ -1,3 +1,4 @@ +use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _}; use hbb_common::{bail, sodiumoxide::crypto::sign, ResultType}; use serde_derive::{Deserialize, Serialize}; @@ -18,7 +19,7 @@ fn get_license_from_string_(s: &str) -> ResultType { 12, 46, 129, 83, 17, 84, 193, 119, 197, 130, 103, ]; let pk = sign::PublicKey(*PK); - let data = base64::decode_config(tmp, base64::URL_SAFE_NO_PAD)?; + let data = URL_SAFE_NO_PAD.decode(tmp)?; if let Ok(lic) = serde_json::from_slice::(&data) { return Ok(lic); } diff --git a/src/naming.rs b/src/naming.rs index 38b514f86..53e675d92 100644 --- a/src/naming.rs +++ b/src/naming.rs @@ -1,10 +1,11 @@ mod license; +use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _}; use hbb_common::ResultType; use license::*; fn gen_name(lic: &License) -> ResultType { let tmp = serde_json::to_vec::(lic)?; - let tmp = base64::encode_config(tmp, base64::URL_SAFE_NO_PAD); + let tmp = URL_SAFE_NO_PAD.encode(&tmp); let tmp: String = tmp.chars().rev().collect(); Ok(tmp) } diff --git a/src/platform/macos.mm b/src/platform/macos.mm index 3c90981c4..a252a9a8f 100644 --- a/src/platform/macos.mm +++ b/src/platform/macos.mm @@ -8,6 +8,9 @@ // https://github.com/codebytere/node-mac-permissions/blob/main/permissions.mm extern "C" bool InputMonitoringAuthStatus(bool prompt) { + #ifdef NO_InputMonitoringAuthStatus + return true; + #else if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_15) { IOHIDAccessType theType = IOHIDCheckAccess(kIOHIDRequestTypeListenEvent); NSLog(@"IOHIDCheckAccess = %d, kIOHIDAccessTypeGranted = %d", theType, kIOHIDAccessTypeGranted); @@ -36,6 +39,7 @@ extern "C" bool InputMonitoringAuthStatus(bool prompt) { return true; } return false; + #endif } extern "C" bool MacCheckAdminAuthorization() { diff --git a/src/server/connection.rs b/src/server/connection.rs index 898939b62..3d419ef08 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -735,7 +735,7 @@ impl Connection { let url = self.server_audit_conn.clone(); let mut v = v; v["id"] = json!(Config::get_id()); - v["uuid"] = json!(base64::encode(hbb_common::get_uuid())); + v["uuid"] = json!(crate::encode64(hbb_common::get_uuid())); v["conn_id"] = json!(self.inner.id); tokio::spawn(async move { allow_err!(Self::post_audit_async(url, v).await); @@ -765,7 +765,7 @@ impl Connection { info["files"] = json!(files); let v = json!({ "id":json!(Config::get_id()), - "uuid":json!(base64::encode(hbb_common::get_uuid())), + "uuid":json!(crate::encode64(hbb_common::get_uuid())), "peer_id":json!(self.lr.my_id), "type": r#type as i8, "path":path, @@ -788,7 +788,7 @@ impl Connection { } let mut v = Value::default(); v["id"] = json!(Config::get_id()); - v["uuid"] = json!(base64::encode(hbb_common::get_uuid())); + v["uuid"] = json!(crate::encode64(hbb_common::get_uuid())); v["typ"] = json!(typ as i8); v["from_remote"] = json!(from_remote); v["info"] = serde_json::Value::String(info.to_string()); diff --git a/src/ui_interface.rs b/src/ui_interface.rs index ec570b42c..fd97f41b0 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -605,7 +605,7 @@ pub fn remove_discovered(id: String) { #[inline] pub fn get_uuid() -> String { - base64::encode(hbb_common::get_uuid()) + crate::encode64(hbb_common::get_uuid()) } #[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))] @@ -876,7 +876,7 @@ pub async fn change_id_shared(id: String, old_id: String) -> &'static str { #[cfg(not(any(target_os = "android", target_os = "ios")))] let uuid = machine_uid::get().unwrap_or("".to_owned()); #[cfg(any(target_os = "android", target_os = "ios"))] - let uuid = base64::encode(hbb_common::get_uuid()); + let uuid = crate::encode64(hbb_common::get_uuid()); if uuid.is_empty() { log::error!("Failed to change id, uuid is_empty"); From f5d0275bf365757256abf725f63f3ccb4f425553 Mon Sep 17 00:00:00 2001 From: csf Date: Thu, 9 Mar 2023 19:55:38 +0900 Subject: [PATCH 289/382] selectedItems use obs state --- .../lib/desktop/pages/file_manager_page.dart | 182 +++++++++--------- flutter/lib/models/file_model.dart | 26 +-- 2 files changed, 101 insertions(+), 107 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index da88405a9..44def46c2 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -15,7 +15,6 @@ import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; import 'package:flutter_hbb/models/file_model.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; -import 'package:provider/provider.dart'; import 'package:wakelock/wakelock.dart'; import '../../consts.dart'; @@ -701,87 +700,93 @@ class _FileManagerViewState extends State { color: Theme.of(context).cardColor, hoverColor: Theme.of(context).hoverColor, ), - MenuButton( - onPressed: selectedItems.valid() - ? () async { - await (controller.removeAction(selectedItems)); - selectedItems.clear(); - } - : null, - child: SvgPicture.asset( - "assets/trash.svg", - color: Theme.of(context).tabBarTheme.labelColor, - ), - color: Theme.of(context).cardColor, - hoverColor: Theme.of(context).hoverColor, - ), + Obx(() => MenuButton( + onPressed: SelectedItems.valid(selectedItems.items) + ? () async { + await (controller + .removeAction(selectedItems)); + selectedItems.clear(); + } + : null, + child: SvgPicture.asset( + "assets/trash.svg", + color: Theme.of(context).tabBarTheme.labelColor, + ), + color: Theme.of(context).cardColor, + hoverColor: Theme.of(context).hoverColor, + )), menu(isLocal: isLocal), ], ), ), - ElevatedButton.icon( - style: ButtonStyle( - padding: MaterialStateProperty.all(isLocal - ? EdgeInsets.only(left: 10) - : EdgeInsets.only(right: 10)), - backgroundColor: MaterialStateProperty.all( - selectedItems.length == 0 - ? MyTheme.accent80 - : MyTheme.accent, - ), - ), - onPressed: selectedItems.valid() - ? () { - final otherSideData = - controller.getOtherSideDirectoryData(); - controller.sendFiles(selectedItems, otherSideData); - selectedItems.clear(); - } - : null, - icon: isLocal - ? Text( - translate('Send'), - textAlign: TextAlign.right, - style: TextStyle( - color: selectedItems.length == 0 - ? Theme.of(context).brightness == Brightness.light - ? MyTheme.grayBg - : MyTheme.darkGray - : Colors.white, - ), - ) - : RotatedBox( - quarterTurns: 2, - child: SvgPicture.asset( - "assets/arrow.svg", - color: selectedItems.length == 0 - ? Theme.of(context).brightness == Brightness.light - ? MyTheme.grayBg - : MyTheme.darkGray - : Colors.white, - alignment: Alignment.bottomRight, - ), + Obx(() => ElevatedButton.icon( + style: ButtonStyle( + padding: MaterialStateProperty.all( + isLocal + ? EdgeInsets.only(left: 10) + : EdgeInsets.only(right: 10)), + backgroundColor: MaterialStateProperty.all( + selectedItems.items.isEmpty + ? MyTheme.accent80 + : MyTheme.accent, ), - label: isLocal - ? SvgPicture.asset( - "assets/arrow.svg", - color: selectedItems.length == 0 - ? Theme.of(context).brightness == Brightness.light - ? MyTheme.grayBg - : MyTheme.darkGray - : Colors.white, - ) - : Text( - translate('Receive'), - style: TextStyle( - color: selectedItems.length == 0 - ? Theme.of(context).brightness == Brightness.light - ? MyTheme.grayBg - : MyTheme.darkGray - : Colors.white, - ), - ), - ), + ), + onPressed: SelectedItems.valid(selectedItems.items) + ? () { + final otherSideData = + controller.getOtherSideDirectoryData(); + controller.sendFiles(selectedItems, otherSideData); + selectedItems.clear(); + } + : null, + icon: isLocal + ? Text( + translate('Send'), + textAlign: TextAlign.right, + style: TextStyle( + color: selectedItems.items.isEmpty + ? Theme.of(context).brightness == + Brightness.light + ? MyTheme.grayBg + : MyTheme.darkGray + : Colors.white, + ), + ) + : RotatedBox( + quarterTurns: 2, + child: SvgPicture.asset( + "assets/arrow.svg", + color: selectedItems.items.isEmpty + ? Theme.of(context).brightness == + Brightness.light + ? MyTheme.grayBg + : MyTheme.darkGray + : Colors.white, + alignment: Alignment.bottomRight, + ), + ), + label: isLocal + ? SvgPicture.asset( + "assets/arrow.svg", + color: selectedItems.items.isEmpty + ? Theme.of(context).brightness == + Brightness.light + ? MyTheme.grayBg + : MyTheme.darkGray + : Colors.white, + ) + : Text( + translate('Receive'), + style: TextStyle( + color: selectedItems.items.isEmpty + ? Theme.of(context).brightness == + Brightness.light + ? MyTheme.grayBg + : MyTheme.darkGray + : Colors.white, + ), + ), + )), ], ).marginOnly(top: 8.0) ], @@ -814,7 +819,7 @@ class _FileManagerViewState extends State { MenuEntryButton( childBuilder: (style) => Text(translate("Unselect All"), style: style), - proc: () => setState(() => selectedItems.clear()), + proc: () => selectedItems.clear(), padding: kDesktopMenuPadding, dismissOnClicked: true) ]; @@ -864,7 +869,7 @@ class _FileManagerViewState extends State { onNext: (buffer) { debugPrint("searching next for $buffer"); assert(buffer.length == 1); - assert(selectedItems.length <= 1); + assert(selectedItems.items.length <= 1); var skipCount = 0; if (selectedItems.items.isNotEmpty) { final index = entries.indexOf(selectedItems.items.first); @@ -883,7 +888,7 @@ class _FileManagerViewState extends State { (element) => element.name.toLowerCase().startsWith(buffer)); } if (searchResult.isEmpty) { - setState(() => selectedItems.clear()); + selectedItems.clear(); return; } _jumpToEntry(isLocal, searchResult.first, scrollController, @@ -896,7 +901,7 @@ class _FileManagerViewState extends State { .where((element) => element.name.toLowerCase().startsWith(buffer)); selectedEntries.clear(); if (searchResult.isEmpty) { - setState(() => selectedItems.clear()); + selectedItems.clear(); return; } _jumpToEntry(isLocal, searchResult.first, scrollController, @@ -915,12 +920,11 @@ class _FileManagerViewState extends State { final lastModifiedStr = entry.isDrive ? " " : "${entry.lastModified().toString().replaceAll(".000", "")} "; - final isSelected = selectedItems.contains(entry); return Padding( padding: EdgeInsets.symmetric(vertical: 1), - child: Container( + child: Obx(() => Container( decoration: BoxDecoration( - color: isSelected + color: selectedItems.items.contains(entry) ? Theme.of(context).hoverColor : Theme.of(context).cardColor, borderRadius: BorderRadius.all( @@ -1025,7 +1029,7 @@ class _FileManagerViewState extends State { ), ), ], - )), + ))), ); }).toList(growable: false); @@ -1077,10 +1081,8 @@ class _FileManagerViewState extends State { entries.indexOf(searchResult.first) * rowHeight), scrollController.position.maxScrollExtent); scrollController.jumpTo(offset); - setState(() { - selectedEntries.add(searchResult.first); - debugPrint("focused on ${searchResult.first.name}"); - }); + selectedEntries.add(searchResult.first); + debugPrint("focused on ${searchResult.first.name}"); } void _onSelectedChanged(SelectedItems selectedItems, List entries, @@ -1090,7 +1092,7 @@ class _FileManagerViewState extends State { final isShiftDown = RawKeyboard.instance.keysPressed.contains(LogicalKeyboardKey.shiftLeft); if (isCtrlDown) { - if (selectedItems.contains(entry)) { + if (selectedItems.items.contains(entry)) { selectedItems.remove(entry); } else { selectedItems.add(entry); diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index 30a897a56..4cfe19135 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -1052,40 +1052,32 @@ class DirectoryOptions { class SelectedItems { final bool isLocal; - final List _items = []; - - List get items => _items; - - int get length => _items.length; + final items = RxList.empty(growable: true); SelectedItems({required this.isLocal}); void add(Entry e) { if (e.isDrive) return; - if (!_items.contains(e)) { - _items.add(e); + if (!items.contains(e)) { + items.add(e); } } - bool contains(Entry e) { - return _items.contains(e); - } - void remove(Entry e) { - _items.remove(e); + items.remove(e); } void clear() { - _items.clear(); + items.clear(); } void selectAll(List entries) { - _items.clear(); - _items.addAll(entries); + items.clear(); + items.addAll(entries); } - bool valid() { - if (length > 0) { + static bool valid(RxList items) { + if (items.isNotEmpty) { // exclude DirDrive type return items.any((item) => !item.isDrive); } From d19d4aacdbba337561e920f5fd6fdab8da909446 Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 9 Mar 2023 19:38:47 +0800 Subject: [PATCH 290/382] avoid invalid texture width and height Signed-off-by: fufesou --- flutter/lib/models/model.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 802a18a52..a8ed56bc5 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -371,7 +371,11 @@ class FfiModel with ChangeNotifier { _updateSessionWidthHeight(String id) { parent.target?.canvasModel.updateViewStyle(); - bind.sessionSetSize(id: id, width: display.width, height: display.height); + if (display.width < 0 || display.height < 0) { + debugPrintStack(label: 'invalid display size (${display.width},${display.height})'); + } else { + bind.sessionSetSize(id: id, width: display.width, height: display.height); + } } /// Handle the peer info event based on [evt]. From 00b1439f32a0fcb9d4488ae0aad1619e54534bde Mon Sep 17 00:00:00 2001 From: csf Date: Thu, 9 Mar 2023 21:09:17 +0900 Subject: [PATCH 291/382] refactor mobile file manager page --- .../lib/mobile/pages/file_manager_page.dart | 881 ++++++++++-------- 1 file changed, 481 insertions(+), 400 deletions(-) diff --git a/flutter/lib/mobile/pages/file_manager_page.dart b/flutter/lib/mobile/pages/file_manager_page.dart index 26e024ca4..aa8794227 100644 --- a/flutter/lib/mobile/pages/file_manager_page.dart +++ b/flutter/lib/mobile/pages/file_manager_page.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_breadcrumb/flutter_breadcrumb.dart'; import 'package:flutter_hbb/models/file_model.dart'; -import 'package:provider/provider.dart'; +import 'package:get/get.dart'; import 'package:toggle_switch/toggle_switch.dart'; import 'package:wakelock/wakelock.dart'; @@ -20,8 +20,13 @@ class FileManagerPage extends StatefulWidget { class _FileManagerPageState extends State { final model = gFFI.fileModel; - final _selectedItems = SelectedItems(); - final _breadCrumbScroller = ScrollController(); + var showLocal = true; + var isSelecting = false.obs; + + FileController get currentFileController => + showLocal ? model.localController : model.remoteController; + FileDirectory get currentDir => currentFileController.directory.value; + DirectoryOptions get currentOptions => currentFileController.options.value; @override void initState() { @@ -32,7 +37,6 @@ class _FileManagerPageState extends State { .showLoading(translate('Connecting...'), onCancel: closeConnection); }); gFFI.ffiModel.updateEventListener(widget.id); - model.onDirChanged = (_) => breadCrumbScrollToEnd(); Wakelock.enable(); } @@ -47,288 +51,447 @@ class _FileManagerPageState extends State { } @override - Widget build(BuildContext context) => ChangeNotifierProvider.value( - value: model, - child: Consumer(builder: (_context, _model, _child) { - return WillPopScope( - onWillPop: () async { - if (model.selectMode) { - model.toggleSelectMode(); - } else { - model.goBack(); + Widget build(BuildContext context) => WillPopScope( + onWillPop: () async { + if (isSelecting.value) { + isSelecting.value = false; + } else { + currentFileController.goBack(); + } + return false; + }, + child: Scaffold( + // backgroundColor: MyTheme.grayBg, + appBar: AppBar( + leading: Row(children: [ + IconButton( + icon: Icon(Icons.close), + onPressed: () => clientClose(widget.id, gFFI.dialogManager)), + ]), + centerTitle: true, + title: ToggleSwitch( + initialLabelIndex: showLocal ? 0 : 1, + activeBgColor: [MyTheme.idColor], + inactiveBgColor: Theme.of(context).brightness == Brightness.light + ? MyTheme.grayBg + : null, + inactiveFgColor: Theme.of(context).brightness == Brightness.light + ? Colors.black54 + : null, + totalSwitches: 2, + minWidth: 100, + fontSize: 15, + iconSize: 18, + labels: [translate("Local"), translate("Remote")], + icons: [Icons.phone_android_sharp, Icons.screen_share], + onToggle: (index) { + final current = showLocal ? 0 : 1; + if (index != current) { + setState(() => showLocal = !showLocal); } - return false; }, - child: Scaffold( - // backgroundColor: MyTheme.grayBg, - appBar: AppBar( - leading: Row(children: [ - IconButton( - icon: Icon(Icons.close), - onPressed: () => - clientClose(widget.id, gFFI.dialogManager)), - ]), - centerTitle: true, - title: ToggleSwitch( - initialLabelIndex: model.isLocal ? 0 : 1, - activeBgColor: [MyTheme.idColor], - inactiveBgColor: - Theme.of(context).brightness == Brightness.light - ? MyTheme.grayBg - : null, - inactiveFgColor: - Theme.of(context).brightness == Brightness.light - ? Colors.black54 - : null, - totalSwitches: 2, - minWidth: 100, - fontSize: 15, - iconSize: 18, - labels: [translate("Local"), translate("Remote")], - icons: [Icons.phone_android_sharp, Icons.screen_share], - onToggle: (index) { - final current = model.isLocal ? 0 : 1; - if (index != current) { - model.togglePage(); - } - }, - ), - actions: [ - PopupMenuButton( - icon: Icon(Icons.more_vert), - itemBuilder: (context) { - return [ - PopupMenuItem( - child: Row( - children: [ - Icon(Icons.refresh, - color: Theme.of(context).iconTheme.color), - SizedBox(width: 5), - Text(translate("Refresh File")) - ], - ), - value: "refresh", - ), - PopupMenuItem( - enabled: model.currentDir.path != "/", - child: Row( - children: [ - Icon(Icons.check, - color: Theme.of(context).iconTheme.color), - SizedBox(width: 5), - Text(translate("Multi Select")) - ], - ), - value: "select", - ), - PopupMenuItem( - enabled: model.currentDir.path != "/", - child: Row( - children: [ - Icon(Icons.folder_outlined, - color: Theme.of(context).iconTheme.color), - SizedBox(width: 5), - Text(translate("Create Folder")) - ], - ), - value: "folder", - ), - PopupMenuItem( - enabled: model.currentDir.path != "/", - child: Row( - children: [ - Icon( - model.getCurrentShowHidden() - ? Icons.check_box_outlined - : Icons.check_box_outline_blank, - color: Theme.of(context).iconTheme.color), - SizedBox(width: 5), - Text(translate("Show Hidden Files")) - ], - ), - value: "hidden", - ) - ]; - }, - onSelected: (v) { - if (v == "refresh") { - model.refresh(); - } else if (v == "select") { - _selectedItems.clear(); - model.toggleSelectMode(); - } else if (v == "folder") { - final name = TextEditingController(); - gFFI.dialogManager - .show((setState, close) => CustomAlertDialog( - title: Text(translate("Create Folder")), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - TextFormField( - decoration: InputDecoration( - labelText: translate( - "Please enter the folder name"), - ), - controller: name, - ), - ], + ), + actions: [ + PopupMenuButton( + icon: Icon(Icons.more_vert), + itemBuilder: (context) { + return [ + PopupMenuItem( + child: Row( + children: [ + Icon(Icons.refresh, + color: Theme.of(context).iconTheme.color), + SizedBox(width: 5), + Text(translate("Refresh File")) + ], + ), + value: "refresh", + ), + PopupMenuItem( + enabled: currentDir.path != "/", + child: Row( + children: [ + Icon(Icons.check, + color: Theme.of(context).iconTheme.color), + SizedBox(width: 5), + Text(translate("Multi Select")) + ], + ), + value: "select", + ), + PopupMenuItem( + enabled: currentDir.path != "/", + child: Row( + children: [ + Icon(Icons.folder_outlined, + color: Theme.of(context).iconTheme.color), + SizedBox(width: 5), + Text(translate("Create Folder")) + ], + ), + value: "folder", + ), + PopupMenuItem( + enabled: currentDir.path != "/", + child: Row( + children: [ + Icon( + currentOptions.showHidden + ? Icons.check_box_outlined + : Icons.check_box_outline_blank, + color: Theme.of(context).iconTheme.color), + SizedBox(width: 5), + Text(translate("Show Hidden Files")) + ], + ), + value: "hidden", + ) + ]; + }, + onSelected: (v) { + if (v == "refresh") { + currentFileController.refresh(); + } else if (v == "select") { + model.localController.selectedItems.clear(); + model.remoteController.selectedItems.clear(); + isSelecting.toggle(); + } else if (v == "folder") { + final name = TextEditingController(); + gFFI.dialogManager + .show((setState, close) => CustomAlertDialog( + title: Text(translate("Create Folder")), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextFormField( + decoration: InputDecoration( + labelText: translate( + "Please enter the folder name"), ), - actions: [ - dialogButton("Cancel", - onPressed: () => close(false), - isOutline: true), - dialogButton("OK", onPressed: () { - if (name.value.text.isNotEmpty) { - model.createDir(PathUtil.join( - model.currentDir.path, - name.value.text, - model.getCurrentIsWindows())); - close(); - } - }) - ])); - } else if (v == "hidden") { - model.toggleShowHidden(); - } - }), - ], - ), - body: body(), - bottomSheet: bottomSheet(), - )); - })); + controller: name, + ), + ], + ), + actions: [ + dialogButton("Cancel", + onPressed: () => close(false), + isOutline: true), + dialogButton("OK", onPressed: () { + if (name.value.text.isNotEmpty) { + currentFileController.createDir( + PathUtil.join( + currentDir.path, + name.value.text, + currentOptions.isWindows)); + close(); + } + }) + ])); + } else if (v == "hidden") { + currentFileController.toggleShowHidden(); + } + }), + ], + ), + body: showLocal + ? FileManagerView( + controller: model.localController, + isSelecting: isSelecting, + showCheckBox: showCheckBox()) + : FileManagerView( + controller: model.remoteController, + isSelecting: isSelecting, + showCheckBox: showCheckBox()), + bottomSheet: bottomSheet(), + )); bool showCheckBox() { - if (!model.selectMode) { - return false; + final selectedItems = getActiveSelectedItems(); + + if (selectedItems != null) { + return selectedItems.isLocal == showLocal; } - return !_selectedItems.isOtherPage(model.isLocal); + return false; } - Widget body() { - final isLocal = model.isLocal; - final fd = model.currentDir; - final entries = fd.entries; + Widget? bottomSheet() { + return Obx(() { + final selectedItems = getActiveSelectedItems(); + + final localLabel = selectedItems?.isLocal == null + ? "" + : " [${selectedItems!.isLocal ? translate("Local") : translate("Remote")}]"; + + if (isSelecting.value) { + final selectedItemsLen = + "${selectedItems?.items.length ?? 0} ${translate("items")}"; + if (selectedItems == null || + selectedItems.items.isEmpty || + showCheckBox()) { + return BottomSheetBody( + leading: Icon(Icons.check), + title: translate("Selected"), + text: selectedItemsLen + localLabel, + onCanceled: () => isSelecting.toggle(), + actions: [ + IconButton( + icon: Icon(Icons.compare_arrows), + onPressed: () => setState(() => showLocal = !showLocal), + ), + IconButton( + icon: Icon(Icons.delete_forever), + onPressed: selectedItems != null + ? () { + if (selectedItems.items.isNotEmpty) { + currentFileController.removeAction(selectedItems); + } + } + : null, + ) + ]); + } else { + return BottomSheetBody( + leading: Icon(Icons.input), + title: translate("Paste here?"), + text: selectedItemsLen + localLabel, + onCanceled: () => isSelecting.toggle(), + actions: [ + IconButton( + icon: Icon(Icons.compare_arrows), + onPressed: () => setState(() => showLocal = !showLocal), + ), + IconButton( + icon: Icon(Icons.paste), + onPressed: () { + isSelecting.toggle(); + final otherSide = showLocal + ? model.remoteController + : model.localController; + final otherSideData = DirectoryData( + otherSide.directory.value, otherSide.options.value); + currentFileController.sendFiles( + selectedItems, otherSideData); + }, + ) + ]); + } + } + + final jobTable = model.jobController.jobTable; + + if (jobTable.isEmpty) { + return Offstage(); + } + + switch (jobTable.last.state) { + case JobState.inProgress: + return Obx(() => BottomSheetBody( + leading: CircularProgressIndicator(), + title: translate("Waiting"), + text: + "${translate("Speed")}: ${readableFileSize(jobTable.last.speed)}/s", + onCanceled: () => + model.jobController.cancelJob(jobTable.last.id), + )); + case JobState.done: + return Obx(() => BottomSheetBody( + leading: Icon(Icons.check), + title: "${translate("Successful")}!", + text: jobTable.last.display(), + onCanceled: () => jobTable.clear(), + )); + case JobState.error: + return Obx(() => BottomSheetBody( + leading: Icon(Icons.error), + title: "${translate("Error")}!", + text: "", + onCanceled: () => jobTable.clear(), + )); + case JobState.none: + break; + case JobState.paused: + // TODO: Handle this case. + break; + } + return Offstage(); + }); + } + + SelectedItems? getActiveSelectedItems() { + final localSelectedItems = model.localController.selectedItems; + final remoteSelectedItems = model.remoteController.selectedItems; + + if (localSelectedItems.items.isNotEmpty && + remoteSelectedItems.items.isNotEmpty) { + // assert unreachable + debugPrint("Wrong SelectedItems state, reset"); + localSelectedItems.clear(); + remoteSelectedItems.clear(); + } + + if (localSelectedItems.items.isEmpty && remoteSelectedItems.items.isEmpty) { + return null; + } + + if (localSelectedItems.items.length > remoteSelectedItems.items.length) { + return localSelectedItems; + } else { + return remoteSelectedItems; + } + } +} + +class FileManagerView extends StatefulWidget { + final FileController controller; + final RxBool isSelecting; + final bool showCheckBox; + + FileManagerView( + {required this.controller, + required this.isSelecting, + required this.showCheckBox}); + + @override + State createState() => _FileManagerViewState(); +} + +class _FileManagerViewState extends State { + final _listScrollController = ScrollController(); + final _breadCrumbScroller = ScrollController(); + + bool get isLocal => widget.controller.isLocal; + FileController get controller => widget.controller; + SelectedItems get _selectedItems => widget.controller.selectedItems; + + @override + void initState() { + super.initState(); + controller.directory.listen((e) => breadCrumbScrollToEnd()); + } + + @override + Widget build(BuildContext context) { return Column(children: [ headTools(), - Expanded( - child: ListView.builder( - controller: ScrollController(), - itemCount: entries.length + 1, - itemBuilder: (context, index) { - if (index >= entries.length) { - return listTail(); - } - var selected = false; - if (model.selectMode) { - selected = _selectedItems.contains(entries[index]); - } + Expanded(child: Obx(() { + final entries = controller.directory.value.entries; + return ListView.builder( + controller: _listScrollController, + itemCount: entries.length + 1, + itemBuilder: (context, index) { + if (index >= entries.length) { + return listTail(); + } + var selected = false; + if (widget.isSelecting.value) { + selected = _selectedItems.items.contains(entries[index]); + } - final sizeStr = entries[index].isFile - ? readableFileSize(entries[index].size.toDouble()) - : ""; - return Card( - child: ListTile( - leading: entries[index].isDrive - ? Padding( - padding: EdgeInsets.symmetric(vertical: 8), - child: Image( - image: iconHardDrive, - fit: BoxFit.scaleDown, - color: Theme.of(context) - .iconTheme - .color - ?.withOpacity(0.7))) - : Icon( - entries[index].isFile - ? Icons.feed_outlined - : Icons.folder, - size: 40), - title: Text(entries[index].name), - selected: selected, - subtitle: entries[index].isDrive - ? null - : Text( - "${entries[index].lastModified().toString().replaceAll(".000", "")} $sizeStr", - style: TextStyle(fontSize: 12, color: MyTheme.darkGray), - ), - trailing: entries[index].isDrive - ? null - : showCheckBox() - ? Checkbox( - value: selected, - onChanged: (v) { - if (v == null) return; - if (v && !selected) { - _selectedItems.add(isLocal, entries[index]); - } else if (!v && selected) { - _selectedItems.remove(entries[index]); - } - setState(() {}); - }) - : PopupMenuButton( - icon: Icon(Icons.more_vert), - itemBuilder: (context) { - return [ - PopupMenuItem( - child: Text(translate("Delete")), - value: "delete", - ), - PopupMenuItem( - child: Text(translate("Multi Select")), - value: "multi_select", - ), - PopupMenuItem( - child: Text(translate("Properties")), - value: "properties", - enabled: false, - ) - ]; - }, - onSelected: (v) { - if (v == "delete") { - final items = SelectedItems(); - items.add(isLocal, entries[index]); - model.removeAction(items); - } else if (v == "multi_select") { - _selectedItems.clear(); - model.toggleSelectMode(); - } - }), - onTap: () { - if (model.selectMode && !_selectedItems.isOtherPage(isLocal)) { - if (selected) { - _selectedItems.remove(entries[index]); - } else { - _selectedItems.add(isLocal, entries[index]); + final sizeStr = entries[index].isFile + ? readableFileSize(entries[index].size.toDouble()) + : ""; + return Card( + child: ListTile( + leading: entries[index].isDrive + ? Padding( + padding: EdgeInsets.symmetric(vertical: 8), + child: Image( + image: iconHardDrive, + fit: BoxFit.scaleDown, + color: Theme.of(context) + .iconTheme + .color + ?.withOpacity(0.7))) + : Icon( + entries[index].isFile + ? Icons.feed_outlined + : Icons.folder, + size: 40), + title: Text(entries[index].name), + selected: selected, + subtitle: entries[index].isDrive + ? null + : Text( + "${entries[index].lastModified().toString().replaceAll(".000", "")} $sizeStr", + style: TextStyle(fontSize: 12, color: MyTheme.darkGray), + ), + trailing: entries[index].isDrive + ? null + : widget.isSelecting.value && widget.showCheckBox + ? Checkbox( + value: selected, + onChanged: (v) { + if (v == null) return; + if (v && !selected) { + _selectedItems.add(entries[index]); + } else if (!v && selected) { + _selectedItems.remove(entries[index]); + } + setState(() {}); + }) + : PopupMenuButton( + icon: Icon(Icons.more_vert), + itemBuilder: (context) { + return [ + PopupMenuItem( + child: Text(translate("Delete")), + value: "delete", + ), + PopupMenuItem( + child: Text(translate("Multi Select")), + value: "multi_select", + ), + PopupMenuItem( + child: Text(translate("Properties")), + value: "properties", + enabled: false, + ) + ]; + }, + onSelected: (v) { + if (v == "delete") { + final items = SelectedItems(isLocal: isLocal); + items.add(entries[index]); + controller.removeAction(items); + } else if (v == "multi_select") { + _selectedItems.clear(); + widget.isSelecting.toggle(); + } + }), + onTap: () { + if (widget.isSelecting.value && widget.showCheckBox) { + if (selected) { + _selectedItems.remove(entries[index]); + } else { + _selectedItems.add(entries[index]); + } + return; } - setState(() {}); - return; - } - if (entries[index].isDirectory || entries[index].isDrive) { - model.openDirectory(entries[index].path); - } else { - // Perform file-related tasks. - } - }, - onLongPress: entries[index].isDrive - ? null - : () { - _selectedItems.clear(); - model.toggleSelectMode(); - if (model.selectMode) { - _selectedItems.add(isLocal, entries[index]); - } - setState(() {}); - }, - ), - ); - }, - )) + if (entries[index].isDirectory || entries[index].isDrive) { + controller.openDirectory(entries[index].path); + } else { + // Perform file-related tasks. + } + }, + onLongPress: entries[index].isDrive + ? null + : () { + _selectedItems.clear(); + widget.isSelecting.toggle(); + if (widget.isSelecting.value) { + _selectedItems.add(entries[index]); + } + setState(() {}); + }, + ), + ); + }, + ); + })) ]); } - breadCrumbScrollToEnd() { + void breadCrumbScrollToEnd() { Future.delayed(Duration(milliseconds: 200), () { if (_breadCrumbScroller.hasClients) { _breadCrumbScroller.animateTo( @@ -342,35 +505,39 @@ class _FileManagerPageState extends State { Widget headTools() => Container( child: Row( children: [ - Expanded( - child: BreadCrumb( - items: getPathBreadCrumbItems(() => model.goHome(), (list) { - var path = ""; - if (model.currentHome.startsWith(list[0])) { - // absolute path - for (var item in list) { - path = PathUtil.join(path, item, model.getCurrentIsWindows()); + Expanded(child: Obx(() { + final home = controller.options.value.home; + final isWindows = controller.options.value.isWindows; + return BreadCrumb( + items: getPathBreadCrumbItems(controller.shortPath, isWindows, + () => controller.goToHomeDirectory(), (list) { + var path = ""; + if (home.startsWith(list[0])) { + // absolute path + for (var item in list) { + path = PathUtil.join(path, item, isWindows); + } + } else { + path += home; + for (var item in list) { + path = PathUtil.join(path, item, isWindows); + } } - } else { - path += model.currentHome; - for (var item in list) { - path = PathUtil.join(path, item, model.getCurrentIsWindows()); - } - } - model.openDirectory(path); - }), - divider: Icon(Icons.chevron_right), - overflow: ScrollableOverflow(controller: _breadCrumbScroller), - )), + controller.openDirectory(path); + }), + divider: Icon(Icons.chevron_right), + overflow: ScrollableOverflow(controller: _breadCrumbScroller), + ); + })), Row( children: [ IconButton( icon: Icon(Icons.arrow_back), - onPressed: model.goBack, + onPressed: controller.goBack, ), IconButton( icon: Icon(Icons.arrow_upward), - onPressed: model.goToParentDirectory, + onPressed: controller.goToParentDirectory, ), PopupMenuButton( icon: Icon(Icons.sort), @@ -382,123 +549,37 @@ class _FileManagerPageState extends State { )) .toList(); }, - onSelected: model.changeSortStyle), + onSelected: controller.changeSortStyle), ], ) ], )); - Widget listTail() { - return Container( - height: 100, - child: Column( - children: [ - Padding( - padding: EdgeInsets.fromLTRB(30, 5, 30, 0), - child: Text( - model.currentDir.path, - style: TextStyle(color: MyTheme.darkGray), - ), - ), - Padding( - padding: EdgeInsets.all(2), - child: Text( - "${translate("Total")}: ${model.currentDir.entries.length} ${translate("items")}", - style: TextStyle(color: MyTheme.darkGray), - ), - ) - ], - ), - ); - } - - Widget? bottomSheet() { - final state = model.jobState; - final isOtherPage = _selectedItems.isOtherPage(model.isLocal); - final selectedItemsLen = "${_selectedItems.length} ${translate("items")}"; - final local = _selectedItems.isLocal == null - ? "" - : " [${_selectedItems.isLocal! ? translate("Local") : translate("Remote")}]"; - - if (model.selectMode) { - if (_selectedItems.length == 0 || !isOtherPage) { - return BottomSheetBody( - leading: Icon(Icons.check), - title: translate("Selected"), - text: selectedItemsLen + local, - onCanceled: () => model.toggleSelectMode(), - actions: [ - IconButton( - icon: Icon(Icons.compare_arrows), - onPressed: model.togglePage, + Widget listTail() => Obx(() => Container( + height: 100, + child: Column( + children: [ + Padding( + padding: EdgeInsets.fromLTRB(30, 5, 30, 0), + child: Text( + controller.directory.value.path, + style: TextStyle(color: MyTheme.darkGray), ), - IconButton( - icon: Icon(Icons.delete_forever), - onPressed: () { - if (_selectedItems.length > 0) { - model.removeAction(_selectedItems); - } - }, - ) - ]); - } else { - return BottomSheetBody( - leading: Icon(Icons.input), - title: translate("Paste here?"), - text: selectedItemsLen + local, - onCanceled: () => model.toggleSelectMode(), - actions: [ - IconButton( - icon: Icon(Icons.compare_arrows), - onPressed: model.togglePage, + ), + Padding( + padding: EdgeInsets.all(2), + child: Text( + "${translate("Total")}: ${controller.directory.value.entries.length} ${translate("items")}", + style: TextStyle(color: MyTheme.darkGray), ), - IconButton( - icon: Icon(Icons.paste), - onPressed: () { - model.toggleSelectMode(); - model.sendFiles(_selectedItems); - }, - ) - ]); - } - } + ) + ], + ), + )); - switch (state) { - case JobState.inProgress: - return BottomSheetBody( - leading: CircularProgressIndicator(), - title: translate("Waiting"), - text: - "${translate("Speed")}: ${readableFileSize(model.jobProgress.speed)}/s", - onCanceled: () => model.cancelJob(model.jobProgress.id), - ); - case JobState.done: - return BottomSheetBody( - leading: Icon(Icons.check), - title: "${translate("Successful")}!", - text: model.jobProgress.display(), - onCanceled: () => model.jobReset(), - ); - case JobState.error: - return BottomSheetBody( - leading: Icon(Icons.error), - title: "${translate("Error")}!", - text: "", - onCanceled: () => model.jobReset(), - ); - case JobState.none: - break; - case JobState.paused: - // TODO: Handle this case. - break; - } - return null; - } - - List getPathBreadCrumbItems( + List getPathBreadCrumbItems(String shortPath, bool isWindows, void Function() onHome, void Function(List) onPressed) { - final path = model.currentShortPath; - final list = PathUtil.split(path, model.getCurrentIsWindows()); + final list = PathUtil.split(shortPath, isWindows); final breadCrumbList = [ BreadCrumbItem( content: IconButton( From 69d84984042116aef754653b9ccc69562a90324f Mon Sep 17 00:00:00 2001 From: csf Date: Thu, 9 Mar 2023 22:34:43 +0900 Subject: [PATCH 292/382] mobile new file SelectMode state --- .../lib/mobile/pages/file_manager_page.dart | 170 +++++++++++------- flutter/lib/models/file_model.dart | 2 +- 2 files changed, 108 insertions(+), 64 deletions(-) diff --git a/flutter/lib/mobile/pages/file_manager_page.dart b/flutter/lib/mobile/pages/file_manager_page.dart index aa8794227..c6ba42d31 100644 --- a/flutter/lib/mobile/pages/file_manager_page.dart +++ b/flutter/lib/mobile/pages/file_manager_page.dart @@ -18,10 +18,46 @@ class FileManagerPage extends StatefulWidget { State createState() => _FileManagerPageState(); } +enum SelectMode { local, remote, none } + +extension SelectModeEq on SelectMode { + bool eq(bool? currentIsLocal) { + if (currentIsLocal == null) { + return false; + } + if (currentIsLocal) { + return this == SelectMode.local; + } else { + return this == SelectMode.remote; + } + } +} + +extension SelectModeExt on Rx { + void toggle(bool currentIsLocal) { + switch (value) { + case SelectMode.local: + value = SelectMode.none; + break; + case SelectMode.remote: + value = SelectMode.none; + break; + case SelectMode.none: + if (currentIsLocal) { + value = SelectMode.local; + } else { + value = SelectMode.remote; + } + break; + } + } +} + class _FileManagerPageState extends State { final model = gFFI.fileModel; + final selectMode = SelectMode.none.obs; + var showLocal = true; - var isSelecting = false.obs; FileController get currentFileController => showLocal ? model.localController : model.remoteController; @@ -53,8 +89,9 @@ class _FileManagerPageState extends State { @override Widget build(BuildContext context) => WillPopScope( onWillPop: () async { - if (isSelecting.value) { - isSelecting.value = false; + if (selectMode.value != SelectMode.none) { + selectMode.value = SelectMode.none; + setState(() {}); } else { currentFileController.goBack(); } @@ -154,7 +191,8 @@ class _FileManagerPageState extends State { } else if (v == "select") { model.localController.selectedItems.clear(); model.remoteController.selectedItems.clear(); - isSelecting.toggle(); + selectMode.toggle(showLocal); + setState(() {}); } else if (v == "folder") { final name = TextEditingController(); gFFI.dialogManager @@ -196,43 +234,38 @@ class _FileManagerPageState extends State { body: showLocal ? FileManagerView( controller: model.localController, - isSelecting: isSelecting, - showCheckBox: showCheckBox()) + selectMode: selectMode, + ) : FileManagerView( controller: model.remoteController, - isSelecting: isSelecting, - showCheckBox: showCheckBox()), + selectMode: selectMode, + ), bottomSheet: bottomSheet(), )); - bool showCheckBox() { - final selectedItems = getActiveSelectedItems(); - - if (selectedItems != null) { - return selectedItems.isLocal == showLocal; - } - return false; - } - Widget? bottomSheet() { return Obx(() { final selectedItems = getActiveSelectedItems(); + final jobTable = model.jobController.jobTable; final localLabel = selectedItems?.isLocal == null ? "" : " [${selectedItems!.isLocal ? translate("Local") : translate("Remote")}]"; - - if (isSelecting.value) { + if (!(selectMode.value == SelectMode.none)) { final selectedItemsLen = "${selectedItems?.items.length ?? 0} ${translate("items")}"; if (selectedItems == null || selectedItems.items.isEmpty || - showCheckBox()) { + selectMode.value.eq(showLocal)) { return BottomSheetBody( leading: Icon(Icons.check), title: translate("Selected"), text: selectedItemsLen + localLabel, - onCanceled: () => isSelecting.toggle(), + onCanceled: () { + selectedItems?.items.clear(); + selectMode.value = SelectMode.none; + setState(() {}); + }, actions: [ IconButton( icon: Icon(Icons.compare_arrows), @@ -241,9 +274,12 @@ class _FileManagerPageState extends State { IconButton( icon: Icon(Icons.delete_forever), onPressed: selectedItems != null - ? () { + ? () async { if (selectedItems.items.isNotEmpty) { - currentFileController.removeAction(selectedItems); + await currentFileController + .removeAction(selectedItems); + selectedItems.items.clear(); + selectMode.value = SelectMode.none; } } : null, @@ -254,7 +290,11 @@ class _FileManagerPageState extends State { leading: Icon(Icons.input), title: translate("Paste here?"), text: selectedItemsLen + localLabel, - onCanceled: () => isSelecting.toggle(), + onCanceled: () { + selectedItems.items.clear(); + selectMode.value = SelectMode.none; + setState(() {}); + }, actions: [ IconButton( icon: Icon(Icons.compare_arrows), @@ -263,50 +303,51 @@ class _FileManagerPageState extends State { IconButton( icon: Icon(Icons.paste), onPressed: () { - isSelecting.toggle(); + selectMode.value = SelectMode.none; final otherSide = showLocal ? model.remoteController : model.localController; - final otherSideData = DirectoryData( - otherSide.directory.value, otherSide.options.value); - currentFileController.sendFiles( - selectedItems, otherSideData); + final thisSideData = + DirectoryData(currentDir, currentOptions); + otherSide.sendFiles(selectedItems, thisSideData); + selectedItems.items.clear(); + selectMode.value = SelectMode.none; }, ) ]); } } - final jobTable = model.jobController.jobTable; - if (jobTable.isEmpty) { return Offstage(); } switch (jobTable.last.state) { case JobState.inProgress: - return Obx(() => BottomSheetBody( - leading: CircularProgressIndicator(), - title: translate("Waiting"), - text: - "${translate("Speed")}: ${readableFileSize(jobTable.last.speed)}/s", - onCanceled: () => - model.jobController.cancelJob(jobTable.last.id), - )); + return BottomSheetBody( + leading: CircularProgressIndicator(), + title: translate("Waiting"), + text: + "${translate("Speed")}: ${readableFileSize(jobTable.last.speed)}/s", + onCanceled: () { + model.jobController.cancelJob(jobTable.last.id); + jobTable.clear(); + }, + ); case JobState.done: - return Obx(() => BottomSheetBody( - leading: Icon(Icons.check), - title: "${translate("Successful")}!", - text: jobTable.last.display(), - onCanceled: () => jobTable.clear(), - )); + return BottomSheetBody( + leading: Icon(Icons.check), + title: "${translate("Successful")}!", + text: jobTable.last.display(), + onCanceled: () => jobTable.clear(), + ); case JobState.error: - return Obx(() => BottomSheetBody( - leading: Icon(Icons.error), - title: "${translate("Error")}!", - text: "", - onCanceled: () => jobTable.clear(), - )); + return BottomSheetBody( + leading: Icon(Icons.error), + title: "${translate("Error")}!", + text: "", + onCanceled: () => jobTable.clear(), + ); case JobState.none: break; case JobState.paused: @@ -343,13 +384,9 @@ class _FileManagerPageState extends State { class FileManagerView extends StatefulWidget { final FileController controller; - final RxBool isSelecting; - final bool showCheckBox; + final Rx selectMode; - FileManagerView( - {required this.controller, - required this.isSelecting, - required this.showCheckBox}); + FileManagerView({required this.controller, required this.selectMode}); @override State createState() => _FileManagerViewState(); @@ -383,13 +420,18 @@ class _FileManagerViewState extends State { return listTail(); } var selected = false; - if (widget.isSelecting.value) { + if (widget.selectMode.value != SelectMode.none) { selected = _selectedItems.items.contains(entries[index]); } final sizeStr = entries[index].isFile ? readableFileSize(entries[index].size.toDouble()) : ""; + + final showCheckBox = () { + return widget.selectMode.value != SelectMode.none && + widget.selectMode.value.eq(controller.selectedItems.isLocal); + }(); return Card( child: ListTile( leading: entries[index].isDrive @@ -417,7 +459,7 @@ class _FileManagerViewState extends State { ), trailing: entries[index].isDrive ? null - : widget.isSelecting.value && widget.showCheckBox + : showCheckBox ? Checkbox( value: selected, onChanged: (v) { @@ -455,16 +497,18 @@ class _FileManagerViewState extends State { controller.removeAction(items); } else if (v == "multi_select") { _selectedItems.clear(); - widget.isSelecting.toggle(); + widget.selectMode.toggle(isLocal); + setState(() {}); } }), onTap: () { - if (widget.isSelecting.value && widget.showCheckBox) { + if (showCheckBox) { if (selected) { _selectedItems.remove(entries[index]); } else { _selectedItems.add(entries[index]); } + setState(() {}); return; } if (entries[index].isDirectory || entries[index].isDrive) { @@ -477,8 +521,8 @@ class _FileManagerViewState extends State { ? null : () { _selectedItems.clear(); - widget.isSelecting.toggle(); - if (widget.isSelecting.value) { + widget.selectMode.toggle(isLocal); + if (widget.selectMode.value != SelectMode.none) { _selectedItems.add(entries[index]); } setState(() {}); diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index 4cfe19135..4170a5461 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -390,7 +390,7 @@ class FileController { } } - /// sendFiles from other side (SelectedItems) to current side (FileController.isLocal). + /// sendFiles from current side (FileController.isLocal) to other side (SelectedItems). void sendFiles(SelectedItems items, DirectoryData otherSideData) { /// ignore wrong items side status if (items.isLocal != isLocal) { From e2f5a82bea3741d677c18cd1d361f31184ee3021 Mon Sep 17 00:00:00 2001 From: "Miguel F. G" <116861809+flusheDData@users.noreply.github.com> Date: Thu, 9 Mar 2023 15:36:40 +0100 Subject: [PATCH 293/382] Update es.rs New terms added --- src/lang/es.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lang/es.rs b/src/lang/es.rs index 7443f8640..3543c5155 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Resolución"), ("No transfers in progress", "No hay transferencias en curso"), ("Set one-time password length", "Establecer contraseña de un solo uso"), - ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", ""), - ("RDP Settings", ""), + ("idd_driver_tip", "Instalar controlador virtual de pantalla a usar cuando no hay pantalla física."), + ("confirm_idd_driver_tip", "La opción de instalar el controlador de pantalla virtual está marcada. Hay que tener en cuenta que se instalará un certificado de prueba para confirar en el controlador de pantalla. Este certificado solo se usará para confiar en controladores Rustdesk."), + ("RDP Settings", "Ajustes RDP"), ].iter().cloned().collect(); } From 828854a6cea41a33726a59323e98d4f3d7be45ed Mon Sep 17 00:00:00 2001 From: rustdesk Date: Thu, 9 Mar 2023 23:18:10 +0800 Subject: [PATCH 294/382] add count to avoid frequent "audio frame ignored" message found in issue #3268 --- src/client.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/client.rs b/src/client.rs index 9202a34ba..705b387a8 100644 --- a/src/client.rs +++ b/src/client.rs @@ -708,6 +708,7 @@ pub struct AudioHandler { audio_stream: Option>, channels: u16, latency_controller: Arc>, + ignore_count: i32, } impl AudioHandler { @@ -810,7 +811,11 @@ impl AudioHandler { .check_audio(frame.timestamp) .not() { - log::debug!("audio frame {} is ignored", frame.timestamp); + self.ignore_count += 1; + if self.ignore_count == 100 { + self.ignore_count = 0; + log::debug!("100 audio frames are ignored"); + } return; } } From 7833c7ce31a4772d2a6293aa5e4504db98e2b2ea Mon Sep 17 00:00:00 2001 From: Kingtous Date: Fri, 10 Mar 2023 00:15:07 +0800 Subject: [PATCH 295/382] fix: window overflow & prevent setMaximize when fullscreen --- flutter/lib/models/state_model.dart | 13 +++++++++---- flutter/pubspec.yaml | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/flutter/lib/models/state_model.dart b/flutter/lib/models/state_model.dart index aa4fab86e..187b1ffc5 100644 --- a/flutter/lib/models/state_model.dart +++ b/flutter/lib/models/state_model.dart @@ -28,10 +28,9 @@ class StateGlobal { setWindowId(int id) => _windowId = id; setMaximize(bool v) { - if (_maximize != v) { + if (_maximize != v && !_fullscreen) { _maximize = v; - _resizeEdgeSize.value = - _maximize ? kMaximizeEdgeSize : kWindowEdgeSize; + _resizeEdgeSize.value = _maximize ? kMaximizeEdgeSize : kWindowEdgeSize; } } setFullscreen(bool v) { @@ -39,7 +38,13 @@ class StateGlobal { _fullscreen = v; _showTabBar.value = !_fullscreen; _resizeEdgeSize.value = - fullscreen ? kFullScreenEdgeSize : kWindowEdgeSize; + fullscreen + ? kFullScreenEdgeSize + : _maximize + ? kMaximizeEdgeSize + : kWindowEdgeSize; + print( + "fullscreen: ${fullscreen}, resizeEdgeSize: ${_resizeEdgeSize.value}"); _windowBorderWidth.value = fullscreen ? 0 : kWindowBorderWidth; WindowController.fromWindowId(windowId) .setFullscreen(_fullscreen) diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index ccb53cc9c..087fba71e 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: 3e2655677c54f421f9e378680d8171b95a211e0f + ref: e3947d4b4f8edaa655de63cd47f2a59a6e024218 freezed_annotation: ^2.0.3 flutter_custom_cursor: ^0.0.4 window_size: From 4a5be4cd155cc057868c9eaaa937e46ac73b4aa9 Mon Sep 17 00:00:00 2001 From: ilGigioVr88 Date: Thu, 9 Mar 2023 18:47:18 +0100 Subject: [PATCH 296/382] Update it.rs --- src/lang/it.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/it.rs b/src/lang/it.rs index 1c531c59f..dc59ccea3 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -463,6 +463,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Set one-time password length", "Imposta la lunghezza della password monouso"), ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), - ("RDP Settings", ""), + ("RDP Settings", "Impostazioni RDP"), ].iter().cloned().collect(); } From 08f238770fa265aebc5b68542715e506edd835fb Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Thu, 9 Mar 2023 22:20:46 +0200 Subject: [PATCH 297/382] Update el.rs --- src/lang/el.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lang/el.rs b/src/lang/el.rs index 4c3698194..b0c8be87a 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -461,8 +461,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Ανάλυση"), ("No transfers in progress", "Δεν υπάρχει μεταφορά σε εξέλιξη"), ("Set one-time password length", "Μέγεθος κωδικού μιας χρήσης"), - ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", ""), - ("RDP Settings", ""), + ("idd_driver_tip", "Εγκαταστήστε το πρόγραμμα οδήγησης εικονικής οθόνης που χρησιμοποιείται όταν δεν έχετε φυσικές οθόνες."), + ("confirm_idd_driver_tip", "Είναι ενεργοποιημένη η επιλογή εγκατάστασης του προγράμματος οδήγησης εικονικής οθόνης. Λάβετε υπόψη ότι θα εγκατασταθεί ένα δοκιμαστικό πιστοποιητικό για το πρόγραμμα οδήγησης εικονικής οθόνης. Αυτό το πιστοποιητικό θα χρησιμοποιηθεί μόνο για την πιστοποίηση των προγραμμάτων οδήγησης του Rustdesk."), + ("RDP Settings", "Ρυθμίσεις RDP"), ].iter().cloned().collect(); } From d681be04ddb03ca139b776a20a378d9f1629e9c9 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Thu, 9 Mar 2023 22:24:32 +0200 Subject: [PATCH 298/382] Update README-GR.md --- docs/README-GR.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/README-GR.md b/docs/README-GR.md index b4a7d5c47..8ec98030d 100644 --- a/docs/README-GR.md +++ b/docs/README-GR.md @@ -37,9 +37,9 @@ | Σεούλ | AWS lightsail | 1 vCPU / 0.5GB RAM | | Γερμανία | Hetzner | 2 vCPU / 4GB RAM | | Γερμανία | Codext | 4 vCPU / 8GB RAM | -| Φινλανδία (Ελσίνκι) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| ΗΠΑ (Άσμπερν) | 0x101 Cyber Security | 4 vCPU / 8GB RAM | -| Ουκρανία (Κίεβο) | dc.volia (2VM) | 2 vCPU / 4GB RAM | +| Φινλανδία (Ελσίνκι) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| ΗΠΑ (Άσμπερν) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| Ουκρανία (Κίεβο) | [dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | ## Dev Container From 6363e3a4ebfdbefdfbce42bd9f44b16feb46e353 Mon Sep 17 00:00:00 2001 From: Chieh Wang <99897242+chiehw@users.noreply.github.com> Date: Fri, 10 Mar 2023 08:02:59 +0800 Subject: [PATCH 299/382] Add keyboard mode to issue_temp --- .github/ISSUE_TEMPLATE/bug_report.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index f83a72de9..d8781bb0c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -6,7 +6,7 @@ body: id: desc attributes: label: Bug Description - description: A clear and concise description of what the bug is + description: A clear and concise description of what the bug is (if it's a keyboard issue, provide the keyboard mode you're using. e.g. legacy, map, translate) validations: required: true - type: textarea From b042643dfb2c6c9e1b3913caa8c19ef227825bc2 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 10 Mar 2023 10:16:36 +0800 Subject: [PATCH 300/382] trivial changes Signed-off-by: fufesou --- src/ui_cm_interface.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index f5c575d43..bd6eab3bf 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -848,7 +848,7 @@ pub fn elevate_portable(_id: i32) { #[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))] #[inline] pub fn handle_incoming_voice_call(id: i32, accept: bool) { - if let Some(client) = CLIENTS.write().unwrap().get_mut(&id) { + if let Some(client) = CLIENTS.read().unwrap().get(&id) { allow_err!(client.tx.send(Data::VoiceCallResponse(accept))); }; } @@ -856,7 +856,7 @@ pub fn handle_incoming_voice_call(id: i32, accept: bool) { #[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))] #[inline] pub fn close_voice_call(id: i32) { - if let Some(client) = CLIENTS.write().unwrap().get_mut(&id) { + if let Some(client) = CLIENTS.read().unwrap().get(&id) { allow_err!(client.tx.send(Data::CloseVoiceCall("".to_owned()))); }; } From 8a09abbf719588f54a5814a4652a81ba8ba54590 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 10 Mar 2023 10:53:41 +0800 Subject: [PATCH 301/382] avoid w/h <= 0 Signed-off-by: fufesou --- flutter/lib/models/model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index a8ed56bc5..8f46fdca8 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -371,7 +371,7 @@ class FfiModel with ChangeNotifier { _updateSessionWidthHeight(String id) { parent.target?.canvasModel.updateViewStyle(); - if (display.width < 0 || display.height < 0) { + if (display.width <= 0 || display.height <= 0) { debugPrintStack(label: 'invalid display size (${display.width},${display.height})'); } else { bind.sessionSetSize(id: id, width: display.width, height: display.height); From cdea6daf89f4479d99deb243157dbc103e46a0b3 Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 10 Mar 2023 11:24:43 +0800 Subject: [PATCH 302/382] fix frequent load RustDesk_default.toml Signed-off-by: 21pages --- libs/hbb_common/src/config.rs | 48 ++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index ed7270a85..4ce2cf07e 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -4,7 +4,7 @@ use std::{ net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, path::{Path, PathBuf}, sync::{Arc, Mutex, RwLock}, - time::SystemTime, + time::{Duration, Instant, SystemTime}, }; use anyhow::Result; @@ -51,6 +51,7 @@ lazy_static::lazy_static! { pub static ref APP_NAME: Arc> = Arc::new(RwLock::new("RustDesk".to_owned())); static ref KEY_PAIR: Arc>> = Default::default(); static ref HW_CODEC_CONFIG: Arc> = Arc::new(RwLock::new(HwCodecConfig::load())); + static ref USER_DEFAULT_CONFIG: Arc> = Arc::new(RwLock::new((UserDefaultConfig::load(), Instant::now()))); } lazy_static::lazy_static! { @@ -123,7 +124,7 @@ macro_rules! serde_field_bool { } impl $struct_name { pub fn $func() -> bool { - UserDefaultConfig::load().get($field_name) == "Y" + UserDefaultConfig::read().get($field_name) == "Y" } } }; @@ -980,21 +981,21 @@ impl PeerConfig { serde_field_string!( default_view_style, deserialize_view_style, - UserDefaultConfig::load().get("view_style") + UserDefaultConfig::read().get("view_style") ); serde_field_string!( default_scroll_style, deserialize_scroll_style, - UserDefaultConfig::load().get("scroll_style") + UserDefaultConfig::read().get("scroll_style") ); serde_field_string!( default_image_quality, deserialize_image_quality, - UserDefaultConfig::load().get("image_quality") + UserDefaultConfig::read().get("image_quality") ); fn default_custom_image_quality() -> Vec { - let f: f64 = UserDefaultConfig::load() + let f: f64 = UserDefaultConfig::read() .get("custom_image_quality") .parse() .unwrap_or(50.0); @@ -1020,15 +1021,15 @@ impl PeerConfig { let mut mp: HashMap = de::Deserialize::deserialize(deserializer)?; let mut key = "codec-preference"; if !mp.contains_key(key) { - mp.insert(key.to_owned(), UserDefaultConfig::load().get(key)); + mp.insert(key.to_owned(), UserDefaultConfig::read().get(key)); } key = "custom-fps"; if !mp.contains_key(key) { - mp.insert(key.to_owned(), UserDefaultConfig::load().get(key)); + mp.insert(key.to_owned(), UserDefaultConfig::read().get(key)); } key = "zoom-cursor"; if !mp.contains_key(key) { - mp.insert(key.to_owned(), UserDefaultConfig::load().get(key)); + mp.insert(key.to_owned(), UserDefaultConfig::read().get(key)); } Ok(mp) } @@ -1046,7 +1047,12 @@ serde_field_bool!( default_show_quality_monitor, "ShowQualityMonitor::default_show_quality_monitor" ); -serde_field_bool!(DisableAudio, "disable_audio", default_disable_audio, "DisableAudio::default_disable_audio"); +serde_field_bool!( + DisableAudio, + "disable_audio", + default_disable_audio, + "DisableAudio::default_disable_audio" +); serde_field_bool!( EnableFileTransfer, "enable_file_transfer", @@ -1065,9 +1071,19 @@ serde_field_bool!( default_lock_after_session_end, "LockAfterSessionEnd::default_lock_after_session_end" ); -serde_field_bool!(PrivacyMode, "privacy_mode", default_privacy_mode, "PrivacyMode::default_privacy_mode"); +serde_field_bool!( + PrivacyMode, + "privacy_mode", + default_privacy_mode, + "PrivacyMode::default_privacy_mode" +); -serde_field_bool!(AllowSwapKey, "allow_swap_key", default_allow_swap_key, "AllowSwapKey::default_allow_swap_key"); +serde_field_bool!( + AllowSwapKey, + "allow_swap_key", + default_allow_swap_key, + "AllowSwapKey::default_allow_swap_key" +); #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct LocalConfig { @@ -1282,6 +1298,14 @@ pub struct UserDefaultConfig { } impl UserDefaultConfig { + pub fn read() -> UserDefaultConfig { + let mut cfg = USER_DEFAULT_CONFIG.write().unwrap(); + if cfg.1.elapsed() > Duration::from_secs(1) { + *cfg = (Self::load(), Instant::now()); + } + cfg.0.clone() + } + pub fn load() -> UserDefaultConfig { Config::load_::("_default") } From bb201a47cb88b331dc0081c9da12d647f69d0e68 Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 10 Mar 2023 13:54:23 +0800 Subject: [PATCH 303/382] separate menubars open only when clicked Signed-off-by: 21pages --- flutter/lib/desktop/widgets/remote_menubar.dart | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 173ed038c..e7ca23ea6 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -414,7 +414,7 @@ class _RemoteMenubarState extends State { scrollDirection: Axis.horizontal, child: Theme( data: themeData(), - child: MenuBar( + child: Row( children: [ SizedBox(width: _MenubarTheme.buttonHMargin), ...menubarItems, @@ -440,6 +440,8 @@ class _RemoteMenubarState extends State { ), ), dividerTheme: DividerThemeData(space: 4), + menuBarTheme: MenuBarThemeData( + style: MenuStyle(padding: MaterialStatePropertyAll(EdgeInsets.zero))), ); } } @@ -552,6 +554,7 @@ class _MonitorMenu extends StatelessWidget { final pi = ffi.ffiModel.pi; for (int i = 0; i < pi.displays.length; i++) { rowChildren.add(_IconMenuButton( + topLevel: false, color: _MenubarTheme.blueColor, hoverColor: _MenubarTheme.hoverBlueColor, tooltip: "", @@ -1819,6 +1822,7 @@ class _IconMenuButton extends StatefulWidget { final VoidCallback? onPressed; final double? hMargin; final double? vMargin; + final bool topLevel; const _IconMenuButton({ Key? key, this.assetName, @@ -1829,6 +1833,7 @@ class _IconMenuButton extends StatefulWidget { required this.onPressed, this.hMargin, this.vMargin, + this.topLevel = true, }) : super(key: key); @override @@ -1848,7 +1853,7 @@ class _IconMenuButtonState extends State<_IconMenuButton> { width: _MenubarTheme.buttonSize, height: _MenubarTheme.buttonSize, ); - return SizedBox( + final button = SizedBox( width: _MenubarTheme.buttonSize, height: _MenubarTheme.buttonSize, child: MenuItemButton( @@ -1874,6 +1879,11 @@ class _IconMenuButtonState extends State<_IconMenuButton> { ).marginSymmetric( horizontal: widget.hMargin ?? _MenubarTheme.buttonHMargin, vertical: widget.vMargin ?? _MenubarTheme.buttonVMargin); + if (widget.topLevel) { + return MenuBar(children: [button]); + } else { + return button; + } } } @@ -1914,7 +1924,7 @@ class _IconSubmenuButtonState extends State<_IconSubmenuButton> { width: _MenubarTheme.buttonSize, height: _MenubarTheme.buttonSize, ); - return SizedBox( + final button = SizedBox( width: _MenubarTheme.buttonSize, height: _MenubarTheme.buttonSize, child: SubmenuButton( @@ -1940,6 +1950,7 @@ class _IconSubmenuButtonState extends State<_IconSubmenuButton> { .marginSymmetric( horizontal: _MenubarTheme.buttonHMargin, vertical: _MenubarTheme.buttonVMargin); + return MenuBar(children: [button]); } } From d28aa6eeb09d428cf1849835526cffb8b1c8966c Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 10 Mar 2023 14:16:18 +0800 Subject: [PATCH 304/382] not show menubar tooltip Signed-off-by: 21pages --- .../lib/desktop/widgets/remote_menubar.dart | 83 ++++++++++--------- 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index e7ca23ea6..3e37cef40 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -516,6 +516,7 @@ class _MonitorMenu extends StatelessWidget { return Offstage(); } return _IconSubmenuButton( + tooltip: 'Select Monitor', icon: icon(), ffi: ffi, color: _MenubarTheme.blueColor, @@ -607,6 +608,7 @@ class _ControlMenu extends StatelessWidget { @override Widget build(BuildContext context) { return _IconSubmenuButton( + tooltip: 'Control Actions', svg: "assets/actions.svg", color: _MenubarTheme.blueColor, hoverColor: _MenubarTheme.hoverBlueColor, @@ -928,6 +930,7 @@ class _DisplayMenuState extends State<_DisplayMenu> { Widget build(BuildContext context) { _updateScreen(); return _IconSubmenuButton( + tooltip: 'Display Settings', svg: "assets/display.svg", ffi: widget.ffi, color: _MenubarTheme.blueColor, @@ -1611,6 +1614,7 @@ class _KeyboardMenu extends StatelessWidget { return Offstage(); } return _IconSubmenuButton( + tooltip: 'Keyboard Settings', svg: "assets/keyboard.svg", ffi: ffi, color: _MenubarTheme.blueColor, @@ -1698,6 +1702,7 @@ class _ChatMenuState extends State<_ChatMenu> { @override Widget build(BuildContext context) { return _IconSubmenuButton( + tooltip: 'Chat', key: chatButtonKey, svg: 'assets/chat.svg', ffi: widget.ffi, @@ -1816,7 +1821,7 @@ class _CloseMenu extends StatelessWidget { class _IconMenuButton extends StatefulWidget { final String? assetName; final Widget? icon; - final String tooltip; + final String? tooltip; final Color color; final Color hoverColor; final VoidCallback? onPressed; @@ -1827,7 +1832,7 @@ class _IconMenuButton extends StatefulWidget { Key? key, this.assetName, this.icon, - required this.tooltip, + this.tooltip, required this.color, required this.hoverColor, required this.onPressed, @@ -1864,17 +1869,14 @@ class _IconMenuButtonState extends State<_IconMenuButton> { hover = value; }), onPressed: widget.onPressed, - child: Tooltip( - message: translate(widget.tooltip), - child: Material( - type: MaterialType.transparency, - child: Ink( - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(_MenubarTheme.iconRadius), - color: hover ? widget.hoverColor : widget.color, - ), - child: icon))), + child: Material( + type: MaterialType.transparency, + child: Ink( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(_MenubarTheme.iconRadius), + color: hover ? widget.hoverColor : widget.color, + ), + child: icon)), ), ).marginSymmetric( horizontal: widget.hMargin ?? _MenubarTheme.buttonHMargin, @@ -1888,6 +1890,7 @@ class _IconMenuButtonState extends State<_IconMenuButton> { } class _IconSubmenuButton extends StatefulWidget { + final String tooltip; final String? svg; final Widget? icon; final Color color; @@ -1900,6 +1903,7 @@ class _IconSubmenuButton extends StatefulWidget { {Key? key, this.svg, this.icon, + required this.tooltip, required this.color, required this.hoverColor, required this.menuChildren, @@ -1925,32 +1929,33 @@ class _IconSubmenuButtonState extends State<_IconSubmenuButton> { height: _MenubarTheme.buttonSize, ); final button = SizedBox( - width: _MenubarTheme.buttonSize, - height: _MenubarTheme.buttonSize, - child: SubmenuButton( - menuStyle: widget.menuStyle, - style: ButtonStyle( - padding: MaterialStatePropertyAll(EdgeInsets.zero), - overlayColor: MaterialStatePropertyAll(Colors.transparent)), - onHover: (value) => setState(() { - hover = value; - }), - child: Material( - type: MaterialType.transparency, - child: Ink( - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(_MenubarTheme.iconRadius), - color: hover ? widget.hoverColor : widget.color, - ), - child: icon)), - menuChildren: widget.menuChildren - .map((e) => _buildPointerTrackWidget(e, widget.ffi)) - .toList())) - .marginSymmetric( - horizontal: _MenubarTheme.buttonHMargin, - vertical: _MenubarTheme.buttonVMargin); - return MenuBar(children: [button]); + width: _MenubarTheme.buttonSize, + height: _MenubarTheme.buttonSize, + child: SubmenuButton( + menuStyle: widget.menuStyle, + style: ButtonStyle( + padding: MaterialStatePropertyAll(EdgeInsets.zero), + overlayColor: MaterialStatePropertyAll(Colors.transparent)), + onHover: (value) => setState(() { + hover = value; + }), + child: Material( + type: MaterialType.transparency, + child: Ink( + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(_MenubarTheme.iconRadius), + color: hover ? widget.hoverColor : widget.color, + ), + child: icon)), + menuChildren: widget.menuChildren + .map((e) => _buildPointerTrackWidget(e, widget.ffi)) + .toList())); + return MenuBar(children: [ + button.marginSymmetric( + horizontal: _MenubarTheme.buttonHMargin, + vertical: _MenubarTheme.buttonVMargin) + ]); } } From a6deacb92b18435e399cb619ade84b459e745d71 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Fri, 10 Mar 2023 15:25:19 +0800 Subject: [PATCH 305/382] remove alias and disable status in peer card sort --- flutter/lib/common/widgets/peers_view.dart | 18 ++++++------------ flutter/lib/models/peer_model.dart | 7 +++++++ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/flutter/lib/common/widgets/peers_view.dart b/flutter/lib/common/widgets/peers_view.dart index 197e55376..71cd5d999 100644 --- a/flutter/lib/common/widgets/peers_view.dart +++ b/flutter/lib/common/widgets/peers_view.dart @@ -19,16 +19,14 @@ typedef PeerCardBuilder = Widget Function(Peer peer); class PeerSortType { static const String remoteId = 'Remote ID'; static const String remoteHost = 'Remote Host'; - static const String alias = 'Alias'; static const String username = 'Username'; - static const String status = 'Status'; + // static const String status = 'Status'; static List values = [ PeerSortType.remoteId, PeerSortType.remoteHost, - PeerSortType.alias, PeerSortType.username, - PeerSortType.status + // PeerSortType.status ]; } @@ -226,23 +224,19 @@ class _PeersViewState extends State<_PeersView> with WindowListener { if (widget.peers.loadEvent != 'load_recent_peers') { switch (sortedBy) { case PeerSortType.remoteId: - peers.sort((p1, p2) => p1.id.compareTo(p2.id)); + peers.sort((p1, p2) => p1.getId().compareTo(p2.getId())); break; case PeerSortType.remoteHost: peers.sort((p1, p2) => p1.hostname.toLowerCase().compareTo(p2.hostname.toLowerCase())); break; - case PeerSortType.alias: - peers.sort((p1, p2) => - p1.alias.toLowerCase().compareTo(p2.alias.toLowerCase())); - break; case PeerSortType.username: peers.sort((p1, p2) => p1.username.toLowerCase().compareTo(p2.username.toLowerCase())); break; - case PeerSortType.status: - peers.sort((p1, p2) => p1.online ? -1 : 1); - break; + // case PeerSortType.status: + // peers.sort((p1, p2) => p1.online ? -1 : 1); + // break; } } diff --git a/flutter/lib/models/peer_model.dart b/flutter/lib/models/peer_model.dart index ad5183ae3..1b71e382e 100644 --- a/flutter/lib/models/peer_model.dart +++ b/flutter/lib/models/peer_model.dart @@ -14,6 +14,13 @@ class Peer { String rdpUsername; bool online = false; + String getId() { + if (alias != '') { + return alias; + } + return id; + } + Peer.fromJson(Map json) : id = json['id'] ?? '', username = json['username'] ?? '', From 3879662896bd9cd8b96844199f658231a0edb308 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Fri, 10 Mar 2023 15:37:48 +0800 Subject: [PATCH 306/382] fix CI, change rust 1.62 -> stable --- .github/workflows/flutter-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter-ci.yml b/.github/workflows/flutter-ci.yml index cae5b82c7..5eda9ad18 100644 --- a/.github/workflows/flutter-ci.yml +++ b/.github/workflows/flutter-ci.yml @@ -62,7 +62,7 @@ jobs: - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: - toolchain: "1.62" + toolchain: stable target: ${{ matrix.job.target }} override: true components: rustfmt From 38ff65ee84fb52b4421836eb10fc4020be2cfb8b Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 10 Mar 2023 16:41:00 +0800 Subject: [PATCH 307/382] try create default video save directory at first Signed-off-by: 21pages --- src/ui_interface.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/ui_interface.rs b/src/ui_interface.rs index fd97f41b0..1dcf93e94 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -648,17 +648,26 @@ pub fn get_langs() -> String { #[inline] pub fn default_video_save_directory() -> String { let appname = crate::get_app_name(); + // In order to make the function call results of the UI process and the video process the same, no result check is performed. + let try_create = |path: &std::path::Path| { + if !path.exists() { + if std::fs::create_dir_all(path).is_err() { + log::warn!("video directory {:?} create failed.", path); + } + } + path.to_string_lossy().to_string() + }; #[cfg(any(target_os = "android", target_os = "ios"))] if let Ok(home) = config::APP_HOME_DIR.read() { let mut path = home.to_owned(); path.push_str("/RustDesk/ScreenRecord"); - return path; + return try_create(&std::path::Path::from(path)); } if let Some(user) = directories_next::UserDirs::new() { if let Some(video_dir) = user.video_dir() { - return video_dir.join(appname).to_string_lossy().to_string(); + return try_create(&video_dir.join(&appname)); } } @@ -669,12 +678,12 @@ pub fn default_video_save_directory() -> String { } else { "Videos" }; - return home.join(name).join(appname).to_string_lossy().to_string(); + return try_create(&home.join(name).join(&appname)); } if let Ok(exe) = std::env::current_exe() { if let Some(dir) = exe.parent() { - return dir.join("videos").to_string_lossy().to_string(); + return try_create(&dir.join("videos")); } } "".to_owned() From af661bf647abf56ab981b9360522612cc98b8556 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Fri, 10 Mar 2023 11:14:43 +0200 Subject: [PATCH 308/382] Update el.rs --- src/lang/el.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/el.rs b/src/lang/el.rs index 6599e7a59..413f36cb0 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -464,6 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", "Εγκαταστήστε το πρόγραμμα οδήγησης εικονικής οθόνης που χρησιμοποιείται όταν δεν έχετε φυσικές οθόνες."), ("confirm_idd_driver_tip", "Είναι ενεργοποιημένη η επιλογή εγκατάστασης του προγράμματος οδήγησης εικονικής οθόνης. Λάβετε υπόψη ότι θα εγκατασταθεί ένα δοκιμαστικό πιστοποιητικό για το πρόγραμμα οδήγησης εικονικής οθόνης. Αυτό το πιστοποιητικό θα χρησιμοποιηθεί μόνο για την πιστοποίηση των προγραμμάτων οδήγησης του Rustdesk."), ("RDP Settings", "Ρυθμίσεις RDP"), - ("Sort by", ""), + ("Sort by", "Ταξινόμηση κατά"), ].iter().cloned().collect(); } From 3dd0da44b3f4cf489057996e7b509426e34a9b85 Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 10 Mar 2023 18:12:35 +0800 Subject: [PATCH 309/382] make sure default video save directory exist Signed-off-by: 21pages --- src/ui_interface.rs | 60 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 1dcf93e94..58d321531 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -648,29 +648,50 @@ pub fn get_langs() -> String { #[inline] pub fn default_video_save_directory() -> String { let appname = crate::get_app_name(); - // In order to make the function call results of the UI process and the video process the same, no result check is performed. + // ui process can show it correctly Once vidoe process created it. let try_create = |path: &std::path::Path| { if !path.exists() { - if std::fs::create_dir_all(path).is_err() { - log::warn!("video directory {:?} create failed.", path); - } + std::fs::create_dir_all(path).ok(); + } + if path.exists() { + path.to_string_lossy().to_string() + } else { + "".to_string() } - path.to_string_lossy().to_string() }; #[cfg(any(target_os = "android", target_os = "ios"))] if let Ok(home) = config::APP_HOME_DIR.read() { let mut path = home.to_owned(); path.push_str("/RustDesk/ScreenRecord"); - return try_create(&std::path::Path::from(path)); + let dir = try_create(&std::path::Path::from(path)); + if !dir.is_empty() { + return dir; + } } if let Some(user) = directories_next::UserDirs::new() { if let Some(video_dir) = user.video_dir() { - return try_create(&video_dir.join(&appname)); + let dir = try_create(&video_dir.join(&appname)); + if !dir.is_empty() { + return dir; + } + if video_dir.exists() { + return video_dir.to_string_lossy().to_string(); + } + } + if let Some(desktop_dir) = user.desktop_dir() { + if desktop_dir.exists() { + return desktop_dir.to_string_lossy().to_string(); + } + } + let home = user.home_dir(); + if home.exists() { + return home.to_string_lossy().to_string(); } } + // same order as above #[cfg(not(any(target_os = "android", target_os = "ios")))] if let Some(home) = crate::platform::get_active_user_home() { let name = if cfg!(target_os = "macos") { @@ -678,12 +699,31 @@ pub fn default_video_save_directory() -> String { } else { "Videos" }; - return try_create(&home.join(name).join(&appname)); + let video_dir = home.join(name); + let dir = try_create(&video_dir.join(&appname)); + if !dir.is_empty() { + return dir; + } + if video_dir.exists() { + return video_dir.to_string_lossy().to_string(); + } + let desktop_dir = home.join("Desktop"); + if desktop_dir.exists() { + return desktop_dir.to_string_lossy().to_string(); + } + if home.exists() { + return home.to_string_lossy().to_string(); + } } if let Ok(exe) = std::env::current_exe() { - if let Some(dir) = exe.parent() { - return try_create(&dir.join("videos")); + if let Some(parent) = exe.parent() { + let dir = try_create(&parent.join("videos")); + if !dir.is_empty() { + return dir; + } + // basically exist + return parent.to_string_lossy().to_string(); } } "".to_owned() From d3ccf6032bb51418a575205a412751f7d1879fd6 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Fri, 10 Mar 2023 13:00:32 +0100 Subject: [PATCH 310/382] Update tabbar_widget.dart --- flutter/lib/desktop/widgets/tabbar_widget.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index 1e62fb33d..7700f197e 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -593,7 +593,7 @@ class WindowActionPanelState extends State Offstage( offstage: !widget.showMinimize || Platform.isMacOS, child: ActionIcon( - message: 'Minimize', + message: translate('Minimize'), icon: IconFont.min, onTap: () { if (widget.isMainWindow) { @@ -608,7 +608,7 @@ class WindowActionPanelState extends State offstage: !widget.showMaximize || Platform.isMacOS, child: Obx(() => ActionIcon( message: - widget.isMaximized.value ? "Restore" : "Maximize", + widget.isMaximized.value ? translate("Restore") : translate("Maximize"), icon: widget.isMaximized.value ? IconFont.restore : IconFont.max, @@ -618,7 +618,7 @@ class WindowActionPanelState extends State Offstage( offstage: !widget.showClose || Platform.isMacOS, child: ActionIcon( - message: 'Close', + message: translate('Close'), icon: IconFont.close, onTap: () async { final res = await widget.onClose?.call() ?? true; @@ -1076,7 +1076,7 @@ class AddButton extends StatelessWidget { @override Widget build(BuildContext context) { return ActionIcon( - message: 'New Connection', + message: translate('New Connection'), icon: IconFont.add, onTap: () => rustDeskWinManager.call( WindowType.Main, kWindowMainWindowOnTop, ""), From af257d1fd552b7001056b4e90dbe92558df8fbca Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Fri, 10 Mar 2023 13:03:18 +0100 Subject: [PATCH 311/382] Add files via upload --- src/lang/ca.rs | 4 ++++ src/lang/cn.rs | 4 ++++ src/lang/cs.rs | 4 ++++ src/lang/da.rs | 4 ++++ src/lang/de.rs | 6 +++++- src/lang/el.rs | 4 ++++ src/lang/eo.rs | 4 ++++ src/lang/es.rs | 4 ++++ src/lang/fa.rs | 4 ++++ src/lang/fr.rs | 4 ++++ src/lang/hu.rs | 4 ++++ src/lang/id.rs | 4 ++++ src/lang/it.rs | 4 ++++ src/lang/ja.rs | 4 ++++ src/lang/ko.rs | 4 ++++ src/lang/kz.rs | 4 ++++ src/lang/nl.rs | 4 ++++ src/lang/pl.rs | 4 ++++ src/lang/pt_PT.rs | 4 ++++ src/lang/ptbr.rs | 4 ++++ src/lang/ro.rs | 4 ++++ src/lang/ru.rs | 4 ++++ src/lang/sk.rs | 4 ++++ src/lang/sl.rs | 4 ++++ src/lang/sq.rs | 4 ++++ src/lang/sr.rs | 4 ++++ src/lang/sv.rs | 4 ++++ src/lang/template.rs | 4 ++++ src/lang/th.rs | 4 ++++ src/lang/tr.rs | 4 ++++ src/lang/tw.rs | 4 ++++ src/lang/ua.rs | 4 ++++ src/lang/vn.rs | 4 ++++ 33 files changed, 133 insertions(+), 1 deletion(-) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index a3c31c55d..0d0219126 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index a32f35a5b..8fe826232 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", "安装虚拟显示器驱动的选项已勾选。请注意,测试证书将被安装以信任虚拟显示器驱动。测试证书仅会用于信任Rustdesk的驱动。"), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 50ea4e61c..5893b3e15 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index c0d722219..0c2a01d63 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index bdd82d471..b9fc7834a 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -464,6 +464,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", "Installieren Sie den virtuellen Anzeigetreiber, der verwendet wird, wenn Sie keine physischen Anzeigen haben."), ("confirm_idd_driver_tip", "Die Option zur Installation des virtuellen Anzeigetreibers ist aktiviert. Beachten Sie, dass ein Testzertifikat installiert wird, um dem virtuellen Anzeigetreiber zu vertrauen. Dieses Testzertifikat wird nur verwendet, um Rustdesk-Treibern zu vertrauen."), ("RDP Settings", "RDP-Einstellungen"), - ("Sort by", ""), + ("Sort by", "Sortieren nach"), + ("New connection", "Neue Verbindung"), + ("Restore", "Verkleinern"), + ("Minimize", "Minimieren"), + ("Maximize", "Maximieren"), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index 413f36cb0..63811f209 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", "Είναι ενεργοποιημένη η επιλογή εγκατάστασης του προγράμματος οδήγησης εικονικής οθόνης. Λάβετε υπόψη ότι θα εγκατασταθεί ένα δοκιμαστικό πιστοποιητικό για το πρόγραμμα οδήγησης εικονικής οθόνης. Αυτό το πιστοποιητικό θα χρησιμοποιηθεί μόνο για την πιστοποίηση των προγραμμάτων οδήγησης του Rustdesk."), ("RDP Settings", "Ρυθμίσεις RDP"), ("Sort by", "Ταξινόμηση κατά"), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 7ccb8a8ca..24df8827b 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 85239cdd1..585a10d68 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", "La opción de instalar el controlador de pantalla virtual está marcada. Hay que tener en cuenta que se instalará un certificado de prueba para confirar en el controlador de pantalla. Este certificado solo se usará para confiar en controladores Rustdesk."), ("RDP Settings", "Ajustes RDP"), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index a64597883..3331ab893 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 887965b9e..98083383d 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index e64d972b6..ef97ce8cf 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index ffba760ee..a9a70d473 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 4d2da35fa..136a51945 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", "L'opzione per installare il driver per lo schermo virtuale è selezionata. Nota che un certificato di test sarà installato per l'attendibilità del driver dello schermo virtuale. Questo certificato di test verrà utilizzato solo per l'attendibilità dei driver di RustDesk."), ("RDP Settings", "Impostazioni RDP"), ("Sort by", "Ordina per"), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 9b7741d4d..b30d1942c 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index ff6fdafb4..8572fa0c1 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index ca7c2d508..78cadf653 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index a617ba2eb..413ad055a 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 0e8bbd311..4bd7459d9 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 96a84de39..da90d34aa 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index f98e1116a..b73b5c743 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 386f88c85..f668e2e87 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index dc714ec72..c075d6442 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", "Включена функция установки драйвера виртуального дисплея. Обратите внимание, что для доверия к драйверу будет установлен тестовый сертификат. Этот сертификат будет использоваться только для подтверждения доверия драйверам Rustdesk."), ("RDP Settings", "Настройки RDP"), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 38a3bd655..f5aaff84c 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 41f4facbb..7e6bf57e3 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 7e559287e..4e263670c 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index b2f5b62f0..1ce22c5c3 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 7a35df417..58fe1c318 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 80e7f04e6..8e1e85bde 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index f9bcf0800..770ccef1d 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 58a38e075..3fd1de33c 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index ff05d5643..b6abf9067 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 04047ce9c..d838265fa 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index e38b06a57..27b24878d 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -465,5 +465,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), + ("New connection", ""), + ("Restore", ""), + ("Minimize", ""), + ("Maximize", ""), ].iter().cloned().collect(); } From ce98427a0ff94a33226bbd62a032ca8a797f2e7b Mon Sep 17 00:00:00 2001 From: who0ps Date: Fri, 10 Mar 2023 14:19:24 +0200 Subject: [PATCH 312/382] Update README-UA.md --- docs/README-UA.md | 67 ++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/docs/README-UA.md b/docs/README-UA.md index 6e933cea9..d7eaaa2ac 100644 --- a/docs/README-UA.md +++ b/docs/README-UA.md @@ -19,25 +19,37 @@ RustDesk вітає внесок кожного. Дивіться [`docs/CONTRIBUTING.md`](CONTRIBUTING.md) для допомоги на початку роботи. +[**FAQ**](https://github.com/rustdesk/rustdesk/wiki/FAQ) + [**Як працює RustDesk?**](https://github.com/rustdesk/rustdesk/wiki/How-does-RustDesk-work%3F) -[**ЗАВАНТАЖИТИ ДОДАТОК**](https://github.com/rustdesk/rustdesk/releases) +[**ЗАВАНТАЖИТИ ЗАСТОСУНОК**](https://github.com/rustdesk/rustdesk/releases) -[Get it on F-Droid](https://f-droid.org/en/packages/com.carriez.flutter_hbb) +[Get it on F-Droid](https://f-droid.org/en/packages/com.carriez.flutter_hbb) ## Безкоштовні загальнодоступні сервери Нижче наведені сервери, для безкоштовного використання, вони можуть змінюватися з часом. Якщо ви не перебуваєте поруч з одним із них, ваша мережа може працювати повільно. | Місцезнаходження | Постачальник | Технічні характеристики | | --------- | ------------- | ------------------ | -| Сеул | AWS lightsail | 1 vCPU / 0.5GB RAM | +| Південна Корея (Сеул) | AWS lightsail | 1 vCPU / 0.5GB RAM | | Сінгапур | Vultr | 1 vCPU / 1GB RAM | -| Даллас | Vultr | 1 vCPU / 1GB RAM -Німеччина | Hetzner | 2 vCPU / 4GB RAM | 2 VCPU / 4GB RAM | Німеччина | Hetzner | 2 VCPU / 4GB RAM | -| Germany | Codext | 4 vCPU / 8GB RAM | -| Finland (Helsinki) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | -| USA (Ashburn) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | -| Ukraine (Kyiv) | [dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | +| США (Даллас) | Vultr | 1 vCPU / 1GB RAM +| Німеччина | Hetzner | 2 VCPU / 4GB RAM | +| Німеччина | Codext | 4 vCPU / 8GB RAM | +| Фінляндія (Гельсінкі) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| США (Ешберн) | [Netlock](https://netlockendpoint.com) | 4 vCPU / 8GB RAM | +| Україна (Київ) | [dc.volia](https://dc.volia.com) | 2 vCPU / 4GB RAM | + +## Dev Container + +[![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Container&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/rustdesk/rustdesk) + +Якщо у вас уже встановлено VS Code і Docker, ви можете натиснути значок вище, щоб почати. Клацання призведе до того, що VS Code автоматично встановить розширення Dev Containers, якщо це необхідно, клонує виcхідний код у том контейнера та розгорне контейнер dev для використання. + +Дивіться [DEVCONTAINER.md](docs/DEVCONTAINER.md) для додаткової інфо. ## Залежності @@ -65,9 +77,16 @@ RustDesk вітає внесок кожного. Дивіться [`docs/CONTRIB ### Ubuntu 18 (Debian 10) ```sh -sudo apt install -y g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake +sudo apt install -y zip g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev \ + libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake make \ + libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev ``` +### openSUSE Tumbleweed + +```sh +sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel +``` ### Fedora 28 (CentOS 8) ```sh @@ -92,30 +111,6 @@ export VCPKG_ROOT=$HOME/vcpkg vcpkg/vcpkg install libvpx libyuv opus ``` -### Fedora 28 (CentOS 8) - -````sh -sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel -``` - -### Arch (Manjaro) - -```sh -sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pipewire -``` - -### Встановлення vcpkg - -```sh -git clone https://github.com/microsoft/vcpkg -cd vcpkg -git checkout 2021.12.01 -cd ... -vcpkg/bootstrap-vcpkg.sh -export VCPKG_ROOT=$HOME/vcpkg -vcpkg/vcpkg install libvpx libyuv opus -``` - ### Виправлення libvpx (для Fedora) ```sh @@ -184,8 +179,10 @@ target/release/rustdesk - **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: графічний інтерфейс користувача - **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: сервіси аудіо/буфера обміну/вводу/відео та мережевих підключень - **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: однорангове з'єднання -- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: зв'яжіться з [rustdesk-server](https://github.com/rustdesk/rustdesk-server), дочекайтеся віддаленого прямого (обхід TCP NAT) або ретрансльованого з'єднання +- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: комунікація з [rustdesk-server](https://github.com/rustdesk/rustdesk-server), очікування віддаленого прямого (обхід TCP NAT) або ретрансльованого з'єднання - **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: специфічний для платформи код +- **[flutter](https://github.com/rustdesk/rustdesk/tree/master/flutter)**: код Flutter для мобільних пристроїв +- **[flutter/web/js](https://github.com/rustdesk/rustdesk/tree/master/flutter/web/js)**: JavaScript для Flutter веб клієнту ## Знімки From fd0e49c10494439c00a81eccc92dcf6b033debf6 Mon Sep 17 00:00:00 2001 From: who0ps Date: Fri, 10 Mar 2023 14:29:35 +0200 Subject: [PATCH 313/382] Update README-UA.md --- docs/README-UA.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/README-UA.md b/docs/README-UA.md index d7eaaa2ac..222da34d2 100644 --- a/docs/README-UA.md +++ b/docs/README-UA.md @@ -1,10 +1,10 @@

    RustDesk - Ваш віддалений робочий стіл
    - Servers • - Build • - Docker • - Structure • - Snapshot
    + Сервери • + Складання • + Docker • + Структура • + Знімки
    [English] | [česky] | [中文] | [Magyar] | [Español] | [فارسی] | [Français] | [Deutsch] | [Polski] | [Indonesian] | [Suomi] | [മലയാളം] | [日本語] | [Nederlands] | [Italiano] | [Русский] | [Português (Brasil)] | [Esperanto] | [한국어] | [العربي] | [Tiếng Việt] | [Ελληνικά]
    Нам потрібна ваша допомога для перекладу цього README і RustDesk UI на вашу рідну мову

    From 4c993fcecb923607cb999a8aaf2c914cbfab10a8 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 1 Mar 2023 08:55:21 +0100 Subject: [PATCH 314/382] Mobile. Share Screen. Fix "service" button causes canvas overflow --- flutter/lib/mobile/pages/server_page.dart | 128 +++++++++++----------- 1 file changed, 66 insertions(+), 62 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index 218559a6e..07a81f8de 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/mobile/widgets/dialog.dart'; +import 'package:get/get.dart'; import 'package:provider/provider.dart'; import '../../common.dart'; @@ -264,70 +265,73 @@ class _PermissionCheckerState extends State { } else { status = 'Ready'; } + + // @todo Theming + Widget ServerStateMessage() { + if (!serverModel.mediaOk) { + return Row(children: [ + const Icon(Icons.warning_amber_outlined, + color: Colors.redAccent, size: 24) + .marginOnly(right: 10), + Expanded(child: Text(translate('Service is not running'))) + ]); + } + + if (serverModel.connectStatus == -1) { + return Row(children: [ + const Icon(Icons.warning_amber_sharp, + color: Colors.redAccent, size: 24) + .marginOnly(right: 10), + Expanded(child: Text(translate('not_ready_status'))) + ]); + } else if (serverModel.connectStatus == 0) { + return Row(children: [ + SizedBox(width: 20, height: 20, child: CircularProgressIndicator()) + .marginOnly(left: 4, right: 10), + Expanded(child: Text(translate('connecting_status'))) + ]); + } else { + return Row(children: [ + const Icon(Icons.check, color: Colors.greenAccent, size: 24) + .marginOnly(right: 10), + Expanded(child: Text(translate('Ready'))) + ]); + } + } + return PaddingCard( title: translate("Permissions"), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - PermissionRow(translate("Screen Capture"), serverModel.mediaOk, - serverModel.toggleService), - PermissionRow(translate("Input Control"), serverModel.inputOk, - serverModel.toggleInput), - PermissionRow(translate("Transfer File"), serverModel.fileOk, - serverModel.toggleFile), - hasAudioPermission - ? PermissionRow(translate("Audio Capture"), serverModel.audioOk, - serverModel.toggleAudio) - : Text( - "* ${translate("android_version_audio_tip")}", - style: const TextStyle(color: MyTheme.darkGray), - ), - const SizedBox(height: 8), - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - flex: 0, - child: serverModel.mediaOk - ? ElevatedButton.icon( - style: ButtonStyle( - backgroundColor: - MaterialStateProperty.all(Colors.red)), - icon: const Icon(Icons.stop), - onPressed: serverModel.toggleService, - label: Text(translate("Stop service"))) - : ElevatedButton.icon( - icon: const Icon(Icons.play_arrow), - onPressed: serverModel.toggleService, - label: Text(translate("Start Service")))), - Expanded( - child: serverModel.mediaOk - ? Row( - children: [ - Expanded( - flex: 0, - child: Padding( - padding: const EdgeInsets.only( - left: 20, right: 5), - child: Icon(Icons.circle, - color: serverModel.connectStatus > 0 - ? Colors.greenAccent - : Colors.deepOrangeAccent, - size: 10))), - Expanded( - child: Text(translate(status), - softWrap: true, - style: const TextStyle( - fontSize: 14.0, - fontWeight: FontWeight.w500, - color: MyTheme.accent80))) - ], - ) - : const SizedBox.shrink()) - ], - ), - ], - )); + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + PermissionRow(translate("Screen Capture"), serverModel.mediaOk, + serverModel.toggleService), + PermissionRow(translate("Input Control"), serverModel.inputOk, + serverModel.toggleInput), + PermissionRow(translate("Transfer File"), serverModel.fileOk, + serverModel.toggleFile), + hasAudioPermission + ? PermissionRow(translate("Audio Capture"), serverModel.audioOk, + serverModel.toggleAudio) + : Text( + "* ${translate("android_version_audio_tip")}", + style: const TextStyle(color: MyTheme.darkGray), + ), + const SizedBox(height: 8), + serverModel.mediaOk + ? ElevatedButton.icon( + style: ButtonStyle( + backgroundColor: + MaterialStateProperty.all(Colors.red)), + icon: const Icon(Icons.stop), + onPressed: serverModel.toggleService, + label: Text(translate("Stop service"))) + .marginOnly(bottom: 8) + : ElevatedButton.icon( + icon: const Icon(Icons.play_arrow), + onPressed: serverModel.toggleService, + label: Text(translate("Start Service"))) + .marginOnly(bottom: 8), + ServerStateMessage() + ])); } } From b3b6c543122c0c6ecf426fed08b1b56edd95d0b5 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 2 Mar 2023 03:05:03 +0100 Subject: [PATCH 315/382] Mobile. Share Screen. Rearrange button und connection state --- flutter/lib/mobile/pages/server_page.dart | 122 +++++++++------------- 1 file changed, 52 insertions(+), 70 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index 07a81f8de..36cc43ebb 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -170,6 +170,35 @@ class ServerInfo extends StatelessWidget { @override Widget build(BuildContext context) { final isPermanent = model.verificationMethod == kUsePermanentPassword; + final serverModel = Provider.of(context); + + // @todo Theming + Widget Notification() { + const Color colorPositive = Colors.greenAccent; + const Color colorNegative = Colors.redAccent; + const double paddingRight = 15; + + if (serverModel.connectStatus == -1) { + return Row(children: [ + const Icon(Icons.warning_amber_sharp, color: colorNegative, size: 24) + .marginOnly(right: paddingRight), + Expanded(child: Text(translate('not_ready_status'))) + ]); + } else if (serverModel.connectStatus == 0) { + return Row(children: [ + SizedBox(width: 20, height: 20, child: CircularProgressIndicator()) + .marginOnly(left: 4, right: paddingRight), + Expanded(child: Text(translate('connecting_status'))) + ]); + } else { + return Row(children: [ + const Icon(Icons.check, color: colorPositive, size: 24) + .marginOnly(right: paddingRight), + Expanded(child: Text(translate('Ready'))) + ]); + } + } + return model.isStart ? PaddingCard( child: Column( @@ -210,14 +239,14 @@ class ServerInfo extends StatelessWidget { bind.mainUpdateTemporaryPassword())), onSaved: (String? value) {}, ), + Notification().marginOnly(top: 20) ], )) : PaddingCard( child: Column( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Center( - child: Row( + Row( children: [ const Icon(Icons.warning_amber_sharp, color: Colors.redAccent, size: 24), @@ -229,17 +258,18 @@ class ServerInfo extends StatelessWidget { fontFamily: 'WorkSans', fontWeight: FontWeight.bold, fontSize: 18, - color: MyTheme.accent, ), )) ], - )), - const SizedBox(height: 5), - Center( - child: Text( - translate("android_start_service_tip"), - style: const TextStyle(fontSize: 12, color: MyTheme.darkGray), - )) + ).marginOnly(bottom: 8), + Text(translate("android_start_service_tip"), + style: const TextStyle( + fontSize: 12, color: MyTheme.darkGray)) + .marginOnly(bottom: 8), + ElevatedButton.icon( + icon: const Icon(Icons.play_arrow), + onPressed: serverModel.toggleService, + label: Text(translate("Start Service"))) ], )); } @@ -257,51 +287,19 @@ class _PermissionCheckerState extends State { Widget build(BuildContext context) { final serverModel = Provider.of(context); final hasAudioPermission = androidVersion >= 30; - final String status; - if (serverModel.connectStatus == -1) { - status = 'not_ready_status'; - } else if (serverModel.connectStatus == 0) { - status = 'connecting_status'; - } else { - status = 'Ready'; - } - - // @todo Theming - Widget ServerStateMessage() { - if (!serverModel.mediaOk) { - return Row(children: [ - const Icon(Icons.warning_amber_outlined, - color: Colors.redAccent, size: 24) - .marginOnly(right: 10), - Expanded(child: Text(translate('Service is not running'))) - ]); - } - - if (serverModel.connectStatus == -1) { - return Row(children: [ - const Icon(Icons.warning_amber_sharp, - color: Colors.redAccent, size: 24) - .marginOnly(right: 10), - Expanded(child: Text(translate('not_ready_status'))) - ]); - } else if (serverModel.connectStatus == 0) { - return Row(children: [ - SizedBox(width: 20, height: 20, child: CircularProgressIndicator()) - .marginOnly(left: 4, right: 10), - Expanded(child: Text(translate('connecting_status'))) - ]); - } else { - return Row(children: [ - const Icon(Icons.check, color: Colors.greenAccent, size: 24) - .marginOnly(right: 10), - Expanded(child: Text(translate('Ready'))) - ]); - } - } - return PaddingCard( title: translate("Permissions"), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + serverModel.mediaOk + ? ElevatedButton.icon( + style: ButtonStyle( + backgroundColor: + MaterialStateProperty.all(Colors.red)), + icon: const Icon(Icons.stop), + onPressed: serverModel.toggleService, + label: Text(translate("Stop service"))) + .marginOnly(bottom: 8) + : SizedBox.shrink(), PermissionRow(translate("Screen Capture"), serverModel.mediaOk, serverModel.toggleService), PermissionRow(translate("Input Control"), serverModel.inputOk, @@ -314,23 +312,7 @@ class _PermissionCheckerState extends State { : Text( "* ${translate("android_version_audio_tip")}", style: const TextStyle(color: MyTheme.darkGray), - ), - const SizedBox(height: 8), - serverModel.mediaOk - ? ElevatedButton.icon( - style: ButtonStyle( - backgroundColor: - MaterialStateProperty.all(Colors.red)), - icon: const Icon(Icons.stop), - onPressed: serverModel.toggleService, - label: Text(translate("Stop service"))) - .marginOnly(bottom: 8) - : ElevatedButton.icon( - icon: const Icon(Icons.play_arrow), - onPressed: serverModel.toggleService, - label: Text(translate("Start Service"))) - .marginOnly(bottom: 8), - ServerStateMessage() + ) ])); } } From 40115163b41c9689b07560fb902c7bb742386339 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 2 Mar 2023 03:50:04 +0100 Subject: [PATCH 316/382] Mobile. Share Screen. Unify button style --- flutter/lib/models/server_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/lib/models/server_model.dart b/flutter/lib/models/server_model.dart index dde452814..4fab2b24c 100644 --- a/flutter/lib/models/server_model.dart +++ b/flutter/lib/models/server_model.dart @@ -289,7 +289,7 @@ class ServerModel with ChangeNotifier { content: Text(translate("android_stop_service_tip")), actions: [ TextButton(onPressed: close, child: Text(translate("Cancel"))), - ElevatedButton(onPressed: submit, child: Text(translate("OK"))), + TextButton(onPressed: submit, child: Text(translate("OK"))), ], onSubmit: submit, onCancel: close, From 21353a9b474f9d2334dde9cf76a0d2b59dbc559c Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 2 Mar 2023 04:25:43 +0100 Subject: [PATCH 317/382] Mobile. Share Screen. Remove hardcoded colors from serverinfo --- flutter/lib/mobile/pages/server_page.dart | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index 36cc43ebb..96b5eef07 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -207,30 +207,26 @@ class ServerInfo extends StatelessWidget { TextFormField( readOnly: true, style: const TextStyle( - fontSize: 25.0, - fontWeight: FontWeight.bold, - color: MyTheme.accent), + fontSize: 25.0, fontWeight: FontWeight.bold), controller: model.serverId, decoration: InputDecoration( icon: const Icon(Icons.perm_identity), labelText: translate("ID"), - labelStyle: const TextStyle( - fontWeight: FontWeight.bold, color: MyTheme.accent80), + labelStyle: const TextStyle(fontWeight: FontWeight.bold), ), onSaved: (String? value) {}, ), TextFormField( readOnly: true, style: const TextStyle( - fontSize: 25.0, - fontWeight: FontWeight.bold, - color: MyTheme.accent), + fontSize: 25.0, fontWeight: FontWeight.bold), controller: isPermanent ? emptyController : model.serverPasswd, decoration: InputDecoration( icon: const Icon(Icons.lock), labelText: translate("Password"), labelStyle: const TextStyle( - fontWeight: FontWeight.bold, color: MyTheme.accent80), + fontWeight: FontWeight.bold, + ), suffix: isPermanent ? null : IconButton( From b007812bb9751985d138029f1b01c36f312c8585 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 2 Mar 2023 14:56:51 +0100 Subject: [PATCH 318/382] Mobile. Share Screen. Move connection manager into viewport --- flutter/lib/mobile/pages/server_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index 96b5eef07..ace1b8329 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -141,8 +141,8 @@ class _ServerPageState extends State { mainAxisAlignment: MainAxisAlignment.start, children: [ ServerInfo(), - const PermissionChecker(), const ConnectionManager(), + const PermissionChecker(), SizedBox.fromSize(size: const Size(0, 15.0)), ], ), From 2d3694549dbd4a0e0379b78cb4c90416c676d6a7 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 9 Mar 2023 12:31:13 +0100 Subject: [PATCH 319/382] Mobile. Share Screen. Reduce layout shift. connection/server page --- flutter/lib/mobile/pages/server_page.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index ace1b8329..2fe8b9d40 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -477,7 +477,10 @@ class PaddingCard extends StatelessWidget { return SizedBox( width: double.maxFinite, child: Card( - margin: const EdgeInsets.fromLTRB(15.0, 15.0, 15.0, 0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(13), + ), + margin: const EdgeInsets.fromLTRB(12.0, 10.0, 12.0, 0), child: Padding( padding: const EdgeInsets.symmetric(vertical: 15.0, horizontal: 30.0), From 1f8c64030ddf7dfe92607b6c1d2417b25cdff038 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Sat, 4 Mar 2023 16:47:29 +0100 Subject: [PATCH 320/382] Mobile. Share Screen. Use "disconnect" instead of "close" --- flutter/lib/mobile/pages/server_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index 2fe8b9d40..ee8600735 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -418,7 +418,7 @@ class ConnectionManager extends StatelessWidget { gFFI.invokeMethod( "cancel_notification", client.id); }, - label: Text(translate("Close"))) + label: Text(translate("Disconnect"))) : Row(children: [ TextButton( child: Text(translate("Dismiss")), From 9c3334baf4b827efae2b29d20dc99f72e561f8b6 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Mon, 6 Mar 2023 15:27:22 +0100 Subject: [PATCH 321/382] Mobile. Share Screen. Split large ternary to smaller parts --- flutter/lib/mobile/pages/server_page.dart | 145 ++++++++++++---------- 1 file changed, 76 insertions(+), 69 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index ee8600735..a83fec29a 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -140,7 +140,9 @@ class _ServerPageState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ - ServerInfo(), + gFFI.serverModel.isStart + ? ServerInfo() + : ServiceNotRunningNotification(), const ConnectionManager(), const PermissionChecker(), SizedBox.fromSize(size: const Size(0, 15.0)), @@ -161,6 +163,45 @@ void checkService() async { } } +class ServiceNotRunningNotification extends StatelessWidget { + ServiceNotRunningNotification({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final serverModel = Provider.of(context); + + return PaddingCard( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + const Icon(Icons.warning_amber_sharp, + color: Colors.redAccent, size: 24), + const SizedBox(width: 10), + Expanded( + child: Text( + translate("Service is not running"), + style: const TextStyle( + fontFamily: 'WorkSans', + fontWeight: FontWeight.bold, + fontSize: 18, + ), + )) + ], + ).marginOnly(bottom: 8), + Text(translate("android_start_service_tip"), + style: const TextStyle(fontSize: 12, color: MyTheme.darkGray)) + .marginOnly(bottom: 8), + ElevatedButton.icon( + icon: const Icon(Icons.play_arrow), + onPressed: serverModel.toggleService, + label: Text(translate("Start Service"))) + ], + )); + } +} + class ServerInfo extends StatelessWidget { final model = gFFI.serverModel; final emptyController = TextEditingController(text: "-"); @@ -199,75 +240,41 @@ class ServerInfo extends StatelessWidget { } } - return model.isStart - ? PaddingCard( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - TextFormField( - readOnly: true, - style: const TextStyle( - fontSize: 25.0, fontWeight: FontWeight.bold), - controller: model.serverId, - decoration: InputDecoration( - icon: const Icon(Icons.perm_identity), - labelText: translate("ID"), - labelStyle: const TextStyle(fontWeight: FontWeight.bold), - ), - onSaved: (String? value) {}, + return PaddingCard( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextFormField( + readOnly: true, + style: const TextStyle(fontSize: 25.0, fontWeight: FontWeight.bold), + controller: model.serverId, + decoration: InputDecoration( + icon: const Icon(Icons.perm_identity), + labelText: translate("ID"), + labelStyle: const TextStyle(fontWeight: FontWeight.bold), + ), + onSaved: (String? value) {}, + ), + TextFormField( + readOnly: true, + style: const TextStyle(fontSize: 25.0, fontWeight: FontWeight.bold), + controller: isPermanent ? emptyController : model.serverPasswd, + decoration: InputDecoration( + icon: const Icon(Icons.lock), + labelText: translate("Password"), + labelStyle: const TextStyle( + fontWeight: FontWeight.bold, ), - TextFormField( - readOnly: true, - style: const TextStyle( - fontSize: 25.0, fontWeight: FontWeight.bold), - controller: isPermanent ? emptyController : model.serverPasswd, - decoration: InputDecoration( - icon: const Icon(Icons.lock), - labelText: translate("Password"), - labelStyle: const TextStyle( - fontWeight: FontWeight.bold, - ), - suffix: isPermanent - ? null - : IconButton( - icon: const Icon(Icons.refresh), - onPressed: () => - bind.mainUpdateTemporaryPassword())), - onSaved: (String? value) {}, - ), - Notification().marginOnly(top: 20) - ], - )) - : PaddingCard( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Icon(Icons.warning_amber_sharp, - color: Colors.redAccent, size: 24), - const SizedBox(width: 10), - Expanded( - child: Text( - translate("Service is not running"), - style: const TextStyle( - fontFamily: 'WorkSans', - fontWeight: FontWeight.bold, - fontSize: 18, - ), - )) - ], - ).marginOnly(bottom: 8), - Text(translate("android_start_service_tip"), - style: const TextStyle( - fontSize: 12, color: MyTheme.darkGray)) - .marginOnly(bottom: 8), - ElevatedButton.icon( - icon: const Icon(Icons.play_arrow), - onPressed: serverModel.toggleService, - label: Text(translate("Start Service"))) - ], - )); + suffix: isPermanent + ? null + : IconButton( + icon: const Icon(Icons.refresh), + onPressed: () => bind.mainUpdateTemporaryPassword())), + onSaved: (String? value) {}, + ), + Notification().marginOnly(top: 20) + ], + )); } } From 2c231824a02457ba4098f5d09f6400570cb582f1 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Tue, 7 Mar 2023 10:11:06 +0100 Subject: [PATCH 322/382] Mobile. Share Screen. Use switches for permissions --- flutter/lib/mobile/pages/server_page.dart | 39 +++++------------------ 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index a83fec29a..d584d3bb4 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -330,37 +330,14 @@ class PermissionRow extends StatelessWidget { @override Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - flex: 5, - child: FittedBox( - fit: BoxFit.scaleDown, - alignment: Alignment.centerLeft, - child: - Text(name, style: Theme.of(context).textTheme.labelLarge))), - Expanded( - flex: 2, - child: FittedBox( - fit: BoxFit.scaleDown, - child: Text(isOk ? translate("ON") : translate("OFF"), - style: TextStyle( - fontSize: 16.0, - color: isOk ? Colors.green : Colors.grey))), - ), - Expanded( - flex: 3, - child: FittedBox( - fit: BoxFit.scaleDown, - alignment: Alignment.centerRight, - child: TextButton( - onPressed: onPressed, - child: Text( - translate(isOk ? "CLOSE" : "OPEN"), - style: const TextStyle(fontWeight: FontWeight.bold), - )))), - ], - ); + return SwitchListTile( + visualDensity: VisualDensity.compact, + contentPadding: EdgeInsets.all(0), + title: Text(name), + value: isOk, + onChanged: (bool value) { + onPressed(); + }); } } From 04c0d73afc98a6cbc4e1569921e93bb830f7a69b Mon Sep 17 00:00:00 2001 From: grummbeer Date: Tue, 7 Mar 2023 10:43:55 +0100 Subject: [PATCH 323/382] Mobile. Share Screen. Add icon to "no audio" info --- flutter/lib/mobile/pages/server_page.dart | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index d584d3bb4..7ed2575ef 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -312,10 +312,14 @@ class _PermissionCheckerState extends State { hasAudioPermission ? PermissionRow(translate("Audio Capture"), serverModel.audioOk, serverModel.toggleAudio) - : Text( - "* ${translate("android_version_audio_tip")}", - style: const TextStyle(color: MyTheme.darkGray), - ) + : Row(children: [ + Icon(Icons.info_outline).marginOnly(right: 15), + Expanded( + child: Text( + translate("android_version_audio_tip"), + style: const TextStyle(color: MyTheme.darkGray), + )) + ]) ])); } } From 1227d6687157dc729fcac8e59ff45edaa5779cd0 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Tue, 7 Mar 2023 10:44:16 +0100 Subject: [PATCH 324/382] Mobile. Share Screen. Rename widget to more descriptive name --- flutter/lib/mobile/pages/server_page.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index 7ed2575ef..9e2bc3f07 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -214,7 +214,7 @@ class ServerInfo extends StatelessWidget { final serverModel = Provider.of(context); // @todo Theming - Widget Notification() { + Widget ConnectionStateNotification() { const Color colorPositive = Colors.greenAccent; const Color colorNegative = Colors.redAccent; const double paddingRight = 15; @@ -272,7 +272,7 @@ class ServerInfo extends StatelessWidget { onPressed: () => bind.mainUpdateTemporaryPassword())), onSaved: (String? value) {}, ), - Notification().marginOnly(top: 20) + ConnectionStateNotification().marginOnly(top: 20) ], )); } From 45d19a62f9df4231769de4508cee1091b856b8c2 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Tue, 7 Mar 2023 11:45:20 +0100 Subject: [PATCH 325/382] Mobile. Share Screen. Unify usage of card.title, avoid title overflow --- flutter/lib/mobile/pages/server_page.dart | 63 ++++++++++------------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index 9e2bc3f07..775173812 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -171,34 +171,22 @@ class ServiceNotRunningNotification extends StatelessWidget { final serverModel = Provider.of(context); return PaddingCard( + title: translate("Service is not running"), + titleIcon: + const Icon(Icons.warning_amber_sharp, color: Colors.redAccent), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Icon(Icons.warning_amber_sharp, - color: Colors.redAccent, size: 24), - const SizedBox(width: 10), - Expanded( - child: Text( - translate("Service is not running"), - style: const TextStyle( - fontFamily: 'WorkSans', - fontWeight: FontWeight.bold, - fontSize: 18, - ), - )) + Text(translate("android_start_service_tip"), + style: + const TextStyle(fontSize: 12, color: MyTheme.darkGray)) + .marginOnly(bottom: 8), + ElevatedButton.icon( + icon: const Icon(Icons.play_arrow), + onPressed: serverModel.toggleService, + label: Text(translate("Start Service"))) ], - ).marginOnly(bottom: 8), - Text(translate("android_start_service_tip"), - style: const TextStyle(fontSize: 12, color: MyTheme.darkGray)) - .marginOnly(bottom: 8), - ElevatedButton.icon( - icon: const Icon(Icons.play_arrow), - onPressed: serverModel.toggleService, - label: Text(translate("Start Service"))) - ], - )); + )); } } @@ -358,8 +346,8 @@ class ConnectionManager extends StatelessWidget { ? "File Connection" : "Screen Connection"), titleIcon: client.isFileTransfer - ? Icons.folder_outlined - : Icons.mobile_screen_share, + ? Icon(Icons.folder_outlined) + : Icon(Icons.mobile_screen_share), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -431,7 +419,7 @@ class PaddingCard extends StatelessWidget { : super(key: key); final String? title; - final IconData? titleIcon; + final Icon? titleIcon; final Widget child; @override @@ -447,16 +435,17 @@ class PaddingCard extends StatelessWidget { titleIcon != null ? Padding( padding: const EdgeInsets.only(right: 10), - child: - Icon(titleIcon, color: MyTheme.accent, size: 30)) + child: titleIcon) : const SizedBox.shrink(), - Text( - title!, - style: const TextStyle( - fontFamily: 'WorkSans', - fontWeight: FontWeight.bold, - fontSize: 20, - color: MyTheme.accent, + Expanded( + child: Text( + title!, + style: const TextStyle( + fontFamily: 'WorkSans', + fontWeight: FontWeight.bold, + fontSize: 20, + color: MyTheme.accent, + ), ), ) ], From 583b5bf4ead9dac619d71378101e1c002b6c170e Mon Sep 17 00:00:00 2001 From: grummbeer Date: Tue, 7 Mar 2023 12:12:31 +0100 Subject: [PATCH 326/382] Mobile. Share Screen. Remove hardcoded colors from connection card --- flutter/lib/mobile/pages/server_page.dart | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index 775173812..7079fc5e1 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -369,10 +369,7 @@ class ConnectionManager extends StatelessWidget { bar.onTap!(1); } }, - icon: const Icon( - Icons.chat, - color: MyTheme.accent, - ))) + icon: const Icon(Icons.chat))) ], ), client.authorized @@ -429,7 +426,7 @@ class PaddingCard extends StatelessWidget { children.insert( 0, Padding( - padding: const EdgeInsets.symmetric(vertical: 5.0), + padding: const EdgeInsets.fromLTRB(0, 5, 0, 8), child: Row( children: [ titleIcon != null @@ -441,11 +438,7 @@ class PaddingCard extends StatelessWidget { child: Text( title!, style: const TextStyle( - fontFamily: 'WorkSans', - fontWeight: FontWeight.bold, - fontSize: 20, - color: MyTheme.accent, - ), + fontSize: 18, fontWeight: FontWeight.bold), ), ) ], @@ -494,13 +487,9 @@ class ClientInfo extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ - Text(client.name, - style: const TextStyle( - color: MyTheme.idColor, fontSize: 18)), + Text(client.name, style: const TextStyle(fontSize: 18)), const SizedBox(width: 8), - Text(client.peerId, - style: const TextStyle( - color: MyTheme.idColor, fontSize: 10)) + Text(client.peerId, style: const TextStyle(fontSize: 10)) ])) ], ), From 772ce658cfcae638c2e600fad0765b572fad2e0c Mon Sep 17 00:00:00 2001 From: grummbeer Date: Tue, 7 Mar 2023 12:16:19 +0100 Subject: [PATCH 327/382] Mobile. Share Screen. Add check icon to "accept" button --- flutter/lib/mobile/pages/server_page.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index 7079fc5e1..dcd1fae7c 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -399,8 +399,9 @@ class ConnectionManager extends StatelessWidget { serverModel.sendLoginResponse(client, false); }), const SizedBox(width: 20), - ElevatedButton( - child: Text(translate("Accept")), + ElevatedButton.icon( + icon: const Icon(Icons.check), + label: Text(translate("Accept")), onPressed: () { serverModel.sendLoginResponse(client, true); }), From 90cc95b1d08713e87e2dc74590d5344126af17b3 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Tue, 7 Mar 2023 13:20:14 +0100 Subject: [PATCH 328/382] Mobile. Share Screen. Connection card button align right --- flutter/lib/mobile/pages/server_page.dart | 125 ++++++++++++---------- 1 file changed, 66 insertions(+), 59 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index dcd1fae7c..a92a13609 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -349,65 +349,72 @@ class ConnectionManager extends StatelessWidget { ? Icon(Icons.folder_outlined) : Icon(Icons.mobile_screen_share), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded(child: ClientInfo(client)), - Expanded( - flex: -1, - child: client.isFileTransfer || !client.authorized - ? const SizedBox.shrink() - : IconButton( - onPressed: () { - gFFI.chatModel.changeCurrentID(client.id); - final bar = - navigationBarKey.currentWidget; - if (bar != null) { - bar as BottomNavigationBar; - bar.onTap!(1); - } - }, - icon: const Icon(Icons.chat))) - ], - ), - client.authorized - ? const SizedBox.shrink() - : Text( - translate("android_new_connection_tip"), - style: Theme.of(globalKey.currentContext!) - .textTheme - .bodyMedium, - ), - client.authorized - ? ElevatedButton.icon( - style: ButtonStyle( - backgroundColor: - MaterialStatePropertyAll(Colors.red)), - icon: const Icon(Icons.close), - onPressed: () { - bind.cmCloseConnection(connId: client.id); - gFFI.invokeMethod( - "cancel_notification", client.id); - }, - label: Text(translate("Disconnect"))) - : Row(children: [ - TextButton( - child: Text(translate("Dismiss")), - onPressed: () { - serverModel.sendLoginResponse(client, false); - }), - const SizedBox(width: 20), - ElevatedButton.icon( - icon: const Icon(Icons.check), - label: Text(translate("Accept")), - onPressed: () { - serverModel.sendLoginResponse(client, true); - }), - ]), - ], - ))) + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded(child: ClientInfo(client)), + Expanded( + flex: -1, + child: client.isFileTransfer || !client.authorized + ? const SizedBox.shrink() + : IconButton( + onPressed: () { + gFFI.chatModel + .changeCurrentID(client.id); + final bar = + navigationBarKey.currentWidget; + if (bar != null) { + bar as BottomNavigationBar; + bar.onTap!(1); + } + }, + icon: const Icon(Icons.chat))) + ], + ), + client.authorized + ? const SizedBox.shrink() + : Text( + translate("android_new_connection_tip"), + style: Theme.of(context).textTheme.bodyMedium, + ).marginOnly(bottom: 5), + client.authorized + ? Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + ElevatedButton.icon( + style: ButtonStyle( + backgroundColor: + MaterialStatePropertyAll( + Colors.red)), + icon: const Icon(Icons.close), + onPressed: () { + bind.cmCloseConnection( + connId: client.id); + gFFI.invokeMethod( + "cancel_notification", client.id); + }, + label: Text(translate("Disconnect"))) + ]) + : Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + child: Text(translate("Dismiss")), + onPressed: () { + serverModel.sendLoginResponse( + client, false); + }).marginOnly(right: 15), + ElevatedButton.icon( + icon: const Icon(Icons.check), + label: Text(translate("Accept")), + onPressed: () { + serverModel.sendLoginResponse( + client, true); + }), + ]), + ]))) .toList()); } } From 03eba7faf0cfdeec749d90fe49952051926ceaf0 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Tue, 7 Mar 2023 14:19:28 +0100 Subject: [PATCH 329/382] Mobile. Share Screen. More contrast for avatar on light --- flutter/lib/mobile/pages/server_page.dart | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index a92a13609..4a93bbec2 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -487,8 +487,11 @@ class ClientInfo extends StatelessWidget { child: Padding( padding: const EdgeInsets.only(right: 12), child: CircleAvatar( - backgroundColor: - str2color(client.name).withOpacity(0.7), + backgroundColor: str2color( + client.name, + Theme.of(context).brightness == Brightness.light + ? 255 + : 150), child: Text(client.name[0])))), Expanded( child: Column( From 5daa985ec5a25f91b63baef8b548a5ea90fa0179 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Tue, 7 Mar 2023 14:55:00 +0100 Subject: [PATCH 330/382] Mobile. Share Screen. Remove obsolete keys from translation files --- src/lang/ca.rs | 4 +--- src/lang/cn.rs | 4 +--- src/lang/cs.rs | 4 +--- src/lang/da.rs | 4 +--- src/lang/de.rs | 2 -- src/lang/el.rs | 4 +--- src/lang/en.rs | 2 +- src/lang/eo.rs | 2 -- src/lang/es.rs | 4 +--- src/lang/fa.rs | 4 +--- src/lang/fr.rs | 4 +--- src/lang/hu.rs | 4 +--- src/lang/id.rs | 4 +--- src/lang/it.rs | 4 +--- src/lang/ja.rs | 4 +--- src/lang/ko.rs | 4 +--- src/lang/kz.rs | 4 +--- src/lang/nl.rs | 4 +--- src/lang/pl.rs | 4 +--- src/lang/pt_PT.rs | 4 +--- src/lang/ptbr.rs | 4 +--- src/lang/ro.rs | 4 +--- src/lang/ru.rs | 4 +--- src/lang/sk.rs | 4 +--- src/lang/sl.rs | 4 +--- src/lang/sq.rs | 4 +--- src/lang/sr.rs | 4 +--- src/lang/sv.rs | 4 +--- src/lang/template.rs | 2 -- src/lang/th.rs | 4 +--- src/lang/tr.rs | 4 +--- src/lang/tw.rs | 4 +--- src/lang/ua.rs | 4 +--- src/lang/vn.rs | 4 +--- 34 files changed, 31 insertions(+), 97 deletions(-) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 0d0219126..9e8770c2b 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Nota"), ("Connection", "connexió"), ("Share Screen", "Compartir pantalla"), - ("CLOSE", "TANCAR"), - ("OPEN", "OBRIR"), ("Chat", "Xat"), ("Total", "Total"), ("items", "ítems"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Habilitar la captura de pantalla iniciarà el servei automàticament, i permetrà que altres dispositius sol·licitin una connexió des d'aquest dispositiu."), ("android_stop_service_tip", "Tancar el servei tancarà totes les connexions establertes."), ("android_version_audio_tip", "La versión actual de Android no admet la captura d'àudio, actualizi a Android 10 o superior."), - ("android_start_service_tip", "Toqui el permís [Iniciar servei] o OBRIR [Captura de pantalla] per iniciar el servei d'ús compartit de pantalla."), + ("android_start_service_tip", ""), ("Account", "Compte"), ("Overwrite", "Sobreescriure"), ("This file exists, skip or overwrite this file?", "Aquest arxiu ja existeix, ometre o sobreescriure l'arxiu?"), diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 8fe826232..c5cf4cd03 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "备注"), ("Connection", "连接"), ("Share Screen", "共享屏幕"), - ("CLOSE", "关闭"), - ("OPEN", "开启"), ("Chat", "聊天消息"), ("Total", "总计"), ("items", "个项目"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "开启录屏权限将自动开启服务,允许其他设备向此设备请求建立连接。"), ("android_stop_service_tip", "关闭服务将自动关闭所有已建立的连接。"), ("android_version_audio_tip", "当前安卓版本不支持音频录制,请升级至安卓 10 或更高。"), - ("android_start_service_tip", "点击 [启动服务] 或打开 [屏幕录制] 权限开启手机屏幕共享服务。"), + ("android_start_service_tip", ""), ("Account", "账户"), ("Overwrite", "覆盖"), ("This file exists, skip or overwrite this file?", "这个文件/文件夹已存在,跳过/覆盖?"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 5893b3e15..620cc1373 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Poznámka"), ("Connection", "Připojení"), ("Share Screen", "Nasdílet obrazovku"), - ("CLOSE", "ZAVŘÍT"), - ("OPEN", "OTEVŘÍT"), ("Chat", "Chat"), ("Total", "Celkem"), ("items", "Položek"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Zapnutí „Zachytávání obsahu obrazovky“ automaticky spustí službu, což umožní ostatním zařízením žádat o připojení k vašemu zařízení."), ("android_stop_service_tip", "Zastavení služby automaticky ukončí veškerá navázaná spojení."), ("android_version_audio_tip", "Vámi nyní používaná verze systému Android nepodporuje zachytávání zvuku – přejděte na Android 10 nebo novější."), - ("android_start_service_tip", "Službu pro sdílení obrazovky spustíte klepnutím na [Spustit službu] nebo UDĚLTE pověření pro [Zachytávání obsahu obrazovky]."), + ("android_start_service_tip", ""), ("Account", ""), ("Overwrite", "Přepsat"), ("This file exists, skip or overwrite this file?", "Tento soubor existuje – přeskočit ho nebo přepsat?"), diff --git a/src/lang/da.rs b/src/lang/da.rs index 0c2a01d63..dbb9e3060 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Note"), ("Connection", "Forbindelse"), ("Share Screen", "Del skærmen"), - ("CLOSE", "LUK"), - ("OPEN", "ÅBEN"), ("Chat", "Chat"), ("Total", "Total"), ("items", "artikel"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Ved at tænde for skærmoptagelsen startes tjenesten automatisk, så andre enheder kan anmode om en forbindelse fra denne enhed."), ("android_stop_service_tip", "Ved at lukke tjenesten lukkes alle fremstillede forbindelser automatisk."), ("android_version_audio_tip", "Den aktuelle Android -version understøtter ikke lydoptagelse, skal du opdatere om Android 10 eller højere."), - ("android_start_service_tip", "Tryk på [Start Service] eller åbn autorisationen [skærmoptagelse] for at starte skærmudgivelsen."), + ("android_start_service_tip", ""), ("Account", "Konto"), ("Overwrite", "Overskriv"), ("This file exists, skip or overwrite this file?", "Denne fil findes, springer over denne fil eller overskriver?"), diff --git a/src/lang/de.rs b/src/lang/de.rs index b9fc7834a..2127ecaac 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Hinweis"), ("Connection", "Verbindung"), ("Share Screen", "Bildschirm freigeben"), - ("CLOSE", "DEAKTIVIEREN"), - ("OPEN", "AKTIVIEREN"), ("Chat", "Chat"), ("Total", "Gesamt"), ("items", "Einträge"), diff --git a/src/lang/el.rs b/src/lang/el.rs index 63811f209..dae1dedf4 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Σημείωση"), ("Connection", "Σύνδεση"), ("Share Screen", "Κοινή χρήση οθόνης"), - ("CLOSE", "Απενεργοποίηση"), - ("OPEN", "Ενεργοποίηση"), ("Chat", "Κουβέντα"), ("Total", "Σύνολο"), ("items", "στοιχεία"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Η ενεργοποίηση της κοινής χρήσης οθόνης θα ξεκινήσει αυτόματα την υπηρεσία, ώστε άλλες συσκευές να μπορούν να ελέγχουν αυτήν τη συσκευή Android."), ("android_stop_service_tip", "Η απενεργοποίηση της υπηρεσίας θα αποσυνδέσει αυτόματα όλες τις εγκατεστημένες συνδέσεις."), ("android_version_audio_tip", "Η έκδοση Android που διαθέτετε δεν υποστηρίζει εγγραφή ήχου, ενημερώστε το σε Android 10 ή νεότερη έκδοση, εάν είναι δυνατόν."), - ("android_start_service_tip", "Πατήστε [Ενεργοποίηση υπηρεσίας] ή ενεργοποιήστε την άδεια [Πρόσβαση στην οθόνη] για να ξεκινήσετε την υπηρεσία κοινής χρήσης οθόνης."), + ("android_start_service_tip", ""), ("Account", "Λογαριασμός"), ("Overwrite", "Αντικατάσταση"), ("This file exists, skip or overwrite this file?", "Αυτό το αρχείο υπάρχει, παράβλεψη ή αντικατάσταση αυτού του αρχείου;"), diff --git a/src/lang/en.rs b/src/lang/en.rs index 100788f6e..7107c1865 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -23,7 +23,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Turning on \"Screen Capture\" will automatically start the service, allowing other devices to request a connection to your device."), ("android_stop_service_tip", "Closing the service will automatically close all established connections."), ("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."), + ("android_start_service_tip", "Tap [Start Service] or enable [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"), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 24df8827b..3ff7b608a 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Notu"), ("Connection", ""), ("Share Screen", ""), - ("CLOSE", ""), - ("OPEN", ""), ("Chat", ""), ("Total", ""), ("items", ""), diff --git a/src/lang/es.rs b/src/lang/es.rs index 585a10d68..ba9e8a3d2 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Nota"), ("Connection", "Conexión"), ("Share Screen", "Compartir pantalla"), - ("CLOSE", "CERRAR"), - ("OPEN", "ABRIR"), ("Chat", "Chat"), ("Total", "Total"), ("items", "items"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Habilitar la captura de pantalla iniciará automáticamente el servicio, lo que permitirá que otros dispositivos soliciten una conexión desde este dispositivo."), ("android_stop_service_tip", "Cerrar el servicio cerrará automáticamente todas las conexiones establecidas."), ("android_version_audio_tip", "La versión actual de Android no admite la captura de audio, actualice a Android 10 o posterior."), - ("android_start_service_tip", "Toque el permiso [Iniciar servicio] o ABRIR [Captura de pantalla] para iniciar el servicio de uso compartido de pantalla."), + ("android_start_service_tip", ""), ("Account", "Cuenta"), ("Overwrite", "Sobrescribir"), ("This file exists, skip or overwrite this file?", "Este archivo existe, ¿omitir o sobrescribir este archivo?"), diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 3331ab893..9194d2b27 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "یادداشت"), ("Connection", "ارتباط"), ("Share Screen", "اشتراک گذاری صفحه"), - ("CLOSE", "بستن"), - ("OPEN", "باز کردن"), ("Chat", "چت"), ("Total", "مجموع"), ("items", "آیتم ها"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "فعال کردن ضبط صفحه به طور خودکار سرویس را راه اندازی می کند و به دستگاه های دیگر امکان می دهد درخواست اتصال به آن دستگاه را داشته باشند."), ("android_stop_service_tip", "با بستن سرویس، تمام اتصالات برقرار شده به طور خودکار بسته می شود"), ("android_version_audio_tip", "نسخه فعلی اندروید از ضبط صدا پشتیبانی نمی‌کند، لطفاً به اندروید 10 یا بالاتر به‌روزرسانی کنید"), - ("android_start_service_tip", "برای شروع سرویس اشتراک‌گذاری صفحه، روی مجوز \"شروع مرحله‌بندی سرور\" یا OPEN \"Screen Capture\" کلیک کنید."), + ("android_start_service_tip", ""), ("Account", "حساب کاربری"), ("Overwrite", "بازنویسی"), ("This file exists, skip or overwrite this file?", "این فایل وجود دارد، از فایل رد شود یا آن را بازنویسی کند؟"), diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 98083383d..2933fcd79 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Noter"), ("Connection", "Connexion"), ("Share Screen", "Partager l'écran"), - ("CLOSE", "FERMER"), - ("OPEN", "OUVRIR"), ("Chat", "Discuter"), ("Total", "Total"), ("items", "éléments"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "L'activation de la capture d'écran démarrera automatiquement le service, permettant à d'autres appareils de demander une connexion à partir de cet appareil."), ("android_stop_service_tip", "La fermeture du service fermera automatiquement toutes les connexions établies."), ("android_version_audio_tip", "La version actuelle d'Android ne prend pas en charge la capture audio, veuillez passer à Android 10 ou supérieur."), - ("android_start_service_tip", "Appuyez sur [Démarrer le service] ou sur l'autorisation OUVRIR [Capture d'écran] pour démarrer le service de partage d'écran."), + ("android_start_service_tip", ""), ("Account", "Compte"), ("Overwrite", "Écraser"), ("This file exists, skip or overwrite this file?", "Ce fichier existe, ignorer ou écraser ce fichier ?"), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index ef97ce8cf..e05d5f928 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Megyjegyzés"), ("Connection", "Kapcsolat"), ("Share Screen", "Képernyőmegosztás"), - ("CLOSE", "BEZÁRÁS"), - ("OPEN", "MEGNYITÁS"), ("Chat", "Chat"), ("Total", "Összes"), ("items", "elemek"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "A \"Képernyőrögzítés\" bekapcsolásával automatikus elindul a szolgáltatás, lehetővé téve, hogy más eszközök csatlakozási kérelmet küldhessenek"), ("android_stop_service_tip", "A szolgáltatás leállítása automatikusan szétkapcsol minden létező kapcsolatot."), ("android_version_audio_tip", "A jelenlegi Android verzió nem támogatja a hangrögzítést, frissítsen legalább Android 10-re, vagy egy újabb verzióra."), - ("android_start_service_tip", "Nyomjon a [Szolgáltatás indítása] gombra, vagy adjon [Képernyőrözítési] engedélyt az applikációnak hogy elindítsa a képernyőmegosztó szolgáltatást."), + ("android_start_service_tip", ""), ("Account", "Fiók"), ("Overwrite", "Felülírás"), ("This file exists, skip or overwrite this file?", "Ez a fájl már létezik, kihagyja vagy felülírja ezt a fájlt?"), diff --git a/src/lang/id.rs b/src/lang/id.rs index a9a70d473..ca988aac3 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Catatan"), ("Connection", "Koneksi"), ("Share Screen", "Bagikan Layar"), - ("CLOSE", "TUTUP"), - ("OPEN", "BUKA"), ("Chat", "Obrolan"), ("Total", "Total"), ("items", "item"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Mengaktifkan \"Tangkapan Layar\" akan memulai layanan secara otomatis, memungkinkan perangkat lain untuk meminta sambungan ke perangkat Anda."), ("android_stop_service_tip", "Menutup layanan akan secara otomatis menutup semua koneksi yang dibuat."), ("android_version_audio_tip", "Versi Android saat ini tidak mendukung pengambilan audio, harap tingkatkan ke Android 10 atau lebih tinggi."), - ("android_start_service_tip", "Ketuk izin [Mulai Layanan] atau BUKA [Tangkapan Layar] untuk memulai layanan berbagi layar."), + ("android_start_service_tip", ""), ("Account", "Akun"), ("Overwrite", "Timpa"), ("This file exists, skip or overwrite this file?", "File ini sudah ada, lewati atau timpa file ini?"), diff --git a/src/lang/it.rs b/src/lang/it.rs index 136a51945..c7654c480 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Nota"), ("Connection", "Connessione"), ("Share Screen", "Condividi schermo"), - ("CLOSE", "CHIUDERE"), - ("OPEN", "APRIRE"), ("Chat", "Chat"), ("Total", "Totale"), ("items", "Oggetti"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "L'attivazione di Cattura schermo avvierà automaticamente il servizio, consentendo ad altri dispositivi di richiedere una connessione da questo dispositivo."), ("android_stop_service_tip", "La chiusura del servizio chiuderà automaticamente tutte le connessioni stabilite."), ("android_version_audio_tip", "L'attuale versione di Android non supporta l'acquisizione audio, esegui l'upgrade ad Android 10 o versioni successive."), - ("android_start_service_tip", "Toccare [Avvia servizio] o APRI l'autorizzazione [Cattura schermo] per avviare il servizio di condivisione dello schermo."), + ("android_start_service_tip", ""), ("Account", "Account"), ("Overwrite", "Sovrascrivi"), ("This file exists, skip or overwrite this file?", "Questo file esiste, saltare o sovrascrivere questo file?"), diff --git a/src/lang/ja.rs b/src/lang/ja.rs index b30d1942c..26a47cd2d 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "ノート"), ("Connection", "接続"), ("Share Screen", "画面を共有"), - ("CLOSE", "閉じる"), - ("OPEN", "開く"), ("Chat", "チャット"), ("Total", "計"), ("items", "個のアイテム"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "「画面キャプチャ」をオンにするとサービスが自動的に開始され、他の端末がこの端末への接続をリクエストできるようになります。"), ("android_stop_service_tip", "サービスを停止すると、現在確立されている接続が全て自動的に閉じられます。"), ("android_version_audio_tip", "現在のAndroidバージョンでは音声キャプチャはサポートされていません。Android 10以降にアップグレードしてください。"), - ("android_start_service_tip", "「サービスを開始」をタップするか「画面キャプチャ」を開くと、画面共有サービスが開始されます。"), + ("android_start_service_tip", ""), ("Account", ""), ("Overwrite", "上書き"), ("This file exists, skip or overwrite this file?", "このファイルは存在しています。スキップするか上書きしますか?"), diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 8572fa0c1..f79154cd7 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "노트"), ("Connection", "연결"), ("Share Screen", "화면 공유"), - ("CLOSE", "종료"), - ("OPEN", "열기"), ("Chat", "채팅"), ("Total", "총합"), ("items", "개체"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "\"화면 캡처\"를 켜면 서비스가 자동으로 시작되어 다른 장치에서 사용자 장치에 대한 연결을 요청할 수 있습니다."), ("android_stop_service_tip", "서비스를 종료하면 모든 연결이 자동으로 닫힙니다."), ("android_version_audio_tip", "현재 Android 버전은 오디오 캡처를 지원하지 않습니다. Android 10 이상으로 업그레이드하십시오."), - ("android_start_service_tip", "[서비스 시작] 또는 [화면 캡처] 권한을 눌러 화면 공유 서비스를 시작합니다."), + ("android_start_service_tip", ""), ("Account", ""), ("Overwrite", "덮어쓰기"), ("This file exists, skip or overwrite this file?", "해당 파일이 이미 존재합니다, 넘어가거나 덮어쓰시겠습니까?"), diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 78cadf653..11d673f00 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Нота"), ("Connection", "Қосылым"), ("Share Screen", "Екіренді Бөлісу"), - ("CLOSE", "ЖАБУ"), - ("OPEN", "АШУ"), ("Chat", "Чат"), ("Total", "Барлығы"), ("items", "зат"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "\"Екіренді Тұсіру\" қосылған кезде сербес аутыматты іске қосылып, басқа құрылғыларға сіздің құрылғыға қосылым сұраныстауға мүмкіндің береді."), ("android_stop_service_tip", "Сербесті жабу аутыматты түрде барлық орнатылған қосылымдарды жабады."), ("android_version_audio_tip", "Ағымдағы Android нұсқасы аудионы түсіруді қолдамайды, Android 10 не жоғарғысына жаңғыртуды өтінеміз."), - ("android_start_service_tip", "[Сербесті Іске қосу]'ды түртіңіз не [Екіренді Түсіру] рұқсатын АШУ арқылы екіренді бөлісу сербесін іске қосыңыз."), + ("android_start_service_tip", ""), ("Account", "Есепкі"), ("Overwrite", "Үстінен қайта жазу"), ("This file exists, skip or overwrite this file?", "Бұл файыл бар, өткізіп жіберу әлде үстінен қайта жазу керек пе?"), diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 413ad055a..b245cbc50 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Opmerking"), ("Connection", "Verbinding"), ("Share Screen", "Scherm Delen"), - ("CLOSE", "SLUITEN"), - ("OPEN", "OPEN"), ("Chat", "Chat"), ("Total", "Totaal"), ("items", "items"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Als u \"Schermopname\" inschakelt, wordt de service automatisch gestart, zodat andere apparaten een verbinding met uw apparaat kunnen aanvragen."), ("android_stop_service_tip", "Het sluiten van de service zal automatisch alle gemaakte verbindingen sluiten."), ("android_version_audio_tip", "De huidige versie van Android ondersteunt geen audio-opname, upgrade naar Android 10 of hoger."), - ("android_start_service_tip", "Druk op [Start Service] of op de permissie OPEN [Screenshot] om de service voor het overnemen van het scherm te starten."), + ("android_start_service_tip", ""), ("Account", "Account"), ("Overwrite", "Overschrijven"), ("This file exists, skip or overwrite this file?", "Dit bestand bestaat reeds, overslaan of overschrijven?"), diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 4bd7459d9..f4f934b97 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Notatka"), ("Connection", "Połączenie"), ("Share Screen", "Udostępnij ekran"), - ("CLOSE", "Zamknij"), - ("OPEN", "Otwórz"), ("Chat", "Czat"), ("Total", "Łącznie"), ("items", "elementów"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Włączenie opcji „Przechwytywanie ekranu” spowoduje automatyczne uruchomienie usługi, umożliwiając innym urządzeniom żądanie połączenia z Twoim urządzeniem."), ("android_stop_service_tip", "Zamknięcie usługi spowoduje automatyczne zamknięcie wszystkich nawiązanych połączeń."), ("android_version_audio_tip", "Bieżąca wersja systemu Android nie obsługuje przechwytywania dźwięku, zaktualizuj system do wersji Android 10 lub nowszej."), - ("android_start_service_tip", "Kliknij [Uruchom usługę] lub Otwórz [Przechwytywanie ekranu], aby uruchomić usługę udostępniania ekranu."), + ("android_start_service_tip", ""), ("Account", "Konto"), ("Overwrite", "Nadpisz"), ("This file exists, skip or overwrite this file?", "Ten plik istnieje, pominąć czy nadpisać ten plik?"), diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index da90d34aa..77181a5dc 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Nota"), ("Connection", "Ligação"), ("Share Screen", "Partilhar ecrã"), - ("CLOSE", "FECHAR"), - ("OPEN", "ABRIR"), ("Chat", "Conversar"), ("Total", "Total"), ("items", "itens"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Activar a Captura de Ecran irá automaticamente inicializar o serviço, permitindo que outros dispositivos solicitem uma ligação deste dispositivo."), ("android_stop_service_tip", "Fechar o serviço irá automaticamente fechar todas as ligações estabelecidas."), ("android_version_audio_tip", "A versão atual do Android não suporta captura de áudio, por favor actualize para o Android 10 ou maior."), - ("android_start_service_tip", "Toque [Iniciar Serviço] ou abra a permissão [Captura de Ecran] para iniciar o serviço de partilha de ecran."), + ("android_start_service_tip", ""), ("Account", ""), ("Overwrite", "Substituir"), ("This file exists, skip or overwrite this file?", "Este ficheiro já existe, ignorar ou substituir este ficheiro?"), diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index b73b5c743..8006c0700 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Nota"), ("Connection", "Conexão"), ("Share Screen", "Compartilhar Tela"), - ("CLOSE", "FECHAR"), - ("OPEN", "ABRIR"), ("Chat", "Chat"), ("Total", "Total"), ("items", "itens"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Habilitar a Captura de Tela irá automaticamente inicalizar o serviço, permitindo que outros dispositivos solicitem uma conexão deste dispositivo."), ("android_stop_service_tip", "Fechar o serviço irá automaticamente fechar todas as conexões estabelecidas."), ("android_version_audio_tip", "A versão atual do Android não suporta captura de áudio, por favor atualize para o Android 10 ou superior."), - ("android_start_service_tip", "Toque [Iniciar Serviço] ou abra a permissão [Captura de Tela] para iniciar o serviço de compartilhamento de tela."), + ("android_start_service_tip", ""), ("Account", "Conta"), ("Overwrite", "Substituir"), ("This file exists, skip or overwrite this file?", "Este arquivo existe, pular ou substituir este arquivo?"), diff --git a/src/lang/ro.rs b/src/lang/ro.rs index f668e2e87..ccbb1c90b 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Reține"), ("Connection", "Conexiune"), ("Share Screen", "Partajează ecran"), - ("CLOSE", "ÎNCHIDE"), - ("OPEN", "DESCHIDE"), ("Chat", "Discută"), ("Total", "Total"), ("items", "elemente"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Activarea setării Captură ecran va porni automat serviciul, permițând altor dispozitive să solicite conectarea la dispozitivul tău."), ("android_stop_service_tip", "Închiderea serviciului va închide automat toate conexiunile stabilite."), ("android_version_audio_tip", "Versiunea actuală de Android nu suportă captura audio. Fă upgrade la Android 10 sau la o versiune superioară."), - ("android_start_service_tip", "Apasă [Pornește serviciu] sau DESCHIDE [Captură ecran] pentru a porni serviciul de partajare a ecranului."), + ("android_start_service_tip", ""), ("Account", "Cont"), ("Overwrite", "Suprascrie"), ("This file exists, skip or overwrite this file?", "Fișier deja existent. Omite sau suprascrie?"), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index c075d6442..a336f74ea 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Примечание"), ("Connection", "Соединение"), ("Share Screen", "Демонстрация экрана"), - ("CLOSE", "ЗАКРЫТЬ"), - ("OPEN", "ОТКРЫТЬ"), ("Chat", "Чат"), ("Total", "Всего"), ("items", "элементы"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Включение захвата экрана автоматически запускает службу, позволяя другим устройствам запрашивать соединение с этим устройством."), ("android_stop_service_tip", "Закрытие службы автоматически закроет все установленные соединения."), ("android_version_audio_tip", "Текущая версия Android не поддерживает захват звука, обновите её до Android 10 или выше."), - ("android_start_service_tip", "Нажмите \"Запуск промежуточного сервера\" или ОТКРЫТЬ разрешение \"Захват экрана\", чтобы запустить службу демонстрации экрана."), + ("android_start_service_tip", ""), ("Account", "Аккаунт"), ("Overwrite", "Перезаписать"), ("This file exists, skip or overwrite this file?", "Этот файл существует, пропустить или перезаписать файл?"), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index f5aaff84c..90ac16fd4 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Poznámka"), ("Connection", "Pripojenie"), ("Share Screen", "Zdielať obrazovku"), - ("CLOSE", "ZATVORIŤ"), - ("OPEN", "OTVORIŤ"), ("Chat", "Chat"), ("Total", "Celkom"), ("items", "položiek"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Zapnutie \"Zachytávanie obsahu obrazovky\" automaticky spistí službu, čo iným zariadeniam umožní požiadať o pripojenie k tomuto zariadeniu."), ("android_stop_service_tip", "Zastavenie služby automaticky ukončí všetky naviazané spojenia."), ("android_version_audio_tip", "Vaša verzia Androidu neumožňuje zaznamenávanie zvuku. Prejdite na verziu Android 10 alebo vyššiu."), - ("android_start_service_tip", "Klepnite na [Spustiť službu] alebo OTVORTE oprávnenie [Zachytávanie obsahu obrazovky], aby sa aktivovala služba zdieľania obrazovky."), + ("android_start_service_tip", ""), ("Account", ""), ("Overwrite", "Prepísať"), ("This file exists, skip or overwrite this file?", "Preskočiť alebo prepísať existujúci súbor?"), diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 7e6bf57e3..b91f6e374 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Opomba"), ("Connection", "Povezava"), ("Share Screen", "Deli zaslon"), - ("CLOSE", "ZAPRI"), - ("OPEN", "ODPRI"), ("Chat", "Pogovor"), ("Total", "Skupaj"), ("items", "elementi"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Z vklopom zajema zaslona se bo samodejno zagnala storitev, ki omogoča da oddaljene naprave pošljejo zahtevo za povezavo na vašo napravo."), ("android_stop_service_tip", "Z zaustavitvijo storitve bodo samodejno prekinjene vse oddaljene povezave."), ("android_version_audio_tip", "Trenutna različica Androida ne omogoča zajema zvoka. Za zajem zvoka nadgradite na Android 10 ali novejši."), - ("android_start_service_tip", "Tapnite »Zaženi storitev« ali »ODPRI« pri dovoljenju za zajem zaslona da zaženete storitev deljenja zaslona."), + ("android_start_service_tip", ""), ("Account", "Račun"), ("Overwrite", "Prepiši"), ("This file exists, skip or overwrite this file?", "Datoteka obstaja, izpusti ali prepiši?"), diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 4e263670c..b26ac909a 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Shënime"), ("Connection", "Lidhja"), ("Share Screen", "Ndaj ekranin"), - ("CLOSE", "Mbyll"), - ("OPEN", "Hap"), ("Chat", "Biseda"), ("Total", "Total"), ("items", "artikuj"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Aktivizimi i \"Regjistrimi i ekranit\" do të nisë automatikisht shërbimin, duke lejuar pajisjet e tjera të kërkojnë një lidhje me pajisjen tuaj."), ("android_stop_service_tip", "Mbyllja e shërbimit do të mbyllë automatikisht të gjitha lidhjet e vendosura."), ("android_version_audio_tip", "Versioni aktual i Android nuk mbështet regjistrimin e audios, ju lutemi përmirësoni në Android 10 ose më të lartë."), - ("android_start_service_tip", "Shtyp [Fillo Shërbimin] ose HAP lejen e [Kapjen e Ekranit] për të nisur shërbimin e ndarjes së ekranit."), + ("android_start_service_tip", ""), ("Account", "Llogaria"), ("Overwrite", "Përshkruaj"), ("This file exists, skip or overwrite this file?", "Ky skedar ekziston , tejkalo ose përshkruaj këtë skedarë"), diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 1ce22c5c3..7d6178c43 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Primedba"), ("Connection", "Konekcija"), ("Share Screen", "Podeli ekran"), - ("CLOSE", "ZATVORI"), - ("OPEN", "OTVORI"), ("Chat", "Dopisivanje"), ("Total", "Ukupno"), ("items", "stavki"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Uključenje \"Screen Capture\" automatski će pokrenuti servis, dozvoljavajući drugim uređajima da zahtevaju spajanje na vaš uređaj."), ("android_stop_service_tip", "Zatvaranje servisa automatski će zatvoriti sve uspostavljene konekcije."), ("android_version_audio_tip", "Tekuća Android verzija ne podržava audio snimanje, molimo nadogradite na Android 10 ili veći."), - ("android_start_service_tip", "Kliknite [Start Service] ili OPEN [Screen Capture] dozvolu da pokrenete servis deljenja ekrana."), + ("android_start_service_tip", ""), ("Account", "Nalog"), ("Overwrite", "Prepiši preko"), ("This file exists, skip or overwrite this file?", "Ova datoteka postoji, preskoči ili prepiši preko?"), diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 58fe1c318..2b926cfc7 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Notering"), ("Connection", "Anslutning"), ("Share Screen", "Dela skärm"), - ("CLOSE", "STÄNG"), - ("OPEN", "ÖPPNA"), ("Chat", "Chatt"), ("Total", "Totalt"), ("items", "föremål"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Sätter du på \"skärminspelning\" kommer tjänsten automatiskt att starta. Detta tillåter andra enheter att kontrollera din enhet."), ("android_stop_service_tip", "Genom att stänga av tjänsten kommer alla enheter att kopplas ifrån."), ("android_version_audio_tip", "Din version av Android stödjer inte ljudinspelning, Android 10 eller nyare krävs"), - ("android_start_service_tip", "Tryck på [Starta tjänsten] eller tillåt [skärminspelning] för att starta skärmdelning."), + ("android_start_service_tip", ""), ("Account", "Konto"), ("Overwrite", "Skriv över"), ("This file exists, skip or overwrite this file?", "Filen finns redan, hoppa över eller skriv över filen?"), diff --git a/src/lang/template.rs b/src/lang/template.rs index 8e1e85bde..fb62a9540 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", ""), ("Connection", ""), ("Share Screen", ""), - ("CLOSE", ""), - ("OPEN", ""), ("Chat", ""), ("Total", ""), ("items", ""), diff --git a/src/lang/th.rs b/src/lang/th.rs index 770ccef1d..ba501da16 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "บันทึกข้อความ"), ("Connection", "การเชื่อมต่อ"), ("Share Screen", "แชร์หน้าจอ"), - ("CLOSE", "ปิด"), - ("OPEN", "เปิด"), ("Chat", "แชท"), ("Total", "รวม"), ("items", "รายการ"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "การเปิดการใช้งาน \"การบันทึกหน้าจอ\" จะเป็นการเริ่มต้นการทำงานของเซอร์วิสโดยอัตโนมัติ ที่จะอนุญาตให้อุปกรณ์อื่นๆ ส่งคำขอเข้าถึงมายังอุปกรณ์ของคุณได้"), ("android_stop_service_tip", "การปิดการใช้งานเซอร์วิสจะปิดการเชื่อมต่อทั้งหมดโดยอัตโนมัติ"), ("android_version_audio_tip", "เวอร์ชั่นแอนดรอยด์ปัจจุบันของคุณไม่รองรับการบันทึกข้อมูลเสียง กรุณาอัปเกรดเป็นแอนดรอยด์เวอร์ชั่น 10 หรือสูงกว่า"), - ("android_start_service_tip", "แตะ [เริ่มต้นใช้งานเซอร์วิส] หรือเปิดสิทธิ์ [การบันทึกหน้าจอ] เพื่อเริ่มเซอร์วิสการแชร์หน้าจอ"), + ("android_start_service_tip", ""), ("Account", "บัญชี"), ("Overwrite", "เขียนทับ"), ("This file exists, skip or overwrite this file?", "พบไฟล์ที่มีอยู่แล้ว ต้องการเขียนทับหรือไม่?"), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 3fd1de33c..641e9cd0b 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Not"), ("Connection", "Bağlantı"), ("Share Screen", "Ekranı Paylaş"), - ("CLOSE", "KAPAT"), - ("OPEN", "AÇ"), ("Chat", "Mesajlaş"), ("Total", "Toplam"), ("items", "öğeler"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Ekran Yakalamanın etkinleştirilmesi, hizmeti otomatik olarak başlatacak ve diğer cihazların bu cihazdan bağlantı talep etmesine izin verecektir."), ("android_stop_service_tip", "Hizmetin kapatılması, kurulan tüm bağlantıları otomatik olarak kapatacaktır."), ("android_version_audio_tip", "Mevcut Android sürümü ses yakalamayı desteklemiyor, lütfen Android 10 veya sonraki bir sürüme yükseltin."), - ("android_start_service_tip", "Ekran paylaşım hizmetini başlatmak için [Hizmeti Başlat] veya AÇ [Ekran Yakalama] iznine dokunun."), + ("android_start_service_tip", ""), ("Account", "Hesap"), ("Overwrite", "üzerine yaz"), ("This file exists, skip or overwrite this file?", "Bu dosya var, bu dosya atlansın veya üzerine yazılsın mı?"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index b6abf9067..c7089620e 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "備註"), ("Connection", "連接"), ("Share Screen", "共享畫面"), - ("CLOSE", "關閉"), - ("OPEN", "開啟"), ("Chat", "聊天消息"), ("Total", "總計"), ("items", "個項目"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "開啟畫面錄製權限將自動開啟服務,允許其他裝置向此裝置請求建立連接。"), ("android_stop_service_tip", "關閉服務將自動關閉所有已建立的連接。"), ("android_version_audio_tip", "目前的 Android 版本不支持音訊錄製,請升級至 Android 10 或以上版本。"), - ("android_start_service_tip", "點擊 「啟動服務」 或啟用 「畫面錄製」 權限以開啟手機畫面共享服務。"), + ("android_start_service_tip", ""), ("Account", "賬戶"), ("Overwrite", "覆寫"), ("This file exists, skip or overwrite this file?", "此檔案/資料夾已存在,要跳過或是覆寫此檔案嗎?"), diff --git a/src/lang/ua.rs b/src/lang/ua.rs index d838265fa..f085a0f26 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Примітка"), ("Connection", "З'єднання"), ("Share Screen", "Поділитися екраном"), - ("CLOSE", "ЗАКРИТИ"), - ("OPEN", "ВІДКРИТИ"), ("Chat", "Чат"), ("Total", "Всього"), ("items", "елементи"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Увімкнення захоплення екрана автоматично запускає службу, дозволяючи іншим пристроям запитувати з'єднання з цього пристрою."), ("android_stop_service_tip", "Закриття служби автоматично закриє всі встановлені з'єднання."), ("android_version_audio_tip", "Поточна версія Android не підтримує захоплення звуку, оновіть її до Android 10 або вище."), - ("android_start_service_tip", "Натисніть [Запуск проміжного сервера] або ВІДКРИТИ роздільну здатність [Захоплення екрана], щоб запустити службу демонстрації екрана."), + ("android_start_service_tip", ""), ("Account", "Акаунт"), ("Overwrite", "Перезаписати"), ("This file exists, skip or overwrite this file?", "Цей файл існує, пропустити або перезаписати файл?"), diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 27b24878d..fe3aaa57b 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -270,8 +270,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Note", "Ghi nhớ"), ("Connection", "Kết nối"), ("Share Screen", "Chia sẻ màn hình"), - ("CLOSE", "ĐÓNG"), - ("OPEN", "MỞ"), ("Chat", "Chat"), ("Total", "Tổng"), ("items", "items"), @@ -290,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Bật \"Ghi màn hình\" sẽ tự động khởi động dịch vụ, cho phép các thiết bị khác yêu cầu kết nối với thiết bị của bạn."), ("android_stop_service_tip", "Đóng dịch vụ sẽ tự động đóng tất cả các kết nối đã thiết lập."), ("android_version_audio_tip", "Phiên bản Android hiện tại không hỗ trợ ghi âm, vui lòng nâng cấp lên Android 10 trở lên."), - ("android_start_service_tip", "Nhấn vào [Bắt đầu dịch vụ] hoặc MỞ quyền [Ghi màn hình] để bắt đầu dịch vụ chia sẻ màn hình."), + ("android_start_service_tip", ""), ("Account", ""), ("Overwrite", "Ghi đè"), ("This file exists, skip or overwrite this file?", "Tệp tin này đã tồn tại, bạn có muốn bỏ qua hay ghi đè lên tệp tin này?"), From 1c634aa7d724fdd804f09b25492f20766c9b573e Mon Sep 17 00:00:00 2001 From: grummbeer Date: Fri, 10 Mar 2023 10:07:24 +0100 Subject: [PATCH 331/382] Mobile. Share Screen. Add "Your Device" to translations --- 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/el.rs | 1 + src/lang/eo.rs | 1 + src/lang/es.rs | 1 + src/lang/fa.rs | 1 + src/lang/fr.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/nl.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 + 33 files changed, 33 insertions(+) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 9e8770c2b..297bfdc35 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index c5cf4cd03..b92a33eea 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 620cc1373..49c286d9c 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index dbb9e3060..401601e2b 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 2127ecaac..6c2c06e45 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", "Verkleinern"), ("Minimize", "Minimieren"), ("Maximize", "Maximieren"), + ("Your Device", "Ihr Gerät"), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index dae1dedf4..c569c8a6e 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 3ff7b608a..fb9ab4dd4 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index ba9e8a3d2..c05f32ff1 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 9194d2b27..63c40c851 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 2933fcd79..ddb8ebb57 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index e05d5f928..ba8e6e86c 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index ca988aac3..8accb7519 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index c7654c480..71344f313 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 26a47cd2d..214f354eb 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index f79154cd7..8641abe36 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 11d673f00..42340ba68 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index b245cbc50..a0d035be5 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index f4f934b97..baf439a2c 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 77181a5dc..805f69488 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 8006c0700..6ac256634 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index ccbb1c90b..f1734f0ea 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index a336f74ea..d37bb367d 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 90ac16fd4..9328f79de 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index b91f6e374..73b3579cf 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index b26ac909a..da461da3b 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 7d6178c43..b1aaafcf1 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 2b926cfc7..b49b73cb6 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index fb62a9540..b785b0d60 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index ba501da16..47eba46de 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 641e9cd0b..027d5de05 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index c7089620e..d342db858 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index f085a0f26..368d5d3d2 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index fe3aaa57b..e4df09d77 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -467,5 +467,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Restore", ""), ("Minimize", ""), ("Maximize", ""), + ("Your Device", ""), ].iter().cloned().collect(); } From 4d95ada3009a97920ad47a1d49c1afe13482ba51 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 9 Mar 2023 16:40:30 +0100 Subject: [PATCH 332/382] Mobile. Share Screen. Remove readonly textinput for ID/password --- flutter/lib/mobile/pages/server_page.dart | 105 +++++++++++++++------- 1 file changed, 72 insertions(+), 33 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index 4a93bbec2..ee47568af 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_hbb/mobile/widgets/dialog.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; @@ -205,7 +206,7 @@ class ServerInfo extends StatelessWidget { Widget ConnectionStateNotification() { const Color colorPositive = Colors.greenAccent; const Color colorNegative = Colors.redAccent; - const double paddingRight = 15; + const double paddingRight = 12; if (serverModel.connectStatus == -1) { return Row(children: [ @@ -229,40 +230,78 @@ class ServerInfo extends StatelessWidget { } return PaddingCard( + title: translate('Your Device'), child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - TextFormField( - readOnly: true, - style: const TextStyle(fontSize: 25.0, fontWeight: FontWeight.bold), - controller: model.serverId, - decoration: InputDecoration( - icon: const Icon(Icons.perm_identity), - labelText: translate("ID"), - labelStyle: const TextStyle(fontWeight: FontWeight.bold), - ), - onSaved: (String? value) {}, - ), - TextFormField( - readOnly: true, - style: const TextStyle(fontSize: 25.0, fontWeight: FontWeight.bold), - controller: isPermanent ? emptyController : model.serverPasswd, - decoration: InputDecoration( - icon: const Icon(Icons.lock), - labelText: translate("Password"), - labelStyle: const TextStyle( - fontWeight: FontWeight.bold, + // mainAxisSize: MainAxisSize.min, + + // ID + children: [ + Row(children: [ + const Icon(Icons.perm_identity, color: Colors.grey, size: 24) + .marginOnly(right: 12), + Text( + translate('ID'), + style: const TextStyle( + fontSize: 16.0, + fontWeight: FontWeight.bold, + color: Colors.grey), + ) + ]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + model.serverId.value.text, + style: const TextStyle( + fontSize: 25.0, fontWeight: FontWeight.bold), ), - suffix: isPermanent - ? null - : IconButton( - icon: const Icon(Icons.refresh), - onPressed: () => bind.mainUpdateTemporaryPassword())), - onSaved: (String? value) {}, - ), - ConnectionStateNotification().marginOnly(top: 20) - ], - )); + IconButton( + visualDensity: VisualDensity.compact, + icon: Icon(Icons.copy_outlined), + onPressed: () { + Clipboard.setData( + ClipboardData(text: model.serverId.value.text.trim())); + showToast(translate('ID copied')); + }) + ]).marginOnly(left: 35, bottom: 10), + + // Password + Row(children: [ + const Icon(Icons.lock_outline, color: Colors.grey, size: 24) + .marginOnly(right: 12), + Text( + translate('One-time Password'), + style: const TextStyle( + fontSize: 16.0, + fontWeight: FontWeight.bold, + color: Colors.grey), + ) + ]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + isPermanent ? '-' : model.serverPasswd.value.text, + style: const TextStyle( + fontSize: 25.0, fontWeight: FontWeight.bold), + ), + isPermanent + ? SizedBox.shrink() + : Row(children: [ + IconButton( + visualDensity: VisualDensity.compact, + icon: const Icon(Icons.refresh), + onPressed: () => bind.mainUpdateTemporaryPassword()), + IconButton( + visualDensity: VisualDensity.compact, + icon: Icon(Icons.copy_outlined), + onPressed: () { + Clipboard.setData(ClipboardData( + text: model.serverPasswd.value.text.trim())); + showToast(translate('Password copied')); + }) + ]) + ]).marginOnly(left: 35, bottom: 10), + + ConnectionStateNotification() + ], + )); } } From b86f27f8bde69a6c75234c2b0bd03be2acc092bd Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 9 Mar 2023 12:09:45 +0100 Subject: [PATCH 333/382] Mobile. Share Screen. Server page. Make card title follow theme --- flutter/lib/mobile/pages/server_page.dart | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index ee47568af..a2eb9decf 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -482,11 +482,12 @@ class PaddingCard extends StatelessWidget { child: titleIcon) : const SizedBox.shrink(), Expanded( - child: Text( - title!, - style: const TextStyle( - fontSize: 18, fontWeight: FontWeight.bold), - ), + child: Text(title!, + style: Theme.of(context) + .textTheme + .titleLarge + // @todo once the font weight is defined in theme, remove it here to be equal insted of individual + ?.merge(TextStyle(fontWeight: FontWeight.bold))), ) ], ))); From 2a5d379c6011dbccfe81b081495ed87117cdc89e Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 9 Mar 2023 17:25:29 +0100 Subject: [PATCH 334/382] Mobile. Share Screen. Remove "connection" headline for connection state --- flutter/lib/mobile/pages/server_page.dart | 71 +++++++++++------------ 1 file changed, 34 insertions(+), 37 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index a2eb9decf..e092bf1e7 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -202,28 +202,38 @@ class ServerInfo extends StatelessWidget { final isPermanent = model.verificationMethod == kUsePermanentPassword; final serverModel = Provider.of(context); - // @todo Theming - Widget ConnectionStateNotification() { - const Color colorPositive = Colors.greenAccent; - const Color colorNegative = Colors.redAccent; - const double paddingRight = 12; + const Color colorPositive = Colors.green; + const Color colorNegative = Colors.red; + const double iconMarginRight = 15; + const double iconSize = 24; + const TextStyle textStyleHeading = TextStyle( + fontSize: 16.0, fontWeight: FontWeight.bold, color: Colors.grey); + const TextStyle textStyleValue = + TextStyle(fontSize: 25.0, fontWeight: FontWeight.bold); + void copyToClipboard(String value) { + Clipboard.setData(ClipboardData(text: value)); + showToast(translate('Copied')); + } + + Widget ConnectionStateNotification() { if (serverModel.connectStatus == -1) { return Row(children: [ - const Icon(Icons.warning_amber_sharp, color: colorNegative, size: 24) - .marginOnly(right: paddingRight), + const Icon(Icons.warning_amber_sharp, + color: colorNegative, size: iconSize) + .marginOnly(right: iconMarginRight), Expanded(child: Text(translate('not_ready_status'))) ]); } else if (serverModel.connectStatus == 0) { return Row(children: [ SizedBox(width: 20, height: 20, child: CircularProgressIndicator()) - .marginOnly(left: 4, right: paddingRight), + .marginOnly(left: 4, right: iconMarginRight), Expanded(child: Text(translate('connecting_status'))) ]); } else { return Row(children: [ - const Icon(Icons.check, color: colorPositive, size: 24) - .marginOnly(right: paddingRight), + const Icon(Icons.check, color: colorPositive, size: iconSize) + .marginOnly(right: iconMarginRight), Expanded(child: Text(translate('Ready'))) ]); } @@ -233,53 +243,42 @@ class ServerInfo extends StatelessWidget { title: translate('Your Device'), child: Column( // mainAxisSize: MainAxisSize.min, - // ID children: [ Row(children: [ - const Icon(Icons.perm_identity, color: Colors.grey, size: 24) - .marginOnly(right: 12), + const Icon(Icons.perm_identity, + color: Colors.grey, size: iconSize) + .marginOnly(right: iconMarginRight), Text( translate('ID'), - style: const TextStyle( - fontSize: 16.0, - fontWeight: FontWeight.bold, - color: Colors.grey), + style: textStyleHeading, ) ]), Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( model.serverId.value.text, - style: const TextStyle( - fontSize: 25.0, fontWeight: FontWeight.bold), + style: textStyleValue, ), IconButton( visualDensity: VisualDensity.compact, icon: Icon(Icons.copy_outlined), onPressed: () { - Clipboard.setData( - ClipboardData(text: model.serverId.value.text.trim())); - showToast(translate('ID copied')); + copyToClipboard(model.serverId.value.text.trim()); }) - ]).marginOnly(left: 35, bottom: 10), - + ]).marginOnly(left: 39, bottom: 10), // Password Row(children: [ - const Icon(Icons.lock_outline, color: Colors.grey, size: 24) - .marginOnly(right: 12), + const Icon(Icons.lock_outline, color: Colors.grey, size: iconSize) + .marginOnly(right: iconMarginRight), Text( translate('One-time Password'), - style: const TextStyle( - fontSize: 16.0, - fontWeight: FontWeight.bold, - color: Colors.grey), + style: textStyleHeading, ) ]), Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( isPermanent ? '-' : model.serverPasswd.value.text, - style: const TextStyle( - fontSize: 25.0, fontWeight: FontWeight.bold), + style: textStyleValue, ), isPermanent ? SizedBox.shrink() @@ -292,13 +291,11 @@ class ServerInfo extends StatelessWidget { visualDensity: VisualDensity.compact, icon: Icon(Icons.copy_outlined), onPressed: () { - Clipboard.setData(ClipboardData( - text: model.serverPasswd.value.text.trim())); - showToast(translate('Password copied')); + copyToClipboard( + model.serverPasswd.value.text.trim()); }) ]) - ]).marginOnly(left: 35, bottom: 10), - + ]).marginOnly(left: 40, bottom: 15), ConnectionStateNotification() ], )); From 7db1440191cb4dfff26ab7c58990bf9ac4c18dbc Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 9 Mar 2023 18:31:34 +0100 Subject: [PATCH 335/382] Mobile. Share Screen. Clean up --- flutter/lib/mobile/pages/server_page.dart | 137 ++++++++++------------ 1 file changed, 60 insertions(+), 77 deletions(-) diff --git a/flutter/lib/mobile/pages/server_page.dart b/flutter/lib/mobile/pages/server_page.dart index e092bf1e7..ae61c91a7 100644 --- a/flutter/lib/mobile/pages/server_page.dart +++ b/flutter/lib/mobile/pages/server_page.dart @@ -242,7 +242,6 @@ class ServerInfo extends StatelessWidget { return PaddingCard( title: translate('Your Device'), child: Column( - // mainAxisSize: MainAxisSize.min, // ID children: [ Row(children: [ @@ -384,73 +383,64 @@ class ConnectionManager extends StatelessWidget { titleIcon: client.isFileTransfer ? Icon(Icons.folder_outlined) : Icon(Icons.mobile_screen_share), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + child: Column(children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded(child: ClientInfo(client)), - Expanded( - flex: -1, - child: client.isFileTransfer || !client.authorized - ? const SizedBox.shrink() - : IconButton( - onPressed: () { - gFFI.chatModel - .changeCurrentID(client.id); - final bar = - navigationBarKey.currentWidget; - if (bar != null) { - bar as BottomNavigationBar; - bar.onTap!(1); - } - }, - icon: const Icon(Icons.chat))) - ], - ), - client.authorized - ? const SizedBox.shrink() - : Text( - translate("android_new_connection_tip"), - style: Theme.of(context).textTheme.bodyMedium, - ).marginOnly(bottom: 5), - client.authorized - ? Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - ElevatedButton.icon( - style: ButtonStyle( - backgroundColor: - MaterialStatePropertyAll( - Colors.red)), - icon: const Icon(Icons.close), - onPressed: () { - bind.cmCloseConnection( - connId: client.id); - gFFI.invokeMethod( - "cancel_notification", client.id); - }, - label: Text(translate("Disconnect"))) - ]) - : Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - child: Text(translate("Dismiss")), - onPressed: () { - serverModel.sendLoginResponse( - client, false); - }).marginOnly(right: 15), - ElevatedButton.icon( - icon: const Icon(Icons.check), - label: Text(translate("Accept")), - onPressed: () { - serverModel.sendLoginResponse( - client, true); - }), - ]), - ]))) + Expanded(child: ClientInfo(client)), + Expanded( + flex: -1, + child: client.isFileTransfer || !client.authorized + ? const SizedBox.shrink() + : IconButton( + onPressed: () { + gFFI.chatModel.changeCurrentID(client.id); + final bar = navigationBarKey.currentWidget; + if (bar != null) { + bar as BottomNavigationBar; + bar.onTap!(1); + } + }, + icon: const Icon(Icons.chat))) + ], + ), + client.authorized + ? const SizedBox.shrink() + : Text( + translate("android_new_connection_tip"), + style: Theme.of(context).textTheme.bodyMedium, + ).marginOnly(bottom: 5), + client.authorized + ? Container( + alignment: Alignment.centerRight, + child: ElevatedButton.icon( + style: ButtonStyle( + backgroundColor: + MaterialStatePropertyAll(Colors.red)), + icon: const Icon(Icons.close), + onPressed: () { + bind.cmCloseConnection(connId: client.id); + gFFI.invokeMethod( + "cancel_notification", client.id); + }, + label: Text(translate("Disconnect")))) + : Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + child: Text(translate("Dismiss")), + onPressed: () { + serverModel.sendLoginResponse( + client, false); + }).marginOnly(right: 15), + ElevatedButton.icon( + icon: const Icon(Icons.check), + label: Text(translate("Accept")), + onPressed: () { + serverModel.sendLoginResponse(client, true); + }), + ]), + ]))) .toList()); } } @@ -473,17 +463,12 @@ class PaddingCard extends StatelessWidget { padding: const EdgeInsets.fromLTRB(0, 5, 0, 8), child: Row( children: [ - titleIcon != null - ? Padding( - padding: const EdgeInsets.only(right: 10), - child: titleIcon) - : const SizedBox.shrink(), + titleIcon?.marginOnly(right: 10) ?? const SizedBox.shrink(), Expanded( child: Text(title!, style: Theme.of(context) .textTheme .titleLarge - // @todo once the font weight is defined in theme, remove it here to be equal insted of individual ?.merge(TextStyle(fontWeight: FontWeight.bold))), ) ], @@ -498,9 +483,8 @@ class PaddingCard extends StatelessWidget { margin: const EdgeInsets.fromLTRB(12.0, 10.0, 12.0, 0), child: Padding( padding: - const EdgeInsets.symmetric(vertical: 15.0, horizontal: 30.0), + const EdgeInsets.symmetric(vertical: 15.0, horizontal: 20.0), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, children: children, ), ), @@ -516,7 +500,7 @@ class ClientInfo extends StatelessWidget { Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8), - child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + child: Column(children: [ Row( children: [ Expanded( @@ -533,7 +517,6 @@ class ClientInfo extends StatelessWidget { Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, children: [ Text(client.name, style: const TextStyle(fontSize: 18)), const SizedBox(width: 8), From 975ea660efbe9dae869864144416db046a62dec2 Mon Sep 17 00:00:00 2001 From: RustDesk <71636191+rustdesk@users.noreply.github.com> Date: Fri, 10 Mar 2023 21:02:28 +0800 Subject: [PATCH 336/382] Revert "make sure default video save directory exist" --- src/ui_interface.rs | 60 ++++++++------------------------------------- 1 file changed, 10 insertions(+), 50 deletions(-) diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 58d321531..1dcf93e94 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -648,50 +648,29 @@ pub fn get_langs() -> String { #[inline] pub fn default_video_save_directory() -> String { let appname = crate::get_app_name(); - // ui process can show it correctly Once vidoe process created it. + // In order to make the function call results of the UI process and the video process the same, no result check is performed. let try_create = |path: &std::path::Path| { if !path.exists() { - std::fs::create_dir_all(path).ok(); - } - if path.exists() { - path.to_string_lossy().to_string() - } else { - "".to_string() + if std::fs::create_dir_all(path).is_err() { + log::warn!("video directory {:?} create failed.", path); + } } + path.to_string_lossy().to_string() }; #[cfg(any(target_os = "android", target_os = "ios"))] if let Ok(home) = config::APP_HOME_DIR.read() { let mut path = home.to_owned(); path.push_str("/RustDesk/ScreenRecord"); - let dir = try_create(&std::path::Path::from(path)); - if !dir.is_empty() { - return dir; - } + return try_create(&std::path::Path::from(path)); } if let Some(user) = directories_next::UserDirs::new() { if let Some(video_dir) = user.video_dir() { - let dir = try_create(&video_dir.join(&appname)); - if !dir.is_empty() { - return dir; - } - if video_dir.exists() { - return video_dir.to_string_lossy().to_string(); - } - } - if let Some(desktop_dir) = user.desktop_dir() { - if desktop_dir.exists() { - return desktop_dir.to_string_lossy().to_string(); - } - } - let home = user.home_dir(); - if home.exists() { - return home.to_string_lossy().to_string(); + return try_create(&video_dir.join(&appname)); } } - // same order as above #[cfg(not(any(target_os = "android", target_os = "ios")))] if let Some(home) = crate::platform::get_active_user_home() { let name = if cfg!(target_os = "macos") { @@ -699,31 +678,12 @@ pub fn default_video_save_directory() -> String { } else { "Videos" }; - let video_dir = home.join(name); - let dir = try_create(&video_dir.join(&appname)); - if !dir.is_empty() { - return dir; - } - if video_dir.exists() { - return video_dir.to_string_lossy().to_string(); - } - let desktop_dir = home.join("Desktop"); - if desktop_dir.exists() { - return desktop_dir.to_string_lossy().to_string(); - } - if home.exists() { - return home.to_string_lossy().to_string(); - } + return try_create(&home.join(name).join(&appname)); } if let Ok(exe) = std::env::current_exe() { - if let Some(parent) = exe.parent() { - let dir = try_create(&parent.join("videos")); - if !dir.is_empty() { - return dir; - } - // basically exist - return parent.to_string_lossy().to_string(); + if let Some(dir) = exe.parent() { + return try_create(&dir.join("videos")); } } "".to_owned() From 7ff3fdeafdf7d35e30b2e10407730b48940d3d4d Mon Sep 17 00:00:00 2001 From: grummbeer Date: Fri, 10 Mar 2023 14:12:28 +0100 Subject: [PATCH 337/382] Add secondary color, fix foreground color for dark mode --- flutter/lib/common.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index d9c052723..c65993d99 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -252,7 +252,8 @@ class MyTheme { ), ), ), - colorScheme: ColorScheme.light(primary: Colors.blue, background: grayBg), + colorScheme: ColorScheme.light( + primary: Colors.blue, secondary: accent, background: grayBg), ).copyWith( extensions: >[ ColorThemeExtension.light, @@ -317,6 +318,7 @@ class MyTheme { elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( backgroundColor: MyTheme.accent, + foregroundColor: Colors.white, disabledForegroundColor: Colors.white70, disabledBackgroundColor: Colors.white10, shape: RoundedRectangleBorder( @@ -336,7 +338,6 @@ class MyTheme { ), ), checkboxTheme: const CheckboxThemeData( - checkColor: MaterialStatePropertyAll(dark), splashRadius: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( @@ -353,6 +354,7 @@ class MyTheme { ), colorScheme: ColorScheme.dark( primary: Colors.blue, + secondary: accent, background: Color(0xFF24252B), ), ).copyWith( From fc99a288deb528501e69d9c2c629253b7bb1898a Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 10 Mar 2023 21:32:43 +0800 Subject: [PATCH 338/382] fix mac can't change video directory Signed-off-by: 21pages --- .../desktop/pages/desktop_setting_page.dart | 7 ++- src/ui_interface.rs | 60 +++++++++++++++---- 2 files changed, 56 insertions(+), 11 deletions(-) diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index f4d77c79b..4609d4f47 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -381,8 +381,13 @@ class _GeneralState extends State<_General> { ), ElevatedButton( onPressed: () async { + String? initialDirectory; + if (await Directory.fromUri(Uri.directory(dir)) + .exists()) { + initialDirectory = dir; + } String? selectedDirectory = await FilePicker.platform - .getDirectoryPath(initialDirectory: dir); + .getDirectoryPath(initialDirectory: initialDirectory); if (selectedDirectory != null) { await bind.mainSetOption( key: 'video-save-directory', diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 1dcf93e94..58d321531 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -648,29 +648,50 @@ pub fn get_langs() -> String { #[inline] pub fn default_video_save_directory() -> String { let appname = crate::get_app_name(); - // In order to make the function call results of the UI process and the video process the same, no result check is performed. + // ui process can show it correctly Once vidoe process created it. let try_create = |path: &std::path::Path| { if !path.exists() { - if std::fs::create_dir_all(path).is_err() { - log::warn!("video directory {:?} create failed.", path); - } + std::fs::create_dir_all(path).ok(); + } + if path.exists() { + path.to_string_lossy().to_string() + } else { + "".to_string() } - path.to_string_lossy().to_string() }; #[cfg(any(target_os = "android", target_os = "ios"))] if let Ok(home) = config::APP_HOME_DIR.read() { let mut path = home.to_owned(); path.push_str("/RustDesk/ScreenRecord"); - return try_create(&std::path::Path::from(path)); + let dir = try_create(&std::path::Path::from(path)); + if !dir.is_empty() { + return dir; + } } if let Some(user) = directories_next::UserDirs::new() { if let Some(video_dir) = user.video_dir() { - return try_create(&video_dir.join(&appname)); + let dir = try_create(&video_dir.join(&appname)); + if !dir.is_empty() { + return dir; + } + if video_dir.exists() { + return video_dir.to_string_lossy().to_string(); + } + } + if let Some(desktop_dir) = user.desktop_dir() { + if desktop_dir.exists() { + return desktop_dir.to_string_lossy().to_string(); + } + } + let home = user.home_dir(); + if home.exists() { + return home.to_string_lossy().to_string(); } } + // same order as above #[cfg(not(any(target_os = "android", target_os = "ios")))] if let Some(home) = crate::platform::get_active_user_home() { let name = if cfg!(target_os = "macos") { @@ -678,12 +699,31 @@ pub fn default_video_save_directory() -> String { } else { "Videos" }; - return try_create(&home.join(name).join(&appname)); + let video_dir = home.join(name); + let dir = try_create(&video_dir.join(&appname)); + if !dir.is_empty() { + return dir; + } + if video_dir.exists() { + return video_dir.to_string_lossy().to_string(); + } + let desktop_dir = home.join("Desktop"); + if desktop_dir.exists() { + return desktop_dir.to_string_lossy().to_string(); + } + if home.exists() { + return home.to_string_lossy().to_string(); + } } if let Ok(exe) = std::env::current_exe() { - if let Some(dir) = exe.parent() { - return try_create(&dir.join("videos")); + if let Some(parent) = exe.parent() { + let dir = try_create(&parent.join("videos")); + if !dir.is_empty() { + return dir; + } + // basically exist + return parent.to_string_lossy().to_string(); } } "".to_owned() From a0dff4838b1035fc3c803eb1711453ee581596af Mon Sep 17 00:00:00 2001 From: ilGigioVr88 Date: Fri, 10 Mar 2023 14:59:16 +0100 Subject: [PATCH 339/382] Update it.rs --- src/lang/it.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lang/it.rs b/src/lang/it.rs index 71344f313..fe265777c 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -463,10 +463,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", "L'opzione per installare il driver per lo schermo virtuale è selezionata. Nota che un certificato di test sarà installato per l'attendibilità del driver dello schermo virtuale. Questo certificato di test verrà utilizzato solo per l'attendibilità dei driver di RustDesk."), ("RDP Settings", "Impostazioni RDP"), ("Sort by", "Ordina per"), - ("New connection", ""), - ("Restore", ""), - ("Minimize", ""), - ("Maximize", ""), - ("Your Device", ""), + ("New connection", "Nuova connessione"), + ("Restore", "Ripristina"), + ("Minimize", "Minimizza"), + ("Maximize", "Massimizza"), + ("Your Device", "Il tuo dispositivo"), ].iter().cloned().collect(); } From 09b823d637a5226c58e8ab0de082b3a7f2e1b7f4 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Fri, 10 Mar 2023 23:41:01 +0800 Subject: [PATCH 340/382] higher sysinfo version --- Cargo.lock | 4 ++-- libs/hbb_common/Cargo.toml | 2 +- src/ipc.rs | 4 ++-- src/platform/macos.rs | 7 ++----- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c48a69e8d..7652f4430 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5746,9 +5746,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.26.9" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c18a6156d1f27a9592ee18c1a846ca8dd5c258b7179fc193ae87c74ebb666f5" +checksum = "d3e847e2de7a137c8c2cede5095872dbb00f4f9bf34d061347e36b43322acd56" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys 0.8.3", diff --git a/libs/hbb_common/Cargo.toml b/libs/hbb_common/Cargo.toml index fd02639ed..2ccaa92e9 100644 --- a/libs/hbb_common/Cargo.toml +++ b/libs/hbb_common/Cargo.toml @@ -34,7 +34,7 @@ tokio-socks = { git = "https://github.com/open-trade/tokio-socks" } chrono = "0.4" backtrace = "0.3" libc = "0.2" -sysinfo = "0.26" +sysinfo = "0.28" [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] mac_address = "1.1" diff --git a/src/ipc.rs b/src/ipc.rs index b1b130340..22cf388f4 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -547,13 +547,13 @@ async fn check_pid(postfix: &str) { if let Ok(mut file) = File::open(&pid_file) { let mut content = String::new(); file.read_to_string(&mut content).ok(); - let pid = content.parse::().unwrap_or(0); + let pid = content.parse::().unwrap_or(0); if pid > 0 { use hbb_common::sysinfo::{ProcessExt, System, SystemExt}; let mut sys = System::new(); sys.refresh_processes(); if let Some(p) = sys.process(pid.into()) { - if let Some(current) = sys.process((std::process::id() as i32).into()) { + if let Some(current) = sys.process((std::process::id() as usize).into()) { if current.name() == p.name() { // double check with connect if connect(1000, postfix).await.is_ok() { diff --git a/src/platform/macos.rs b/src/platform/macos.rs index 5c4c68e2c..251211c29 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -581,7 +581,7 @@ fn check_main_window() -> bool { sys.refresh_processes(); let app = format!("/Applications/{}.app", crate::get_app_name()); let my_uid = sys - .process((std::process::id() as i32).into()) + .process((std::process::id() as usize).into()) .map(|x| x.user_id()) .unwrap_or_default(); for (_, p) in sys.processes().iter() { @@ -667,9 +667,6 @@ pub fn change_resolution(name: &str, width: usize, height: usize) -> ResultType< Ok(()) } - pub fn check_super_user_permission() -> ResultType { - unsafe { - Ok(MacCheckAdminAuthorization() == YES) - } + unsafe { Ok(MacCheckAdminAuthorization() == YES) } } From 451d54d768fcfc78829d8367c7fe38307115dfc7 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sat, 11 Mar 2023 00:32:28 +0800 Subject: [PATCH 341/382] fix ci --- src/ui_interface.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 58d321531..17b4fafca 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -664,7 +664,7 @@ pub fn default_video_save_directory() -> String { if let Ok(home) = config::APP_HOME_DIR.read() { let mut path = home.to_owned(); path.push_str("/RustDesk/ScreenRecord"); - let dir = try_create(&std::path::Path::from(path)); + let dir = try_create(&std::path::Path::new(&path)); if !dir.is_empty() { return dir; } From 8a27c55db2d065f53ccce002c1b15c69cc9b8010 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sat, 11 Mar 2023 01:34:33 +0800 Subject: [PATCH 342/382] remove sys-info crate for mobile because which depends on libunwind, it is not in ndk r22b --- libs/hbb_common/Cargo.toml | 4 ++-- src/ipc.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/hbb_common/Cargo.toml b/libs/hbb_common/Cargo.toml index 2ccaa92e9..ed9ec73be 100644 --- a/libs/hbb_common/Cargo.toml +++ b/libs/hbb_common/Cargo.toml @@ -34,11 +34,11 @@ tokio-socks = { git = "https://github.com/open-trade/tokio-socks" } chrono = "0.4" backtrace = "0.3" libc = "0.2" -sysinfo = "0.28" [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] mac_address = "1.1" machine-uid = "0.2" +sysinfo = "0.28" [features] quic = [] @@ -55,4 +55,4 @@ osascript = "0.3.0" [dev-dependencies] toml = "0.7" -serde_json = "1.0" \ No newline at end of file +serde_json = "1.0" diff --git a/src/ipc.rs b/src/ipc.rs index 22cf388f4..5f415c6e8 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -251,7 +251,7 @@ pub async fn start(postfix: &str) -> ResultType<()> { pub async fn new_listener(postfix: &str) -> ResultType { let path = Config::ipc_path(postfix); - #[cfg(not(windows))] + #[cfg(not(any(windows, target_os = "android", target_os = "ios")))] check_pid(postfix).await; let mut endpoint = Endpoint::new(path.clone()); match SecurityAttributes::allow_everyone_create() { @@ -541,7 +541,7 @@ fn get_pid_file(postfix: &str) -> String { format!("{}.pid", path) } -#[cfg(not(windows))] +#[cfg(not(any(windows, target_os = "android", target_os = "ios")))] async fn check_pid(postfix: &str) { let pid_file = get_pid_file(postfix); if let Ok(mut file) = File::open(&pid_file) { From 22174bea37eb5c8ecb47fb0d40367f1ed2a649c5 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sat, 11 Mar 2023 01:53:36 +0800 Subject: [PATCH 343/382] fix ci --- libs/hbb_common/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/hbb_common/src/lib.rs b/libs/hbb_common/src/lib.rs index 21566aa23..799093d24 100644 --- a/libs/hbb_common/src/lib.rs +++ b/libs/hbb_common/src/lib.rs @@ -42,6 +42,7 @@ pub use chrono; pub use directories_next; pub use libc; pub mod keyboard; +#[cfg(not(any(target_os = "android", target_os = "ios")))] pub use sysinfo; #[cfg(feature = "quic")] From c1d5f743a929197541bdaae3463de26256581695 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Fri, 10 Mar 2023 19:37:49 +0100 Subject: [PATCH 344/382] added phrases for every empty peer type --- flutter/lib/common/widgets/peer_tab_page.dart | 2 +- flutter/lib/common/widgets/peers_view.dart | 55 +++++++++++++++---- src/lang/ca.rs | 4 ++ src/lang/cn.rs | 4 ++ src/lang/cs.rs | 4 ++ src/lang/da.rs | 4 ++ src/lang/de.rs | 4 ++ src/lang/el.rs | 4 ++ src/lang/en.rs | 6 +- src/lang/eo.rs | 4 ++ src/lang/es.rs | 4 ++ src/lang/fa.rs | 4 ++ src/lang/fr.rs | 4 ++ src/lang/hu.rs | 4 ++ src/lang/id.rs | 4 ++ src/lang/it.rs | 4 ++ src/lang/ja.rs | 4 ++ src/lang/ko.rs | 4 ++ src/lang/kz.rs | 4 ++ src/lang/nl.rs | 4 ++ src/lang/pl.rs | 4 ++ src/lang/pt_PT.rs | 4 ++ src/lang/ptbr.rs | 4 ++ src/lang/ro.rs | 4 ++ src/lang/ru.rs | 4 ++ src/lang/sk.rs | 4 ++ src/lang/sl.rs | 4 ++ src/lang/sq.rs | 4 ++ src/lang/sr.rs | 4 ++ src/lang/sv.rs | 4 ++ src/lang/template.rs | 4 ++ src/lang/th.rs | 4 ++ src/lang/tr.rs | 4 ++ src/lang/tw.rs | 4 ++ src/lang/ua.rs | 4 ++ src/lang/vn.rs | 4 ++ 36 files changed, 181 insertions(+), 14 deletions(-) diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index 869bd5fd9..52bdc8cc6 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -167,7 +167,7 @@ class _PeerTabPageState extends State color: model.currentTab == t ? Theme.of(context).colorScheme.background : null, - borderRadius: BorderRadius.circular(isDesktop ? 2 : 6), + borderRadius: BorderRadius.circular(6), ), child: Align( alignment: Alignment.center, diff --git a/flutter/lib/common/widgets/peers_view.dart b/flutter/lib/common/widgets/peers_view.dart index 71cd5d999..43f65b4b4 100644 --- a/flutter/lib/common/widgets/peers_view.dart +++ b/flutter/lib/common/widgets/peers_view.dart @@ -1,8 +1,8 @@ import 'dart:async'; +import 'dart:collection'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_hbb/consts.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; import 'package:visibility_detector/visibility_detector.dart'; @@ -30,6 +30,13 @@ class PeerSortType { ]; } +class LoadEvent { + static const String recent = 'load_recent_peers'; + static const String favorite = 'load_fav_peers'; + static const String lan = 'load_lan_peers'; + static const String addressBook = 'load_address_book_peers'; +} + /// for peer search text, global obs value final peerSearchText = "".obs; @@ -61,6 +68,12 @@ class _PeersView extends StatefulWidget { /// State for the peer widget. class _PeersViewState extends State<_PeersView> with WindowListener { static const int _maxQueryCount = 3; + final HashMap _emptyMessages = HashMap.from({ + LoadEvent.recent: 'empty_recent_tip', + LoadEvent.favorite: 'empty_favorite_tip', + LoadEvent.lan: 'empty_lan_tip', + LoadEvent.addressBook: 'empty_address_book_tip', + }); final space = isDesktop ? 12.0 : 8.0; final _curPeers = {}; var _lastChangeTime = DateTime.now(); @@ -112,12 +125,30 @@ class _PeersViewState extends State<_PeersView> with WindowListener { return ChangeNotifierProvider( create: (context) => widget.peers, child: Consumer( - builder: (context, peers, child) => peers.peers.isEmpty - ? Container( - margin: EdgeInsets.only(top: kEmptyMarginTop), - alignment: Alignment.topCenter, - child: Text(translate("Empty"))) - : _buildPeersView(peers)), + builder: (context, peers, child) => peers.peers.isEmpty + ? Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.sentiment_very_dissatisfied_rounded, + color: Theme.of(context).tabBarTheme.labelColor, + size: 40, + ).paddingOnly(bottom: 10), + Text( + translate( + _emptyMessages[widget.peers.loadEvent] ?? 'Empty', + ), + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).tabBarTheme.labelColor, + ), + ), + ], + ), + ) + : _buildPeersView(peers), + ), ); } @@ -221,7 +252,7 @@ class _PeersViewState extends State<_PeersView> with WindowListener { ); } - if (widget.peers.loadEvent != 'load_recent_peers') { + if (widget.peers.loadEvent != LoadEvent.recent) { switch (sortedBy) { case PeerSortType.remoteId: peers.sort((p1, p2) => p1.getId().compareTo(p2.getId())); @@ -289,7 +320,7 @@ class RecentPeersView extends BasePeersView { : super( key: key, name: 'recent peer', - loadEvent: 'load_recent_peers', + loadEvent: LoadEvent.recent, peerCardBuilder: (Peer peer) => RecentPeerCard( peer: peer, menuPadding: menuPadding, @@ -311,7 +342,7 @@ class FavoritePeersView extends BasePeersView { : super( key: key, name: 'favorite peer', - loadEvent: 'load_fav_peers', + loadEvent: LoadEvent.favorite, peerCardBuilder: (Peer peer) => FavoritePeerCard( peer: peer, menuPadding: menuPadding, @@ -333,7 +364,7 @@ class DiscoveredPeersView extends BasePeersView { : super( key: key, name: 'discovered peer', - loadEvent: 'load_lan_peers', + loadEvent: LoadEvent.lan, peerCardBuilder: (Peer peer) => DiscoveredPeerCard( peer: peer, menuPadding: menuPadding, @@ -358,7 +389,7 @@ class AddressBookPeersView extends BasePeersView { : super( key: key, name: 'address book peer', - loadEvent: 'load_address_book_peers', + loadEvent: LoadEvent.addressBook, peerFilter: (Peer peer) => _hitTag(gFFI.abModel.selectedTags, peer.tags), peerCardBuilder: (Peer peer) => AddressBookPeerCard( diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 297bfdc35..68f46438c 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index b92a33eea..a04bd7c04 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 49c286d9c..6e7ae7172 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 401601e2b..a5aad7929 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 6c2c06e45..13d17c833 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", "Minimieren"), ("Maximize", "Maximieren"), ("Your Device", "Ihr Gerät"), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index c569c8a6e..0e7a3e5ae 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index 7107c1865..b5d4d8b25 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -46,6 +46,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("relay_hint_tip", "It may not be possible to connect directly, you can try to connect via relay. \nIn addition, if you want to use relay on your first try, you can add the \"/r\" suffix to the ID, or select the option \"Always connect via relay\" in the peer card."), ("No transfers in progress", ""), ("idd_driver_tip", "Install virtual display driver which is used when you have no physical displays."), - ("confirm_idd_driver_tip", "The option to install the virtual display driver is checked. Note that a test certificate will be installed to trust the virtual display driver. This test certificate will only be used to trust Rustdesk drivers.") + ("confirm_idd_driver_tip", "The option to install the virtual display driver is checked. Note that a test certificate will be installed to trust the virtual display driver. This test certificate will only be used to trust Rustdesk drivers."), + ("empty_recent_tip", "Oops, no recent sessions!\nTime to plan a new one."), + ("empty_favorite_tip", "No favorite peers yet?\nLet's find someone to connect with and add it to your favorites!"), + ("empty_lan_tip", "Oh no, it looks like we haven't discovered any peers yet."), + ("empty_address_book_tip", "Oh dear, it appears that there are currently no peers listed in your address book."), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index fb9ab4dd4..5f5934012 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index c05f32ff1..e161e228b 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 63c40c851..c5d708b0d 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index ddb8ebb57..3ddb5603a 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index ba8e6e86c..11c49bd44 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 8accb7519..d256259e7 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index fe265777c..9d7239352 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", "Minimizza"), ("Maximize", "Massimizza"), ("Your Device", "Il tuo dispositivo"), + ("empty_recent_tip", "Oops, non c'è nessuna sessione recente!\nTempo di pianificarne una."), + ("empty_favorite_tip", "Ancora nessun peer?\nTrova qualcuno con cui connetterti e aggiungilo ai tuoi preferiti!"), + ("empty_lan_tip", "Oh no, sembra proprio che non abbiamo ancora rilevato nessun peer."), + ("empty_address_book_tip", "Oh diamine, sembra che per ora non ci siano peer nella tua rubrica."), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 214f354eb..53c7cda36 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 8641abe36..d208f399f 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 42340ba68..8505c7336 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index a0d035be5..2ae74ecb7 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index baf439a2c..3226157fb 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 805f69488..7a6d0106d 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 6ac256634..98fd2161f 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index f1734f0ea..3396dc50e 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index d37bb367d..4f263ded5 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 9328f79de..ae47c809d 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 73b3579cf..fa4fc17fd 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index da461da3b..27297c659 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index b1aaafcf1..1bf53571c 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index b49b73cb6..00abe840b 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index b785b0d60..9b920e6f7 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 47eba46de..7fee731b6 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 027d5de05..5f7062331 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index d342db858..84e8b822e 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 368d5d3d2..87e060eb0 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index e4df09d77..f7563b281 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -468,5 +468,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Minimize", ""), ("Maximize", ""), ("Your Device", ""), + ("empty_recent_tip", ""), + ("empty_favorite_tip", ""), + ("empty_lan_tip", ""), + ("empty_address_book_tip", ""), ].iter().cloned().collect(); } From 746c1de118286a2b56170e8abcf15a5a3fb55e68 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sat, 11 Mar 2023 10:59:33 +0800 Subject: [PATCH 345/382] fix: try upgrade ndk version to r23 --- .github/workflows/flutter-ci.yml | 3 ++- .github/workflows/flutter-nightly.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/flutter-ci.yml b/.github/workflows/flutter-ci.yml index 5eda9ad18..74f233276 100644 --- a/.github/workflows/flutter-ci.yml +++ b/.github/workflows/flutter-ci.yml @@ -23,6 +23,7 @@ env: # for multiarch gcc compatibility VCPKG_COMMIT_ID: "14e7bb4ae24616ec54ff6b2f6ef4e8659434ea44" VERSION: "1.2.0" + NDK_VERSION: "r23" jobs: build-for-windows: @@ -354,7 +355,7 @@ jobs: - uses: nttld/setup-ndk@v1 id: setup-ndk with: - ndk-version: r22b + ndk-version: ${{ env.NDK_VERSION }} add-to-path: true - name: Download deps diff --git a/.github/workflows/flutter-nightly.yml b/.github/workflows/flutter-nightly.yml index 2a1254e23..da83637e8 100644 --- a/.github/workflows/flutter-nightly.yml +++ b/.github/workflows/flutter-nightly.yml @@ -14,6 +14,7 @@ env: # for multiarch gcc compatibility VCPKG_COMMIT_ID: "14e7bb4ae24616ec54ff6b2f6ef4e8659434ea44" VERSION: "1.2.0" + NDK_VERSION: "r23" #signing keys env variable checks ANDROID_SIGNING_KEY: '${{ secrets.ANDROID_SIGNING_KEY }}' MACOS_P12_BASE64: '${{ secrets.MACOS_P12_BASE64 }}' @@ -454,7 +455,7 @@ jobs: - uses: nttld/setup-ndk@v1 id: setup-ndk with: - ndk-version: r22b + ndk-version: ${{ env.NDK_VERSION }} add-to-path: true - name: Download deps From 975918f85d4a5f5eeb44cacc749b6e19fe9d6716 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sat, 11 Mar 2023 12:05:42 +0800 Subject: [PATCH 346/382] fix: install ndk by force --- .github/workflows/flutter-nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter-nightly.yml b/.github/workflows/flutter-nightly.yml index da83637e8..6ec398c73 100644 --- a/.github/workflows/flutter-nightly.yml +++ b/.github/workflows/flutter-nightly.yml @@ -431,7 +431,7 @@ jobs: - { arch: x86_64, target: aarch64-linux-android, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-features: "", } # - { From 07220c7138f34d9d2176390cb7fda4117a341cf2 Mon Sep 17 00:00:00 2001 From: mehdi-song Date: Sat, 11 Mar 2023 09:31:14 +0330 Subject: [PATCH 347/382] Update fa.rs --- src/lang/fa.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/lang/fa.rs b/src/lang/fa.rs index c5d708b0d..83837eb14 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -459,18 +459,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "وضوح"), ("No transfers in progress", "هیچ انتقالی در حال انجام نیست"), ("Set one-time password length", "طول رمز یکبار مصرف را تعیین کنید"), - ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", ""), - ("RDP Settings", ""), - ("Sort by", ""), - ("New connection", ""), - ("Restore", ""), - ("Minimize", ""), - ("Maximize", ""), - ("Your Device", ""), - ("empty_recent_tip", ""), - ("empty_favorite_tip", ""), - ("empty_lan_tip", ""), - ("empty_address_book_tip", ""), + ("idd_driver_tip", "درایور صفحه نمایش مجازی را نصب کنید این برای زمانیست که هیچ نمایشگر فیزیکی ندارید."), + ("confirm_idd_driver_tip", "گزینه نصب درایور نمایش مجازی تیک خورده است. توجه داشته باشید که یک گواهی آزمایشی برای اعتماد به درایور نمایش مجازی نصب خواهد شد. این گواهی آزمایشی فقط برای اعتماد به درایورهای Rustdesk استفاده خواهد شد."), + ("RDP Settings", "RDP تنظیمات"), + ("Sort by", "مرتب سازی بر اساس"), + ("New connection", "اتصال جدید"), + ("Restore", "بازیابی"), + ("Minimize", "کوچک کردن پنجره"), + ("Maximize", "بزرک کردن پنجره"), + ("Your Device", "دستگاه شما"), + ("empty_recent_tip", "اوه، هیچ جلسه اخیری وجود ندارد!\nزمان برنامه ریزی جلسه جدید است"), + ("empty_favorite_tip", "هنوز همتای مورد علاقه‌ای ندارید؟\nبیایید فردی را برای ارتباط پیدا کنیم و آن را به موارد دلخواه خود اضافه کنیم!"), + ("empty_lan_tip", "اوه نه، به نظر می رسد که ما هنوز همتای خود را پیدا نکرده ایم"), + ("empty_address_book_tip", "اوه ، به نظر می رسد که در حال حاضر هیچ همتایی در دفترچه آدرس شما وجود ندارد"), ].iter().cloned().collect(); } From e77fc2583653908309c8c156d4443fb587a7d206 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 11 Mar 2023 17:18:13 +0800 Subject: [PATCH 348/382] periodicly get cursor pos on conn Signed-off-by: fufesou --- src/server/connection.rs | 10 ++-- src/server/input_service.rs | 95 ++++++++++++++++++++++++++----------- 2 files changed, 72 insertions(+), 33 deletions(-) diff --git a/src/server/connection.rs b/src/server/connection.rs index 3d419ef08..f63cd6066 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -541,7 +541,9 @@ impl Connection { conn.reset_resolution(); ALIVE_CONNS.lock().unwrap().retain(|&c| c != id); if let Some(s) = conn.server.upgrade() { - s.write().unwrap().remove_connection(&conn.inner); + let mut s = s.write().unwrap(); + s.remove_connection(&conn.inner); + try_stop_record_cursor_pos(); } log::info!("#{} connection loop exited", id); } @@ -948,9 +950,9 @@ impl Connection { if !self.audio_enabled() { noperms.push(super::audio_service::NAME); } - s.write() - .unwrap() - .add_connection(self.inner.clone(), &noperms); + let mut s = s.write().unwrap(); + s.add_connection(self.inner.clone(), &noperms); + try_start_record_cursor_pos(); } } } diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 917a815bb..1d6d9422c 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -13,7 +13,8 @@ use std::{ convert::TryFrom, ops::Sub, sync::atomic::{AtomicBool, Ordering}, - time::Instant, + thread, + time::{self, Instant}, }; const INVALID_CURSOR_POS: i32 = i32::MIN; @@ -128,6 +129,7 @@ pub fn new_pos() -> GenericService { sp } +#[inline] fn update_last_cursor_pos(x: i32, y: i32) { let mut lock = LATEST_SYS_CURSOR_POS.lock().unwrap(); if lock.1 .0 != x || lock.1 .1 != y { @@ -136,28 +138,29 @@ fn update_last_cursor_pos(x: i32, y: i32) { } fn run_pos(sp: GenericService, state: &mut StatePos) -> ResultType<()> { - if let Some((x, y)) = crate::get_cursor_pos() { - update_last_cursor_pos(x, y); - if state.is_moved(x, y) { - let mut msg_out = Message::new(); - msg_out.set_cursor_position(CursorPosition { - x, - y, - ..Default::default() - }); - let exclude = { - let now = get_time(); - let lock = LATEST_PEER_INPUT_CURSOR.lock().unwrap(); - if now - lock.time < 300 { - lock.conn - } else { - 0 - } - }; - sp.send_without(msg_out, exclude); - } - state.cursor_pos = (x, y); + let (_, (x, y)) = *LATEST_SYS_CURSOR_POS.lock().unwrap(); + if state.is_moved(x, y) { + let mut msg_out = Message::new(); + msg_out.set_cursor_position(CursorPosition { + x, + y, + ..Default::default() + }); + let exclude = { + let now = get_time(); + let lock = LATEST_PEER_INPUT_CURSOR.lock().unwrap(); + if now - lock.time < 300 { + lock.conn + } else { + 0 + } + }; + sp.send_without(msg_out, exclude); + } else if x == 0 && y == 0 { + // Early return if cursor retains origin. + return Ok(()); } + state.cursor_pos = (x, y); sp.snapshot(|sps| { let mut msg_out = Message::new(); @@ -221,6 +224,44 @@ const MOUSE_MOVE_PROTECTION_TIMEOUT: Duration = Duration::from_millis(1_000); // Actual diff of (x,y) is (1,1) here. But 5 may be tolerant. const MOUSE_ACTIVE_DISTANCE: i32 = 5; +static RECORD_CURSOR_POS_RUNNING: AtomicBool = AtomicBool::new(false); + +pub fn try_start_record_cursor_pos() { + if RECORD_CURSOR_POS_RUNNING.load(Ordering::SeqCst) { + return; + } + if *CONN_COUNT.lock().unwrap() == 0 { + return; + } + + RECORD_CURSOR_POS_RUNNING.store(true, Ordering::SeqCst); + thread::spawn(|| { + let interval = time::Duration::from_millis(33); + loop { + if !RECORD_CURSOR_POS_RUNNING.load(Ordering::SeqCst) { + break; + } + + let now = time::Instant::now(); + if let Some((x, y)) = crate::get_cursor_pos() { + update_last_cursor_pos(x, y); + } + let elapsed = now.elapsed(); + if elapsed < interval { + thread::sleep(interval - elapsed); + } + } + }); +} + +pub fn try_stop_record_cursor_pos() { + let count_lock = CONN_COUNT.lock().unwrap(); + if *count_lock > 0 { + return; + } + RECORD_CURSOR_POS_RUNNING.store(false, Ordering::SeqCst); +} + // mac key input must be run in main thread, otherwise crash on >= osx 10.15 #[cfg(target_os = "macos")] lazy_static::lazy_static! { @@ -717,11 +758,8 @@ pub fn handle_key(evt: &KeyEvent) { fn reset_input() { unsafe { let _lock = VIRTUAL_INPUT_MTX.lock(); - VIRTUAL_INPUT = VirtualInput::new( - CGEventSourceStateID::Private, - CGEventTapLocation::Session, - ) - .ok(); + VIRTUAL_INPUT = + VirtualInput::new(CGEventSourceStateID::Private, CGEventTapLocation::Session).ok(); } } @@ -1095,8 +1133,7 @@ fn translate_keyboard_mode(evt: &KeyEvent) { Some(key_event::Union::Seq(seq)) => { ENIGO.lock().unwrap().key_sequence(seq); } - Some(key_event::Union::Chr(..)) => - { + Some(key_event::Union::Chr(..)) => { #[cfg(target_os = "windows")] translate_process_code(evt.chr(), evt.down); #[cfg(not(target_os = "windows"))] From 041a5186555a5cf36697c640a11436650337cf8b Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 11 Mar 2023 17:48:35 +0800 Subject: [PATCH 349/382] refactor cursor pos loop Signed-off-by: fufesou --- src/server/connection.rs | 2 +- src/server/input_service.rs | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/server/connection.rs b/src/server/connection.rs index f63cd6066..6bf602596 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -951,8 +951,8 @@ impl Connection { noperms.push(super::audio_service::NAME); } let mut s = s.write().unwrap(); - s.add_connection(self.inner.clone(), &noperms); try_start_record_cursor_pos(); + s.add_connection(self.inner.clone(), &noperms); } } } diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 1d6d9422c..f205e3f02 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -139,6 +139,10 @@ fn update_last_cursor_pos(x: i32, y: i32) { fn run_pos(sp: GenericService, state: &mut StatePos) -> ResultType<()> { let (_, (x, y)) = *LATEST_SYS_CURSOR_POS.lock().unwrap(); + if x == INVALID_CURSOR_POS || y == INVALID_CURSOR_POS { + return Ok(()); + } + if state.is_moved(x, y) { let mut msg_out = Message::new(); msg_out.set_cursor_position(CursorPosition { @@ -156,9 +160,6 @@ fn run_pos(sp: GenericService, state: &mut StatePos) -> ResultType<()> { } }; sp.send_without(msg_out, exclude); - } else if x == 0 && y == 0 { - // Early return if cursor retains origin. - return Ok(()); } state.cursor_pos = (x, y); @@ -216,7 +217,7 @@ lazy_static::lazy_static! { }; static ref KEYS_DOWN: Arc>> = Default::default(); static ref LATEST_PEER_INPUT_CURSOR: Arc> = Default::default(); - static ref LATEST_SYS_CURSOR_POS: Arc> = Arc::new(Mutex::new((Instant::now().sub(MOUSE_MOVE_PROTECTION_TIMEOUT), (0, 0)))); + static ref LATEST_SYS_CURSOR_POS: Arc> = Arc::new(Mutex::new((Instant::now().sub(MOUSE_MOVE_PROTECTION_TIMEOUT), (INVALID_CURSOR_POS, INVALID_CURSOR_POS)))); } static EXITING: AtomicBool = AtomicBool::new(false); @@ -230,9 +231,6 @@ pub fn try_start_record_cursor_pos() { if RECORD_CURSOR_POS_RUNNING.load(Ordering::SeqCst) { return; } - if *CONN_COUNT.lock().unwrap() == 0 { - return; - } RECORD_CURSOR_POS_RUNNING.store(true, Ordering::SeqCst); thread::spawn(|| { @@ -251,6 +249,7 @@ pub fn try_start_record_cursor_pos() { thread::sleep(interval - elapsed); } } + update_last_cursor_pos(INVALID_CURSOR_POS, INVALID_CURSOR_POS); }); } From 411ddb949bc23145ae01956c703d3b1e0ad5b753 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 11 Mar 2023 18:11:19 +0800 Subject: [PATCH 350/382] fix build android Signed-off-by: fufesou --- src/server/connection.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/server/connection.rs b/src/server/connection.rs index 6bf602596..7127187d8 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -543,6 +543,7 @@ impl Connection { if let Some(s) = conn.server.upgrade() { let mut s = s.write().unwrap(); s.remove_connection(&conn.inner); + #[cfg(not(any(target_os = "android", target_os = "ios")))] try_stop_record_cursor_pos(); } log::info!("#{} connection loop exited", id); @@ -951,6 +952,7 @@ impl Connection { noperms.push(super::audio_service::NAME); } let mut s = s.write().unwrap(); + #[cfg(not(any(target_os = "android", target_os = "ios")))] try_start_record_cursor_pos(); s.add_connection(self.inner.clone(), &noperms); } @@ -1740,6 +1742,7 @@ impl Connection { self.lock_after_session_end = q == BoolOption::Yes; } } + #[cfg(not(any(target_os = "android", target_os = "ios")))] if let Ok(q) = o.show_remote_cursor.enum_value() { if q != BoolOption::NotSet { self.show_remote_cursor = q == BoolOption::Yes; From 6cf81c811f1bfaaeb2adf03a2c9f003d7abbb17c Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 11 Mar 2023 18:21:23 +0800 Subject: [PATCH 351/382] do not show 'Show remote cursor' if peer side is android 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 3e37cef40..ac66c68a3 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -1437,6 +1437,9 @@ class _DisplayMenuState extends State<_DisplayMenu> { } showRemoteCursor() { + if (widget.ffi.ffiModel.pi.platform == kPeerPlatformAndroid) { + return Offstage(); + } final visible = !widget.ffi.canvasModel.cursorEmbedded; if (!visible) return Offstage(); final state = ShowRemoteCursorState.find(widget.id); From dc408002105979b0e2a136d711c34e716cbbb962 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 11 Mar 2023 18:26:36 +0800 Subject: [PATCH 352/382] do not show 'zoom cursor' if peer side is android 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 ac66c68a3..e38e5c992 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -1457,6 +1457,9 @@ class _DisplayMenuState extends State<_DisplayMenu> { } zoomCursor() { + if (widget.ffi.ffiModel.pi.platform == kPeerPlatformAndroid) { + return Offstage(); + } final visible = widget.state.viewStyle.value != kRemoteViewStyleOriginal; if (!visible) return Offstage(); final option = 'zoom-cursor'; From 293dea94c94492fc563d44bacfd1083c8b562cea Mon Sep 17 00:00:00 2001 From: grummbeer Date: Sat, 11 Mar 2023 12:14:47 +0100 Subject: [PATCH 353/382] fix. multiple call of translate for the same phrase --- flutter/lib/desktop/widgets/tabbar_widget.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index 7700f197e..4211911ff 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -593,7 +593,7 @@ class WindowActionPanelState extends State Offstage( offstage: !widget.showMinimize || Platform.isMacOS, child: ActionIcon( - message: translate('Minimize'), + message: 'Minimize', icon: IconFont.min, onTap: () { if (widget.isMainWindow) { @@ -608,7 +608,7 @@ class WindowActionPanelState extends State offstage: !widget.showMaximize || Platform.isMacOS, child: Obx(() => ActionIcon( message: - widget.isMaximized.value ? translate("Restore") : translate("Maximize"), + widget.isMaximized.value ? 'Restore' : 'Maximize', icon: widget.isMaximized.value ? IconFont.restore : IconFont.max, @@ -618,7 +618,7 @@ class WindowActionPanelState extends State Offstage( offstage: !widget.showClose || Platform.isMacOS, child: ActionIcon( - message: translate('Close'), + message: 'Close', icon: IconFont.close, onTap: () async { final res = await widget.onClose?.call() ?? true; @@ -1076,7 +1076,7 @@ class AddButton extends StatelessWidget { @override Widget build(BuildContext context) { return ActionIcon( - message: translate('New Connection'), + message: 'New Connection', icon: IconFont.add, onTap: () => rustDeskWinManager.call( WindowType.Main, kWindowMainWindowOnTop, ""), From fc8e3df7dcba9f4e626da48df3d6c2f89832f726 Mon Sep 17 00:00:00 2001 From: 21pages Date: Sat, 11 Mar 2023 19:29:26 +0800 Subject: [PATCH 354/382] fix remote menubar theme Signed-off-by: 21pages --- flutter/lib/common.dart | 6 ++++++ .../lib/desktop/widgets/remote_menubar.dart | 21 +++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index c65993d99..8b0cb710c 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -252,6 +252,9 @@ class MyTheme { ), ), ), + menuBarTheme: MenuBarThemeData( + style: + MenuStyle(backgroundColor: MaterialStatePropertyAll(Colors.white))), colorScheme: ColorScheme.light( primary: Colors.blue, secondary: accent, background: grayBg), ).copyWith( @@ -352,6 +355,9 @@ class MyTheme { ), ), ), + menuBarTheme: MenuBarThemeData( + style: MenuStyle( + backgroundColor: MaterialStatePropertyAll(Color(0xFF121212)))), colorScheme: ColorScheme.dark( primary: Colors.blue, secondary: accent, diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 3e37cef40..0f63a2814 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -408,7 +408,12 @@ class _RemoteMenubarState extends State { children: [ Container( decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(10)), + borderRadius: BorderRadius.all(Radius.circular(4.0)), + color: Theme.of(context) + .menuBarTheme + .style + ?.backgroundColor + ?.resolve(MaterialState.values.toSet()), ), child: SingleChildScrollView( scrollDirection: Axis.horizontal, @@ -416,9 +421,9 @@ class _RemoteMenubarState extends State { data: themeData(), child: Row( children: [ - SizedBox(width: _MenubarTheme.buttonHMargin), + SizedBox(width: _MenubarTheme.buttonHMargin * 2), ...menubarItems, - SizedBox(width: _MenubarTheme.buttonHMargin) + SizedBox(width: _MenubarTheme.buttonHMargin * 2) ], ), ), @@ -441,7 +446,13 @@ class _RemoteMenubarState extends State { ), dividerTheme: DividerThemeData(space: 4), menuBarTheme: MenuBarThemeData( - style: MenuStyle(padding: MaterialStatePropertyAll(EdgeInsets.zero))), + style: MenuStyle( + padding: MaterialStatePropertyAll(EdgeInsets.zero), + elevation: MaterialStatePropertyAll(0), + shape: MaterialStatePropertyAll(BeveledRectangleBorder()), + ).copyWith( + backgroundColor: + Theme.of(context).menuBarTheme.style?.backgroundColor)), ); } } @@ -1863,6 +1874,7 @@ class _IconMenuButtonState extends State<_IconMenuButton> { height: _MenubarTheme.buttonSize, child: MenuItemButton( style: ButtonStyle( + backgroundColor: MaterialStatePropertyAll(Colors.transparent), padding: MaterialStatePropertyAll(EdgeInsets.zero), overlayColor: MaterialStatePropertyAll(Colors.transparent)), onHover: (value) => setState(() { @@ -1934,6 +1946,7 @@ class _IconSubmenuButtonState extends State<_IconSubmenuButton> { child: SubmenuButton( menuStyle: widget.menuStyle, style: ButtonStyle( + backgroundColor: MaterialStatePropertyAll(Colors.transparent), padding: MaterialStatePropertyAll(EdgeInsets.zero), overlayColor: MaterialStatePropertyAll(Colors.transparent)), onHover: (value) => setState(() { From 45ab0e5a625f505490cfbac7f155eacbeb69f32a Mon Sep 17 00:00:00 2001 From: 21pages Date: Sat, 11 Mar 2023 19:53:19 +0800 Subject: [PATCH 355/382] make draggable color same with menubar color Signed-off-by: 21pages --- flutter/lib/common.dart | 22 +++++++++++++------ .../lib/desktop/widgets/remote_menubar.dart | 8 +++++-- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 8b0cb710c..21dc427cc 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -111,32 +111,39 @@ class ColorThemeExtension extends ThemeExtension { required this.border, required this.border2, required this.highlight, + required this.drag_indicator, }); final Color? border; final Color? border2; final Color? highlight; + final Color? drag_indicator; - static const light = ColorThemeExtension( + static final light = ColorThemeExtension( border: Color(0xFFCCCCCC), border2: Color(0xFFBBBBBB), highlight: Color(0xFFE5E5E5), + drag_indicator: Colors.grey[800], ); - static const dark = ColorThemeExtension( + static final dark = ColorThemeExtension( border: Color(0xFF555555), border2: Color(0xFFE5E5E5), highlight: Color(0xFF3F3F3F), + drag_indicator: Colors.grey, ); @override ThemeExtension copyWith( - {Color? border, Color? border2, Color? highlight}) { + {Color? border, + Color? border2, + Color? highlight, + Color? drag_indicator}) { return ColorThemeExtension( - border: border ?? this.border, - border2: border2 ?? this.border2, - highlight: highlight ?? this.highlight, - ); + border: border ?? this.border, + border2: border2 ?? this.border2, + highlight: highlight ?? this.highlight, + drag_indicator: drag_indicator ?? this.drag_indicator); } @override @@ -149,6 +156,7 @@ class ColorThemeExtension extends ThemeExtension { border: Color.lerp(border, other.border, t), border2: Color.lerp(border2, other.border2, t), highlight: Color.lerp(highlight, other.highlight, t), + drag_indicator: Color.lerp(drag_indicator, other.drag_indicator, t), ); } } diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 0f63a2814..c444214c6 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -2107,7 +2107,7 @@ class _DraggableShowHideState extends State<_DraggableShowHide> { child: Icon( Icons.drag_indicator, size: 20, - color: Colors.grey[800], + color: MyTheme.color(context).drag_indicator, ), feedback: widget, onDragStarted: (() { @@ -2159,7 +2159,11 @@ class _DraggableShowHideState extends State<_DraggableShowHide> { data: TextButtonThemeData(style: buttonStyle), child: Container( decoration: BoxDecoration( - color: Colors.white, + color: Theme.of(context) + .menuBarTheme + .style + ?.backgroundColor + ?.resolve(MaterialState.values.toSet()), borderRadius: BorderRadius.vertical( bottom: Radius.circular(5), ), From 161ea7272ba5f4421c5563f3dbb5af2b3e6d086a Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sat, 11 Mar 2023 15:17:01 +0100 Subject: [PATCH 356/382] Update template.rs --- src/lang/template.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/template.rs b/src/lang/template.rs index 9b920e6f7..5e3a32022 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), From 3a9b9dddf10e444592549bc4a23a2db170d6da48 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sat, 11 Mar 2023 15:18:12 +0100 Subject: [PATCH 357/382] Add files via upload --- src/lang/ca.rs | 2 +- src/lang/cn.rs | 2 +- src/lang/cs.rs | 2 +- src/lang/da.rs | 2 +- src/lang/de.rs | 10 +++++----- src/lang/el.rs | 2 +- src/lang/eo.rs | 2 +- src/lang/es.rs | 2 +- src/lang/fa.rs | 2 +- src/lang/fr.rs | 2 +- src/lang/hu.rs | 2 +- src/lang/id.rs | 2 +- src/lang/it.rs | 2 +- src/lang/ja.rs | 2 +- src/lang/ko.rs | 2 +- src/lang/kz.rs | 2 +- src/lang/nl.rs | 2 +- src/lang/pl.rs | 2 +- src/lang/pt_PT.rs | 2 +- src/lang/ptbr.rs | 2 +- src/lang/ro.rs | 2 +- src/lang/ru.rs | 2 +- src/lang/sk.rs | 2 +- src/lang/sl.rs | 2 +- src/lang/sq.rs | 2 +- src/lang/sr.rs | 2 +- src/lang/sv.rs | 2 +- src/lang/th.rs | 2 +- src/lang/tr.rs | 2 +- src/lang/tw.rs | 2 +- src/lang/ua.rs | 2 +- src/lang/vn.rs | 2 +- 32 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 68f46438c..add867d8a 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/cn.rs b/src/lang/cn.rs index a04bd7c04..dae7b732e 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", "安装虚拟显示器驱动的选项已勾选。请注意,测试证书将被安装以信任虚拟显示器驱动。测试证书仅会用于信任Rustdesk的驱动。"), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 6e7ae7172..d55531ddd 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/da.rs b/src/lang/da.rs index a5aad7929..c2913ef15 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/de.rs b/src/lang/de.rs index 13d17c833..9df1c7096 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -463,14 +463,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", "Die Option zur Installation des virtuellen Anzeigetreibers ist aktiviert. Beachten Sie, dass ein Testzertifikat installiert wird, um dem virtuellen Anzeigetreiber zu vertrauen. Dieses Testzertifikat wird nur verwendet, um Rustdesk-Treibern zu vertrauen."), ("RDP Settings", "RDP-Einstellungen"), ("Sort by", "Sortieren nach"), - ("New connection", "Neue Verbindung"), + ("New Connection", "Neue Verbindung"), ("Restore", "Verkleinern"), ("Minimize", "Minimieren"), ("Maximize", "Maximieren"), ("Your Device", "Ihr Gerät"), - ("empty_recent_tip", ""), - ("empty_favorite_tip", ""), - ("empty_lan_tip", ""), - ("empty_address_book_tip", ""), + ("empty_recent_tip", "Ups, keine aktuellen Sitzungen!\nZeit, eine neue zu planen."), + ("empty_favorite_tip", "Noch keine favorisierte Gegenstelle?\nLassen Sie uns jemanden finden, mit dem wir uns verbinden können und fügen Sie ihn zu Ihren Favoriten hinzu!"), + ("empty_lan_tip", "Oh nein, es sieht so aus, als hätten wir noch keine Gegenstelle entdeckt."), + ("empty_address_book_tip", "Oh je, es scheint, dass in Ihrem Adressbuch derzeit keine Gegenstellen aufgeführt sind."), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index 0e7a3e5ae..52399f726 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", "Είναι ενεργοποιημένη η επιλογή εγκατάστασης του προγράμματος οδήγησης εικονικής οθόνης. Λάβετε υπόψη ότι θα εγκατασταθεί ένα δοκιμαστικό πιστοποιητικό για το πρόγραμμα οδήγησης εικονικής οθόνης. Αυτό το πιστοποιητικό θα χρησιμοποιηθεί μόνο για την πιστοποίηση των προγραμμάτων οδήγησης του Rustdesk."), ("RDP Settings", "Ρυθμίσεις RDP"), ("Sort by", "Ταξινόμηση κατά"), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 5f5934012..f4030c7f2 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/es.rs b/src/lang/es.rs index e161e228b..dc87bc752 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", "La opción de instalar el controlador de pantalla virtual está marcada. Hay que tener en cuenta que se instalará un certificado de prueba para confirar en el controlador de pantalla. Este certificado solo se usará para confiar en controladores Rustdesk."), ("RDP Settings", "Ajustes RDP"), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 83837eb14..3492e5bd6 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", "گزینه نصب درایور نمایش مجازی تیک خورده است. توجه داشته باشید که یک گواهی آزمایشی برای اعتماد به درایور نمایش مجازی نصب خواهد شد. این گواهی آزمایشی فقط برای اعتماد به درایورهای Rustdesk استفاده خواهد شد."), ("RDP Settings", "RDP تنظیمات"), ("Sort by", "مرتب سازی بر اساس"), - ("New connection", "اتصال جدید"), + ("New Connection", "اتصال جدید"), ("Restore", "بازیابی"), ("Minimize", "کوچک کردن پنجره"), ("Maximize", "بزرک کردن پنجره"), diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 3ddb5603a..6ee0b7799 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 11c49bd44..76e6999e4 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/id.rs b/src/lang/id.rs index d256259e7..836c3e083 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/it.rs b/src/lang/it.rs index 9d7239352..5f25a1a51 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", "L'opzione per installare il driver per lo schermo virtuale è selezionata. Nota che un certificato di test sarà installato per l'attendibilità del driver dello schermo virtuale. Questo certificato di test verrà utilizzato solo per l'attendibilità dei driver di RustDesk."), ("RDP Settings", "Impostazioni RDP"), ("Sort by", "Ordina per"), - ("New connection", "Nuova connessione"), + ("New Connection", "Nuova connessione"), ("Restore", "Ripristina"), ("Minimize", "Minimizza"), ("Maximize", "Massimizza"), diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 53c7cda36..2b91ced06 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/ko.rs b/src/lang/ko.rs index d208f399f..72ed4b374 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 8505c7336..81298bc27 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 2ae74ecb7..f3bb6e119 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 3226157fb..48a7ea99d 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 7a6d0106d..f31aad614 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 98fd2161f..8a06ce65a 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 3396dc50e..899b06986 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 4f263ded5..bca2e4312 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", "Включена функция установки драйвера виртуального дисплея. Обратите внимание, что для доверия к драйверу будет установлен тестовый сертификат. Этот сертификат будет использоваться только для подтверждения доверия драйверам Rustdesk."), ("RDP Settings", "Настройки RDP"), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index ae47c809d..7d7d3a157 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/sl.rs b/src/lang/sl.rs index fa4fc17fd..8ee5c59ca 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 27297c659..18f9606dc 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 1bf53571c..374ee96cc 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 00abe840b..5383c7fd3 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/th.rs b/src/lang/th.rs index 7fee731b6..16c6b0349 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 5f7062331..d5992b5a0 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 84e8b822e..ddcd14984 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 87e060eb0..bfe27b24f 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), diff --git a/src/lang/vn.rs b/src/lang/vn.rs index f7563b281..de063ed0d 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -463,7 +463,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), ("Sort by", ""), - ("New connection", ""), + ("New Connection", ""), ("Restore", ""), ("Minimize", ""), ("Maximize", ""), From 93cd12a6b34e1bdcd584df3d15f24fd85a1adb60 Mon Sep 17 00:00:00 2001 From: solokot Date: Sat, 11 Mar 2023 20:55:57 +0300 Subject: [PATCH 358/382] Update ru.rs --- src/lang/ru.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/lang/ru.rs b/src/lang/ru.rs index bca2e4312..16996e1de 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -288,7 +288,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_service_will_start_tip", "Включение захвата экрана автоматически запускает службу, позволяя другим устройствам запрашивать соединение с этим устройством."), ("android_stop_service_tip", "Закрытие службы автоматически закроет все установленные соединения."), ("android_version_audio_tip", "Текущая версия Android не поддерживает захват звука, обновите её до Android 10 или выше."), - ("android_start_service_tip", ""), + ("android_start_service_tip", "Нажмите [Запустить службу] или разрешите [Захват экрана], чтобы запустить службу демонстрации экрана."), ("Account", "Аккаунт"), ("Overwrite", "Перезаписать"), ("This file exists, skip or overwrite this file?", "Этот файл существует, пропустить или перезаписать файл?"), @@ -453,7 +453,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Voice call", "Голосовой вызов"), ("Text chat", "Текстовый чат"), ("Stop voice call", "Завершить голосовой вызов"), - ("relay_hint_tip", "Прямое подключение может оказаться невозможным. В этом случае можно попытаться подключиться через сервер ретрансляции. \nКроме того, если вы хотите сразу использовать сервер ретрансляции, можно добавить к ID суффикс \"/r\" или включить \"Всегда подключаться через ретранслятор\" в настройках удалённого узла."), + ("relay_hint_tip", "Прямое подключение может оказаться невозможным. В этом случае можно попытаться подключиться через сервер ретрансляции. \nКроме того, если вы хотите сразу использовать сервер ретрансляции, можно добавить к ID суффикс \"/r\" или включить \"Всегда подключаться через ретранслятор\" в настройках удалённого узла."), ("Reconnect", "Переподключить"), ("Codec", "Кодек"), ("Resolution", "Разрешение"), @@ -462,15 +462,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", "Установите драйвер виртуального дисплея, который используется при отсутствии физических дисплеев."), ("confirm_idd_driver_tip", "Включена функция установки драйвера виртуального дисплея. Обратите внимание, что для доверия к драйверу будет установлен тестовый сертификат. Этот сертификат будет использоваться только для подтверждения доверия драйверам Rustdesk."), ("RDP Settings", "Настройки RDP"), - ("Sort by", ""), - ("New Connection", ""), - ("Restore", ""), - ("Minimize", ""), - ("Maximize", ""), - ("Your Device", ""), - ("empty_recent_tip", ""), - ("empty_favorite_tip", ""), - ("empty_lan_tip", ""), - ("empty_address_book_tip", ""), + ("Sort by", "Сортировка"), + ("New Connection", "Новое подключение"), + ("Restore", "Восстановить"), + ("Minimize", "Свернуть"), + ("Maximize", "Развернуть"), + ("Your Device", "Ваше устройство"), + ("empty_recent_tip", "Нет последних сеансов!\nПора спланировать новый."), + ("empty_favorite_tip", "Ещё нет избранных удалённых узлов?\nДавайте найдём, кого можно добавить в избранное!"), + ("empty_lan_tip", "Не найдено удалённых узлов."), + ("empty_address_book_tip", "В адресной книге нет удалённых узлов."), ].iter().cloned().collect(); } From abeffb958b37f00715c093501e3804324efdc734 Mon Sep 17 00:00:00 2001 From: "Miguel F. G" <116861809+flusheDData@users.noreply.github.com> Date: Sat, 11 Mar 2023 21:36:19 +0100 Subject: [PATCH 359/382] Update es.rs New terms added --- src/lang/es.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/lang/es.rs b/src/lang/es.rs index dc87bc752..c738f9ffe 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -462,15 +462,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", "Instalar controlador virtual de pantalla a usar cuando no hay pantalla física."), ("confirm_idd_driver_tip", "La opción de instalar el controlador de pantalla virtual está marcada. Hay que tener en cuenta que se instalará un certificado de prueba para confirar en el controlador de pantalla. Este certificado solo se usará para confiar en controladores Rustdesk."), ("RDP Settings", "Ajustes RDP"), - ("Sort by", ""), - ("New Connection", ""), - ("Restore", ""), - ("Minimize", ""), - ("Maximize", ""), - ("Your Device", ""), - ("empty_recent_tip", ""), - ("empty_favorite_tip", ""), - ("empty_lan_tip", ""), - ("empty_address_book_tip", ""), + ("Sort by", "Ordenar por"), + ("New Connection", "Nueva conexión"), + ("Restore", "Restaurar"), + ("Minimize", "Minimizar"), + ("Maximize", "Maximizar"), + ("Your Device", "Tu dispositivo"), + ("empty_recent_tip", "Vaya, no hay conexiones recientes!\nBuen momento para planificar una."), + ("empty_favorite_tip", "¿Sin pares favoritos aún?\nEncuentra uno al que conectarte y añádelo a favoritos!"), + ("empty_lan_tip", "Oh no, parece que aún no has descubierto ningún par."), + ("empty_address_book_tip", "Parece que actualmente no hay pares en tu libreta de direcciones."), ].iter().cloned().collect(); } From b7f16997b1843e47b3b0085f76d9f52c182e32fe Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sun, 12 Mar 2023 14:08:26 +0100 Subject: [PATCH 360/382] Update dialog.dart --- flutter/lib/mobile/widgets/dialog.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index 9a5891330..b14401795 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -467,7 +467,7 @@ void showRequestElevationDialog(String id, OverlayDialogManager dialogManager) { decoration: InputDecoration( isDense: true, contentPadding: EdgeInsets.symmetric(vertical: 15), - hintText: 'eg: admin', + hintText: translate('eg: admin'), errorText: errUser.isEmpty ? null : errUser.value), onChanged: (s) { if (s.isNotEmpty) { From 41a394a843d5b7c64efc2310b0c38fb373067cee Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sun, 12 Mar 2023 14:09:58 +0100 Subject: [PATCH 361/382] Add files via upload --- src/lang/ca.rs | 3 +++ src/lang/cn.rs | 3 +++ src/lang/cs.rs | 3 +++ src/lang/da.rs | 3 +++ src/lang/de.rs | 3 +++ src/lang/el.rs | 3 +++ src/lang/eo.rs | 3 +++ src/lang/es.rs | 3 +++ src/lang/fa.rs | 3 +++ src/lang/fr.rs | 3 +++ src/lang/hu.rs | 3 +++ src/lang/id.rs | 3 +++ src/lang/it.rs | 3 +++ src/lang/ja.rs | 3 +++ src/lang/ko.rs | 3 +++ src/lang/kz.rs | 3 +++ src/lang/nl.rs | 3 +++ src/lang/pl.rs | 3 +++ src/lang/pt_PT.rs | 3 +++ src/lang/ptbr.rs | 3 +++ src/lang/ro.rs | 3 +++ src/lang/ru.rs | 3 +++ src/lang/sk.rs | 3 +++ src/lang/sl.rs | 3 +++ src/lang/sq.rs | 3 +++ src/lang/sr.rs | 3 +++ src/lang/sv.rs | 3 +++ src/lang/template.rs | 3 +++ src/lang/th.rs | 3 +++ src/lang/tr.rs | 3 +++ src/lang/tw.rs | 3 +++ src/lang/ua.rs | 3 +++ src/lang/vn.rs | 3 +++ 33 files changed, 99 insertions(+) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index add867d8a..f09223111 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index dae7b732e..69a3bdac5 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index d55531ddd..bd0cc452a 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index c2913ef15..6c486ffc0 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 9df1c7096..647215392 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", "Noch keine favorisierte Gegenstelle?\nLassen Sie uns jemanden finden, mit dem wir uns verbinden können und fügen Sie ihn zu Ihren Favoriten hinzu!"), ("empty_lan_tip", "Oh nein, es sieht so aus, als hätten wir noch keine Gegenstelle entdeckt."), ("empty_address_book_tip", "Oh je, es scheint, dass in Ihrem Adressbuch derzeit keine Gegenstellen aufgeführt sind."), + ("eg: admin", "z. B.: admin"), + ("Empty Username", "Leerer Benutzername"), + ("Empty Password", "Leeres Passwort"), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index 52399f726..91a627628 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index f4030c7f2..ee47688e2 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index c738f9ffe..d19eae344 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", "¿Sin pares favoritos aún?\nEncuentra uno al que conectarte y añádelo a favoritos!"), ("empty_lan_tip", "Oh no, parece que aún no has descubierto ningún par."), ("empty_address_book_tip", "Parece que actualmente no hay pares en tu libreta de direcciones."), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 3492e5bd6..b971de772 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", "هنوز همتای مورد علاقه‌ای ندارید؟\nبیایید فردی را برای ارتباط پیدا کنیم و آن را به موارد دلخواه خود اضافه کنیم!"), ("empty_lan_tip", "اوه نه، به نظر می رسد که ما هنوز همتای خود را پیدا نکرده ایم"), ("empty_address_book_tip", "اوه ، به نظر می رسد که در حال حاضر هیچ همتایی در دفترچه آدرس شما وجود ندارد"), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 6ee0b7799..08bf3a0ce 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 76e6999e4..95b1aa23f 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 836c3e083..de56499fc 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 5f25a1a51..23eaf6bb4 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", "Ancora nessun peer?\nTrova qualcuno con cui connetterti e aggiungilo ai tuoi preferiti!"), ("empty_lan_tip", "Oh no, sembra proprio che non abbiamo ancora rilevato nessun peer."), ("empty_address_book_tip", "Oh diamine, sembra che per ora non ci siano peer nella tua rubrica."), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 2b91ced06..7a04a9230 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 72ed4b374..8a1f6f18e 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 81298bc27..95903ec2e 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index f3bb6e119..885d6f0bd 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 48a7ea99d..0e990d7df 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index f31aad614..c87f2ede3 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 8a06ce65a..364bc21fd 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 899b06986..188fc09e9 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 16996e1de..3233ced2b 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", "Ещё нет избранных удалённых узлов?\nДавайте найдём, кого можно добавить в избранное!"), ("empty_lan_tip", "Не найдено удалённых узлов."), ("empty_address_book_tip", "В адресной книге нет удалённых узлов."), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 7d7d3a157..81091a23d 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 8ee5c59ca..86c76e6b0 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 18f9606dc..e8c423603 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 374ee96cc..7a8a43467 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 5383c7fd3..28f16c547 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 5e3a32022..bed743e32 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 16c6b0349..543b78cda 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index d5992b5a0..4a50b0a89 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index ddcd14984..428de753d 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index bfe27b24f..ec8012cef 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index de063ed0d..77fc3cfa3 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -472,5 +472,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", ""), ("empty_lan_tip", ""), ("empty_address_book_tip", ""), + ("eg: admin", ""), + ("Empty Username", ""), + ("Empty Password", ""), ].iter().cloned().collect(); } From e7f522d769ed1e420e4d6535b95278f9077e1a52 Mon Sep 17 00:00:00 2001 From: tsarmis <126983335+tsarmis@users.noreply.github.com> Date: Mon, 13 Mar 2023 01:08:37 +0200 Subject: [PATCH 362/382] Update el.rs --- src/lang/el.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/lang/el.rs b/src/lang/el.rs index 91a627628..93b921af4 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -463,17 +463,17 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("confirm_idd_driver_tip", "Είναι ενεργοποιημένη η επιλογή εγκατάστασης του προγράμματος οδήγησης εικονικής οθόνης. Λάβετε υπόψη ότι θα εγκατασταθεί ένα δοκιμαστικό πιστοποιητικό για το πρόγραμμα οδήγησης εικονικής οθόνης. Αυτό το πιστοποιητικό θα χρησιμοποιηθεί μόνο για την πιστοποίηση των προγραμμάτων οδήγησης του Rustdesk."), ("RDP Settings", "Ρυθμίσεις RDP"), ("Sort by", "Ταξινόμηση κατά"), - ("New Connection", ""), - ("Restore", ""), - ("Minimize", ""), - ("Maximize", ""), - ("Your Device", ""), - ("empty_recent_tip", ""), - ("empty_favorite_tip", ""), - ("empty_lan_tip", ""), - ("empty_address_book_tip", ""), - ("eg: admin", ""), - ("Empty Username", ""), - ("Empty Password", ""), + ("New Connection", "Νέα σύνδεση"), + ("Restore", "Επαναφορά"), + ("Minimize", "Ελαχιστοποίηση"), + ("Maximize", "Μεγιστοποίηση"), + ("Your Device", "Η συσκευή σας"), + ("empty_recent_tip", "Δεν υπάρχουν πρόσφατες συνεδρίες!\nΔοκιμάστε να ξεκινήσετε μια νέα."), + ("empty_favorite_tip", "Δεν υπάρχουν ακόμη αγαπημένες συνδέσεις;\nΑφού πραγματοποιήστε σύνδεση με κάποιο απομακρυσμένο σταθμό, μπορείτε να τον προσθέσετε στα αγαπημένα σας!"), + ("empty_lan_tip", "Δεν έχουμε ανακαλυφθεί ακόμη απομακρυσμένοι σταθμοί."), + ("empty_address_book_tip", "Φαίνεται ότι αυτή τη στιγμή δεν υπάρχουν αγαπημένες συνδέσεις στο βιβλίο διευθύνσεών σας."), + ("eg: admin", "π.χ. admin"), + ("Empty Username", "Κενό όνομα χρήστη"), + ("Empty Password", "Κενός κωδικός πρόσβασης"), ].iter().cloned().collect(); } From 1b2d3e87f731d759530cc9c113958984287dc1fa Mon Sep 17 00:00:00 2001 From: csf Date: Mon, 13 Mar 2023 10:37:26 +0900 Subject: [PATCH 363/382] android server add android_permission_may_not_change_tip --- flutter/lib/models/server_model.dart | 30 +++++++++++++++++++++++++++- 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/el.rs | 1 + src/lang/en.rs | 1 + src/lang/eo.rs | 1 + src/lang/es.rs | 1 + src/lang/fa.rs | 1 + src/lang/fr.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/nl.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 + 35 files changed, 63 insertions(+), 1 deletion(-) diff --git a/flutter/lib/models/server_model.dart b/flutter/lib/models/server_model.dart index 4fab2b24c..846f20ed4 100644 --- a/flutter/lib/models/server_model.dart +++ b/flutter/lib/models/server_model.dart @@ -231,6 +231,9 @@ class ServerModel with ChangeNotifier { } toggleAudio() async { + if (clients.isNotEmpty) { + await showClientsMayNotBeChangedAlert(parent.target); + } if (!_audioOk && !await AndroidPermissionManager.check(kRecordAudio)) { final res = await AndroidPermissionManager.request(kRecordAudio); if (!res) { @@ -245,6 +248,9 @@ class ServerModel with ChangeNotifier { } toggleFile() async { + if (clients.isNotEmpty) { + await showClientsMayNotBeChangedAlert(parent.target); + } if (!_fileOk && !await AndroidPermissionManager.check(kManageExternalStorage)) { final res = @@ -260,7 +266,10 @@ class ServerModel with ChangeNotifier { notifyListeners(); } - toggleInput() { + toggleInput() async { + if (clients.isNotEmpty) { + await showClientsMayNotBeChangedAlert(parent.target); + } if (_inputOk) { parent.target?.invokeMethod("stop_input"); bind.mainSetOption(key: "enable-keyboard", value: 'N'); @@ -712,3 +721,22 @@ showInputWarnAlert(FFI ffi) { ); }); } + +Future showClientsMayNotBeChangedAlert(FFI? ffi) async { + await ffi?.dialogManager.show((setState, close) { + return CustomAlertDialog( + title: Text(translate("Permissions")), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text(translate("android_permission_may_not_change_tip")), + ], + ), + actions: [ + dialogButton("OK", onPressed: close), + ], + onSubmit: close, + onCancel: close, + ); + }); +} diff --git a/src/lang/ca.rs b/src/lang/ca.rs index f09223111..46499535e 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Tancar el servei tancarà totes les connexions establertes."), ("android_version_audio_tip", "La versión actual de Android no admet la captura d'àudio, actualizi a Android 10 o superior."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Compte"), ("Overwrite", "Sobreescriure"), ("This file exists, skip or overwrite this file?", "Aquest arxiu ja existeix, ometre o sobreescriure l'arxiu?"), diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 69a3bdac5..e3488043c 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "关闭服务将自动关闭所有已建立的连接。"), ("android_version_audio_tip", "当前安卓版本不支持音频录制,请升级至安卓 10 或更高。"), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", "对于已建立的连接,权限可能不会立即发生改变,除非重新建立连接。"), ("Account", "账户"), ("Overwrite", "覆盖"), ("This file exists, skip or overwrite this file?", "这个文件/文件夹已存在,跳过/覆盖?"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index bd0cc452a..905ef62b6 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Zastavení služby automaticky ukončí veškerá navázaná spojení."), ("android_version_audio_tip", "Vámi nyní používaná verze systému Android nepodporuje zachytávání zvuku – přejděte na Android 10 nebo novější."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", ""), ("Overwrite", "Přepsat"), ("This file exists, skip or overwrite this file?", "Tento soubor existuje – přeskočit ho nebo přepsat?"), diff --git a/src/lang/da.rs b/src/lang/da.rs index 6c486ffc0..71952584b 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Ved at lukke tjenesten lukkes alle fremstillede forbindelser automatisk."), ("android_version_audio_tip", "Den aktuelle Android -version understøtter ikke lydoptagelse, skal du opdatere om Android 10 eller højere."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Konto"), ("Overwrite", "Overskriv"), ("This file exists, skip or overwrite this file?", "Denne fil findes, springer over denne fil eller overskriver?"), diff --git a/src/lang/de.rs b/src/lang/de.rs index 647215392..5b2be99f0 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Durch das Deaktivieren des Dienstes werden automatisch alle hergestellten Verbindungen getrennt."), ("android_version_audio_tip", "Ihre Android-Version unterstützt keine Audioaufnahme, bitte aktualisieren Sie auf Android 10 oder höher, falls möglich."), ("android_start_service_tip", "Tippen Sie auf \"Vermittlungsdienst starten\" oder aktivieren Sie die Berechtigung \"Bildschirmaufnahme\", um den Bildschirmfreigabedienst zu starten."), + ("android_permission_may_not_change_tip", ""), ("Account", "Konto"), ("Overwrite", "Überschreiben"), ("This file exists, skip or overwrite this file?", "Diese Datei existiert; überspringen oder überschreiben?"), diff --git a/src/lang/el.rs b/src/lang/el.rs index 91a627628..7e7806ae0 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Η απενεργοποίηση της υπηρεσίας θα αποσυνδέσει αυτόματα όλες τις εγκατεστημένες συνδέσεις."), ("android_version_audio_tip", "Η έκδοση Android που διαθέτετε δεν υποστηρίζει εγγραφή ήχου, ενημερώστε το σε Android 10 ή νεότερη έκδοση, εάν είναι δυνατόν."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Λογαριασμός"), ("Overwrite", "Αντικατάσταση"), ("This file exists, skip or overwrite this file?", "Αυτό το αρχείο υπάρχει, παράβλεψη ή αντικατάσταση αυτού του αρχείου;"), diff --git a/src/lang/en.rs b/src/lang/en.rs index b5d4d8b25..b44ff2e40 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -24,6 +24,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Closing the service will automatically close all established connections."), ("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 enable [Screen Capture] permission to start the screen sharing service."), + ("android_permission_may_not_change_tip", "Permissions for established connections may not be changed instantly until reconnected."), ("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"), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index ee47688e2..a916569df 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", ""), ("android_version_audio_tip", ""), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", ""), ("Overwrite", ""), ("This file exists, skip or overwrite this file?", ""), diff --git a/src/lang/es.rs b/src/lang/es.rs index d19eae344..82c10cb1a 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Cerrar el servicio cerrará automáticamente todas las conexiones establecidas."), ("android_version_audio_tip", "La versión actual de Android no admite la captura de audio, actualice a Android 10 o posterior."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Cuenta"), ("Overwrite", "Sobrescribir"), ("This file exists, skip or overwrite this file?", "Este archivo existe, ¿omitir o sobrescribir este archivo?"), diff --git a/src/lang/fa.rs b/src/lang/fa.rs index b971de772..bd75f7405 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "با بستن سرویس، تمام اتصالات برقرار شده به طور خودکار بسته می شود"), ("android_version_audio_tip", "نسخه فعلی اندروید از ضبط صدا پشتیبانی نمی‌کند، لطفاً به اندروید 10 یا بالاتر به‌روزرسانی کنید"), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "حساب کاربری"), ("Overwrite", "بازنویسی"), ("This file exists, skip or overwrite this file?", "این فایل وجود دارد، از فایل رد شود یا آن را بازنویسی کند؟"), diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 08bf3a0ce..795ce62c3 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "La fermeture du service fermera automatiquement toutes les connexions établies."), ("android_version_audio_tip", "La version actuelle d'Android ne prend pas en charge la capture audio, veuillez passer à Android 10 ou supérieur."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Compte"), ("Overwrite", "Écraser"), ("This file exists, skip or overwrite this file?", "Ce fichier existe, ignorer ou écraser ce fichier ?"), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 95b1aa23f..9ae7284c1 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "A szolgáltatás leállítása automatikusan szétkapcsol minden létező kapcsolatot."), ("android_version_audio_tip", "A jelenlegi Android verzió nem támogatja a hangrögzítést, frissítsen legalább Android 10-re, vagy egy újabb verzióra."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Fiók"), ("Overwrite", "Felülírás"), ("This file exists, skip or overwrite this file?", "Ez a fájl már létezik, kihagyja vagy felülírja ezt a fájlt?"), diff --git a/src/lang/id.rs b/src/lang/id.rs index de56499fc..8e3a4c68a 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Menutup layanan akan secara otomatis menutup semua koneksi yang dibuat."), ("android_version_audio_tip", "Versi Android saat ini tidak mendukung pengambilan audio, harap tingkatkan ke Android 10 atau lebih tinggi."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Akun"), ("Overwrite", "Timpa"), ("This file exists, skip or overwrite this file?", "File ini sudah ada, lewati atau timpa file ini?"), diff --git a/src/lang/it.rs b/src/lang/it.rs index 23eaf6bb4..a9efb7c39 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "La chiusura del servizio chiuderà automaticamente tutte le connessioni stabilite."), ("android_version_audio_tip", "L'attuale versione di Android non supporta l'acquisizione audio, esegui l'upgrade ad Android 10 o versioni successive."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Account"), ("Overwrite", "Sovrascrivi"), ("This file exists, skip or overwrite this file?", "Questo file esiste, saltare o sovrascrivere questo file?"), diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 7a04a9230..10c69ac79 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "サービスを停止すると、現在確立されている接続が全て自動的に閉じられます。"), ("android_version_audio_tip", "現在のAndroidバージョンでは音声キャプチャはサポートされていません。Android 10以降にアップグレードしてください。"), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", ""), ("Overwrite", "上書き"), ("This file exists, skip or overwrite this file?", "このファイルは存在しています。スキップするか上書きしますか?"), diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 8a1f6f18e..2d979ff67 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "서비스를 종료하면 모든 연결이 자동으로 닫힙니다."), ("android_version_audio_tip", "현재 Android 버전은 오디오 캡처를 지원하지 않습니다. Android 10 이상으로 업그레이드하십시오."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", ""), ("Overwrite", "덮어쓰기"), ("This file exists, skip or overwrite this file?", "해당 파일이 이미 존재합니다, 넘어가거나 덮어쓰시겠습니까?"), diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 95903ec2e..8e0346bfe 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Сербесті жабу аутыматты түрде барлық орнатылған қосылымдарды жабады."), ("android_version_audio_tip", "Ағымдағы Android нұсқасы аудионы түсіруді қолдамайды, Android 10 не жоғарғысына жаңғыртуды өтінеміз."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Есепкі"), ("Overwrite", "Үстінен қайта жазу"), ("This file exists, skip or overwrite this file?", "Бұл файыл бар, өткізіп жіберу әлде үстінен қайта жазу керек пе?"), diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 885d6f0bd..1e7b8fc95 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Het sluiten van de service zal automatisch alle gemaakte verbindingen sluiten."), ("android_version_audio_tip", "De huidige versie van Android ondersteunt geen audio-opname, upgrade naar Android 10 of hoger."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Account"), ("Overwrite", "Overschrijven"), ("This file exists, skip or overwrite this file?", "Dit bestand bestaat reeds, overslaan of overschrijven?"), diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 0e990d7df..050e210f4 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Zamknięcie usługi spowoduje automatyczne zamknięcie wszystkich nawiązanych połączeń."), ("android_version_audio_tip", "Bieżąca wersja systemu Android nie obsługuje przechwytywania dźwięku, zaktualizuj system do wersji Android 10 lub nowszej."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Konto"), ("Overwrite", "Nadpisz"), ("This file exists, skip or overwrite this file?", "Ten plik istnieje, pominąć czy nadpisać ten plik?"), diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index c87f2ede3..6910c39e3 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Fechar o serviço irá automaticamente fechar todas as ligações estabelecidas."), ("android_version_audio_tip", "A versão atual do Android não suporta captura de áudio, por favor actualize para o Android 10 ou maior."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", ""), ("Overwrite", "Substituir"), ("This file exists, skip or overwrite this file?", "Este ficheiro já existe, ignorar ou substituir este ficheiro?"), diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 364bc21fd..5ebe185d8 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Fechar o serviço irá automaticamente fechar todas as conexões estabelecidas."), ("android_version_audio_tip", "A versão atual do Android não suporta captura de áudio, por favor atualize para o Android 10 ou superior."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Conta"), ("Overwrite", "Substituir"), ("This file exists, skip or overwrite this file?", "Este arquivo existe, pular ou substituir este arquivo?"), diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 188fc09e9..723a58f15 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Închiderea serviciului va închide automat toate conexiunile stabilite."), ("android_version_audio_tip", "Versiunea actuală de Android nu suportă captura audio. Fă upgrade la Android 10 sau la o versiune superioară."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Cont"), ("Overwrite", "Suprascrie"), ("This file exists, skip or overwrite this file?", "Fișier deja existent. Omite sau suprascrie?"), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 3233ced2b..63f49b833 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Закрытие службы автоматически закроет все установленные соединения."), ("android_version_audio_tip", "Текущая версия Android не поддерживает захват звука, обновите её до Android 10 или выше."), ("android_start_service_tip", "Нажмите [Запустить службу] или разрешите [Захват экрана], чтобы запустить службу демонстрации экрана."), + ("android_permission_may_not_change_tip", ""), ("Account", "Аккаунт"), ("Overwrite", "Перезаписать"), ("This file exists, skip or overwrite this file?", "Этот файл существует, пропустить или перезаписать файл?"), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 81091a23d..7ddd1e87f 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Zastavenie služby automaticky ukončí všetky naviazané spojenia."), ("android_version_audio_tip", "Vaša verzia Androidu neumožňuje zaznamenávanie zvuku. Prejdite na verziu Android 10 alebo vyššiu."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", ""), ("Overwrite", "Prepísať"), ("This file exists, skip or overwrite this file?", "Preskočiť alebo prepísať existujúci súbor?"), diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 86c76e6b0..63276fd7a 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Z zaustavitvijo storitve bodo samodejno prekinjene vse oddaljene povezave."), ("android_version_audio_tip", "Trenutna različica Androida ne omogoča zajema zvoka. Za zajem zvoka nadgradite na Android 10 ali novejši."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Račun"), ("Overwrite", "Prepiši"), ("This file exists, skip or overwrite this file?", "Datoteka obstaja, izpusti ali prepiši?"), diff --git a/src/lang/sq.rs b/src/lang/sq.rs index e8c423603..77012249a 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Mbyllja e shërbimit do të mbyllë automatikisht të gjitha lidhjet e vendosura."), ("android_version_audio_tip", "Versioni aktual i Android nuk mbështet regjistrimin e audios, ju lutemi përmirësoni në Android 10 ose më të lartë."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Llogaria"), ("Overwrite", "Përshkruaj"), ("This file exists, skip or overwrite this file?", "Ky skedar ekziston , tejkalo ose përshkruaj këtë skedarë"), diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 7a8a43467..e82842c06 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Zatvaranje servisa automatski će zatvoriti sve uspostavljene konekcije."), ("android_version_audio_tip", "Tekuća Android verzija ne podržava audio snimanje, molimo nadogradite na Android 10 ili veći."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Nalog"), ("Overwrite", "Prepiši preko"), ("This file exists, skip or overwrite this file?", "Ova datoteka postoji, preskoči ili prepiši preko?"), diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 28f16c547..84cacd7c6 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Genom att stänga av tjänsten kommer alla enheter att kopplas ifrån."), ("android_version_audio_tip", "Din version av Android stödjer inte ljudinspelning, Android 10 eller nyare krävs"), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Konto"), ("Overwrite", "Skriv över"), ("This file exists, skip or overwrite this file?", "Filen finns redan, hoppa över eller skriv över filen?"), diff --git a/src/lang/template.rs b/src/lang/template.rs index bed743e32..0f1ec6362 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", ""), ("android_version_audio_tip", ""), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", ""), ("Overwrite", ""), ("This file exists, skip or overwrite this file?", ""), diff --git a/src/lang/th.rs b/src/lang/th.rs index 543b78cda..00f521e1d 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "การปิดการใช้งานเซอร์วิสจะปิดการเชื่อมต่อทั้งหมดโดยอัตโนมัติ"), ("android_version_audio_tip", "เวอร์ชั่นแอนดรอยด์ปัจจุบันของคุณไม่รองรับการบันทึกข้อมูลเสียง กรุณาอัปเกรดเป็นแอนดรอยด์เวอร์ชั่น 10 หรือสูงกว่า"), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "บัญชี"), ("Overwrite", "เขียนทับ"), ("This file exists, skip or overwrite this file?", "พบไฟล์ที่มีอยู่แล้ว ต้องการเขียนทับหรือไม่?"), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 4a50b0a89..54d4cd951 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Hizmetin kapatılması, kurulan tüm bağlantıları otomatik olarak kapatacaktır."), ("android_version_audio_tip", "Mevcut Android sürümü ses yakalamayı desteklemiyor, lütfen Android 10 veya sonraki bir sürüme yükseltin."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Hesap"), ("Overwrite", "üzerine yaz"), ("This file exists, skip or overwrite this file?", "Bu dosya var, bu dosya atlansın veya üzerine yazılsın mı?"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 428de753d..7737ad41d 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "關閉服務將自動關閉所有已建立的連接。"), ("android_version_audio_tip", "目前的 Android 版本不支持音訊錄製,請升級至 Android 10 或以上版本。"), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", "對於已經建立的連接,權限可能不會立即發生改變,除非重新建立連接。"), ("Account", "賬戶"), ("Overwrite", "覆寫"), ("This file exists, skip or overwrite this file?", "此檔案/資料夾已存在,要跳過或是覆寫此檔案嗎?"), diff --git a/src/lang/ua.rs b/src/lang/ua.rs index ec8012cef..23523a820 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Закриття служби автоматично закриє всі встановлені з'єднання."), ("android_version_audio_tip", "Поточна версія Android не підтримує захоплення звуку, оновіть її до Android 10 або вище."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", "Акаунт"), ("Overwrite", "Перезаписати"), ("This file exists, skip or overwrite this file?", "Цей файл існує, пропустити або перезаписати файл?"), diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 77fc3cfa3..5e0ef3d03 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -289,6 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Đóng dịch vụ sẽ tự động đóng tất cả các kết nối đã thiết lập."), ("android_version_audio_tip", "Phiên bản Android hiện tại không hỗ trợ ghi âm, vui lòng nâng cấp lên Android 10 trở lên."), ("android_start_service_tip", ""), + ("android_permission_may_not_change_tip", ""), ("Account", ""), ("Overwrite", "Ghi đè"), ("This file exists, skip or overwrite this file?", "Tệp tin này đã tồn tại, bạn có muốn bỏ qua hay ghi đè lên tệp tin này?"), From a5fe4ee3e632a1471604229c912ab87d9b24bcf2 Mon Sep 17 00:00:00 2001 From: 21pages Date: Sun, 12 Mar 2023 10:48:54 +0800 Subject: [PATCH 364/382] add elevation for remote menubar/draggable Signed-off-by: 21pages --- .../lib/desktop/widgets/remote_menubar.dart | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index c444214c6..fb4439905 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -108,6 +108,7 @@ class _MenubarTheme { static const double buttonHMargin = 3; static const double buttonVMargin = 6; static const double iconRadius = 8; + static const double elevation = 3; } typedef DismissFunc = void Function(); @@ -369,10 +370,13 @@ class _RemoteMenubarState extends State { alignment: FractionalOffset(_fractionX.value, 0), child: Offstage( offstage: _dragging.isTrue, - child: _DraggableShowHide( - dragging: _dragging, - fractionX: _fractionX, - show: show, + child: Material( + elevation: _MenubarTheme.elevation, + child: _DraggableShowHide( + dragging: _dragging, + fractionX: _fractionX, + show: show, + ), ), ), ); @@ -406,15 +410,14 @@ class _RemoteMenubarState extends State { return Column( mainAxisSize: MainAxisSize.min, children: [ - Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4.0)), - color: Theme.of(context) - .menuBarTheme - .style - ?.backgroundColor - ?.resolve(MaterialState.values.toSet()), - ), + Material( + elevation: _MenubarTheme.elevation, + borderRadius: BorderRadius.all(Radius.circular(4.0)), + color: Theme.of(context) + .menuBarTheme + .style + ?.backgroundColor + ?.resolve(MaterialState.values.toSet()), child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Theme( From 118bd9523a8d6275ce056277620d3b8ed309861c Mon Sep 17 00:00:00 2001 From: 21pages Date: Mon, 13 Mar 2023 08:17:16 +0800 Subject: [PATCH 365/382] Increase contrast of quality monitor Signed-off-by: 21pages --- flutter/lib/common/widgets/overlay.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/lib/common/widgets/overlay.dart b/flutter/lib/common/widgets/overlay.dart index ba7b8a059..c67f0f7fb 100644 --- a/flutter/lib/common/widgets/overlay.dart +++ b/flutter/lib/common/widgets/overlay.dart @@ -331,7 +331,7 @@ class QualityMonitor extends StatelessWidget { Expanded( flex: 8, child: AutoSizeText(info, - style: TextStyle(color: MyTheme.darkGray), + style: TextStyle(color: Color.fromARGB(255, 210, 210, 210)), textAlign: TextAlign.right, maxLines: 1)), Spacer(flex: 1), @@ -353,7 +353,7 @@ class QualityMonitor extends StatelessWidget { ? Container( constraints: BoxConstraints(maxWidth: 200), padding: const EdgeInsets.all(8), - color: MyTheme.canvasColor.withAlpha(120), + color: MyTheme.canvasColor.withAlpha(150), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ From 04afca08a4cf0d9e1f9688c510a327a6cf3e7027 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Mon, 13 Mar 2023 11:42:54 +0800 Subject: [PATCH 366/382] opt: update and cherry-pick latest window_manager --- flutter/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 46278bf0d..b2102997e 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -55,11 +55,11 @@ dependencies: window_manager: git: url: https://github.com/Kingtous/rustdesk_window_manager - ref: 32b24c66151b72bba033ef8b954486aa9351d97b + ref: c140f9685bead805c433c9f5a4618a5115f01fa8 desktop_multi_window: git: url: https://github.com/Kingtous/rustdesk_desktop_multi_window - ref: e3947d4b4f8edaa655de63cd47f2a59a6e024218 + ref: d1da784d3e8d89f3134b026d00d19711de894e7d freezed_annotation: ^2.0.3 flutter_custom_cursor: ^0.0.4 window_size: From 7caafd563eb1ef0a20539a5adaab50d3e89342e7 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 13 Mar 2023 13:46:44 +0800 Subject: [PATCH 367/382] cm, better position to start ipc Signed-off-by: fufesou --- flutter/lib/main.dart | 1 - flutter/lib/models/native_model.dart | 3 +++ flutter/lib/models/server_model.dart | 11 +++++++---- src/server/connection.rs | 3 +++ 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index bb1b4f552..f0a9a938f 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -217,7 +217,6 @@ void runMultiWindow( void runConnectionManagerScreen(bool hide) async { await initEnv(kAppTypeConnectionManager); - await bind.cmStartListenIpcThread(); _runApp( '', const DesktopServerPage(), diff --git a/flutter/lib/models/native_model.dart b/flutter/lib/models/native_model.dart index 28dc8085e..2b99e1823 100644 --- a/flutter/lib/models/native_model.dart +++ b/flutter/lib/models/native_model.dart @@ -234,6 +234,9 @@ class PlatformFFI { debugPrint( '_appType:$_appType,info1-id:$id,info2-name:$name,dir:$_dir'); } + if (desktopType == DesktopType.cm) { + await _ffiBind.cmStartListenIpcThread(); + } await _ffiBind.mainDeviceId(id: id); await _ffiBind.mainDeviceName(name: name); await _ffiBind.mainSetHomeDir(home: _homeDir); diff --git a/flutter/lib/models/server_model.dart b/flutter/lib/models/server_model.dart index 4fab2b24c..031d52c79 100644 --- a/flutter/lib/models/server_model.dart +++ b/flutter/lib/models/server_model.dart @@ -128,10 +128,13 @@ class ServerModel with ChangeNotifier { _connectStatus = status; notifyListeners(); } - final res = await bind.cmCheckClientsLength(length: _clients.length); - if (res != null) { - debugPrint("clients not match!"); - updateClientState(res); + + if (desktopType == DesktopType.cm) { + final res = await bind.cmCheckClientsLength(length: _clients.length); + if (res != null) { + debugPrint("clients not match!"); + updateClientState(res); + } } updatePasswordModel(); diff --git a/src/server/connection.rs b/src/server/connection.rs index 7127187d8..9941dcea5 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -2013,10 +2013,12 @@ async fn start_ipc( for _ in 0..10 { #[cfg(not(target_os = "linux"))] { + log::debug!("Start cm"); res = crate::platform::run_as_user(args.clone()); } #[cfg(target_os = "linux")] { + log::debug!("Start cm"); res = crate::platform::run_as_user(args.clone(), None); } if res.is_ok() { @@ -2032,6 +2034,7 @@ async fn start_ipc( run_done = false; } if !run_done { + log::debug!("Start cm"); super::CHILD_PROCESS .lock() .unwrap() From 717202fdeef5d48913eebca35afeab1b60cc43f7 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 13 Mar 2023 14:22:04 +0800 Subject: [PATCH 368/382] change wait timeout for cm ipc Signed-off-by: fufesou --- src/server/connection.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/connection.rs b/src/server/connection.rs index 9941dcea5..7899009c4 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -2040,7 +2040,7 @@ async fn start_ipc( .unwrap() .push(crate::run_me(args)?); } - for _ in 0..10 { + for _ in 0..20 { sleep(0.3).await; if let Ok(s) = crate::ipc::connect(1000, "_cm").await { stream = Some(s); From 46293cd378be23a993a124bb5057276c383caa69 Mon Sep 17 00:00:00 2001 From: FastAct <93490087+FastAct@users.noreply.github.com> Date: Mon, 13 Mar 2023 08:36:50 +0100 Subject: [PATCH 369/382] Update nl.rs --- src/lang/nl.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 1e7b8fc95..6abb1b87f 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -459,22 +459,22 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Codec", "Codec"), ("Resolution", "Resolutie"), ("No transfers in progress", "Geen overdrachten in uitvoering"), - ("Set one-time password length", ""), - ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", ""), - ("RDP Settings", ""), - ("Sort by", ""), - ("New Connection", ""), - ("Restore", ""), - ("Minimize", ""), - ("Maximize", ""), - ("Your Device", ""), - ("empty_recent_tip", ""), - ("empty_favorite_tip", ""), - ("empty_lan_tip", ""), - ("empty_address_book_tip", ""), - ("eg: admin", ""), - ("Empty Username", ""), - ("Empty Password", ""), + ("Set one-time password length", "Stel de lengte van het eenmalige wachtwoord in"), + ("idd_driver_tip", "Installeer het virtuele beeldschermstuurprogramma dat wordt gebruikt wanneer u geen fysieke beeldschermen hebt."), + ("confirm_idd_driver_tip", "De optie om het virtuele displaystuurprogramma te installeren is ingeschakeld. Er wordt een testcertificaat geplaatst om het virtuele displaystuurprogramma te vertrouwen. Dit testcertificaat wordt alleen gebruikt om RustDesk-stuurprogramma's te vertrouwen."), + ("RDP Settings", "RDP Instellingen"), + ("Sort by", "Sorteren op"), + ("New Connection", "Nieuwe Verbinding"), + ("Restore", "Herstel"), + ("Minimize", "Minimaliseren"), + ("Maximize", "Maximaliseren"), + ("Your Device", "Uw Apparaat"), + ("empty_recent_tip", "Oeps, geen actuele situatie!\nTijd om een nieuwe te plannen."), + ("empty_favorite_tip", "Nog geen favoriete Station op afstand? Laat ons iemand vinden om mee te verbinden en voeg hem toe aan je favorieten!"), + ("empty_lan_tip", "Oh nee, het lijkt erop dat we nog geen extern station hebben ontdekt."), + ("empty_address_book_tip", "Oh jee, het lijkt erop dat er momenteel geen externe stations in je adresboek staan."), + ("eg: admin", "bijv: admin"), + ("Empty Username", "Gebruikersnaam Leeg"), + ("Empty Password", "Wachtwoord Leeg"), ].iter().cloned().collect(); } From 050e107cb6c5a6c4b925d661ec4897354a2f7044 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Mon, 13 Mar 2023 09:05:38 +0100 Subject: [PATCH 370/382] dynamic width based on translated strings #3625 --- flutter/lib/common/widgets/peer_tab_page.dart | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index 52bdc8cc6..2d36d9150 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:math'; import 'dart:ui' as ui; import 'package:bot_toast/bot_toast.dart'; @@ -453,6 +454,13 @@ class _PeerSortDropdownState extends State { color: Theme.of(context).colorScheme.background, borderRadius: BorderRadius.circular(5), ); + + final translated_text = + PeerSortType.values.map((e) => translate(e)).toList(); + + final double max_width = + 50 + translated_text.map((e) => e.length).reduce(max) * 10; + return Container( padding: EdgeInsets.all(4.0), decoration: deco, @@ -471,12 +479,13 @@ class _PeerSortDropdownState extends State { Icons.sort, size: 18, ), + isExpanded: true, dropdownStyleData: DropdownStyleData( decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(10), ), - width: 160, + width: max_width, ), items: [ DropdownMenuItem( @@ -487,7 +496,7 @@ class _PeerSortDropdownState extends State { ), enabled: false, ), - ...PeerSortType.values + ...translated_text .map>( (String value) => DropdownMenuItem( value: value, @@ -500,7 +509,7 @@ class _PeerSortDropdownState extends State { size: 18, ).paddingOnly(right: 12), Text( - translate(value), + value, overflow: TextOverflow.ellipsis, ), ], From 23b7bcc2a03ef010701a0d29f774bf1321f1fede Mon Sep 17 00:00:00 2001 From: FastAct <93490087+FastAct@users.noreply.github.com> Date: Mon, 13 Mar 2023 09:53:14 +0100 Subject: [PATCH 371/382] Update nl.rs --- src/lang/nl.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 6abb1b87f..34ffff9a5 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -37,10 +37,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Clipboard is empty", "Klembord is leeg"), ("Stop service", "Stop service"), ("Change ID", "Wijzig ID"), - ("Your new ID", ""), - ("length %min% to %max%", ""), - ("starts with a letter", ""), - ("allowed characters", ""), + ("Your new ID", "Uw nieuw ID"), + ("length %min% to %max%", "lengte %min% tot %max%"), + ("starts with a letter", "begint met een letter"), + ("allowed characters", "toegestane tekens"), ("id_change_tip", "Alleen de letters a-z, A-Z, 0-9, _ (underscore) kunnen worden gebruikt. De eerste letter moet a-z, A-Z zijn. De lengte moet tussen 6 en 16 liggen."), ("Website", "Website"), ("About", "Over"), @@ -213,7 +213,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the peer", "Handmatig gesloten door de peer"), ("Enable remote configuration modification", "Wijziging configuratie op afstand inschakelen"), ("Run without install", "Uitvoeren zonder installatie"), - ("Connect via relay", ""), + ("Connect via relay", "Verbinden via relais"), ("Always connect via relay", "Altijd verbinden via relay"), ("whitelist_tip", "Alleen een IP-adres op de witte lijst krijgt toegang tot mijn toestel"), ("Login", "Log In"), @@ -311,8 +311,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk achtergronddienst behouden"), ("Ignore Battery Optimizations", "Negeer Batterij Optimalisaties"), ("android_open_battery_optimizations_tip", "Ga naar de volgende pagina met instellingen"), - ("Start on Boot", ""), - ("Start the screen sharing service on boot, requires special permissions", ""), + ("Start on Boot", "Starten bij Opstarten"), + ("Start the screen sharing service on boot, requires special permissions", "Start de schermdelings service bij het opstarten, vereist speciale rechten"), ("Connection not allowed", "Verbinding niet toegestaan"), ("Legacy mode", "Verouderde modus"), ("Map mode", "Map mode"), @@ -348,7 +348,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Security", "Beveiliging"), ("Theme", "Thema"), ("Dark Theme", "Donker Thema"), - ("Light Theme", ""), + ("Light Theme", "Lichte Thema"), ("Dark", "Donker"), ("Light", "Licht"), ("Follow System", "Volg Systeem"), From 28aecbb9e95d84d7d5c183a049a4c2f0745b1899 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 13 Mar 2023 21:03:43 +0800 Subject: [PATCH 372/382] maybe better mouse hover Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 8 ++- flutter/lib/models/input_model.dart | 63 ++++++++++++++++++++-- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index ab0daece7..03074efc3 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -308,6 +308,10 @@ class _RemotePageState extends State } void leaveView(PointerExitEvent evt) { + if (_ffi.ffiModel.keyboard()) { + _ffi.inputModel.tryHoverEdgeOnExit(evt.position); + } + _cursorOverImage.value = false; _firstEnterImage.value = false; if (_onEnterOrLeaveImage4Menubar != null) { @@ -329,8 +333,8 @@ class _RemotePageState extends State PointerExitEventListener? onExit, ) { return RawPointerMouseRegion( - onEnter: enterView, - onExit: leaveView, + onEnter: onEnter, + onExit: onExit, onPointerDown: (event) { // A double check for blur status. // Note: If there's an `onPointerDown` event is triggered, `_isWindowBlur` is expected being false. diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index df9ad2585..f09bc3d60 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -419,7 +419,50 @@ class InputModel { 'type': _kMouseEventMove, }); - void handleMouse(Map evt) { + void tryHoverEdgeOnExit(Offset pos) => handleMouse( + { + 'x': pos.dx, + 'y': pos.dy, + 'buttons': 0, + 'type': _kMouseEventMove, + }, + onExit: true, + ); + + int trySetNearestRange(int v, int min, int max, int n) { + if (v < min && v >= min - n) { + v = min; + } + if (v > max && v <= max + n) { + v = max; + } + return v; + } + + Offset setNearestEdge(double x, double y, Display d) { + double left = x - d.x; + double right = d.x + d.width - 1 - x; + double top = y - d.y; + double bottom = d.y + d.height - 1 - y; + if (left < right && left < top && left < bottom) { + x = d.x; + } + if (right < left && right < top && right < bottom) { + x = d.x + d.width - 1; + } + if (top < left && top < right && top < bottom) { + y = d.y; + } + if (bottom < left && bottom < right && bottom < top) { + y = d.y + d.height - 1; + } + return Offset(x, y); + } + + void handleMouse( + Map evt, { + bool onExit = false, + }) { double x = evt['x']; double y = max(0.0, evt['y']); final cursorModel = parent.target!.cursorModel; @@ -501,6 +544,13 @@ class InputModel { } x += d.x; y += d.y; + + if (onExit) { + final pos = setNearestEdge(x, y, d); + x = pos.dx; + y = pos.dy; + } + var evtX = 0; var evtY = 0; try { @@ -512,10 +562,13 @@ class InputModel { return; } - if (evtX < d.x || - evtY < d.y || - evtX > (d.x + d.width) || - evtY > (d.y + d.height)) { + int minX = d.x.toInt(); + int maxX = (d.x + d.width).toInt() - 1; + int minY = d.y.toInt(); + int maxY = (d.y + d.height).toInt() - 1; + evtX = trySetNearestRange(evtX, minX, maxX, 3); + evtY = trySetNearestRange(evtY, minY, maxY, 3); + if (evtX < minX || evtY < minY || evtX > maxX || evtY > maxY) { // If left mouse up, no early return. if (evt['buttons'] != kPrimaryMouseButton || type != 'up') { return; From 3a6f94503cb8233a569cece096f8ea2126e73589 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 13 Mar 2023 21:05:41 +0800 Subject: [PATCH 373/382] trivial changes Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 2 +- flutter/lib/models/input_model.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 03074efc3..2099f2e95 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -309,7 +309,7 @@ class _RemotePageState extends State void leaveView(PointerExitEvent evt) { if (_ffi.ffiModel.keyboard()) { - _ffi.inputModel.tryHoverEdgeOnExit(evt.position); + _ffi.inputModel.tryMoveEdgeOnExit(evt.position); } _cursorOverImage.value = false; diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index f09bc3d60..21bbb9a39 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -419,7 +419,7 @@ class InputModel { 'type': _kMouseEventMove, }); - void tryHoverEdgeOnExit(Offset pos) => handleMouse( + void tryMoveEdgeOnExit(Offset pos) => handleMouse( { 'x': pos.dx, 'y': pos.dy, From 38de74f522b6bea06a628aac877f94fcf1855095 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 13 Mar 2023 21:18:10 +0800 Subject: [PATCH 374/382] set range from 3 to 5 Signed-off-by: fufesou --- flutter/lib/models/input_model.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index 21bbb9a39..9366d5b46 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -566,8 +566,8 @@ class InputModel { int maxX = (d.x + d.width).toInt() - 1; int minY = d.y.toInt(); int maxY = (d.y + d.height).toInt() - 1; - evtX = trySetNearestRange(evtX, minX, maxX, 3); - evtY = trySetNearestRange(evtY, minY, maxY, 3); + evtX = trySetNearestRange(evtX, minX, maxX, 5); + evtY = trySetNearestRange(evtY, minY, maxY, 5); if (evtX < minX || evtY < minY || evtX > maxX || evtY > maxY) { // If left mouse up, no early return. if (evt['buttons'] != kPrimaryMouseButton || type != 'up') { From d503b31011945bac0001f94aedc51698fcc1d734 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Mon, 13 Mar 2023 20:43:03 +0100 Subject: [PATCH 375/382] Update chat_model.dart --- flutter/lib/models/chat_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/lib/models/chat_model.dart b/flutter/lib/models/chat_model.dart index 8666e13e4..9db5a1571 100644 --- a/flutter/lib/models/chat_model.dart +++ b/flutter/lib/models/chat_model.dart @@ -43,7 +43,7 @@ class ChatModel with ChangeNotifier { final ChatUser me = ChatUser( id: "", - firstName: "Me", + firstName: translate("Me"), ); late final Map _messages = {}..[clientModeID] = From 915ab0ec808f1444b3d72d2f6501dedef375989f Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Mon, 13 Mar 2023 20:44:04 +0100 Subject: [PATCH 376/382] Add files via upload --- src/lang/ca.rs | 1 + src/lang/cn.rs | 1 + src/lang/cs.rs | 1 + src/lang/da.rs | 1 + src/lang/de.rs | 7 ++++--- src/lang/el.rs | 1 + src/lang/eo.rs | 1 + src/lang/es.rs | 1 + src/lang/fa.rs | 1 + src/lang/fr.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/nl.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 + 33 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 46499535e..93d9c76fe 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index e3488043c..bdc2257b3 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 905ef62b6..651043850 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 71952584b..0235df8fe 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 5b2be99f0..09fad80eb 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -210,7 +210,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Settings", "Einstellungen"), ("Username", "Benutzername"), ("Invalid port", "Ungültiger Port"), - ("Closed manually by the peer", "Von der Gegenstelle manuell geschlossen"), + ("Closed manually by the peer", "Von der Gegenstelle manuell geschlossen."), ("Enable remote configuration modification", "Änderung der Konfiguration aus der Ferne zulassen"), ("Run without install", "Ohne Installation ausführen"), ("Connect via relay", "Über Relay-Server verbinden"), @@ -289,7 +289,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "Durch das Deaktivieren des Dienstes werden automatisch alle hergestellten Verbindungen getrennt."), ("android_version_audio_tip", "Ihre Android-Version unterstützt keine Audioaufnahme, bitte aktualisieren Sie auf Android 10 oder höher, falls möglich."), ("android_start_service_tip", "Tippen Sie auf \"Vermittlungsdienst starten\" oder aktivieren Sie die Berechtigung \"Bildschirmaufnahme\", um den Bildschirmfreigabedienst zu starten."), - ("android_permission_may_not_change_tip", ""), + ("android_permission_may_not_change_tip", "Die Berechtigungen für bestehende Verbindungen können nicht sofort geändert werden, bis die Verbindung wiederhergestellt ist."), ("Account", "Konto"), ("Overwrite", "Überschreiben"), ("This file exists, skip or overwrite this file?", "Diese Datei existiert; überspringen oder überschreiben?"), @@ -426,7 +426,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Wait", "Warten"), ("Elevation Error", "Berechtigungsfehler"), ("Ask the remote user for authentication", "Den entfernten Benutzer zur Authentifizierung auffordern"), - ("Choose this if the remote account is administrator", "Wählen Sie dies, wenn das entfernte Konto Administrator ist"), + ("Choose this if the remote account is administrator", "Wählen Sie dies, wenn das entfernte Konto Administrator ist."), ("Transmit the username and password of administrator", "Übermitteln Sie den Benutzernamen und das Passwort des Administrators"), ("still_click_uac_tip", "Der entfernte Benutzer muss immer noch im UAC-Fenster von RustDesk auf OK klicken."), ("Request Elevation", "Erhöhte Rechte anfordern"), @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", "z. B.: admin"), ("Empty Username", "Leerer Benutzername"), ("Empty Password", "Leeres Passwort"), + ("Me", "Ich"), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index d4336e041..923d4b64e 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", "π.χ. admin"), ("Empty Username", "Κενό όνομα χρήστη"), ("Empty Password", "Κενός κωδικός πρόσβασης"), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index a916569df..57a519338 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 82c10cb1a..3ee8fcb51 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index bd75f7405..be9821083 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 795ce62c3..5798253ad 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 9ae7284c1..672c65bbb 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 8e3a4c68a..a6272dbd3 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index a9efb7c39..207d075b1 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 10c69ac79..5b1bcec4c 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 2d979ff67..3b31b631b 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 8e0346bfe..ccce435fc 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 34ffff9a5..568d923ea 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", "bijv: admin"), ("Empty Username", "Gebruikersnaam Leeg"), ("Empty Password", "Wachtwoord Leeg"), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 050e210f4..5534bbe1b 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 6910c39e3..780bc46c6 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 5ebe185d8..5cfc2e5a3 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 723a58f15..c354c4685 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 63f49b833..3abea8029 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 7ddd1e87f..820b7a7db 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 63276fd7a..e81124d5c 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 77012249a..d237b8895 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index e82842c06..8e7ecf824 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 84cacd7c6..e0807d892 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 0f1ec6362..085ed025d 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 00f521e1d..6b3e34e48 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 54d4cd951..c92044e39 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 7737ad41d..a16bf26b8 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 23523a820..302dd9166 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 5e0ef3d03..e72be8ea5 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -476,5 +476,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("eg: admin", ""), ("Empty Username", ""), ("Empty Password", ""), + ("Me", ""), ].iter().cloned().collect(); } From 044bbee3d9b45f7298308ee6271a7612fa4f44ea Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 14 Mar 2023 13:02:30 +0800 Subject: [PATCH 377/382] fix linux window restore Signed-off-by: fufesou --- flutter/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index b2102997e..c9d876f09 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: d1da784d3e8d89f3134b026d00d19711de894e7d + ref: 980ae3b45837a4bc55d82231801ffcbb0806b0c1 freezed_annotation: ^2.0.3 flutter_custom_cursor: ^0.0.4 window_size: From b1a632bb08a98e146795105d320dbd821ec14244 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 14 Mar 2023 15:01:02 +0800 Subject: [PATCH 378/382] fix macos memory leak Signed-off-by: fufesou --- flutter/pubspec.lock | 14 +++++++------- flutter/pubspec.yaml | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index f3db95378..c2e1f58fc 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -325,8 +325,8 @@ packages: dependency: "direct main" description: path: "." - ref: "3e2655677c54f421f9e378680d8171b95a211e0f" - resolved-ref: "3e2655677c54f421f9e378680d8171b95a211e0f" + ref: "980ae3b45837a4bc55d82231801ffcbb0806b0c1" + resolved-ref: "980ae3b45837a4bc55d82231801ffcbb0806b0c1" url: "https://github.com/Kingtous/rustdesk_desktop_multi_window" source: git version: "0.1.0" @@ -1236,10 +1236,10 @@ packages: dependency: "direct main" description: name: texture_rgba_renderer - sha256: ec8d124e4c1d7dfff854ae34e95d7d9d877b8f9d291c383c67686e4b15cf538e + sha256: "52bc9f217b7b07a760ee837d5a17329ad1f78ae8ed1e3fa612c6f1bed3c77f79" url: "https://pub.dev" source: hosted - version: "0.0.12" + version: "0.0.13" timing: dependency: transitive description: @@ -1516,11 +1516,11 @@ packages: dependency: "direct main" description: path: "." - ref: "32b24c66151b72bba033ef8b954486aa9351d97b" - resolved-ref: "32b24c66151b72bba033ef8b954486aa9351d97b" + ref: c140f9685bead805c433c9f5a4618a5115f01fa8 + resolved-ref: c140f9685bead805c433c9f5a4618a5115f01fa8 url: "https://github.com/Kingtous/rustdesk_window_manager" source: git - version: "0.2.7" + version: "0.3.1" window_size: dependency: "direct main" description: diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index c9d876f09..3e301e107 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -92,7 +92,7 @@ dependencies: password_strength: ^0.2.0 flutter_launcher_icons: ^0.11.0 flutter_keyboard_visibility: ^5.4.0 - texture_rgba_renderer: ^0.0.12 + texture_rgba_renderer: ^0.0.13 percent_indicator: ^4.2.2 dropdown_button2: ^2.0.0 From 0d5e1b76985f81dc6174206f65672cb6b313e99b Mon Sep 17 00:00:00 2001 From: ilGigioVr88 Date: Tue, 14 Mar 2023 09:52:57 +0100 Subject: [PATCH 379/382] 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 207d075b1..2333e23dd 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -473,9 +473,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("empty_favorite_tip", "Ancora nessun peer?\nTrova qualcuno con cui connetterti e aggiungilo ai tuoi preferiti!"), ("empty_lan_tip", "Oh no, sembra proprio che non abbiamo ancora rilevato nessun peer."), ("empty_address_book_tip", "Oh diamine, sembra che per ora non ci siano peer nella tua rubrica."), - ("eg: admin", ""), - ("Empty Username", ""), - ("Empty Password", ""), - ("Me", ""), + ("eg: admin", "es: admin"), + ("Empty Username", "Nome Utente Vuoto"), + ("Empty Password", "Password Vuota"), + ("Me", "Io"), ].iter().cloned().collect(); } From 7c3ad4fd21f32c25c7a9daa01c66e506562a4d68 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Tue, 14 Mar 2023 17:14:07 +0800 Subject: [PATCH 380/382] turn on cargo sparse protocol --- .cargo/config.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.cargo/config.toml b/.cargo/config.toml index 0e9fd44a9..b4c5e7d2b 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -6,3 +6,5 @@ rustflags = ["-Ctarget-feature=+crt-static"] rustflags = [ "-C", "link-args=-sectcreate __CGPreLoginApp __cgpreloginapp /dev/null", ] +[registries.crates-io] +protocol = "sparse" From f6b7e2e314244bf68523921534277a25e5cc2318 Mon Sep 17 00:00:00 2001 From: FastAct <93490087+FastAct@users.noreply.github.com> Date: Tue, 14 Mar 2023 11:27:47 +0100 Subject: [PATCH 381/382] Update nl.rs --- src/lang/nl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 568d923ea..9574581e5 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -44,7 +44,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("id_change_tip", "Alleen de letters a-z, A-Z, 0-9, _ (underscore) kunnen worden gebruikt. De eerste letter moet a-z, A-Z zijn. De lengte moet tussen 6 en 16 liggen."), ("Website", "Website"), ("About", "Over"), - ("Slogan_tip", "Gedaan met het hart in deze chaotische wereld!"), + ("Slogan_tip", "Ontwikkeld met het hart voor deze chaotische wereld!"), ("Privacy Statement", "Privacyverklaring"), ("Mute", "Geluid uit"), ("Build Date", "Versie datum"), From e5706da30ddbf56554540669d5c75263ef74e623 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Tue, 14 Mar 2023 19:47:43 +0800 Subject: [PATCH 382/382] revert sparse protocol which cause trouble --- .cargo/config.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index b4c5e7d2b..0e9fd44a9 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -6,5 +6,3 @@ rustflags = ["-Ctarget-feature=+crt-static"] rustflags = [ "-C", "link-args=-sectcreate __CGPreLoginApp __cgpreloginapp /dev/null", ] -[registries.crates-io] -protocol = "sparse"