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 d0ce9e0d..bf6ef7aa 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 4b6cf2a6..67eb0234 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 00000000..da23ae42 --- /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 2d7d3fb8..bee585d9 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 91480ba3..2764a440 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 9ce53c96..17d4e376 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 ec2e0a74..20228ea0 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 999b409e..2d0d4d2c 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 dc0e365a..a0c4f06b 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 da23ae42..00000000 --- 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 67eb0234..4b6cf2a6 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 6bb49000..7db7d43a 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 1e4d80c9..8b08e1e2 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 020bea1f..fb255176 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 bee585d9..2d7d3fb8 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 18314dbc..00a2edd7 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 17d4e376..9ce53c96 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 009995f4..414edab5 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 20228ea0..ec2e0a74 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 2d0d4d2c..999b409e 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 f20d1470..96cd9836 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 00a2edd7..56e11f32 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 b315024e..c171e84e 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 fb255176..b98f9fde 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 56e11f32..105b8440 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 96cd9836..d55073b9 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 b98f9fde..78feceb7 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 d55073b9..73f16478 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 08e343d4..47184e79 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 9a5b06b1..fca73eac 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 7256b13d..04b2488a 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 9b25f497..ede6353e 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 4f9a227b..329df4e1 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 01808a15..257ba417 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 37367c19..f764aa3e 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 818e6320..fd2e04c5 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 39d66f56..a709ccba 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 a709ccba..96ab4044 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 96ab4044..5df9c9a8 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 df2c48ab..17b160fe 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 00000000..85e6ff19 --- /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 00000000..f0204277 --- /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 00000000..02c6e589 --- /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 00000000..ea8c4bf7 --- /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 00000000..d4254717 --- /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 00000000..62c96412 --- /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 00000000..3b29a10e --- /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 00000000..f79c691f --- /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 44335146..8be0c6db 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 02527484..b663b0f4 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 a9a9fd9a..affb5eb1 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 a197cb25..e0449fd9 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 eae41679..e48d74da 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 37bbbd66..8500bec0 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 8500bec0..c27546d9 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 d7e43b6b..5ae36858 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 ca1193ea..e20c7f25 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 ff373cc9..e8967171 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 4aad66ee..edbd5b7c 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 0866ff73..e49ba65f 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 e0449fd9..22c44ec5 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 ec2e0a74..0e224707 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 c6e0229b..ed16f1e0 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 3b2ba089..62eba25c 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 eea46acc..fe6454fa 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 00000000..24149bf5 --- /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 5df9c9a8..c3322fef 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 45c55284..4a6536af 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 4824ac5e..593e023d 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 e2761e45..d09bba09 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 2020a2b6..428150ef 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 7cf563fc..8bfa973c 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 4bfa8634..3e87cd66 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 c2253244..1ea05d5a 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 3ce2860f..494dd4cb 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 70051f3e..72dd93a1 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 1f6e9f55..a600c92e 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 b7ebf457..26e5a649 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 21ab2821..125d982d 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 f48de17f..17a9589a 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 4c63106d..0749603b 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 b291a6e7..7c810cba 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 d63e8318..87425b40 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 b8b9eb1d..49017f4f 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 1a806c80..615c3601 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 2b29c7cb..ae1743ee 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 e91cd390..4e619a6e 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 b0fe9175..8f4b2b13 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 d0232ba3..ebefd1a8 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 fe5d708a..d652904c 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 458002f4..47843fd5 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 2abd1870..95d65a45 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 6b739e8a..3ec67d77 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 90a435fd..31f40874 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 a98ea634..3afcf1a9 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 61c2b5d2..53df7b4f 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 236ee5e8..a5db9708 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 f2a34e21..96e35e2b 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 84e74716..f49e81a7 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 0c4caf4d..1729d42a 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 19e1184d..5521022b 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 5269c4ee..13027a68 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 f93f776a..b53615c4 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 02c6e589..f0016b5b 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 d4254717..7b7cf26b 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 62c96412..6a67813a 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 e8967171..53a40123 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 fca73eac..37c4a39d 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 e48d74da..74cc7f14 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 37c4a39d..b9145313 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 ee28fe0e..3d95832e 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 8ee4a51f..dd2aa860 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 00000000..6258a9a7 --- /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 00000000..2a0d73f1 --- /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 8be0c6db..ac9a69d0 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 b663b0f4..5c4c68e2 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 62eba25c..471150f6 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 ac9a69d0..3c90981c 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 53778491..789517bf 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 f2d75d00..394d89e3 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 0deb646c..e7aed035 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 bb6bc431..64af4140 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 ee3aaaf2..958c4c03 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 761c95de..7de258a3 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 572b3e20..b10dd1ec 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 74cc7f14..21949705 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 53a40123..a73ab8bd 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 badb68a8..31f9e154 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 789517bf..b43f3e7d 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 053a2d8a..4a1a4024 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 148d928d..39958e88 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 394d89e3..32f02c9b 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 e7aed035..d810650f 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 7de258a3..aa4fab86 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 b10dd1ec..8d390d37 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 b43f3e7d..3c414cd8 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 eb7c214a..f38c1479 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 e7bb2881..d7202e30 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 c61287d4..baf7193b 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 727b53fe..b30f76f9 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 16951542..3759f605 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 6b3f8013..0bba649f 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 7514ead3..c49f974a 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 07b8af99..3bfb5357 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 ede6353e..6f646b91 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 32870156..a49dcc32 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 fd340f7e..73dbd2da 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 cf8e12e9..e2831196 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 00000000..3beb7ec6 --- /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 4bf244a0..a812686e 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 d74aa35c..146267c9 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 b0819397..ffcadd18 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 21949705..fd97b1e5 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 73dbd2da..7050e7a4 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 a812686e..0bc6c1c2 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 53a40123..41ac595f 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 3c414cd8..a0766a87 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 abccdf68..648448f4 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 c5f3b693..6bdb7e81 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 b2043f3c..433990a2 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 74e4efa9..cae5b82c 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 a73ab8bd..3680b0a1 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 31f9e154..f276961b 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 5817e54f..7e702f6f 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 af0da047..a95d3977 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 6f646b91..b3c65591 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 0bc6c1c2..2d53ea01 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 a0766a87..1dc1c0b5 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 6bdb7e81..0e160396 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 3e87cd66..25053001 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 fd97b1e5..cea6785f 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 d768005f..f93f776a 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 c27546d9..4b021570 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 b9145313..8c6a8937 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 cea6785f..6def5746 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 e041b591..52f64c0e 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 a2cdf91a..8f8895bd 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 32ed149e..c5bc3394 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 53a40123..023fe751 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 0c31e153..f76567ee 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 41ac595f..89b2c1b2 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 1dc1c0b5..3edafbf6 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 0e160396..397c117f 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 433990a2..7ee23ec4 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 b30f76f9..8d64553c 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 126e169d..e4b42cf0 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 2d53ea01..0c34c222 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 89b2c1b2..155fcc74 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 3edafbf6..b075ee76 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 397c117f..d4887bb5 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 8d64553c..45fe1b13 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 e4b42cf0..be8c857c 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 0c34c222..6970fd13 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 3680b0a1..29d4a195 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 f276961b..9210a30c 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 a69fc3bb..1d3a18c7 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 a49dcc32..8f6767e5 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 be8c857c..79fb6079 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 e2831196..e323d295 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 6970fd13..bd91d582 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 d4887bb5..e54f66ff 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 e323d295..6b6169c6 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 8c6a8937..df9ad258 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 6def5746..802a18a5 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 1d3a18c7..13321db5 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 13321db5..cc5568bc 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 93199938..fde9ac4a 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 0019335e..c73e666c 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 8f6767e5..71bbba75 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 79fb6079..52a5ff75 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 6b6169c6..fa7440c8 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 bd91d582..f8ef07fd 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 b075ee76..95e4d17e 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 baf7193b..6d3f863e 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 13f5b458..28dc8085 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 e49ba65f..e5b24fa5 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 e54f66ff..e07f8f59 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 aa33ae6e..53ec69b5 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 f975e343..4c037234 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 cfe69924..25a494ee 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 19310357..8fd6f9be 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 3d95832e..754d7b9e 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 9b7912cf..dfee4fb8 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 af0da047..8477ba99 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 0c31e153..2cefaa98 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 0e45827f..28f1dd9d 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 fca98f22..55a3c9bb 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 437cf445..f47d522d 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 84892a7f..7d02e154 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 101685c4..8aedc04f 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 c19b607c..d097a8b6 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 97574e67..8ca881f1 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 54a51b43..a9acdce6 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 f38c1479..cf3eb430 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 13027a68..a0808f5b 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 923bbab0..b62bd5a3 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 aa491f95..546ef2a3 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 e992b19d..af9389a2 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 3bfb5357..b9af4ce9 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 6468b7ee..8a6b765b 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 d128e732..5721d01f 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 29c5cbbf..1c488d47 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 63173dc1..249c0b59 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 1a00ece4..90ec8c1c 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 2c83f947..6563d605 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 6fcf02ed..31662239 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 d35d288d..7359bf06 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 20a2998e..70533c48 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 4c4b5d4b..6b54c83c 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 32cd084c..a379b318 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 c27546d9..90b48160 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 fde9ac4a..6b87d62b 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 481d6555..aa5f99f8 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 648448f4..bab2911f 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 f236a782..47d58ce5 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 0bba649f..561bb457 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 00000000..95169df8 --- /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 7bc82ed9..6fb2c895 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 6fb2c895..ed7270a8 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 cf3eb430..c0e627c6 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 c0e627c6..d1c15454 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 a0808f5b..49471552 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 d7202e30..00ca2bb2 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 958c4c03..edc779fb 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 6d3f863e..bb1b4f55 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 e0306a3a..e049c0fe 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 52f64c0e..7d907d72 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 5ffe805b..76fe929e 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 8d390d37..71a840c9 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 e049c0fe..c438a3c7 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 7d907d72..0aafd48b 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 29d4a195..47850fdb 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 cc5568bc..5a7f2bfa 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 9210a30c..9c72caa5 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 6b87d62b..3832ca7b 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 7e702f6f..a899f410 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 47850fdb..eeae0972 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 90b48160..49c56466 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 abccdf68..1a77b898 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 a899f410..56c9339f 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 74e4efa9..cae5b82c 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 b0819397..ffcadd18 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 a2cdf91a..8f8895bd 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 f93f776a..b53615c4 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 727b53fe..45fe1b13 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 00000000..6258a9a7 --- /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 00000000..2a0d73f1 --- /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 8ee4a51f..dd2aa860 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 ede6353e..b3c65591 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 32870156..71bbba75 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 fd340f7e..52a5ff75 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 cf8e12e9..fa7440c8 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 00000000..3beb7ec6 --- /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 4bf244a0..f8ef07fd 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 d74aa35c..146267c9 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 eeae0972..ceff7480 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 53778491..95e4d17e 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 e041b591..0aafd48b 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 053a2d8a..4a1a4024 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 148d928d..39958e88 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 e7bb2881..00ca2bb2 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 f2d75d00..32f02c9b 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 0deb646c..d810650f 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 bb6bc431..64af4140 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 49c56466..081cd164 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 32ed149e..c5bc3394 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 ee3aaaf2..edc779fb 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 c61287d4..bb1b4f55 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 1a77b898..218559a6 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 c5f3b693..e07f8f59 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 fca73eac..df9ad258 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 e48d74da..802a18a5 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 13f5b458..28dc8085 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 b2043f3c..7ee23ec4 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 761c95de..aa4fab86 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 0019335e..c73e666c 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 5ffe805b..2202b2cc 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 572b3e20..71a840c9 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 00000000..95169df8 --- /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 3bfc885c..ed7270a8 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 481d6555..aa5f99f8 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 ebfda728..40a9f05b 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 e49ba65f..e5b24fa5 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 aa33ae6e..53ec69b5 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 f975e343..4c037234 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 cfe69924..25a494ee 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 19310357..8fd6f9be 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 ee28fe0e..754d7b9e 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 3e87cd66..25053001 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 9b7912cf..dfee4fb8 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 af0da047..dc28cdae 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 0c31e153..824bd039 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 0e45827f..28f1dd9d 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 fca98f22..55a3c9bb 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 437cf445..f47d522d 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 84892a7f..7d02e154 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 101685c4..8aedc04f 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 c19b607c..d097a8b6 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 97574e67..8ca881f1 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 54a51b43..a9acdce6 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 eb7c214a..d1c15454 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 13027a68..49471552 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 923bbab0..b62bd5a3 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 aa491f95..546ef2a3 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 e992b19d..af9389a2 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 07b8af99..b9af4ce9 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 6468b7ee..8a6b765b 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 d128e732..5721d01f 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 29c5cbbf..1c488d47 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 63173dc1..249c0b59 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 1a00ece4..90ec8c1c 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 2c83f947..6563d605 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 6fcf02ed..31662239 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 d35d288d..7359bf06 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 20a2998e..70533c48 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 4c4b5d4b..6b54c83c 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 32cd084c..a379b318 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 16951542..3759f605 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 8be0c6db..3c90981c 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 b663b0f4..5c4c68e2 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 6b3f8013..561bb457 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 7514ead3..c49f974a 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 e25c0d54..257ba417 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 62eba25c..471150f6 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 f726ed52..11bcff92 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 02c6e589..f0016b5b 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 d4254717..7b7cf26b 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 62c96412..6a67813a 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 6c7055b4..77c28a94 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 73bb993a..6124cbb7 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 cd0e5871..01855536 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 ad058d4c..f2b609d3 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 617ec2c9..38ed9b0c 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 22c44ec5..f7419cd3 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 824bd039..158e16f7 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 2202b2cc..76fe929e 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 754d7b9e..d6ebe7f1 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 8aedc04f..05fffedb 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 2619a1c0..8db8b646 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 561bb457..3d8b415b 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 1b9d18aa..4c21f1bd 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 3adc24a1..868a93f5 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 40a9f05b..a2e893c4 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 5f24fd5c..a6ef0142 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 2f660775..6d4f143f 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 868a93f5..1aada72e 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 d2b9f414..82f8b728 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 7bda0b69..694a5e3e 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 7a65b193..a94db61b 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 a6ef0142..181f283e 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 6d4f143f..4984dbdb 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 a2e893c4..66eccfe2 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 4984dbdb..76583eb3 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 76fe929e..63f6c804 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 71a840c9..ccb53cc9 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 66eccfe2..2249c98e 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 181f283e..c781d3ea 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 76583eb3..03949f89 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 5df97838..13ebc5f7 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 1aada72e..1f02f86d 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 f3ad51a2..1c19ac0c 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 82f8b728..0047672a 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 694a5e3e..306b511f 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 c7da5773..bc193d22 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 a94db61b..3ee3e391 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 2249c98e..14cba6c8 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 c781d3ea..28d8dddc 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 03949f89..1fbf92c1 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 dbf59908..f3f4c1cc 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 471150f6..03d6787f 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 f3f4c1cc..23ffa08d 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 03d6787f..1d4bd5cf 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 ebac18da..bc1a562b 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 63f6c804..76fe929e 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 ccb53cc9..71a840c9 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 13ebc5f7..5df97838 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 1f02f86d..3adc24a1 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 1c19ac0c..f3ad51a2 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 0047672a..d2b9f414 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 306b511f..7bda0b69 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 bc193d22..c7da5773 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 3ee3e391..7a65b193 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 14cba6c8..40a9f05b 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 28d8dddc..5f24fd5c 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 1fbf92c1..2f660775 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 76fe929e..63f6c804 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 71a840c9..ccb53cc9 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 3adc24a1..9e4b6fce 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 d2b9f414..4425c412 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 7bda0b69..a0272d86 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 40a9f05b..ab27c018 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 5f24fd5c..28d8dddc 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 2f660775..c69c2f80 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 b9af4ce9..d524b8f4 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 4425c412..3c86af94 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 7a65b193..b91871c8 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 c69c2f80..9ea4dc84 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 9ea4dc84..a39b992b 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 dfa5762b..8f16e365 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 f1066306..78fd1e80 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 0de86055..b2bea1dd 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 00000000..ccd47b24 --- /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 f3ad51a2..65e3a16a 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 c7da5773..9e15cf08 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 e07f8f59..c1960195 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 53ec69b5..89cc4692 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 4c037234..3f4f6d25 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 25a494ee..a2813815 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 8fd6f9be..2760f94f 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 d6ebe7f1..dd8d2e8f 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 dfee4fb8..7a191f05 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 dc28cdae..b290c769 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 158e16f7..22ecf035 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 28f1dd9d..dd436831 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 55a3c9bb..cbd4f89e 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 f47d522d..8727c53c 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 7d02e154..b363a2ae 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 05fffedb..340794ce 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 d097a8b6..260c2760 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 8ca881f1..f101ae20 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 a9acdce6..fe0937a6 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 d1c15454..63d3cee7 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 49471552..162dec05 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 b62bd5a3..8eb4df2a 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 546ef2a3..973048f3 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 af9389a2..9e252aa8 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 d524b8f4..4c1f9ae3 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 8a6b765b..d6038428 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 5721d01f..bd07b1ac 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 1c488d47..b8f9203c 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 249c0b59..4a9b7337 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 90ec8c1c..f73154e3 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 6563d605..e51a095c 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 31662239..3214c345 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 7359bf06..82f95ef8 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 70533c48..d0f12cdf 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 6b54c83c..793d1e14 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 a379b318..fc665834 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 9c72caa5..0afff263 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 9c72caa5..476e2e50 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 56c9339f..feaecd35 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 da7e37e6..d0ab5105 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 9c98f24b..88e05238 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 d6ebe7f1..3798ee19 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 22ecf035..7fe279a1 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 edbd5b7c..30fe07b9 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 ceff7480..dc91e941 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 8f16e365..541ec6aa 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 0aafd48b..f4d77c79 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 edc779fb..1e62fb33 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 8f8895bd..d0f22a0a 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 b53615c4..ba92733c 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 a125078d..c77f11eb 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 bfb77390..21566aa2 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 0eeb2c6f..60a7d9c9 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 23c091a5..36493f74 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 cdce6f12..71d281ea 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 cdce6f12..4e4b2451 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 cbd4f89e..f517f61a 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 f517f61a..8629879c 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 d7f6e316..3ded34b2 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 00000000..8b137891 --- /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 8b137891..8af79915 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 8af79915..29860bc4 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 29860bc4..6a804730 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 6a804730..eee370dc 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 eee370dc..9821517f 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 9821517f..24bc139f 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 24bc139f..0c298122 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 0c298122..656c8aab 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 656c8aab..6605f905 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 8af79915..3e0fb463 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 6605f905..02c46cd4 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 02c46cd4..1534c426 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 1534c426..667e6a1d 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 667e6a1d..4cdcbaea 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 4cdcbaea..7f52f494 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 7f52f494..6e6f3cb0 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 ffcadd18..4ae28158 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 3ded34b2..3cfca4d3 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 6e6f3cb0..b30d5047 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 b30d5047..77a11f70 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 77a11f70..34627148 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 34627148..841c6ef4 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 841c6ef4..33328f7e 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 33328f7e..fec17f7a 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 fec17f7a..e8b18c22 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 e8b18c22..20a880ca 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 fea1a367..f83a72de 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 29b0d0e0..ae2d0aa4 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 20a880ca..b1ca7b71 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 b1ca7b71..ffa95dc9 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 ffa95dc9..62fae34f 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 62fae34f..0a63e5f8 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 0a63e5f8..e0d6c64e 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 e0d6c64e..a16a644a 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 a16a644a..284e1235 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 284e1235..92c2d04e 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 ad730380..10b5f0cf 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 d56464ef..592b28eb 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 10b5f0cf..4f576983 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 592b28eb..74c6fcb1 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 dde5c7a0..d7283d8a 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 dd2aa860..ff3ec1d7 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 7471636e..fdde88f1 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 16f65adc..b7b828f1 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 496e8184..177e3c12 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 f7a08708..d110e195 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 fdb253bd..c11edc21 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 6c22a3b7..62ba3348 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 9616cd31..2fdcd364 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 f074510c..0b628f90 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 36c74dfe..fafc5ef8 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 8cefbbce..6f9ba222 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 288a78db..5b4c3782 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 1aca2b89..42289082 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 85c5f4a6..05e6d8da 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 f9d5e0fc..491d5315 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 242341a6..b050d40a 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 3615b906..5d4a0a1a 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 295f54c6..2f66d011 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 7ec87ec5..27c35ff5 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 92c2d04e..3fc202d7 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 3fc202d7..30ec1703 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 30ec1703..2e73aacb 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 2e73aacb..ef1e2b51 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 ef1e2b51..9a4a904c 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 9a4a904c..09999818 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 09999818..eb7ba02d 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 e51a095c..638bb4d2 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 89cc4692..a8f5758e 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 3f4f6d25..03e253bf 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 a2813815..e85c9596 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 2760f94f..f933972d 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 36493f74..5ac7de62 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 7a191f05..667071e3 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 b290c769..a93d0ccd 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 7fe279a1..d20f321f 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 dd436831..bc6a23d7 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 f517f61a..336b1092 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 8727c53c..62ec3b01 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 b363a2ae..996fd3a3 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 340794ce..65e685f4 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 260c2760..00b71c57 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 f101ae20..f2cbc2ab 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 fe0937a6..d0b712ff 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 63d3cee7..fc4490aa 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 162dec05..b1cd7eb7 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 8eb4df2a..6f350421 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 973048f3..cbb0651a 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 9e252aa8..76a234af 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 4c1f9ae3..a8705d53 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 d6038428..55bf55af 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 bd07b1ac..39e54b66 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 b8f9203c..86f877aa 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 4a9b7337..24ddb85b 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 f73154e3..a565be50 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 3214c345..2f2c4fa3 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 82f95ef8..cf7e9997 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 d0f12cdf..fc1576db 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 793d1e14..1eb6eea7 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 fc665834..193408b0 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 eb7ba02d..65cf3fb1 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 65cf3fb1..b4a7d5c4 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 ccd47b24..003830f9 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 6e3fc94f..514608e4 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 dc91e941..50e6beac 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 3832ca7b..9a589133 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 da7e37e6..d0ab5105 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 9c98f24b..88e05238 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 5a7f2bfa..7d2d0cd2 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 e5b24fa5..2a3baad9 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 081cd164..f5e79155 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 b2bea1dd..62e90c08 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 f5e79155..173ed038 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 89cc4692..ac776032 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 3f4f6d25..3dfa63b8 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 a2813815..64874d2c 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 2760f94f..5970f893 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 36493f74..5907fb0c 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 7a191f05..d465b3de 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 b290c769..95f2f69e 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 7fe279a1..bd3e1b28 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 dd436831..0eeb71af 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 8629879c..ec961f2e 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 8727c53c..6ea7c561 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 b363a2ae..b617190f 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 340794ce..713c73fa 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 260c2760..c4d29ad7 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 f101ae20..3d1330a3 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 fe0937a6..c1480377 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 63d3cee7..377e40a1 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 162dec05..e4c4839f 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 8eb4df2a..54102319 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 973048f3..1a35421f 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 9e252aa8..ccfeb412 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 4c1f9ae3..8692d1d8 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 d6038428..be48c733 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 bd07b1ac..0706c38c 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 b8f9203c..fac32f1a 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 4a9b7337..85903f03 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 f73154e3..2987c9e5 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 e51a095c..94e0d8fa 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 3214c345..05d727e7 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 82f95ef8..280ed409 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 d0f12cdf..7ad3074f 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 793d1e14..9211bd28 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 fc665834..a26ae122 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 62e90c08..b2bea1dd 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 ac776032..57787dea 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 3dfa63b8..55e80584 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 64874d2c..3ee9e523 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 5970f893..e3e5a404 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 5907fb0c..c562472b 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 d465b3de..cbbeecc1 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 95f2f69e..bd4df8e0 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 bd3e1b28..66ec011c 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 0eeb71af..a343202e 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 ec961f2e..b38a9606 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 6ea7c561..2f6aafe9 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 b617190f..65f9f236 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 713c73fa..b8a4af50 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 c4d29ad7..275b520c 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 3d1330a3..2f303a2f 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 c1480377..9966bb3a 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 377e40a1..769bd24d 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 e4c4839f..16e14ad3 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 54102319..90d83241 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 1a35421f..4dcf298a 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 ccfeb412..69de05fd 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 8692d1d8..8d3ea0e3 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 be48c733..24937438 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 0706c38c..56dc7537 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 fac32f1a..389f01df 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 85903f03..15deabb3 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 2987c9e5..2ba640b2 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 94e0d8fa..4e4b20e4 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 05d727e7..8fb653fd 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 280ed409..424c18f1 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 7ad3074f..3ec44813 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 9211bd28..19b3aa35 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 a26ae122..f2a2bb74 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 9944bf26..ad66c463 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 b2bea1dd..62e90c08 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 ad66c463..9944bf26 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 66ec011c..99099bfd 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 57787dea..89cc4692 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 55e80584..3f4f6d25 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 3ee9e523..a2813815 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 e3e5a404..2760f94f 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 c562472b..36493f74 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 cbbeecc1..7a191f05 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 bd4df8e0..b290c769 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 99099bfd..7fe279a1 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 a343202e..dd436831 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 b38a9606..8629879c 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 2f6aafe9..8727c53c 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 65f9f236..b363a2ae 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 b8a4af50..340794ce 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 275b520c..260c2760 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 2f303a2f..f101ae20 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 9966bb3a..fe0937a6 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 769bd24d..63d3cee7 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 16e14ad3..0c5f1365 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 90d83241..8eb4df2a 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 4dcf298a..973048f3 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 69de05fd..9e252aa8 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 8d3ea0e3..4c1f9ae3 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 24937438..d6038428 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 56dc7537..bd07b1ac 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 389f01df..b8f9203c 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 15deabb3..4a9b7337 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 2ba640b2..f73154e3 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 4e4b20e4..e51a095c 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 8fb653fd..3214c345 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 424c18f1..82f95ef8 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 3ec44813..d0f12cdf 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 19b3aa35..793d1e14 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 f2a2bb74..fc665834 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 a8f5758e..c4bc10bb 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 03e253bf..163c50e1 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 e85c9596..e3ddc5db 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 f933972d..f37f30a6 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 5ac7de62..0829bc2b 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 667071e3..ed64addf 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 a93d0ccd..1c780f84 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 d20f321f..a04103d0 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 bc6a23d7..c0d739f9 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 9158c37e..819c257c 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 62ec3b01..46750eb1 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 996fd3a3..4133f136 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 65e685f4..17f066ee 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 00b71c57..b8031573 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 f2cbc2ab..fe6a0bfe 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 d0b712ff..4b1e92ca 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 fc4490aa..7888eed8 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 b1cd7eb7..b997267f 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 6f350421..98b8035a 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 cbb0651a..18c9168c 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 76a234af..225fa727 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 a8705d53..8a8b7f9c 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 55bf55af..cec9e5b3 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 39e54b66..295cd28a 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 86f877aa..ebbdf4a2 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 24ddb85b..67fb4979 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 a565be50..9da1f107 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 638bb4d2..cbbd65b4 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 2f2c4fa3..97a8725e 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 cf7e9997..3b1137cb 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 fc1576db..72a38afc 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 1eb6eea7..4665d7c3 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 193408b0..0130b11c 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 dc91e941..3d6f62ef 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 3f4f6d25..b5f71e58 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 d0f12cdf..3fb2297e 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 3e0fb463..45311c4b 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 45311c4b..4e3b309c 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 42289082..4a5372e6 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 5d4a0a1a..6e933cea 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 62ba3348..9582cf1c 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 b7b828f1..66fc609f 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 05e6d8da..df8254f3 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 2fdcd364..70296656 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 d110e195..8674bc1b 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 0b628f90..2dec27e4 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 fdde88f1..4bca4a79 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 a7722312..55f13629 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 1c780f84..3270ae26 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 95e4d17e..e2a3c6f0 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 a39b992b..354e418e 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 7ee23ec4..40aa68d2 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 a04103d0..e2a7e951 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 8a8b7f9c..59957a2c 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 7ee23ec4..90059e47 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 0829bc2b..7a935d29 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 c1991633..9460f4f4 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 ff3ec1d7..2c159bd0 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 8bb57145..8d9cd0a5 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 feaecd35..e8f7cf15 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 819c257c..40cf36b9 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 23ffa08d..97251032 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 d0ab5105..b0ad4138 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 7d2d0cd2..536d5e0c 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 b0ad4138..cbc3b137 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 88e05238..2bc0f6fb 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 fa7440c8..1c3fbce6 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 191ea2e6..f6133415 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 c4bc10bb..1e3b4930 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 9a8f176a..94f0cd2d 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 e3ddc5db..e7fb7684 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 f37f30a6..08758d7d 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 7a935d29..78d6d6c1 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 40cf36b9..89458bec 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 ed64addf..63995a91 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 3270ae26..fb45ddcd 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 e2a7e951..9c24ca6c 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 c0d739f9..7cb6d123 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 46750eb1..f9ff3bd0 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 4133f136..e210432c 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 17f066ee..7dfc67f2 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 b8031573..48391d8f 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 fe6a0bfe..91b73fc4 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 4b1e92ca..9d7cf397 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 7888eed8..5b959a35 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 b997267f..4d99f3be 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 98b8035a..e568daeb 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 18c9168c..54389652 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 225fa727..14675762 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 59957a2c..adc5872a 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 cec9e5b3..1031fb9d 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 295cd28a..b1b5dbeb 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 ebbdf4a2..a73a5f10 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 67fb4979..c4e70bd8 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 9da1f107..88db1e93 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 cbbd65b4..2255d8aa 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 97a8725e..e0bfe884 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 3b1137cb..e0d1d577 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 3cf05689..6bf0b0fa 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 4665d7c3..d5142452 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 0130b11c..c71d12d1 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 1d4bd5cf..ec570b42 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 d0f22a0a..1029bfed 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 ba92733c..47c2bb0e 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 00ca2bb2..856430dc 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 3d8b415b..fe91b618 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 856430dc..5dbba39d 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 1e3b4930..8ce7c59e 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 94f0cd2d..4ae8cbd7 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 e7fb7684..a835825d 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 08758d7d..afa86e2d 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 63995a91..c07f34be 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 fb45ddcd..ca486a75 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 7cb6d123..4f39d295 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 f9ff3bd0..32cf282e 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 e210432c..1da76479 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 7dfc67f2..41d3000d 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 48391d8f..24dc25b0 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 91b73fc4..fc92d964 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 9d7cf397..cb74d04b 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 5b959a35..900a1c4b 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 4d99f3be..3665b00c 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 e568daeb..4f9074f0 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 54389652..a7e831fb 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 14675762..0b2b1407 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 1031fb9d..086ef00e 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 b1b5dbeb..7db2a9d2 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 a73a5f10..c18080d9 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 c4e70bd8..30e2e7a0 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 88db1e93..6284a346 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 2255d8aa..19474fc1 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 e0bfe884..06b6731a 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 e0d1d577..80938a70 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 6bf0b0fa..882a779a 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 d5142452..70512a71 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 c71d12d1..c7e6e8f4 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 fe91b618..11a8ee53 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 4ae28158..c9aa01a8 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 45fe1b13..d7e6e0ed 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 c9aa01a8..2a1254e2 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 d7e6e0ed..45fe1b13 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 11a8ee53..22896e65 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 45fe1b13..0f511fc5 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 0f511fc5..4a39f596 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 4ae8cbd7..7f579ecd 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 22896e65..dbf30311 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 60a7d9c9..76b630f8 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 78d6d6c1..26fb727c 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 9c24ca6c..a4576870 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 adc5872a..145700c0 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 dbf30311..696a18ab 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 fce2c852..666eab0b 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 5dbba39d..96a090b1 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 8ce7c59e..7f0d902d 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 7f579ecd..2dad9d63 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 a835825d..d6a27eed 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 afa86e2d..082e0ec0 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 26fb727c..56392539 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 c07f34be..631d66a2 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 ca486a75..bbfce42c 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 a4576870..f7b609bd 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 4f39d295..933944fa 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 32cf282e..557ce943 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 1da76479..40483bc6 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 41d3000d..afbf862c 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 24dc25b0..f64e95c6 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 fc92d964..e43df3cc 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 cb74d04b..636dcaf7 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 900a1c4b..912eaec3 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 3665b00c..b89f2fb2 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 4f9074f0..dad48c82 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 a7e831fb..c5d32b19 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 0b2b1407..1a9ecd78 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 145700c0..f8603a44 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 086ef00e..3a938349 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 7db2a9d2..8ae15250 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 c18080d9..77af8b5c 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 30e2e7a0..2fb24a22 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 6284a346..18259f32 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 19474fc1..f0bb91f3 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 06b6731a..b0b31829 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 80938a70..81ac5cbb 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 882a779a..3d394307 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 70512a71..c4045277 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 c7e6e8f4..6ecf025a 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 96a090b1..2334d633 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 7f0d902d..7c238c81 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 2dad9d63..d1207118 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 d6a27eed..622730d9 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 082e0ec0..ce84b480 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 56392539..37de302b 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 89458bec..162218ed 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 25053001..01a4c843 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 631d66a2..5c6c9278 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 bbfce42c..fefa8b74 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 f7b609bd..f6be0e01 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 933944fa..1e438bba 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 557ce943..1c243e2f 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 40483bc6..8edc78e1 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 afbf862c..400e0ad9 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 f64e95c6..e87a232f 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 e43df3cc..06d10d01 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 636dcaf7..ede87875 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 912eaec3..55ad9504 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 b89f2fb2..08106782 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 dad48c82..11583b26 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 c5d32b19..7aa01468 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 1a9ecd78..49b3b358 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 f8603a44..243ffda4 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 3a938349..1a5b9207 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 8ae15250..1efc4de4 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 77af8b5c..ffe3c9ed 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 2fb24a22..fe7e0bae 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 18259f32..98ceed9a 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 f0bb91f3..e0d7929a 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 b0b31829..615c1550 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 81ac5cbb..5bbddde5 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 3d394307..a056d6b8 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 c4045277..1bab4a55 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 6ecf025a..f5b8052e 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 2334d633..adc0df13 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 7c238c81..3cea5e60 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 d1207118..161fa035 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 622730d9..86e9c47c 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 ce84b480..d262c08c 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 37de302b..21e57701 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 162218ed..b0e629ba 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 01a4c843..100788f6 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 5c6c9278..f36afedc 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 fefa8b74..2b38ecd1 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 f6be0e01..0cc8188b 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 1e438bba..ef74b066 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 1c243e2f..f984afcd 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 8edc78e1..53f718e8 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 400e0ad9..c3b77ddf 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 e87a232f..4a0fc3ab 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 06d10d01..a3aef55c 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 ede87875..8b7582af 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 55ad9504..6fb53711 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 08106782..d60fe2d3 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 11583b26..2747a0ca 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 7aa01468..e8fca4b8 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 49b3b358..e4521305 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 243ffda4..473ec402 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 1a5b9207..aeed03fc 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 1efc4de4..eaa8b1b5 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 ffe3c9ed..46f14c73 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 fe7e0bae..ee48beb3 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 98ceed9a..b099acc9 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 e0d7929a..bfab1a33 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 615c1550..d77eb5fc 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 5bbddde5..d4d0b942 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 a056d6b8..e1119b12 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 1bab4a55..216f764c 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 f5b8052e..c7fbc5b9 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 7dfc67f2..00974b43 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 cd7e20a9..0cab5720 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 7d2d0cd2..51ab3066 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 3cea5e60..9507ffc2 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 161fa035..e5ba70aa 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 86e9c47c..5920e002 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 d262c08c..6e7394d7 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 21e57701..26925a9f 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 b0e629ba..4c369819 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 f36afedc..457fbea0 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 2b38ecd1..7443f864 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 0cc8188b..f1503a83 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 ef74b066..63d1ce31 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 f984afcd..4789ba55 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 53f718e8..e2a969a8 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 0cab5720..1c531c59 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 4a0fc3ab..a2d3446b 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 a3aef55c..9c2076d6 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 8b7582af..b8a415e4 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 6fb53711..595e0710 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 d60fe2d3..08f6ca90 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 2747a0ca..1eb5fc6e 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 e8fca4b8..df0f5a26 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 e4521305..7515ccbf 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 473ec402..afeb8d17 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 aeed03fc..1d8c6c62 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 eaa8b1b5..07bb2b54 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 46f14c73..a7cdfa8e 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 ee48beb3..bcdedef5 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 b099acc9..63167ed8 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 bfab1a33..3fb6d17a 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 d77eb5fc..808f69f8 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 d4d0b942..34949aa4 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 e1119b12..17ef4b7e 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 216f764c..cc44d86d 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 c7fbc5b9..b774e094 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 51ab3066..73660cc3 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 8d9cd0a5..0a8ebdd3 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 7aa9a000..26e024ca 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 e8f7cf15..621df4d6 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 802a18a5..0b2ae9dd 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 3f7ed677..bfff9ff8 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 26925a9f..f753265f 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 0a8ebdd3..99b873cd 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 621df4d6..aa4b6253 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 99b873cd..1010d56c 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 aa4b6253..2073991e 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 2073991e..6670677d 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 1010d56c..59dff551 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 6670677d..11720ad5 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 c4bc10bb..9cb09cef 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 163c50e1..408013ea 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 e3ddc5db..ddc29cbc 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 f37f30a6..be49f5c2 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 7a935d29..35c1b58d 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 ed64addf..02b65adc 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 3270ae26..a8b61699 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 e2a7e951..741149b9 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 c0d739f9..be39c42d 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 819c257c..13931509 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 46750eb1..19212689 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 4133f136..ed4167d9 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 17f066ee..c4d2236c 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 b8031573..6b98b4a1 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 fe6a0bfe..237b2738 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 4b1e92ca..c0adba50 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 7888eed8..f749d45f 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 b997267f..95f145a2 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 98b8035a..7fff174f 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 18c9168c..1efcaf6c 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 225fa727..6ad0c297 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 59957a2c..1bb44608 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 cec9e5b3..3c19b9cf 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 295cd28a..78e2e850 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 ebbdf4a2..9aa5a38c 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 67fb4979..fccb383a 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 9da1f107..ef93478c 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 cbbd65b4..005e1cf0 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 97a8725e..68dc955d 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 3b1137cb..717c79bd 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 72a38afc..3bfcfaf2 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 4665d7c3..fa8c40cb 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 0130b11c..33007597 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 cbc3b137..cdafbc4f 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 63f6c804..f3db9537 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 ccb53cc9..a212a509 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 cdafbc4f..e3bb3a5b 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 2bc0f6fb..640f7d08 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 e3bb3a5b..869bd5fd 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 2ada1e20..4d2da35f 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 666eab0b..d9c05272 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 59dff551..a1a686af 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 11720ad5..1b5afd95 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 9c98f24b..695266fb 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 695266fb..720e6727 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 afeb8d17..a1182843 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 a1a686af..da88405a 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 1b5afd95..30a897a5 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 1029bfed..c48a69e8 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 47c2bb0e..7ad979f8 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 d15f2742..bf141e53 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 c77f11eb..fd02639e 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 82cb88fa..99e15aee 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 a02d55eb..dc59edac 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 ab27c018..9202a34b 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 28d8dddc..0b475805 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 f8f5d27d..8875d2b6 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 38b514f8..53e675d9 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 3c90981c..a252a9a8 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 898939b6..3d419ef0 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 ec570b42..fd97f41b 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 da88405a..44def46c 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 30a897a5..4cfe1913 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 802a18a5..a8ed56bc 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 26e024ca..aa879422 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 aa879422..c6ba42d3 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 4cfe1913..4170a546 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 7443f864..3543c515 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 9202a34b..705b387a 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 aa4fab86..187b1ffc 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 ccb53cc9..087fba71 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 1c531c59..dc59ccea 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 4c369819..b0c8be87 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 b4a7d5c4..8ec98030 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 f83a72de..d8781bb0 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 f5c575d4..bd6eab3b 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 a8ed56bc..8f46fdca 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 ed7270a8..4ce2cf07 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 173ed038..e7ca23ea 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 e7ca23ea..3e37cef4 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 197e5537..71cd5d99 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 ad5183ae..1b71e382 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 cae5b82c..5eda9ad1 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 fd97f41b..1dcf93e9 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 6599e7a5..413f36cb 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 1dcf93e9..58d32153 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 1e62fb33..7700f197 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 a3c31c55..0d021912 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 a32f35a5..8fe82623 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 50ea4e61..5893b3e1 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 c0d72221..0c2a01d6 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 bdd82d47..b9fc7834 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 413f36cb..63811f20 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 7ccb8a8c..24df8827 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 85239cdd..585a10d6 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 a6459788..3331ab89 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 887965b9..98083383 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 e64d972b..ef97ce8c 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 ffba760e..a9a70d47 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 4d2da35f..136a5194 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 9b7741d4..b30d1942 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 ff6fdafb..8572fa0c 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 ca7c2d50..78cadf65 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 a617ba2e..413ad055 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 0e8bbd31..4bd7459d 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 96a84de3..da90d34a 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 f98e1116..b73b5c74 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 386f88c8..f668e2e8 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 dc714ec7..c075d644 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 38a3bd65..f5aaff84 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 41f4facb..7e6bf57e 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 7e559287..4e263670 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 b2f5b62f..1ce22c5c 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 7a35df41..58fe1c31 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 80e7f04e..8e1e85bd 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 f9bcf080..770ccef1 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 58a38e07..3fd1de33 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 ff05d564..b6abf906 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 04047ce9..d838265f 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 e38b06a5..27b24878 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 6e933cea..d7eaaa2a 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 d7eaaa2a..222da34d 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 218559a6..07a81f8d 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 07a81f8d..36cc43eb 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 dde45281..4fab2b24 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 36cc43eb..96b5eef0 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 96b5eef0..ace1b832 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 ace1b832..2fe8b9d4 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 2fe8b9d4..ee860073 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 ee860073..a83fec29 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 a83fec29..d584d3bb 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 d584d3bb..7ed2575e 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 7ed2575e..9e2bc3f0 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 9e2bc3f0..77517381 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 77517381..7079fc5e 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 7079fc5e..dcd1fae7 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 dcd1fae7..a92a1360 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 a92a1360..4a93bbec 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 0d021912..9e8770c2 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 8fe82623..c5cf4cd0 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 5893b3e1..620cc137 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 0c2a01d6..dbb9e306 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 b9fc7834..2127ecaa 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 63811f20..dae1dedf 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 100788f6..7107c186 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 24df8827..3ff7b608 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 585a10d6..ba9e8a3d 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 3331ab89..9194d2b2 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 98083383..2933fcd7 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 ef97ce8c..e05d5f92 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 a9a70d47..ca988aac 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 136a5194..c7654c48 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 b30d1942..26a47cd2 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 8572fa0c..f79154cd 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 78cadf65..11d673f0 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 413ad055..b245cbc5 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 4bd7459d..f4f934b9 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 da90d34a..77181a5d 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 b73b5c74..8006c070 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 f668e2e8..ccbb1c90 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 c075d644..a336f74e 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 f5aaff84..90ac16fd 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 7e6bf57e..b91f6e37 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 4e263670..b26ac909 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 1ce22c5c..7d6178c4 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 58fe1c31..2b926cfc 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 8e1e85bd..fb62a954 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 770ccef1..ba501da1 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 3fd1de33..641e9cd0 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 b6abf906..c7089620 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 d838265f..f085a0f2 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 27b24878..fe3aaa57 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 9e8770c2..297bfdc3 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 c5cf4cd0..b92a33ee 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 620cc137..49c286d9 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 dbb9e306..401601e2 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 2127ecaa..6c2c06e4 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 dae1dedf..c569c8a6 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 3ff7b608..fb9ab4dd 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 ba9e8a3d..c05f32ff 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 9194d2b2..63c40c85 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 2933fcd7..ddb8ebb5 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 e05d5f92..ba8e6e86 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 ca988aac..8accb751 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 c7654c48..71344f31 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 26a47cd2..214f354e 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 f79154cd..8641abe3 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 11d673f0..42340ba6 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 b245cbc5..a0d035be 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 f4f934b9..baf439a2 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 77181a5d..805f6948 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 8006c070..6ac25663 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 ccbb1c90..f1734f0e 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 a336f74e..d37bb367 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 90ac16fd..9328f79d 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 b91f6e37..73b3579c 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 b26ac909..da461da3 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 7d6178c4..b1aaafcf 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 2b926cfc..b49b73cb 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 fb62a954..b785b0d6 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 ba501da1..47eba46d 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 641e9cd0..027d5de0 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 c7089620..d342db85 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 f085a0f2..368d5d3d 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 fe3aaa57..e4df09d7 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 4a93bbec..ee47568a 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 ee47568a..a2eb9dec 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 a2eb9dec..e092bf1e 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 e092bf1e..ae61c91a 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 58d32153..1dcf93e9 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 d9c05272..c65993d9 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 f4d77c79..4609d4f4 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 1dcf93e9..58d32153 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 71344f31..fe265777 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 c48a69e8..7652f443 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 fd02639e..2ccaa92e 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 b1b13034..22cf388f 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 5c4c68e2..251211c2 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 58d32153..17b4fafc 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 2ccaa92e..ed9ec73b 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 22cf388f..5f415c6e 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 21566aa2..799093d2 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 869bd5fd..52bdc8cc 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 71cd5d99..43f65b4b 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 297bfdc3..68f46438 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 b92a33ee..a04bd7c0 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 49c286d9..6e7ae717 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 401601e2..a5aad792 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 6c2c06e4..13d17c83 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 c569c8a6..0e7a3e5a 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 7107c186..b5d4d8b2 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 fb9ab4dd..5f593401 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 c05f32ff..e161e228 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 63c40c85..c5d708b0 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 ddb8ebb5..3ddb5603 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 ba8e6e86..11c49bd4 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 8accb751..d256259e 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 fe265777..9d723935 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 214f354e..53c7cda3 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 8641abe3..d208f399 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 42340ba6..8505c733 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 a0d035be..2ae74ecb 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 baf439a2..3226157f 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 805f6948..7a6d0106 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 6ac25663..98fd2161 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 f1734f0e..3396dc50 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 d37bb367..4f263ded 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 9328f79d..ae47c809 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 73b3579c..fa4fc17f 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 da461da3..27297c65 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 b1aaafcf..1bf53571 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 b49b73cb..00abe840 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 b785b0d6..9b920e6f 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 47eba46d..7fee731b 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 027d5de0..5f706233 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 d342db85..84e8b822 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 368d5d3d..87e060eb 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 e4df09d7..f7563b28 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 5eda9ad1..74f23327 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 2a1254e2..da83637e 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 da83637e..6ec398c7 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 c5d708b0..83837eb1 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 3d419ef0..f63cd606 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 917a815b..1d6d9422 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 f63cd606..6bf60259 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 1d6d9422..f205e3f0 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 6bf60259..7127187d 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 3e37cef4..ac66c68a 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 ac66c68a..e38e5c99 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 7700f197..4211911f 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 c65993d9..8b0cb710 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 3e37cef4..0f63a281 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 8b0cb710..21dc427c 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 0f63a281..c444214c 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 9b920e6f..5e3a3202 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 68f46438..add867d8 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 a04bd7c0..dae7b732 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 6e7ae717..d55531dd 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 a5aad792..c2913ef1 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 13d17c83..9df1c709 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 0e7a3e5a..52399f72 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 5f593401..f4030c7f 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 e161e228..dc87bc75 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 83837eb1..3492e5bd 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 3ddb5603..6ee0b779 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 11c49bd4..76e6999e 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 d256259e..836c3e08 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 9d723935..5f25a1a5 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 53c7cda3..2b91ced0 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 d208f399..72ed4b37 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 8505c733..81298bc2 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 2ae74ecb..f3bb6e11 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 3226157f..48a7ea99 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 7a6d0106..f31aad61 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 98fd2161..8a06ce65 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 3396dc50..899b0698 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 4f263ded..bca2e431 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 ae47c809..7d7d3a15 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 fa4fc17f..8ee5c59c 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 27297c65..18f9606d 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 1bf53571..374ee96c 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 00abe840..5383c7fd 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 7fee731b..16c6b034 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 5f706233..d5992b5a 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 84e8b822..ddcd1498 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 87e060eb..bfe27b24 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 f7563b28..de063ed0 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 bca2e431..16996e1d 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 dc87bc75..c738f9ff 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 9a589133..b1440179 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 add867d8..f0922311 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 dae7b732..69a3bdac 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 d55531dd..bd0cc452 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 c2913ef1..6c486ffc 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 9df1c709..64721539 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 52399f72..91a62762 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 f4030c7f..ee47688e 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 c738f9ff..d19eae34 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 3492e5bd..b971de77 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 6ee0b779..08bf3a0c 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 76e6999e..95b1aa23 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 836c3e08..de56499f 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 5f25a1a5..23eaf6bb 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 2b91ced0..7a04a923 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 72ed4b37..8a1f6f18 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 81298bc2..95903ec2 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 f3bb6e11..885d6f0b 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 48a7ea99..0e990d7d 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 f31aad61..c87f2ede 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 8a06ce65..364bc21f 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 899b0698..188fc09e 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 16996e1d..3233ced2 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 7d7d3a15..81091a23 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 8ee5c59c..86c76e6b 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 18f9606d..e8c42360 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 374ee96c..7a8a4346 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 5383c7fd..28f16c54 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 5e3a3202..bed743e3 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 16c6b034..543b78cd 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 d5992b5a..4a50b0a8 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 ddcd1498..428de753 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 bfe27b24..ec8012ce 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 de063ed0..77fc3cfa 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 91a62762..93b921af 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 4fab2b24..846f20ed 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 f0922311..46499535 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 69a3bdac..e3488043 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 bd0cc452..905ef62b 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 6c486ffc..71952584 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 64721539..5b2be99f 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 91a62762..7e7806ae 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 b5d4d8b2..b44ff2e4 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 ee47688e..a916569d 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 d19eae34..82c10cb1 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 b971de77..bd75f740 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 08bf3a0c..795ce62c 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 95b1aa23..9ae7284c 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 de56499f..8e3a4c68 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 23eaf6bb..a9efb7c3 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 7a04a923..10c69ac7 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 8a1f6f18..2d979ff6 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 95903ec2..8e0346bf 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 885d6f0b..1e7b8fc9 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 0e990d7d..050e210f 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 c87f2ede..6910c39e 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 364bc21f..5ebe185d 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 188fc09e..723a58f1 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 3233ced2..63f49b83 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 81091a23..7ddd1e87 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 86c76e6b..63276fd7 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 e8c42360..77012249 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 7a8a4346..e82842c0 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 28f16c54..84cacd7c 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 bed743e3..0f1ec636 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 543b78cd..00f521e1 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 4a50b0a8..54d4cd95 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 428de753..7737ad41 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 ec8012ce..23523a82 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 77fc3cfa..5e0ef3d0 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 c444214c..fb443990 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 ba7b8a05..c67f0f7f 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 46278bf0..b2102997 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 bb1b4f55..f0a9a938 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 28dc8085..2b99e182 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 4fab2b24..031d52c7 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 7127187d..9941dcea 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 9941dcea..7899009c 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 1e7b8fc9..6abb1b87 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 52bdc8cc..2d36d915 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 6abb1b87..34ffff9a 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 ab0daece..03074efc 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 df9ad258..f09bc3d6 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 03074efc..2099f2e9 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 f09bc3d6..21bbb9a3 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 21bbb9a3..9366d5b4 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 8666e13e..9db5a157 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 46499535..93d9c76f 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 e3488043..bdc2257b 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 905ef62b..65104385 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 71952584..0235df8f 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 5b2be99f..09fad80e 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 d4336e04..923d4b64 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 a916569d..57a51933 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 82c10cb1..3ee8fcb5 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 bd75f740..be982108 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 795ce62c..5798253a 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 9ae7284c..672c65bb 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 8e3a4c68..a6272dbd 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 a9efb7c3..207d075b 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 10c69ac7..5b1bcec4 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 2d979ff6..3b31b631 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 8e0346bf..ccce435f 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 34ffff9a..568d923e 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 050e210f..5534bbe1 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 6910c39e..780bc46c 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 5ebe185d..5cfc2e5a 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 723a58f1..c354c468 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 63f49b83..3abea802 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 7ddd1e87..820b7a7d 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 63276fd7..e81124d5 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 77012249..d237b889 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 e82842c0..8e7ecf82 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 84cacd7c..e0807d89 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 0f1ec636..085ed025 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 00f521e1..6b3e34e4 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 54d4cd95..c92044e3 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 7737ad41..a16bf26b 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 23523a82..302dd916 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 5e0ef3d0..e72be8ea 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 b2102997..c9d876f0 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 f3db9537..c2e1f58f 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 c9d876f0..3e301e10 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 207d075b..2333e23d 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 0e9fd44a..b4c5e7d2 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 568d923e..9574581e 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 b4c5e7d2..0e9fd44a 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"