diff --git a/.github/workflows/flutter-nightly.yml b/.github/workflows/flutter-nightly.yml index f2391e77e..499a5f996 100644 --- a/.github/workflows/flutter-nightly.yml +++ b/.github/workflows/flutter-nightly.yml @@ -10,7 +10,9 @@ env: LLVM_VERSION: "10.0" FLUTTER_VERSION: "3.0.5" TAG_NAME: "nightly" - VCPKG_COMMIT_ID: '6ca56aeb457f033d344a7106cb3f9f1abf8f4e98' + # vcpkg version: 2022.05.10 + # for multiarch gcc compatibility + VCPKG_COMMIT_ID: "14e7bb4ae24616ec54ff6b2f6ef4e8659434ea44" VERSION: "1.2.0" jobs: @@ -23,7 +25,7 @@ jobs: job: # - { target: i686-pc-windows-msvc , os: windows-2019 } # - { target: x86_64-pc-windows-gnu , os: windows-2019 } - - { target: x86_64-pc-windows-msvc , os: windows-2019 } + - { target: x86_64-pc-windows-msvc, os: windows-2019 } steps: - name: Checkout source code uses: actions/checkout@v3 @@ -36,9 +38,9 @@ jobs: - name: Install flutter uses: subosito/flutter-action@v2 with: - channel: 'stable' + channel: "stable" flutter-version: ${{ env.FLUTTER_VERSION }} - + - name: Replace engine with rustdesk custom flutter engine run: | flutter doctor -v @@ -100,45 +102,30 @@ jobs: files: | rustdesk-*.exe - build-for-linux: - name: ${{ matrix.job.target }} (${{ matrix.job.os }},${{ matrix.job.extra-build-args }}) + build-for-macOS: + name: ${{ matrix.job.target }} (${{ matrix.job.os }}) [${{ matrix.job.extra-build-args }}] runs-on: ${{ matrix.job.os }} strategy: fail-fast: false matrix: job: - # - { target: aarch64-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true } - # - { target: arm-unknown-linux-gnueabihf , os: ubuntu-20.04, use-cross: true } - # - { target: arm-unknown-linux-musleabihf, os: ubuntu-20.04, use-cross: true } - # - { target: i686-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true } - # - { target: i686-unknown-linux-musl , os: ubuntu-20.04, use-cross: true } - # - { target: x86_64-apple-darwin , os: macos-10.15 } - - { target: x86_64-unknown-linux-gnu , os: ubuntu-18.04, extra-build-args: ""} - - { target: x86_64-unknown-linux-gnu , os: ubuntu-18.04, extra-build-args: "--flatpak"} - # - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true } + - { + target: x86_64-apple-darwin, + os: macos-10.15, + extra-build-args: "", + } steps: - name: Checkout source code uses: actions/checkout@v3 - - name: Get build target triple - uses: jungwinter/split@v2 - id: build-target-triple - with: - separator: '-' - msg: ${{ matrix.job.target }} - - - name: Install prerequisites + - name: Install build runtime run: | - case ${{ matrix.job.target }} in - x86_64-unknown-linux-gnu) sudo apt-get -y update ; 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 libclang-dev ninja-build libappindicator3-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libvdpau-dev libva-dev libclang-dev llvm-dev libclang-10-dev llvm-10-dev;; - # arm-unknown-linux-*) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;; - # aarch64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;; - esac + brew install llvm create-dmg nasm yasm cmake gcc wget ninja - name: Install flutter uses: subosito/flutter-action@v2 with: - channel: 'stable' + channel: "stable" flutter-version: ${{ env.FLUTTER_VERSION }} - name: Install Rust toolchain @@ -172,16 +159,15 @@ jobs: - name: Install vcpkg dependencies run: | $VCPKG_ROOT/vcpkg install libvpx libyuv opus - shell: bash - name: Install cargo bundle tools run: | cargo install cargo-bundle - - name: Show version information (Rust, cargo, GCC) + - name: Show version information (Rust, cargo, Clang) shell: bash run: | - gcc --version || true + clang --version || true rustup -V rustup toolchain list rustup default @@ -189,7 +175,318 @@ jobs: rustc -V - name: Build rustdesk - run: ./build.py --flutter --hwcodec ${{ matrix.job.extra-build-args }} + run: | + # --hwcodec not supported on macos yet + ./build.py --flutter ${{ matrix.job.extra-build-args }} + + - name: Rename rustdesk + run: | + for name in rustdesk*??.dmg; do + mv "$name" "${name%%.dmg}-untested-${{ matrix.job.target }}.dmg" + done + + - name: Publish DMG package + uses: softprops/action-gh-release@v1 + with: + prerelease: true + tag_name: ${{ env.TAG_NAME }} + files: | + rustdesk*-${{ matrix.job.target }}.dmg + + build-vcpkg-deps-linux: + runs-on: ${{ matrix.job.os }} + strategy: + fail-fast: false + matrix: + job: + # - { arch: armv7 , os: ubuntu-18.04} + - { arch: x86_64, os: ubuntu-18.04 } + # - { arch: aarch64 , os: ubuntu-18.04} + steps: + - name: Create vcpkg artifacts folder + run: mkdir -p /opt/artifacts + + - name: Cache Vcpkg + id: cache-vcpkg + uses: actions/cache@v3 + with: + path: /opt/artifacts + key: vcpkg-${{ matrix.job.arch }} + + - uses: Kingtous/run-on-arch-action@amd64-support + name: Run vcpkg install on ${{ matrix.job.arch }} + id: vcpkg + with: + arch: ${{ matrix.job.arch }} + distro: ubuntu18.04 + githubToken: ${{ github.token }} + setup: | + ls -l "/opt/artifacts" + dockerRunArgs: | + --volume "/opt/artifacts:/artifacts" + shell: /bin/bash + install: | + apt update -y + # CMake 3.15+ + apt install -y gpg wget ca-certificates + echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ bionic main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null + wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null + apt update -y + apt install -y curl zip unzip tar git cmake g++ gcc build-essential pkg-config wget nasm yasm ninja-build + cmake --version + gcc -v + run: | + export VCPKG_FORCE_SYSTEM_BINARIES=1 + pushd /artifacts + git clone https://github.com/microsoft/vcpkg.git || true + git config --global --add safe.directory /artifacts/vcpkg || true + pushd vcpkg + git reset --hard ${{ env.VCPKG_COMMIT_ID }} + ./bootstrap-vcpkg.sh + ./vcpkg install libvpx libyuv opus + + - name: Upload artifacts + uses: actions/upload-artifact@master + with: + name: vcpkg-artifact-${{ matrix.job.arch }} + path: | + /opt/artifacts/vcpkg/installed + + generate-bridge-linux: + name: generate bridge + runs-on: ${{ matrix.job.os }} + strategy: + fail-fast: false + matrix: + job: + - { + target: x86_64-unknown-linux-gnu, + os: ubuntu-18.04, + extra-build-args: "", + } + steps: + - name: Checkout source code + uses: actions/checkout@v3 + + - name: Install prerequisites + run: | + sudo apt update -y + 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 libclang-dev ninja-build libappindicator3-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libvdpau-dev libva-dev libclang-dev llvm-dev libclang-10-dev llvm-10-dev pkg-config + + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: ${{ matrix.job.target }} + override: true + profile: minimal # minimal component installation (ie, no documentation) + + - uses: Swatinem/rust-cache@v2 + with: + prefix-key: bridge-${{ matrix.job.os }} + + - name: Cache Bridge + id: cache-bridge + uses: actions/cache@v3 + with: + path: /tmp/flutter_rust_bridge + key: vcpkg-${{ matrix.job.arch }} + + - name: Install flutter + uses: subosito/flutter-action@v2 + with: + channel: "stable" + flutter-version: ${{ env.FLUTTER_VERSION }} + + - name: Install ffigen + run: | + dart pub global activate ffigen --version 5.0.1 + + - name: Install flutter rust bridge deps + shell: bash + run: | + pushd /tmp && git clone https://github.com/SoLongAndThanksForAllThePizza/flutter_rust_bridge --depth=1 || true && popd + pushd /tmp/flutter_rust_bridge/frb_codegen && cargo install --path . && popd + pushd flutter && flutter pub get && popd + + - name: Run flutter rust bridge + run: | + ~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart + + - name: Upload Artifcat + uses: actions/upload-artifact@master + with: + name: bridge-artifact + path: | + ./src/bridge_generated.rs + ./flutter/lib/generated_bridge.dart + ./flutter/lib/generated_bridge.freezed.dart + + build-rustdesk-lib-linux: + needs: [generate-bridge-linux, build-vcpkg-deps-linux] + name: build-rust-lib ${{ matrix.job.target }} (${{ matrix.job.os }}) [${{ matrix.job.extra-build-features }}] + runs-on: ${{ matrix.job.os }} + strategy: + fail-fast: false + matrix: + job: + # - { arch: aarch64, target: aarch64-unknown-linux-gnu , os: ubuntu-18.04, use-cross: true, extra-build-features: "" } + # - { arch: aarch64, target: aarch64-unknown-linux-gnu , os: ubuntu-18.04, use-cross: true, extra-build-features: "flatpak" } + # - { arch: armv7, target: arm-unknown-linux-gnueabihf , os: ubuntu-18.04, use-cross: true, extra-build-features: "" } + # - { arch: armv7, target: arm-unknown-linux-gnueabihf , os: ubuntu-18.04, use-cross: true, extra-build-features: "flatpak" } + # - { target: arm-unknown-linux-musleabihf, os: ubuntu-20.04, use-cross: true } + # - { target: i686-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true } + # - { target: i686-unknown-linux-musl , os: ubuntu-20.04, use-cross: true } + - { + arch: x86_64, + target: x86_64-unknown-linux-gnu, + os: ubuntu-18.04, + extra-build-features: "", + } + - { + arch: x86_64, + target: x86_64-unknown-linux-gnu, + os: ubuntu-18.04, + extra-build-features: "flatpak", + } + # - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true } + steps: + - name: Checkout source code + uses: actions/checkout@v3 + + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: ${{ matrix.job.target }} + override: true + profile: minimal # minimal component installation (ie, no documentation) + + - uses: Swatinem/rust-cache@v2 + with: + prefix-key: bridge-${{ matrix.job.os }} + + - name: Disable rust bridge build + run: | + sed -i "s/gen_flutter_rust_bridge();/\/\//g" build.rs + + - name: Restore bridge files + uses: actions/download-artifact@master + with: + name: bridge-artifact + path: ./ + + - name: Restore vcpkg files + uses: actions/download-artifact@master + with: + name: vcpkg-artifact-${{ matrix.job.arch }} + path: /opt/artifacts/vcpkg/installed + + - name: Output devs + run: | + ls -l ./ + tree -L 3 /opt/artifacts/vcpkg/installed + + - name: Install prerequisites + run: | + sudo apt update -y + case ${{ matrix.job.target }} in + x86_64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt install -y g++ gcc;; + arm-unknown-linux-*) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;; + aarch64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;; + esac + # common package + sudo apt install -y 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 libclang-dev ninja-build libappindicator3-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libvdpau-dev libva-dev libclang-dev llvm-dev libclang-10-dev llvm-10-dev pkg-config tree + + - name: Build rustdesk lib + run: | + export VCPKG_ROOT=/opt/artifacts/vcpkg + cargo build --lib --features hwcodec,flutter,${{ matrix.job.extra-build-features }} --release + + - name: Upload Artifacts + uses: actions/upload-artifact@master + with: + name: librustdesk-${{ matrix.job.arch }}-${{ matrix.job.extra-build-features }}.so + path: target/release/liblibrustdesk.so + + build-rustdesk-linux: + needs: [build-rustdesk-lib-linux] + name: build-rustdesk ${{ matrix.job.target }} (${{ matrix.job.os }}) [${{ matrix.job.extra-build-args }}] + runs-on: ${{ matrix.job.os }} + strategy: + fail-fast: false + matrix: + job: + # - { arch: aarch64, target: aarch64-unknown-linux-gnu , os: ubuntu-18.04, use-cross: true, extra-build-features: "" } + # - { arch: aarch64, target: aarch64-unknown-linux-gnu , os: ubuntu-18.04, use-cross: true, extra-build-features: "flatpak" } + # - { arch: armv7, target: arm-unknown-linux-gnueabihf , os: ubuntu-18.04, use-cross: true, extra-build-features: "" } + # - { arch: armv7, target: arm-unknown-linux-gnueabihf , os: ubuntu-18.04, use-cross: true, extra-build-features: "flatpak" } + # - { target: arm-unknown-linux-musleabihf, os: ubuntu-20.04, use-cross: true } + # - { target: i686-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true } + # - { target: i686-unknown-linux-musl , os: ubuntu-20.04, use-cross: true } + - { + arch: x86_64, + target: x86_64-unknown-linux-gnu, + os: ubuntu-18.04, + extra-build-features: "", + } + - { + arch: x86_64, + target: x86_64-unknown-linux-gnu, + os: ubuntu-18.04, + extra-build-features: "flatpak", + } + # - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true } + steps: + - name: Checkout source code + uses: actions/checkout@v3 + + - name: Restore bridge files + uses: actions/download-artifact@master + with: + name: bridge-artifact + path: ./ + + - name: Prepare env + run: | + sudo apt update -y + sudo apt install -y git curl wget nasm yasm libgtk-3-dev + mkdir -p ./target/release/ + + - name: Restore the rustdesk lib file + uses: actions/download-artifact@master + with: + name: librustdesk-${{ matrix.job.arch }}-${{ matrix.job.extra-build-features }}.so + path: ./target/release/ + + - uses: Kingtous/run-on-arch-action@amd64-support + name: Build rustdesk binary for ${{ matrix.job.arch }} + id: vcpkg + with: + arch: ${{ matrix.job.arch }} + distro: ubuntu18.04 + githubToken: ${{ github.token }} + setup: | + ls -l "${PWD}" + dockerRunArgs: | + --volume "${PWD}:/workspace" + --volume "/opt/artifacts:/opt/artifacts" + shell: /bin/bash + install: | + apt update -y + apt install -y git cmake g++ gcc build-essential nasm yasm curl unzip xz-utils python3 wget pkg-config ninja-build pkg-config libgtk-3-dev liblzma-dev clang libappindicator3-dev + run: | + # disable git safe.directory + git config --global --add safe.directory "*" + # Setup Flutter + pushd /opt + wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${{ env.FLUTTER_VERSION }}-stable.tar.xz + tar xf flutter_linux_${{ env.FLUTTER_VERSION }}-stable.tar.xz + ls -l . + export PATH=/opt/flutter/bin:$PATH + flutter doctor -v + pushd /workspace + python3 ./build.py --flutter --hwcodec --skip-cargo - name: Rename rustdesk shell: bash @@ -205,16 +502,21 @@ jobs: tag_name: ${{ env.TAG_NAME }} files: | rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}-${{ matrix.job.os }}.deb - + - name: Upload Artifcat uses: actions/upload-artifact@master - if: ${{ contains(matrix.job.extra-build-args, 'flatpak') }} + if: ${{ contains(matrix.job.extra-build-features, 'flatpak') }} with: name: rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}-${{ matrix.job.os }}.deb path: rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}-${{ matrix.job.os }}.deb + - name: Patch archlinux PKGBUILD + if: ${{ matrix.job.extra-build-features == '' }} + run: | + sed -i "s/arch=('x86_64')/arch=('${{ matrix.job.arch }}')/g" res/PKGBUILD + - name: Build archlinux package - if: ${{ matrix.job.extra-build-args == '' }} + if: ${{ matrix.job.extra-build-features == '' }} uses: vufa/arch-makepkg-action@master with: packages: > @@ -249,7 +551,7 @@ jobs: cd res && HBB=`pwd`/.. FLUTTER=1 makepkg -f - name: Publish archlinux package - if: ${{ matrix.job.extra-build-args == '' }} + if: ${{ matrix.job.extra-build-features == '' }} uses: softprops/action-gh-release@v1 with: prerelease: true @@ -259,40 +561,34 @@ jobs: - name: Make RPM package shell: bash - if: ${{ matrix.job.extra-build-args == '' }} + if: ${{ matrix.job.extra-build-features == '' }} run: | sudo apt install -y rpm HBB=`pwd` rpmbuild ./res/rpm-flutter.spec -bb - pushd ~/rpmbuild/RPMS/${{ steps.build-target-triple.outputs._0 }} + pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }} for name in rustdesk*??.rpm; do mv "$name" "${name%%.rpm}-fedora28-centos8.rpm" done - name: Publish fedora28/centos8 package - if: ${{ matrix.job.extra-build-args == '' }} + if: ${{ matrix.job.extra-build-features == '' }} uses: softprops/action-gh-release@v1 with: prerelease: true tag_name: ${{ env.TAG_NAME }} files: | - /home/runner/rpmbuild/RPMS/${{ steps.build-target-triple.outputs._0 }}/*.rpm + /home/runner/rpmbuild/RPMS/${{ matrix.job.arch }}/*.rpm build-flatpak: name: Build Flatpak - needs: [build-for-linux] + needs: [build-rustdesk-linux] runs-on: ${{ matrix.job.os }} strategy: fail-fast: false matrix: job: - # - { target: aarch64-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true } - # - { target: arm-unknown-linux-gnueabihf , os: ubuntu-20.04, use-cross: true } - # - { target: arm-unknown-linux-musleabihf, os: ubuntu-20.04, use-cross: true } - # - { target: i686-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true } - # - { target: i686-unknown-linux-musl , os: ubuntu-20.04, use-cross: true } - # - { target: x86_64-apple-darwin , os: macos-10.15 } - - { target: x86_64-unknown-linux-gnu , os: ubuntu-18.04, arch: x86_64} - # - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true } + # - { target: aarch64-unknown-linux-gnu , os: ubuntu-18.04, use-cross: true, arch: arm64 } + - { target: x86_64-unknown-linux-gnu, os: ubuntu-18.04, arch: x86_64 } steps: - name: Checkout source code uses: actions/checkout@v3 @@ -307,11 +603,11 @@ jobs: with: name: rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}-${{ matrix.job.os }}.deb path: . - - - name: Rename Binary + + - name: Rename Binary run: | mv rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}-${{ matrix.job.os }}.deb rustdesk-${{ env.VERSION }}.deb - + - name: Install Flatpak deps run: | flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo @@ -332,4 +628,3 @@ jobs: tag_name: ${{ env.TAG_NAME }} files: | flatpak/rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}.flatpak - diff --git a/Cargo.lock b/Cargo.lock index 9eb270683..09485efa6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -633,6 +633,19 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "cidr-utils" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "355d5b5df67e58b523953d0c1a8d3d2c05f5af51f1332b0199b9c92263614ed0" +dependencies = [ + "debug-helper", + "num-bigint", + "num-traits 0.2.15", + "once_cell", + "regex", +] + [[package]] name = "clang-sys" version = "1.3.3" @@ -1244,6 +1257,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7046468a81e6a002061c01e6a7c83139daf91b11c30e66795b13217c2d885c8b" +[[package]] +name = "debug-helper" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e" + [[package]] name = "default-net" version = "0.11.0" @@ -3291,6 +3310,17 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg 1.1.0", + "num-integer", + "num-traits 0.2.15", +] + [[package]] name = "num-complex" version = "0.4.2" @@ -4375,6 +4405,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "chrono", + "cidr-utils", "clap 3.2.17", "clipboard", "cocoa", diff --git a/Cargo.toml b/Cargo.toml index 6375bce26..fd84b73aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,6 +68,7 @@ url = { version = "2.1", features = ["serde"] } reqwest = { version = "0.11", features = ["blocking", "json", "rustls-tls"], default-features=false } chrono = "0.4.23" +cidr-utils = "0.5.9" [target.'cfg(not(any(target_os = "android", target_os = "linux")))'.dependencies] cpal = "0.13.5" @@ -161,3 +162,4 @@ codegen-units = 1 panic = 'abort' strip = true #opt-level = 'z' # only have smaller size after strip +rpath = true \ No newline at end of file diff --git a/build.py b/build.py index a95c64dc1..aa98ec17e 100755 --- a/build.py +++ b/build.py @@ -10,10 +10,12 @@ import hashlib import argparse windows = platform.platform().startswith('Windows') -osx = platform.platform().startswith('Darwin') or platform.platform().startswith("macOS") +osx = platform.platform().startswith( + 'Darwin') or platform.platform().startswith("macOS") hbb_name = 'rustdesk' + ('.exe' if windows else '') exe_path = 'target/release/' + hbb_name flutter_win_target_dir = 'flutter/build/windows/runner/Release/' +skip_cargo = False def get_version(): @@ -86,6 +88,11 @@ def make_parser(): action='store_true', help='Build rustdesk libs with the flatpak feature enabled' ) + parser.add_argument( + '--skip-cargo', + action='store_true', + help='Skip cargo build process, only flutter version + Linux supported currently' + ) return parser @@ -124,6 +131,7 @@ def generate_build_script_for_docker(): os.system("chmod +x /tmp/build.sh") os.system("bash /tmp/build.sh") + def download_extract_features(features, res_dir): proxy = '' @@ -139,7 +147,8 @@ def download_extract_features(features, res_dir): for (feat, feat_info) in features.items(): print(f'{feat} download begin') download_filename = feat_info['zip_url'].split('/')[-1] - checksum_md5_response = urllib.request.urlopen(req(feat_info['checksum_url'])) + checksum_md5_response = urllib.request.urlopen( + req(feat_info['checksum_url'])) for line in checksum_md5_response.read().decode('utf-8').splitlines(): if line.split()[1] == download_filename: checksum_md5 = line.split()[0] @@ -186,7 +195,7 @@ def get_rc_features(args): def get_features(args): - features = ['inline'] + features = ['inline'] if not args.flutter else [] if windows: features.extend(get_rc_features(args)) if args.hwcodec: @@ -224,17 +233,16 @@ def ffi_bindgen_function_refactor(): def build_flutter_deb(version, features): - os.system(f'cargo build --features {features} --lib --release') - ffi_bindgen_function_refactor() + if not skip_cargo: + os.system(f'cargo build --features {features} --lib --release') + ffi_bindgen_function_refactor() os.chdir('flutter') - os.system('dpkg-deb -R rustdesk.deb tmpdeb') os.system('flutter build linux --release') os.system('mkdir -p tmpdeb/usr/bin/') os.system('mkdir -p tmpdeb/usr/lib/rustdesk') os.system('mkdir -p tmpdeb/usr/share/rustdesk/files/systemd/') os.system('mkdir -p tmpdeb/usr/share/applications/') os.system('mkdir -p tmpdeb/usr/share/polkit-1/actions') - os.system('rm tmpdeb/usr/bin/rustdesk') os.system( 'cp -r build/linux/x64/release/bundle/* tmpdeb/usr/lib/rustdesk/') @@ -263,8 +271,26 @@ def build_flutter_deb(version, features): os.chdir("..") +def build_flutter_dmg(version, features): + if not skip_cargo: + os.system(f'cargo build --features {features} --lib --release') + # copy dylib + os.system( + "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") + os.rename("rustdesk.dmg", f"../rustdesk-{version}.dmg") + os.chdir("..") + + def build_flutter_arch_manjaro(version, features): - os.system(f'cargo build --features {features} --lib --release') + if not skip_cargo: + os.system(f'cargo build --features {features} --lib --release') ffi_bindgen_function_refactor() os.chdir('flutter') os.system('flutter build linux --release') @@ -274,29 +300,36 @@ def build_flutter_arch_manjaro(version, features): def build_flutter_windows(version, features): - os.system(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) + if not skip_cargo: + os.system(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') os.chdir('..') - shutil.copy2('target/release/deps/dylib_virtual_display.dll', flutter_win_target_dir) + 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( 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'): - os.replace('./target/release/rustdesk-portable-packer.exe', './rustdesk_portable.exe') + os.replace('./target/release/rustdesk-portable-packer.exe', + './rustdesk_portable.exe') else: - os.rename('./target/release/rustdesk-portable-packer.exe', './rustdesk_portable.exe') - print(f'output location: {os.path.abspath(os.curdir)}/rustdesk_portable.exe') + os.rename('./target/release/rustdesk-portable-packer.exe', + './rustdesk_portable.exe') + print( + f'output location: {os.path.abspath(os.curdir)}/rustdesk_portable.exe') os.rename('./rustdesk_portable.exe', f'./rustdesk-{version}-install.exe') - print(f'output location: {os.path.abspath(os.curdir)}/rustdesk-{version}-install.exe') + print( + f'output location: {os.path.abspath(os.curdir)}/rustdesk-{version}-install.exe') def main(): + global skip_cargo parser = make_parser() args = parser.parse_args() @@ -314,7 +347,11 @@ def main(): version = get_version() features = ','.join(get_features(args)) flutter = args.flutter - os.system('python3 res/inline-sciter.py') + if not flutter: + os.system('python3 res/inline-sciter.py') + print(args.skip_cargo) + if args.skip_cargo: + skip_cargo = True portable = args.portable if windows: # build virtual display dynamic library @@ -335,7 +372,8 @@ def main(): 'target\\release\\rustdesk.exe') else: print('Not signed') - os.system(f'cp -rf target/release/RustDesk.exe rustdesk-{version}-win7-install.exe') + os.system( + 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) @@ -348,12 +386,13 @@ def main(): 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' % ( - version, version)) + 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("sed -i 's/Version: .*/Version: %s/g' res/rpm.spec" % version) + os.system( + "sed -i 's/Version: .*/Version: %s/g' res/rpm.spec" % version) os.system('HBB=`pwd` rpmbuild -ba res/rpm.spec') os.system( 'mv $HOME/rpmbuild/RPMS/x86_64/rustdesk-%s-0.x86_64.rpm ./rustdesk-%s-fedora28-centos8.rpm' % ( @@ -362,23 +401,24 @@ def main(): elif os.path.isfile('/usr/bin/zypper'): os.system('cargo build --release --features ' + features) os.system('strip target/release/rustdesk') - os.system("sed -i 's/Version: .*/Version: %s/g' res/rpm-suse.spec" % version) + os.system( + "sed -i 's/Version: .*/Version: %s/g' res/rpm-suse.spec" % version) os.system('HBB=`pwd` rpmbuild -ba res/rpm-suse.spec') os.system( 'mv $HOME/rpmbuild/RPMS/x86_64/rustdesk-%s-0.x86_64.rpm ./rustdesk-%s-suse.rpm' % ( - version, version)) + version, version)) # yum localinstall rustdesk.rpm else: - os.system('cargo bundle --release --features ' + features) if flutter: if osx: - # todo: OSX build + build_flutter_dmg(version, features) pass else: - os.system( - 'mv target/release/bundle/deb/rustdesk*.deb ./flutter/rustdesk.deb') + # os.system( + # 'mv target/release/bundle/deb/rustdesk*.deb ./flutter/rustdesk.deb') build_flutter_deb(version, features) else: + os.system('cargo bundle --release --features ' + features) if osx: os.system( 'strip target/release/bundle/osx/RustDesk.app/Contents/MacOS/rustdesk') diff --git a/flutter/lib/common/widgets/dialog.dart b/flutter/lib/common/widgets/dialog.dart index 35a303c0b..a6de0384f 100644 --- a/flutter/lib/common/widgets/dialog.dart +++ b/flutter/lib/common/widgets/dialog.dart @@ -133,9 +133,12 @@ void changeWhiteList({Function()? callback}) async { final ips = newWhiteListField.trim().split(RegExp(r"[\s,;\n]+")); // test ip - final ipMatch = RegExp(r"^\d+\.\d+\.\d+\.\d+$"); + final ipMatch = RegExp( + r"^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)(\/([1-9]|[1-2][0-9]|3[0-2])){0,1}$"); + final ipv6Match = RegExp( + r"^(((?:[0-9A-Fa-f]{1,4}))*((?::[0-9A-Fa-f]{1,4}))*::((?:[0-9A-Fa-f]{1,4}))*((?::[0-9A-Fa-f]{1,4}))*|((?:[0-9A-Fa-f]{1,4}))((?::[0-9A-Fa-f]{1,4})){7})(\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])){0,1}$"); for (final ip in ips) { - if (!ipMatch.hasMatch(ip)) { + if (!ipMatch.hasMatch(ip) && !ipv6Match.hasMatch(ip)) { msg = "${translate("Invalid IP")} $ip"; setState(() { isInProgress = false; diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index acba32780..4d3cd8cd9 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -70,6 +70,30 @@ const kMouseControlDistance = 12; /// [kMouseControlTimeoutMSec] indicates the timeout (in milliseconds) that self-side can get control of mouse. const kMouseControlTimeoutMSec = 1000; +/// [kRemoteViewStyleOriginal] Show remote image without scaling. +const kRemoteViewStyleOriginal = 'original'; + +/// [kRemoteViewStyleAdaptive] Show remote image scaling by ratio factor. +const kRemoteViewStyleAdaptive = 'adaptive'; + +/// [kRemoteScrollStyleAuto] Scroll image auto by position. +const kRemoteScrollStyleAuto = 'scrollauto'; + +/// [kRemoteScrollStyleBar] Scroll image with scroll bar. +const kRemoteScrollStyleBar = 'scrollbar'; + +/// [kRemoteImageQualityBest] Best image quality. +const kRemoteImageQualityBest = 'best'; + +/// [kRemoteImageQualityBalanced] Balanced image quality, mid performance. +const kRemoteImageQualityBalanced = 'balanced'; + +/// [kRemoteImageQualityLow] Low image quality, better performance. +const kRemoteImageQualityLow = 'low'; + +/// [kRemoteImageQualityCustom] Custom image quality. +const kRemoteImageQualityCustom = 'custom'; + /// flutter/packages/flutter/lib/src/services/keyboard_key.dart -> _keyLabels /// see [LogicalKeyboardKey.keyLabel] const Map logicalKeyMap = { diff --git a/flutter/lib/desktop/pages/connection_page.dart b/flutter/lib/desktop/pages/connection_page.dart index 671335bfd..83e57dba8 100644 --- a/flutter/lib/desktop/pages/connection_page.dart +++ b/flutter/lib/desktop/pages/connection_page.dart @@ -4,6 +4,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/common/widgets/address_book.dart'; import 'package:flutter_hbb/consts.dart'; @@ -177,12 +178,15 @@ class _ConnectionPageState extends State children: [ Row( children: [ - Text( - translate('Control Remote Desktop'), - style: Theme.of(context) - .textTheme - .titleLarge - ?.merge(TextStyle(height: 1)), + Expanded( + child: AutoSizeText( + translate('Control Remote Desktop'), + maxLines: 1, + style: Theme.of(context) + .textTheme + .titleLarge + ?.merge(TextStyle(height: 1)), + ), ), ], ).marginOnly(bottom: 15), diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index b5aeaa7c3..056b1028b 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -658,13 +658,9 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin { initialKey: modeInitialKey, onChanged: (key) => model.setApproveMode(key), ).marginOnly(left: _kContentHMargin), - Offstage( - offstage: !usePassword, - child: radios[0], - ), - Offstage( - offstage: !usePassword, - child: _SubLabeledWidget( + if (usePassword) radios[0], + if (usePassword) + _SubLabeledWidget( 'One-time password length', Row( children: [ @@ -672,20 +668,13 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin { ], ), enabled: tmpEnabled && !locked), - ), - Offstage( - offstage: !usePassword, - child: radios[1], - ), - Offstage( - offstage: !usePassword, - child: _SubButton('Set permanent password', setPasswordDialog, + if (usePassword) radios[1], + if (usePassword) + _SubButton('Set permanent password', setPasswordDialog, permEnabled && !locked), - ), - Offstage( - offstage: !usePassword, - child: radios[2], - ), + if (usePassword) + hide_cm(!locked).marginOnly(left: _kContentHSubMargin - 6), + if (usePassword) radios[2], ]); }))); } @@ -814,6 +803,46 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin { ).marginOnly(left: _kCheckBoxLeftMargin); }); } + + Widget hide_cm(bool enabled) { + return ChangeNotifierProvider.value( + value: gFFI.serverModel, + child: Consumer(builder: (context, model, child) { + final enableHideCm = model.approveMode == 'password' && + model.verificationMethod == kUsePermanentPassword; + onHideCmChanged(bool? b) { + if (b != null) { + bind.mainSetOption( + key: 'allow-hide-cm', value: bool2option('allow-hide-cm', b)); + } + } + + return Tooltip( + message: enableHideCm ? "" : translate('hide_cm_tip'), + child: GestureDetector( + onTap: + enableHideCm ? () => onHideCmChanged(!model.hideCm) : null, + child: Row( + children: [ + Checkbox( + value: model.hideCm, + onChanged: enabled && enableHideCm + ? onHideCmChanged + : null) + .marginOnly(right: 5), + Expanded( + child: Text( + translate('Hide connection management window'), + style: TextStyle( + color: _disabledTextColor( + context, enabled && enableHideCm)), + ), + ), + ], + ), + )); + })); + } } class _Network extends StatefulWidget { diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 84ea36d78..c0a05c6d5 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -70,8 +70,7 @@ class _RemotePageState extends State ShowRemoteCursorState.init(id); RemoteCursorMovedState.init(id); final optZoomCursor = 'zoom-cursor'; - PeerBoolOption.init(id, optZoomCursor, - () => bind.sessionGetToggleOptionSync(id: id, arg: optZoomCursor)); + PeerBoolOption.init(id, optZoomCursor, () => false); _zoomCursor = PeerBoolOption.find(id, optZoomCursor); _showRemoteCursor = ShowRemoteCursorState.find(id); _keyboardEnabled = KeyboardEnabledState.find(id); @@ -91,9 +90,7 @@ class _RemotePageState extends State void initState() { super.initState(); _initStates(widget.id); - _ffi = FFI(); - Get.put(_ffi, tag: widget.id); _ffi.start(widget.id); WidgetsBinding.instance.addPostFrameCallback((_) { @@ -107,8 +104,11 @@ class _RemotePageState extends State _rawKeyFocusNode.requestFocus(); _ffi.ffiModel.updateEventListener(widget.id); _ffi.qualityMonitorModel.checkShowQualityMonitor(widget.id); + // Session option should be set after models.dart/FFI.start _showRemoteCursor.value = bind.sessionGetToggleOptionSync( id: widget.id, arg: 'show-remote-cursor'); + _zoomCursor.value = + bind.sessionGetToggleOptionSync(id: widget.id, arg: 'zoom-cursor'); if (!_isCustomCursorInited) { customCursorController.registerNeedUpdateCursorCallback( (String? lastKey, String? currentKey) async { @@ -356,9 +356,8 @@ class _ImagePaintState extends State { } } - MouseCursor _buildCustomCursor(BuildContext context, double scale) { - final cursor = Provider.of(context); - final cache = cursor.cache ?? cursor.defaultCache; + MouseCursor _buildCursorOfCache( + CursorModel cursor, double scale, CursorData? cache) { if (cache == null) { return MouseCursor.defer; } else { @@ -375,26 +374,16 @@ class _ImagePaintState extends State { } } + MouseCursor _buildCustomCursor(BuildContext context, double scale) { + final cursor = Provider.of(context); + final cache = cursor.cache ?? preDefaultCursor.cache; + return _buildCursorOfCache(cursor, scale, cache); + } + MouseCursor _buildDisabledCursor(BuildContext context, double scale) { final cursor = Provider.of(context); - final cache = cursor.cache; - if (cache == null) { - return MouseCursor.defer; - } else { - if (cursor.cachedForbidmemoryCursorData == null) { - cursor.updateForbiddenCursorBuffer(); - } - final key = 'disabled_cursor_key'; - cursor.addKey(key); - return FlutterCustomMemoryImageCursor( - pixbuf: cursor.cachedForbidmemoryCursorData, - key: key, - hotx: 0, - hoty: 0, - imageWidth: 32, - imageHeight: 32, - ); - } + final cache = preForbiddenCursor.cache; + return _buildCursorOfCache(cursor, scale, cache); } Widget _buildCrossScrollbarFromLayout( @@ -521,22 +510,22 @@ class CursorPaint extends StatelessWidget { double hotx = m.hotx; double hoty = m.hoty; if (m.image == null) { - if (m.defaultCache != null) { - hotx = m.defaultImage!.width / 2; - hoty = m.defaultImage!.height / 2; + if (preDefaultCursor.image != null) { + hotx = preDefaultCursor.image!.width / 2; + hoty = preDefaultCursor.image!.height / 2; } } return zoomCursor.isTrue ? CustomPaint( painter: ImagePainter( - image: m.image ?? m.defaultImage, + image: m.image ?? preDefaultCursor.image, x: m.x - hotx + c.x / c.scale, y: m.y - hoty + c.y / c.scale, scale: c.scale), ) : CustomPaint( painter: ImagePainter( - image: m.image ?? m.defaultImage, + image: m.image ?? preDefaultCursor.image, x: (m.x - hotx) * c.scale + c.x, y: (m.y - hoty) * c.scale + c.y, scale: 1.0), diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index 1e942272c..85df25477 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -236,12 +236,12 @@ class _ConnectionTabPageState extends State { optionsGetter: () => [ MenuEntryRadioOption( text: translate('Scale original'), - value: 'original', + value: kRemoteViewStyleOriginal, dismissOnClicked: true, ), MenuEntryRadioOption( text: translate('Scale adaptive'), - value: 'adaptive', + value: kRemoteViewStyleAdaptive, dismissOnClicked: true, ), ], @@ -249,8 +249,7 @@ class _ConnectionTabPageState extends State { // null means peer id is not found, which there's no need to care about await bind.sessionGetViewStyle(id: key) ?? '', optionSetter: (String oldValue, String newValue) async { - await bind.sessionSetViewStyle( - id: key, value: newValue); + await bind.sessionSetViewStyle(id: key, value: newValue); ffi.canvasModel.updateViewStyle(); cancelFunc(); }, diff --git a/flutter/lib/desktop/pages/server_page.dart b/flutter/lib/desktop/pages/server_page.dart index aae6da8fc..6c586994b 100644 --- a/flutter/lib/desktop/pages/server_page.dart +++ b/flutter/lib/desktop/pages/server_page.dart @@ -107,13 +107,14 @@ class ConnectionManagerState extends State { @override Widget build(BuildContext context) { final serverModel = Provider.of(context); - final pointerHandler = serverModel.cmHiddenTimer != null - ? (PointerEvent e) { - serverModel.cmHiddenTimer!.cancel(); - serverModel.cmHiddenTimer = null; - debugPrint("CM hidden timer has been canceled"); - } - : null; + pointerHandler(PointerEvent e) { + if (serverModel.cmHiddenTimer != null) { + serverModel.cmHiddenTimer!.cancel(); + serverModel.cmHiddenTimer = null; + debugPrint("CM hidden timer has been canceled"); + } + } + return serverModel.clients.isEmpty ? Column( children: [ diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index ed69f3e65..656dc8546 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -7,6 +7,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hbb/models/chat_model.dart'; import 'package:flutter_hbb/models/state_model.dart'; +import 'package:flutter_hbb/consts.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; import 'package:rxdart/rxdart.dart' as rxdart; @@ -25,6 +26,7 @@ class MenubarState { final kStoreKey = 'remoteMenubarState'; late RxBool show; late RxBool _pin; + RxString viewStyle = RxString(kRemoteViewStyleOriginal); MenubarState() { final s = bind.getLocalFlutterConfig(k: kStoreKey); @@ -67,21 +69,25 @@ class MenubarState { switchPin() async { _pin.value = !_pin.value; // Save everytime changed, as this func will not be called frequently - await save(); + await _savePin(); } setPin(bool v) async { if (_pin.value != v) { _pin.value = v; // Save everytime changed, as this func will not be called frequently - await save(); + await _savePin(); } } - save() async { + _savePin() async { bind.setLocalFlutterConfig( k: kStoreKey, v: jsonEncode({'pin': _pin.value})); } + + save() async { + await _savePin(); + } } class _MenubarTheme { @@ -404,6 +410,8 @@ class _RemoteMenubarState extends State { Widget _buildDisplay(BuildContext context) { return FutureBuilder(future: () async { + widget.state.viewStyle.value = + await bind.sessionGetViewStyle(id: widget.id) ?? ''; final supportedHwcodec = await bind.sessionSupportedHwcodec(id: widget.id); return {'supportedHwcodec': supportedHwcodec}; @@ -719,20 +727,24 @@ class _RemoteMenubarState extends State { optionsGetter: () => [ MenuEntryRadioOption( text: translate('Scale original'), - value: 'original', + value: kRemoteViewStyleOriginal, dismissOnClicked: true, ), MenuEntryRadioOption( text: translate('Scale adaptive'), - value: 'adaptive', + value: kRemoteViewStyleAdaptive, dismissOnClicked: true, ), ], - curOptionGetter: () async => - // null means peer id is not found, which there's no need to care about - await bind.sessionGetViewStyle(id: widget.id) ?? '', + curOptionGetter: () async { + // null means peer id is not found, which there's no need to care about + final viewStyle = await bind.sessionGetViewStyle(id: widget.id) ?? ''; + widget.state.viewStyle.value = viewStyle; + return viewStyle; + }, optionSetter: (String oldValue, String newValue) async { await bind.sessionSetViewStyle(id: widget.id, value: newValue); + widget.state.viewStyle.value = newValue; widget.ffi.canvasModel.updateViewStyle(); }, padding: padding, @@ -744,12 +756,12 @@ class _RemoteMenubarState extends State { optionsGetter: () => [ MenuEntryRadioOption( text: translate('ScrollAuto'), - value: 'scrollauto', + value: kRemoteScrollStyleAuto, dismissOnClicked: true, ), MenuEntryRadioOption( text: translate('Scrollbar'), - value: 'scrollbar', + value: kRemoteScrollStyleBar, dismissOnClicked: true, ), ], @@ -769,22 +781,22 @@ class _RemoteMenubarState extends State { optionsGetter: () => [ MenuEntryRadioOption( text: translate('Good image quality'), - value: 'best', + value: kRemoteImageQualityBest, dismissOnClicked: true, ), MenuEntryRadioOption( text: translate('Balanced'), - value: 'balanced', + value: kRemoteImageQualityBalanced, dismissOnClicked: true, ), MenuEntryRadioOption( text: translate('Optimize reaction time'), - value: 'low', + value: kRemoteImageQualityLow, dismissOnClicked: true, ), MenuEntryRadioOption( text: translate('Custom'), - value: 'custom', + value: kRemoteImageQualityCustom, dismissOnClicked: true), ], curOptionGetter: () async => @@ -821,7 +833,7 @@ class _RemoteMenubarState extends State { } } - if (newValue == 'custom') { + if (newValue == kRemoteImageQualityCustom) { final btnClose = msgBoxButton(translate('Close'), () async { await setCustomValues(); widget.ffi.dialogManager.dismissAll(); @@ -1089,24 +1101,26 @@ class _RemoteMenubarState extends State { ); }()); - /// Show remote cursor - displayMenu.add(() { - final opt = 'zoom-cursor'; - final state = PeerBoolOption.find(widget.id, opt); - return MenuEntrySwitch2( - switchType: SwitchType.scheckbox, - text: translate('Zoom cursor'), - getter: () { - return state; - }, - setter: (bool v) async { - state.value = v; - await bind.sessionToggleOption(id: widget.id, value: opt); - }, - padding: padding, - dismissOnClicked: true, - ); - }()); + /// Show remote cursor scaling with image + if (widget.state.viewStyle.value != kRemoteViewStyleOriginal) { + displayMenu.add(() { + final opt = 'zoom-cursor'; + final state = PeerBoolOption.find(widget.id, opt); + return MenuEntrySwitch2( + switchType: SwitchType.scheckbox, + text: translate('Zoom cursor'), + getter: () { + return state; + }, + setter: (bool v) async { + state.value = v; + await bind.sessionToggleOption(id: widget.id, value: opt); + }, + padding: padding, + dismissOnClicked: true, + ); + }()); + } /// Show quality monitor displayMenu.add(MenuEntrySwitch( @@ -1179,7 +1193,6 @@ class _RemoteMenubarState extends State { optionSetter: (String oldValue, String newValue) async { await bind.sessionSetKeyboardMode( id: widget.id, keyboardMode: newValue); - widget.ffi.canvasModel.updateViewStyle(); }, ) ]; diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index 989ba12f5..44db1436e 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -42,7 +42,9 @@ Future main(List args) async { if (args.isNotEmpty && args.first == 'multi_window') { windowId = int.parse(args[1]); stateGlobal.setWindowId(windowId!); - WindowController.fromWindowId(windowId!).showTitleBar(false); + if (!Platform.isMacOS) { + WindowController.fromWindowId(windowId!).showTitleBar(false); + } final argument = args[2].isEmpty ? {} : jsonDecode(args[2]) as Map; @@ -83,7 +85,7 @@ Future main(List args) async { debugPrint("--cm started"); desktopType = DesktopType.cm; await windowManager.ensureInitialized(); - runConnectionManagerScreen(); + runConnectionManagerScreen(args.contains('--hide')); } else if (args.contains('--install')) { runInstallPage(); } else { @@ -168,13 +170,14 @@ void runMultiWindow( ); switch (appType) { case kAppTypeDesktopRemote: - await restoreWindowPosition(WindowType.RemoteDesktop, windowId: windowId!); + await restoreWindowPosition(WindowType.RemoteDesktop, + windowId: windowId!); break; case kAppTypeDesktopFileTransfer: - await restoreWindowPosition(WindowType.FileTransfer, windowId: windowId!); + await restoreWindowPosition(WindowType.FileTransfer, windowId: windowId!); break; case kAppTypeDesktopPortForward: - await restoreWindowPosition(WindowType.PortForward, windowId: windowId!); + await restoreWindowPosition(WindowType.PortForward, windowId: windowId!); break; default: // no such appType @@ -182,16 +185,23 @@ void runMultiWindow( } } -void runConnectionManagerScreen() async { +void runConnectionManagerScreen(bool hide) async { await initEnv(kAppTypeMain); - // initialize window - WindowOptions windowOptions = - getHiddenTitleBarWindowOptions(size: kConnectionManagerWindowSize); _runApp( '', const DesktopServerPage(), MyTheme.currentThemeMode(), ); + if (hide) { + hideCmWindow(); + } else { + showCmWindow(); + } +} + +void showCmWindow() { + WindowOptions windowOptions = + getHiddenTitleBarWindowOptions(size: kConnectionManagerWindowSize); windowManager.waitUntilReadyToShow(windowOptions, () async { await windowManager.show(); await Future.wait([windowManager.focus(), windowManager.setOpacity(1)]); @@ -201,6 +211,15 @@ void runConnectionManagerScreen() async { }); } +void hideCmWindow() { + WindowOptions windowOptions = + getHiddenTitleBarWindowOptions(size: kConnectionManagerWindowSize); + windowManager.setOpacity(0); + windowManager.waitUntilReadyToShow(windowOptions, () async { + await windowManager.hide(); + }); +} + void _runApp( String title, Widget home, diff --git a/flutter/lib/mobile/pages/remote_page.dart b/flutter/lib/mobile/pages/remote_page.dart index b48e9960a..e6ebfcb73 100644 --- a/flutter/lib/mobile/pages/remote_page.dart +++ b/flutter/lib/mobile/pages/remote_page.dart @@ -4,6 +4,7 @@ import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_hbb/consts.dart'; import 'package:flutter_hbb/mobile/widgets/gesture_help.dart'; import 'package:flutter_hbb/models/chat_model.dart'; import 'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart'; @@ -642,7 +643,7 @@ class _RemotePageState extends State { // FIXME: // null means no session of id // empty string means no password - var password = await bind.sessionGetOption(id: id, arg: "os-password"); + var password = await bind.sessionGetOption(id: id, arg: 'os-password'); if (password != null) { bind.sessionInputOsPassword(id: widget.id, value: password); } else { @@ -865,14 +866,14 @@ class CursorPaint extends StatelessWidget { double hotx = m.hotx; double hoty = m.hoty; if (m.image == null) { - if (m.defaultCache != null) { - hotx = m.defaultImage!.width / 2; - hoty = m.defaultImage!.height / 2; + if (preDefaultCursor.image != null) { + hotx = preDefaultCursor.image!.width / 2; + hoty = preDefaultCursor.image!.height / 2; } } return CustomPaint( painter: ImagePainter( - image: m.image ?? m.defaultImage, + image: m.image ?? preDefaultCursor.image, x: m.x * s - hotx * s + c.x, y: m.y * s - hoty * s + c.y - adjust, scale: 1), @@ -908,13 +909,13 @@ class ImagePainter extends CustomPainter { void showOptions( BuildContext context, String id, OverlayDialogManager dialogManager) async { - String quality = await bind.sessionGetImageQuality(id: id) ?? 'balanced'; - if (quality == '') quality = 'balanced'; + String quality = + await bind.sessionGetImageQuality(id: id) ?? kRemoteImageQualityBalanced; + if (quality == '') quality = kRemoteImageQualityBalanced; String codec = await bind.sessionGetOption(id: id, arg: 'codec-preference') ?? 'auto'; if (codec == '') codec = 'auto'; - String viewStyle = - await bind.sessionGetOption(id: id, arg: 'view-style') ?? ''; + String viewStyle = await bind.sessionGetViewStyle(id: id) ?? ''; var displays = []; final pi = gFFI.ffiModel.pi; @@ -1017,12 +1018,16 @@ void showOptions( } final radios = [ - getRadio('Scale original', 'original', viewStyle, setViewStyle), - getRadio('Scale adaptive', 'adaptive', viewStyle, setViewStyle), + getRadio( + 'Scale original', kRemoteViewStyleOriginal, viewStyle, setViewStyle), + getRadio( + 'Scale adaptive', kRemoteViewStyleAdaptive, viewStyle, setViewStyle), const Divider(color: MyTheme.border), - getRadio('Good image quality', 'best', quality, setQuality), - getRadio('Balanced', 'balanced', quality, setQuality), - getRadio('Optimize reaction time', 'low', quality, setQuality), + getRadio( + 'Good image quality', kRemoteImageQualityBest, quality, setQuality), + getRadio('Balanced', kRemoteImageQualityBalanced, quality, setQuality), + getRadio('Optimize reaction time', kRemoteImageQualityLow, quality, + setQuality), const Divider(color: MyTheme.border) ]; diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 7a08fc671..a7a51b9a0 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -565,7 +565,7 @@ class CanvasModel with ChangeNotifier { updateScrollStyle() async { final style = await bind.sessionGetScrollStyle(id: id); - if (style == 'scrollbar') { + if (style == kRemoteScrollStyleBar) { _scrollStyle = ScrollStyle.scrollbar; _scrollX = 0.0; _scrollY = 0.0; @@ -763,13 +763,78 @@ class CursorData { } } +const _forbiddenCursorPng = + 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAkZQTFRFAAAA2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4GWAwCAAAAAAAA2B4GAAAAMTExAAAAAAAA2B4G2B4G2B4GAAAAmZmZkZGRAQEBAAAA2B4G2B4G2B4G////oKCgAwMDag8D2B4G2B4G2B4Gra2tBgYGbg8D2B4G2B4Gubm5CQkJTwsCVgwC2B4GxcXFDg4OAAAAAAAA2B4G2B4Gz8/PFBQUAAAAAAAA2B4G2B4G2B4G2B4G2B4G2B4G2B4GDgIA2NjYGxsbAAAAAAAA2B4GFwMB4eHhIyMjAAAAAAAA2B4G6OjoLCwsAAAAAAAA2B4G2B4G2B4G2B4G2B4GCQEA4ODgv7+/iYmJY2NjAgICAAAA9PT0Ojo6AAAAAAAAAAAA+/v7SkpKhYWFr6+vAAAAAAAA8/PzOTk5ERER9fX1KCgoAAAAgYGBKioqAAAAAAAApqamlpaWAAAAAAAAAAAAAAAAAAAAAAAALi4u/v7+GRkZAAAAAAAAAAAAAAAAAAAAfn5+AAAAAAAAV1dXkJCQAAAAAAAAAQEBAAAAAAAAAAAA7Hz6BAAAAMJ0Uk5TAAIWEwEynNz6//fVkCAatP2fDUHs6cDD8d0mPfT5fiEskiIR584A0gejr3AZ+P4plfALf5ZiTL85a4ziD6697fzN3UYE4v/4TwrNHuT///tdRKZh///+1U/ZBv///yjb///eAVL//50Cocv//6oFBbPvpGZCbfT//7cIhv///8INM///zBEcWYSZmO7//////1P////ts/////8vBv//////gv//R/z///QQz9sevP///2waXhNO/+fc//8mev/5gAe2r90MAAAByUlEQVR4nGNggANGJmYWBpyAlY2dg5OTi5uHF6s0H78AJxRwCAphyguLgKRExcQlQLSkFLq8tAwnp6ycPNABjAqKQKNElVDllVU4OVVhVquJA81Q10BRoAkUUYbJa4Edoo0sr6PLqaePLG/AyWlohKTAmJPTBFnelAFoixmSAnNOTgsUeQZLTk4rJAXWnJw2EHlbiDyDPCenHZICe04HFrh+RydnBgYWPU5uJAWinJwucPNd3dw9GDw5Ob2QFHBzcnrD7ffx9fMPCOTkDEINhmC4+3x8Q0LDwlEDIoKTMzIKKg9SEBIdE8sZh6SAJZ6Tkx0qD1YQkpCYlIwclCng0AXLQxSEpKalZyCryATKZwkhKQjJzsnNQ1KQXwBUUVhUXBJYWgZREFJeUVmFpMKlWg+anmqgCkJq6+obkG1pLEBTENLU3NKKrIKhrb2js8u4G6Kgpze0r3/CRAZMAHbkpJDJU6ZMmTqtFbuC6TNmhsyaMnsOFlmwgrnzpsxfELJwEXZ5Bp/FS3yWLlsesmLlKuwKVk9Ys5Zh3foN0zduwq5g85atDAzbpqSGbN9RhV0FGOzctWH3lD14FOzdt3H/gQw8Cg4u2gQPAwBYDXXdIH+wqAAAAABJRU5ErkJggg=='; +const _defaultCursorPng = + 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARzQklUCAgICHwIZIgAAAFmSURBVFiF7dWxSlxREMbx34QFDRowYBchZSxSCWlMCOwD5FGEFHap06UI7KPsAyyEEIQFqxRaCqYTsqCJFsKkuAeRXb17wrqV918dztw55zszc2fo6Oh47MR/e3zO1/iAHWmznHKGQwx9ip/LEbCfazbsoY8j/JLOhcC6sCW9wsjEwJf483AC9nPNc1+lFRwI13d+l3rYFS799rFGxJMqARv2pBXh+72XQ7gWvklPS7TmMl9Ak/M+DqrENvxAv/guKKApuKPWl0/TROK4+LbSqzhuB+OZ3fRSeFPWY+Fkyn56Y29hfgTSpnQ+s98cvorVey66uPlNFxKwZOYLCGfCs5n9NMYVrsp6mvXSoFqpqYFDvMBkStgJJe93dZOwVXxbqUnBENulydSReqUrDhcX0PT2EXarBYS3GNXMhboinBgIl9K71kg0L3+PvyYGdVpruT2MwrF0iotiXfIwus0Dj+OOjo6Of+e7ab74RkpgAAAAAElFTkSuQmCC'; + +final preForbiddenCursor = PredefinedCursor( + png: _forbiddenCursorPng, + id: -2, +); +final preDefaultCursor = PredefinedCursor( + png: _defaultCursorPng, + id: -1, + hotxGetter: (double w) => w / 2, + hotyGetter: (double h) => h / 2, +); + +class PredefinedCursor { + ui.Image? _image; + img2.Image? _image2; + CursorData? _cache; + String png; + int id; + double Function(double)? hotxGetter; + double Function(double)? hotyGetter; + + PredefinedCursor( + {required this.png, required this.id, this.hotxGetter, this.hotyGetter}) { + init(); + } + + ui.Image? get image => _image; + CursorData? get cache => _cache; + + init() { + _image2 = img2.decodePng(base64Decode(png)); + if (_image2 != null) { + () async { + final defaultImg = _image2!; + // This function is called only one time, no need to care about the performance. + Uint8List data = defaultImg.getBytes(format: img2.Format.rgba); + _image = await img.decodeImageFromPixels( + data, defaultImg.width, defaultImg.height, ui.PixelFormat.rgba8888); + + double scale = 1.0; + if (Platform.isWindows) { + data = _image2!.getBytes(format: img2.Format.bgra); + } else { + data = Uint8List.fromList(img2.encodePng(_image2!)); + } + + _cache = CursorData( + peerId: '', + id: id, + image: _image2?.clone(), + scale: scale, + data: data, + hotxOrigin: + hotxGetter != null ? hotxGetter!(_image2!.width.toDouble()) : 0, + hotyOrigin: + hotyGetter != null ? hotyGetter!(_image2!.height.toDouble()) : 0, + width: _image2!.width, + height: _image2!.height, + ); + }(); + } + } +} + class CursorModel with ChangeNotifier { ui.Image? _image; - ui.Image? _defaultImage; final _images = >{}; CursorData? _cache; - final _defaultCacheId = -1; - CursorData? _defaultCache; final _cacheMap = {}; final _cacheKeys = {}; double _x = -10000; @@ -785,9 +850,7 @@ class CursorModel with ChangeNotifier { WeakReference parent; ui.Image? get image => _image; - ui.Image? get defaultImage => _defaultImage; CursorData? get cache => _cache; - CursorData? get defaultCache => _getDefaultCache(); double get x => _x - _displayOriginX; double get y => _y - _displayOriginY; @@ -801,50 +864,11 @@ class CursorModel with ChangeNotifier { DateTime.now().difference(_lastPeerMouse).inMilliseconds < kMouseControlTimeoutMSec; - CursorModel(this.parent) { - _getDefaultImage(); - _getDefaultCache(); - } + CursorModel(this.parent); Set get cachedKeys => _cacheKeys; addKey(String key) => _cacheKeys.add(key); - Future _getDefaultImage() async { - if (_defaultImage == null) { - final defaultImg = defaultCursorImage!; - // This function is called only one time, no need to care about the performance. - Uint8List data = defaultImg.getBytes(format: img2.Format.rgba); - _defaultImage = await img.decodeImageFromPixels( - data, defaultImg.width, defaultImg.height, ui.PixelFormat.rgba8888); - } - return _defaultImage; - } - - CursorData? _getDefaultCache() { - if (_defaultCache == null) { - Uint8List data; - double scale = 1.0; - if (Platform.isWindows) { - data = defaultCursorImage!.getBytes(format: img2.Format.bgra); - } else { - data = Uint8List.fromList(img2.encodePng(defaultCursorImage!)); - } - - _defaultCache = CursorData( - peerId: id, - id: _defaultCacheId, - image: defaultCursorImage?.clone(), - scale: scale, - data: data, - hotxOrigin: defaultCursorImage!.width / 2, - hotyOrigin: defaultCursorImage!.height / 2, - width: defaultCursorImage!.width, - height: defaultCursorImage!.height, - ); - } - return _defaultCache; - } - // remote physical display coordinate Rect getVisibleRect() { final size = MediaQueryData.fromWindow(ui.window).size; @@ -1085,15 +1109,6 @@ class CursorModel with ChangeNotifier { customCursorController.freeCache(k); } } - - Uint8List? cachedForbidmemoryCursorData; - void updateForbiddenCursorBuffer() { - cachedForbidmemoryCursorData ??= base64Decode( - 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAkZQTFRFAAAA2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4GWAwCAAAAAAAA2B4GAAAAMTExAAAAAAAA2B4G2B4G2B4GAAAAmZmZkZGRAQEBAAAA2B4G2B4G2B4G////oKCgAwMDag8D2B4G2B4G2B4Gra2tBgYGbg8D2B4G2B4Gubm5CQkJTwsCVgwC2B4GxcXFDg4OAAAAAAAA2B4G2B4Gz8/PFBQUAAAAAAAA2B4G2B4G2B4G2B4G2B4G2B4G2B4GDgIA2NjYGxsbAAAAAAAA2B4GFwMB4eHhIyMjAAAAAAAA2B4G6OjoLCwsAAAAAAAA2B4G2B4G2B4G2B4G2B4GCQEA4ODgv7+/iYmJY2NjAgICAAAA9PT0Ojo6AAAAAAAAAAAA+/v7SkpKhYWFr6+vAAAAAAAA8/PzOTk5ERER9fX1KCgoAAAAgYGBKioqAAAAAAAApqamlpaWAAAAAAAAAAAAAAAAAAAAAAAALi4u/v7+GRkZAAAAAAAAAAAAAAAAAAAAfn5+AAAAAAAAV1dXkJCQAAAAAAAAAQEBAAAAAAAAAAAA7Hz6BAAAAMJ0Uk5TAAIWEwEynNz6//fVkCAatP2fDUHs6cDD8d0mPfT5fiEskiIR584A0gejr3AZ+P4plfALf5ZiTL85a4ziD6697fzN3UYE4v/4TwrNHuT///tdRKZh///+1U/ZBv///yjb///eAVL//50Cocv//6oFBbPvpGZCbfT//7cIhv///8INM///zBEcWYSZmO7//////1P////ts/////8vBv//////gv//R/z///QQz9sevP///2waXhNO/+fc//8mev/5gAe2r90MAAAByUlEQVR4nGNggANGJmYWBpyAlY2dg5OTi5uHF6s0H78AJxRwCAphyguLgKRExcQlQLSkFLq8tAwnp6ycPNABjAqKQKNElVDllVU4OVVhVquJA81Q10BRoAkUUYbJa4Edoo0sr6PLqaePLG/AyWlohKTAmJPTBFnelAFoixmSAnNOTgsUeQZLTk4rJAXWnJw2EHlbiDyDPCenHZICe04HFrh+RydnBgYWPU5uJAWinJwucPNd3dw9GDw5Ob2QFHBzcnrD7ffx9fMPCOTkDEINhmC4+3x8Q0LDwlEDIoKTMzIKKg9SEBIdE8sZh6SAJZ6Tkx0qD1YQkpCYlIwclCng0AXLQxSEpKalZyCryATKZwkhKQjJzsnNQ1KQXwBUUVhUXBJYWgZREFJeUVmFpMKlWg+anmqgCkJq6+obkG1pLEBTENLU3NKKrIKhrb2js8u4G6Kgpze0r3/CRAZMAHbkpJDJU6ZMmTqtFbuC6TNmhsyaMnsOFlmwgrnzpsxfELJwEXZ5Bp/FS3yWLlsesmLlKuwKVk9Ys5Zh3foN0zduwq5g85atDAzbpqSGbN9RhV0FGOzctWH3lD14FOzdt3H/gQw8Cg4u2gQPAwBYDXXdIH+wqAAAAABJRU5ErkJggg=='); - } - - img2.Image? defaultCursorImage = img2.decodePng(base64Decode( - 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARzQklUCAgICHwIZIgAAAFmSURBVFiF7dWxSlxREMbx34QFDRowYBchZSxSCWlMCOwD5FGEFHap06UI7KPsAyyEEIQFqxRaCqYTsqCJFsKkuAeRXb17wrqV918dztw55zszc2fo6Oh47MR/e3zO1/iAHWmznHKGQwx9ip/LEbCfazbsoY8j/JLOhcC6sCW9wsjEwJf483AC9nPNc1+lFRwI13d+l3rYFS799rFGxJMqARv2pBXh+72XQ7gWvklPS7TmMl9Ak/M+DqrENvxAv/guKKApuKPWl0/TROK4+LbSqzhuB+OZ3fRSeFPWY+Fkyn56Y29hfgTSpnQ+s98cvorVey66uPlNFxKwZOYLCGfCs5n9NMYVrsp6mvXSoFqpqYFDvMBkStgJJe93dZOwVXxbqUnBENulydSReqUrDhcX0PT2EXarBYS3GNXMhboinBgIl9K71kg0L3+PvyYGdVpruT2MwrF0iotiXfIwus0Dj+OOjo6Of+e7ab74RkpgAAAAAElFTkSuQmCC')); } class QualityMonitorData { diff --git a/flutter/lib/models/native_model.dart b/flutter/lib/models/native_model.dart index 3af6f4fd7..d29e0fd2c 100644 --- a/flutter/lib/models/native_model.dart +++ b/flutter/lib/models/native_model.dart @@ -97,7 +97,7 @@ class PlatformFFI { : Platform.isWindows ? DynamicLibrary.open('librustdesk.dll') : Platform.isMacOS - ? DynamicLibrary.open('librustdesk.dylib') + ? DynamicLibrary.open("liblibrustdesk.dylib") : DynamicLibrary.process(); debugPrint('initializing FFI $_appType'); try { diff --git a/flutter/lib/models/server_model.dart b/flutter/lib/models/server_model.dart index be3f02b5d..456c3cdd2 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/main.dart'; import 'package:flutter_hbb/models/platform_model.dart'; import 'package:get/get.dart'; import 'package:wakelock/wakelock.dart'; @@ -28,6 +29,7 @@ class ServerModel with ChangeNotifier { bool _audioOk = false; bool _fileOk = false; bool _showElevation = true; + bool _hideCm = false; int _connectStatus = 0; // Rendezvous Server status String _verificationMethod = ""; String _temporaryPasswordLength = ""; @@ -56,6 +58,8 @@ class ServerModel with ChangeNotifier { bool get showElevation => _showElevation; + bool get hideCm => _hideCm; + int get connectStatus => _connectStatus; String get verificationMethod { @@ -74,6 +78,10 @@ class ServerModel with ChangeNotifier { setVerificationMethod(String method) async { await bind.mainSetOption(key: "verification-method", value: method); + if (method != kUsePermanentPassword) { + await bind.mainSetOption( + key: 'allow-hide-cm', value: bool2option('allow-hide-cm', false)); + } } String get temporaryPasswordLength { @@ -90,6 +98,10 @@ class ServerModel with ChangeNotifier { setApproveMode(String mode) async { await bind.mainSetOption(key: 'approve-mode', value: mode); + if (mode != 'password') { + await bind.mainSetOption( + key: 'allow-hide-cm', value: bool2option('allow-hide-cm', false)); + } } TextEditingController get serverId => _serverId; @@ -125,7 +137,11 @@ class ServerModel with ChangeNotifier { } if (!isTest) { - Future.delayed(Duration.zero, timerCallback); + Future.delayed(Duration.zero, () async { + if (await bind.optionSynced()) { + await timerCallback(); + } + }); Timer.periodic(Duration(milliseconds: 500), (timer) async { await timerCallback(); }); @@ -166,6 +182,12 @@ class ServerModel with ChangeNotifier { final temporaryPasswordLength = await bind.mainGetOption(key: "temporary-password-length"); final approveMode = await bind.mainGetOption(key: 'approve-mode'); + var hideCm = option2bool( + 'allow-hide-cm', await bind.mainGetOption(key: 'allow-hide-cm')); + if (!(approveMode == 'password' && + verificationMethod == kUsePermanentPassword)) { + hideCm = false; + } if (_approveMode != approveMode) { _approveMode = approveMode; update = true; @@ -190,6 +212,17 @@ class ServerModel with ChangeNotifier { _temporaryPasswordLength = temporaryPasswordLength; update = true; } + if (_hideCm != hideCm) { + _hideCm = hideCm; + if (desktopType == DesktopType.cm) { + if (hideCm) { + hideCmWindow(); + } else { + showCmWindow(); + } + } + update = true; + } if (update) { notifyListeners(); } @@ -436,11 +469,11 @@ class ServerModel with ChangeNotifier { }, page: desktop.buildConnectionCard(client))); Future.delayed(Duration.zero, () async { - window_on_top(null); + if (!hideCm) window_on_top(null); }); if (client.authorized) { cmHiddenTimer = Timer(const Duration(seconds: 3), () { - windowManager.minimize(); + if (!hideCm) windowManager.minimize(); cmHiddenTimer = null; }); } diff --git a/flutter/macos/Podfile.lock b/flutter/macos/Podfile.lock index 812fbf8b3..952996e5f 100644 --- a/flutter/macos/Podfile.lock +++ b/flutter/macos/Podfile.lock @@ -17,19 +17,21 @@ PODS: - FlutterMacOS - screen_retriever (0.0.1): - FlutterMacOS - - shared_preferences_macos (0.0.1): - - FlutterMacOS - sqflite (0.0.2): - FlutterMacOS - FMDB (>= 2.7.5) - tray_manager (0.0.1): - FlutterMacOS + - uni_links_desktop (0.0.1): + - FlutterMacOS - url_launcher_macos (0.0.1): - FlutterMacOS - wakelock_macos (0.0.1): - FlutterMacOS - window_manager (0.2.0): - FlutterMacOS + - window_size (0.0.2): + - FlutterMacOS DEPENDENCIES: - desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`) @@ -40,12 +42,13 @@ DEPENDENCIES: - package_info_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos`) - path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`) - screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`) - - shared_preferences_macos (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_macos/macos`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) - tray_manager (from `Flutter/ephemeral/.symlinks/plugins/tray_manager/macos`) + - uni_links_desktop (from `Flutter/ephemeral/.symlinks/plugins/uni_links_desktop/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - wakelock_macos (from `Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos`) - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`) + - window_size (from `Flutter/ephemeral/.symlinks/plugins/window_size/macos`) SPEC REPOS: trunk: @@ -68,35 +71,38 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos screen_retriever: :path: Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos - shared_preferences_macos: - :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_macos/macos sqflite: :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos tray_manager: :path: Flutter/ephemeral/.symlinks/plugins/tray_manager/macos + uni_links_desktop: + :path: Flutter/ephemeral/.symlinks/plugins/uni_links_desktop/macos url_launcher_macos: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos wakelock_macos: :path: Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos window_manager: :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos + window_size: + :path: Flutter/ephemeral/.symlinks/plugins/window_size/macos SPEC CHECKSUMS: desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898 desktop_multi_window: 566489c048b501134f9d7fb6a2354c60a9126486 device_info_plus_macos: 1ad388a1ef433505c4038e7dd9605aadd1e2e9c7 flutter_custom_cursor: 629957115075c672287bd0fa979d863ccf6024f7 - FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811 + FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a package_info_plus_macos: f010621b07802a241d96d01876d6705f15e77c1c path_provider_macos: 3c0c3b4b0d4a76d2bf989a913c2de869c5641a19 screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38 - shared_preferences_macos: a64dc611287ed6cbe28fd1297898db1336975727 sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea tray_manager: 9064e219c56d75c476e46b9a21182087930baf90 + uni_links_desktop: 45900fb319df48fcdea2df0756e9c2626696b026 url_launcher_macos: 597e05b8e514239626bcf4a850fcf9ef5c856ec3 wakelock_macos: bc3f2a9bd8d2e6c89fee1e1822e7ddac3bd004a9 window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 + window_size: 339dafa0b27a95a62a843042038fa6c3c48de195 PODFILE CHECKSUM: c7161fcf45d4fd9025dc0f48a76d6e64e52f8176 diff --git a/flutter/macos/Runner.xcodeproj/project.pbxproj b/flutter/macos/Runner.xcodeproj/project.pbxproj index 23549954b..5f369ea9e 100644 --- a/flutter/macos/Runner.xcodeproj/project.pbxproj +++ b/flutter/macos/Runner.xcodeproj/project.pbxproj @@ -26,9 +26,9 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 84010BA8292CF66600152837 /* liblibrustdesk.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 84010BA7292CF66600152837 /* liblibrustdesk.dylib */; settings = {ATTRIBUTES = (Weak, ); }; }; + 84010BA9292CF68300152837 /* liblibrustdesk.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = 84010BA7292CF66600152837 /* liblibrustdesk.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; C5E54335B73C89F72DB1B606 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26C84465887F29AE938039CB /* Pods_Runner.framework */; }; - CC13D44B2847D53E00EF8B54 /* librustdesk.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CC13D4362847C8C200EF8B54 /* librustdesk.dylib */; }; - CC13D4502847D5E800EF8B54 /* librustdesk.dylib in Bundle Framework */ = {isa = PBXBuildFile; fileRef = CC13D4362847C8C200EF8B54 /* librustdesk.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -39,53 +39,18 @@ remoteGlobalIDString = 33CC111A2044C6BA0003C045; remoteInfo = FLX; }; - CC13D4352847C8C200EF8B54 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CC13D42E2847C8C200EF8B54 /* rustdesk.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = CA6071B5A0F5A7A3EF2297AA; - remoteInfo = "librustdesk-cdylib"; - }; - CC13D4372847C8C200EF8B54 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CC13D42E2847C8C200EF8B54 /* rustdesk.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = CA604C7415FB2A3731F5016A; - remoteInfo = "librustdesk-staticlib"; - }; - CC13D4392847C8C200EF8B54 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CC13D42E2847C8C200EF8B54 /* rustdesk.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = CA60D3BC5386D3D7DBD96893; - remoteInfo = "naming-bin"; - }; - CC13D43B2847C8C200EF8B54 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CC13D42E2847C8C200EF8B54 /* rustdesk.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = CA60D3BC5386B357B2AB834F; - remoteInfo = "rustdesk-bin"; - }; - CC13D43D2847C8CB00EF8B54 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CC13D42E2847C8C200EF8B54 /* rustdesk.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = CA6071B5A0F5D6691E4C3FF1; - remoteInfo = "librustdesk-cdylib"; - }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - 33CC110E2044A8840003C045 /* Bundle Framework */ = { + 840109CF292B240500152837 /* Embed Libraries */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( - CC13D4502847D5E800EF8B54 /* librustdesk.dylib in Bundle Framework */, + 84010BA9292CF68300152837 /* liblibrustdesk.dylib in Embed Libraries */, ); - name = "Bundle Framework"; + name = "Embed Libraries"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ @@ -95,7 +60,7 @@ 295AD07E63F13855C270A0E0 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* flutter_hbb.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = flutter_hbb.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* rustdesk.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = rustdesk.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -109,9 +74,9 @@ 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; 7436B85D94E8F7B5A9324869 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 84010BA7292CF66600152837 /* liblibrustdesk.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = liblibrustdesk.dylib; path = ../../target/release/liblibrustdesk.dylib; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; C3BB669FF6190AE1B11BCAEA /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - CC13D42E2847C8C200EF8B54 /* rustdesk.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = rustdesk.xcodeproj; sourceTree = SOURCE_ROOT; }; CCB6FE9A2848A6B800E58D48 /* bridge_generated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bridge_generated.h; path = Runner/bridge_generated.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -120,8 +85,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - CC13D44B2847D53E00EF8B54 /* librustdesk.dylib in Frameworks */, C5E54335B73C89F72DB1B606 /* Pods_Runner.framework in Frameworks */, + 84010BA8292CF66600152837 /* liblibrustdesk.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -154,7 +119,7 @@ 33CC10EE2044A3C60003C045 /* Products */ = { isa = PBXGroup; children = ( - 33CC10ED2044A3C60003C045 /* flutter_hbb.app */, + 33CC10ED2044A3C60003C045 /* rustdesk.app */, ); name = Products; sourceTree = ""; @@ -184,7 +149,6 @@ 33FAB671232836740065AC1E /* Runner */ = { isa = PBXGroup; children = ( - CC13D42E2847C8C200EF8B54 /* rustdesk.xcodeproj */, 33CC10F02044A3C60003C045 /* AppDelegate.swift */, 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, 33E51913231747F40026EE4D /* DebugProfile.entitlements */, @@ -205,20 +169,10 @@ path = Pods; sourceTree = ""; }; - CC13D42F2847C8C200EF8B54 /* Products */ = { - isa = PBXGroup; - children = ( - CC13D4362847C8C200EF8B54 /* librustdesk.dylib */, - CC13D4382847C8C200EF8B54 /* liblibrustdesk_static.a */, - CC13D43A2847C8C200EF8B54 /* naming */, - CC13D43C2847C8C200EF8B54 /* rustdesk */, - ); - name = Products; - sourceTree = ""; - }; D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + 84010BA7292CF66600152837 /* liblibrustdesk.dylib */, 26C84465887F29AE938039CB /* Pods_Runner.framework */, ); name = Frameworks; @@ -235,19 +189,18 @@ 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, - 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + 840109CF292B240500152837 /* Embed Libraries */, 4688A20DD8E4F3E900927B2C /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( - CC13D43E2847C8CB00EF8B54 /* PBXTargetDependency */, 33CC11202044C79F0003C045 /* PBXTargetDependency */, ); name = Runner; productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* flutter_hbb.app */; + productReference = 33CC10ED2044A3C60003C045 /* rustdesk.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -287,12 +240,6 @@ mainGroup = 33CC10E42044A3C60003C045; productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = CC13D42F2847C8C200EF8B54 /* Products */; - ProjectRef = CC13D42E2847C8C200EF8B54 /* rustdesk.xcodeproj */; - }, - ); projectRoot = ""; targets = ( 33CC10EC2044A3C60003C045 /* Runner */, @@ -301,37 +248,6 @@ }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - CC13D4362847C8C200EF8B54 /* librustdesk.dylib */ = { - isa = PBXReferenceProxy; - fileType = "compiled.mach-o.dylib"; - path = librustdesk.dylib; - remoteRef = CC13D4352847C8C200EF8B54 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CC13D4382847C8C200EF8B54 /* liblibrustdesk_static.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = liblibrustdesk_static.a; - remoteRef = CC13D4372847C8C200EF8B54 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CC13D43A2847C8C200EF8B54 /* naming */ = { - isa = PBXReferenceProxy; - fileType = "compiled.mach-o.executable"; - path = naming; - remoteRef = CC13D4392847C8C200EF8B54 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CC13D43C2847C8C200EF8B54 /* rustdesk */ = { - isa = PBXReferenceProxy; - fileType = "compiled.mach-o.executable"; - path = rustdesk; - remoteRef = CC13D43B2847C8C200EF8B54 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - /* Begin PBXResourcesBuildPhase section */ 33CC10EB2044A3C60003C045 /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -442,11 +358,6 @@ target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; }; - CC13D43E2847C8CB00EF8B54 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "librustdesk-cdylib"; - targetProxy = CC13D43D2847C8CB00EF8B54 /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -467,6 +378,7 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = x86_64; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -502,6 +414,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; + ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; @@ -522,6 +435,12 @@ "$(inherited)", "@executable_path/../Frameworks", ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../target/profile, + ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + PRODUCT_BUNDLE_IDENTIFIER = com.carriez.rustdesk; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; }; @@ -540,6 +459,7 @@ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = x86_64; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -579,7 +499,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -593,6 +513,7 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = x86_64; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -626,8 +547,9 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; + ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; @@ -648,6 +570,12 @@ "$(inherited)", "@executable_path/../Frameworks", ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../target/debug, + ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + PRODUCT_BUNDLE_IDENTIFIER = com.carriez.rustdesk; PROVISIONING_PROFILE_SPECIFIER = ""; "SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = Runner/bridge_generated.h; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -669,6 +597,12 @@ "$(inherited)", "@executable_path/../Frameworks", ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../target/release, + ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + PRODUCT_BUNDLE_IDENTIFIER = com.carriez.rustdesk; PROVISIONING_PROFILE_SPECIFIER = ""; "SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = Runner/bridge_generated.h; SWIFT_VERSION = 5.0; diff --git a/flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 85831efcf..898fbe4e7 100644 --- a/flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -15,7 +15,7 @@ @@ -31,7 +31,7 @@ @@ -54,7 +54,7 @@ @@ -71,7 +71,7 @@ diff --git a/flutter/macos/Runner/Info.plist b/flutter/macos/Runner/Info.plist index 8245f21a0..7b985c870 100644 --- a/flutter/macos/Runner/Info.plist +++ b/flutter/macos/Runner/Info.plist @@ -18,16 +18,6 @@ APPL CFBundleShortVersionString $(FLUTTER_BUILD_NAME) - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - $(PRODUCT_COPYRIGHT) - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication CFBundleURLTypes @@ -41,5 +31,15 @@ + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication diff --git a/flutter/macos/Runner/MainFlutterWindow.swift b/flutter/macos/Runner/MainFlutterWindow.swift index 688292371..2ebdf7fc0 100644 --- a/flutter/macos/Runner/MainFlutterWindow.swift +++ b/flutter/macos/Runner/MainFlutterWindow.swift @@ -1,7 +1,22 @@ import Cocoa import FlutterMacOS +import desktop_multi_window // import bitsdojo_window_macos +import desktop_drop +import device_info_plus_macos +import flutter_custom_cursor +import package_info_plus_macos +import path_provider_macos +import screen_retriever +import sqflite +import tray_manager +import uni_links_desktop +import url_launcher_macos +import wakelock_macos +import window_manager +import window_size + class MainFlutterWindow: NSWindow { override func awakeFromNib() { if (!rustdesk_core_main()){ @@ -14,6 +29,22 @@ class MainFlutterWindow: NSWindow { self.setFrame(windowFrame, display: true) RegisterGeneratedPlugins(registry: flutterViewController) + + FlutterMultiWindowPlugin.setOnWindowCreatedCallback { controller in + // Register the plugin which you want access from other isolate. + // DesktopLifecyclePlugin.register(with: controller.registrar(forPlugin: "DesktopLifecyclePlugin")) + DesktopDropPlugin.register(with: controller.registrar(forPlugin: "DesktopDropPlugin")) + DeviceInfoPlusMacosPlugin.register(with: controller.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + FlutterCustomCursorPlugin.register(with: controller.registrar(forPlugin: "FlutterCustomCursorPlugin")) + FLTPackageInfoPlusPlugin.register(with: controller.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) + PathProviderPlugin.register(with: controller.registrar(forPlugin: "PathProviderPlugin")) + SqflitePlugin.register(with: controller.registrar(forPlugin: "SqflitePlugin")) + TrayManagerPlugin.register(with: controller.registrar(forPlugin: "TrayManagerPlugin")) + UniLinksDesktopPlugin.register(with: controller.registrar(forPlugin: "UniLinksDesktopPlugin")) + UrlLauncherPlugin.register(with: controller.registrar(forPlugin: "UrlLauncherPlugin")) + WakelockMacosPlugin.register(with: controller.registrar(forPlugin: "WakelockMacosPlugin")) + WindowSizePlugin.register(with: controller.registrar(forPlugin: "WindowSizePlugin")) + } super.awakeFromNib() } diff --git a/flutter/macos/rustdesk.xcodeproj/project.pbxproj b/flutter/macos/rustdesk.xcodeproj/project.pbxproj index 7aacb5f05..e334f0ac5 100644 --- a/flutter/macos/rustdesk.xcodeproj/project.pbxproj +++ b/flutter/macos/rustdesk.xcodeproj/project.pbxproj @@ -6,37 +6,8 @@ objectVersion = 53; objects = { -/* Begin PBXBuildFile section */ - CA6061C6409F12977AAB839F /* Cargo.toml in Sources */ = {isa = PBXBuildFile; fileRef = CA603C4309E13EF4668187A5 /* Cargo.toml */; settings = {COMPILER_FLAGS = "--lib"; }; }; - CA6061C6409FC858B7409EE3 /* Cargo.toml in Sources */ = {isa = PBXBuildFile; fileRef = CA603C4309E13EF4668187A5 /* Cargo.toml */; settings = {COMPILER_FLAGS = "--bin naming"; }; }; - CA6061C6409FC9FA710A2219 /* Cargo.toml in Sources */ = {isa = PBXBuildFile; fileRef = CA603C4309E13EF4668187A5 /* Cargo.toml */; settings = {COMPILER_FLAGS = "--bin rustdesk"; }; }; - CA6061C6409FD6691E4C3FF1 /* Cargo.toml in Sources */ = {isa = PBXBuildFile; fileRef = CA603C4309E13EF4668187A5 /* Cargo.toml */; settings = {COMPILER_FLAGS = "--lib"; }; }; -/* End PBXBuildFile section */ - -/* Begin PBXBuildRule section */ - CA603C4309E1AC6C1400ACA8 /* PBXBuildRule */ = { - isa = PBXBuildRule; - compilerSpec = com.apple.compilers.proxy.script; - dependencyFile = "$(DERIVED_FILE_DIR)/$(CARGO_XCODE_TARGET_ARCH)-$(EXECUTABLE_NAME).d"; - filePatterns = "*/Cargo.toml"; - fileType = pattern.proxy; - inputFiles = ( - ); - isEditable = 0; - name = "Cargo project build"; - outputFiles = ( - "$(OBJECT_FILE_DIR)/$(CARGO_XCODE_TARGET_ARCH)-$(EXECUTABLE_NAME)", - ); - script = "# generated with cargo-xcode 1.4.1\n\nset -eu; export PATH=$PATH:~/.cargo/bin:/usr/local/bin;\nif [ \"${IS_MACCATALYST-NO}\" = YES ]; then\n CARGO_XCODE_TARGET_TRIPLE=\"${CARGO_XCODE_TARGET_ARCH}-apple-ios-macabi\"\nelse\n CARGO_XCODE_TARGET_TRIPLE=\"${CARGO_XCODE_TARGET_ARCH}-apple-${CARGO_XCODE_TARGET_OS}\"\nfi\nif [ \"$CARGO_XCODE_TARGET_OS\" != \"darwin\" ]; then\n PATH=\"${PATH/\\/Contents\\/Developer\\/Toolchains\\/XcodeDefault.xctoolchain\\/usr\\/bin:/xcode-provided-ld-cant-link-lSystem-for-the-host-build-script:}\"\nfi\nPATH=\"$PATH:/opt/homebrew/bin\" # Rust projects often depend on extra tools like nasm, which Xcode lacks\nif [ \"$CARGO_XCODE_BUILD_MODE\" == release ]; then\n OTHER_INPUT_FILE_FLAGS=\"${OTHER_INPUT_FILE_FLAGS} --release\"\nfi\nif command -v rustup &> /dev/null; then\n if ! rustup target list --installed | egrep -q \"${CARGO_XCODE_TARGET_TRIPLE}\"; then\n echo \"warning: this build requires rustup toolchain for $CARGO_XCODE_TARGET_TRIPLE, but it isn't installed\"\n rustup target add \"${CARGO_XCODE_TARGET_TRIPLE}\" || echo >&2 \"warning: can't install $CARGO_XCODE_TARGET_TRIPLE\"\n fi\nfi\nif [ \"$ACTION\" = clean ]; then\n ( set -x; cargo clean --manifest-path=\"$SCRIPT_INPUT_FILE\" ${OTHER_INPUT_FILE_FLAGS} --target=\"${CARGO_XCODE_TARGET_TRIPLE}\"; );\nelse\n ( set -x; cargo build --manifest-path=\"$SCRIPT_INPUT_FILE\" --features=\"${CARGO_XCODE_FEATURES:-}\" ${OTHER_INPUT_FILE_FLAGS} --target=\"${CARGO_XCODE_TARGET_TRIPLE}\"; );\nfi\n# it's too hard to explain Cargo's actual exe path to Xcode build graph, so hardlink to a known-good path instead\nBUILT_SRC=\"${CARGO_TARGET_DIR}/${CARGO_XCODE_TARGET_TRIPLE}/${CARGO_XCODE_BUILD_MODE}/${CARGO_XCODE_CARGO_FILE_NAME}\"\nln -f -- \"$BUILT_SRC\" \"$SCRIPT_OUTPUT_FILE_0\"\n\n# xcode generates dep file, but for its own path, so append our rename to it\nDEP_FILE_SRC=\"${CARGO_TARGET_DIR}/${CARGO_XCODE_TARGET_TRIPLE}/${CARGO_XCODE_BUILD_MODE}/${CARGO_XCODE_CARGO_DEP_FILE_NAME}\"\nif [ -f \"$DEP_FILE_SRC\" ]; then\n DEP_FILE_DST=\"${DERIVED_FILE_DIR}/${CARGO_XCODE_TARGET_ARCH}-${EXECUTABLE_NAME}.d\"\n cp -f \"$DEP_FILE_SRC\" \"$DEP_FILE_DST\"\n echo >> \"$DEP_FILE_DST\" \"$SCRIPT_OUTPUT_FILE_0: $BUILT_SRC\"\nfi\n\n# lipo script needs to know all the platform-specific files that have been built\n# archs is in the file name, so that paths don't stay around after archs change\n# must match input for LipoScript\nFILE_LIST=\"${DERIVED_FILE_DIR}/${ARCHS}-${EXECUTABLE_NAME}.xcfilelist\"\ntouch \"$FILE_LIST\"\nif ! egrep -q \"$SCRIPT_OUTPUT_FILE_0\" \"$FILE_LIST\" ; then\n echo >> \"$FILE_LIST\" \"$SCRIPT_OUTPUT_FILE_0\"\nfi\n"; - }; -/* End PBXBuildRule section */ - /* Begin PBXFileReference section */ ADDEDBA66A6E1 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; }; - CA604C7415FB2A3731F5016A /* liblibrustdesk_static.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = liblibrustdesk_static.a; sourceTree = BUILT_PRODUCTS_DIR; }; - CA6071B5A0F5A7A3EF2297AA /* librustdesk.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = librustdesk.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; - CA60D3BC5386B357B2AB834F /* rustdesk */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = rustdesk; sourceTree = BUILT_PRODUCTS_DIR; }; - CA60D3BC5386D3D7DBD96893 /* naming */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = naming; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXGroup section */ @@ -51,10 +22,6 @@ CA603C4309E122869D176AE5 /* Products */ = { isa = PBXGroup; children = ( - CA6071B5A0F5A7A3EF2297AA /* librustdesk.dylib */, - CA604C7415FB2A3731F5016A /* liblibrustdesk_static.a */, - CA60D3BC5386D3D7DBD96893 /* naming */, - CA60D3BC5386B357B2AB834F /* rustdesk */, ); name = Products; sourceTree = ""; @@ -70,7 +37,6 @@ CA603C4309E1D65BC3C892A8 = { isa = PBXGroup; children = ( - CA603C4309E13EF4668187A5 /* Cargo.toml */, CA603C4309E122869D176AE5 /* Products */, CA603C4309E198AF0B5890DB /* Frameworks */, ); @@ -78,100 +44,11 @@ }; /* End PBXGroup section */ -/* Begin PBXNativeTarget section */ - CA604C7415FB12977AAB839F /* librustdesk-staticlib */ = { - isa = PBXNativeTarget; - buildConfigurationList = CA6028B9540B12977AAB839F /* Build configuration list for PBXNativeTarget "librustdesk-staticlib" */; - buildPhases = ( - CA6033723F8212977AAB839F /* Sources */, - CA603C4309E1AF6EBB7F357C /* Universal Binary lipo */, - ); - buildRules = ( - CA603C4309E1AC6C1400ACA8 /* PBXBuildRule */, - ); - dependencies = ( - ); - name = "librustdesk-staticlib"; - productName = liblibrustdesk_static.a; - productReference = CA604C7415FB2A3731F5016A /* liblibrustdesk_static.a */; - productType = "com.apple.product-type.library.static"; - }; - CA6071B5A0F5D6691E4C3FF1 /* librustdesk-cdylib */ = { - isa = PBXNativeTarget; - buildConfigurationList = CA6028B9540BD6691E4C3FF1 /* Build configuration list for PBXNativeTarget "librustdesk-cdylib" */; - buildPhases = ( - CA6033723F82D6691E4C3FF1 /* Sources */, - CA603C4309E1AF6EBB7F357C /* Universal Binary lipo */, - ); - buildRules = ( - CA603C4309E1AC6C1400ACA8 /* PBXBuildRule */, - ); - dependencies = ( - ); - name = "librustdesk-cdylib"; - productName = librustdesk.dylib; - productReference = CA6071B5A0F5A7A3EF2297AA /* librustdesk.dylib */; - productType = "com.apple.product-type.library.dynamic"; - }; - CA60D3BC5386C858B7409EE3 /* naming-bin */ = { - isa = PBXNativeTarget; - buildConfigurationList = CA6028B9540BC858B7409EE3 /* Build configuration list for PBXNativeTarget "naming-bin" */; - buildPhases = ( - CA6033723F82C858B7409EE3 /* Sources */, - CA603C4309E1AF6EBB7F357C /* Universal Binary lipo */, - ); - buildRules = ( - CA603C4309E1AC6C1400ACA8 /* PBXBuildRule */, - ); - dependencies = ( - ); - name = "naming-bin"; - productName = naming; - productReference = CA60D3BC5386D3D7DBD96893 /* naming */; - productType = "com.apple.product-type.tool"; - }; - CA60D3BC5386C9FA710A2219 /* rustdesk-bin */ = { - isa = PBXNativeTarget; - buildConfigurationList = CA6028B9540BC9FA710A2219 /* Build configuration list for PBXNativeTarget "rustdesk-bin" */; - buildPhases = ( - CA6033723F82C9FA710A2219 /* Sources */, - CA603C4309E1AF6EBB7F357C /* Universal Binary lipo */, - ); - buildRules = ( - CA603C4309E1AC6C1400ACA8 /* PBXBuildRule */, - ); - dependencies = ( - ); - name = "rustdesk-bin"; - productName = rustdesk; - productReference = CA60D3BC5386B357B2AB834F /* rustdesk */; - productType = "com.apple.product-type.tool"; - }; -/* End PBXNativeTarget section */ - /* Begin PBXProject section */ CA603C4309E1E04653AD465F /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 1300; - TargetAttributes = { - CA604C7415FB12977AAB839F = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Automatic; - }; - CA6071B5A0F5D6691E4C3FF1 = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Automatic; - }; - CA60D3BC5386C858B7409EE3 = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Automatic; - }; - CA60D3BC5386C9FA710A2219 = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Automatic; - }; - }; }; buildConfigurationList = CA603C4309E180E02D6C7F57 /* Build configuration list for PBXProject "rustdesk" */; compatibilityVersion = "Xcode 11.4"; @@ -186,161 +63,11 @@ projectDirPath = ""; projectRoot = ""; targets = ( - CA6071B5A0F5D6691E4C3FF1 /* librustdesk-cdylib */, - CA604C7415FB12977AAB839F /* librustdesk-staticlib */, - CA60D3BC5386C858B7409EE3 /* naming-bin */, - CA60D3BC5386C9FA710A2219 /* rustdesk-bin */, ); }; /* End PBXProject section */ -/* Begin PBXShellScriptBuildPhase section */ - CA603C4309E1AF6EBB7F357C /* Universal Binary lipo */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "$(DERIVED_FILE_DIR)/$(ARCHS)-$(EXECUTABLE_NAME).xcfilelist", - ); - name = "Universal Binary lipo"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "# generated with cargo-xcode 1.4.1\nset -eux; cat \"$DERIVED_FILE_DIR/$ARCHS-$EXECUTABLE_NAME.xcfilelist\" | tr '\\n' '\\0' | xargs -0 lipo -create -output \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\""; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - CA6033723F8212977AAB839F /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CA6061C6409F12977AAB839F /* Cargo.toml in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CA6033723F82C858B7409EE3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CA6061C6409FC858B7409EE3 /* Cargo.toml in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CA6033723F82C9FA710A2219 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CA6061C6409FC9FA710A2219 /* Cargo.toml in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CA6033723F82D6691E4C3FF1 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CA6061C6409FD6691E4C3FF1 /* Cargo.toml in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - /* Begin XCBuildConfiguration section */ - CA604B55B26012977AAB839F /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CARGO_XCODE_CARGO_DEP_FILE_NAME = liblibrustdesk.d; - CARGO_XCODE_CARGO_FILE_NAME = liblibrustdesk.a; - INSTALL_GROUP = ""; - INSTALL_MODE_FLAG = ""; - INSTALL_OWNER = ""; - PRODUCT_NAME = librustdesk_static; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos appletvsimulator appletvos"; - }; - name = Debug; - }; - CA604B55B260C858B7409EE3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CARGO_XCODE_CARGO_DEP_FILE_NAME = naming.d; - CARGO_XCODE_CARGO_FILE_NAME = naming; - PRODUCT_NAME = naming; - SUPPORTED_PLATFORMS = macosx; - }; - name = Debug; - }; - CA604B55B260C9FA710A2219 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CARGO_XCODE_CARGO_DEP_FILE_NAME = rustdesk.d; - CARGO_XCODE_CARGO_FILE_NAME = rustdesk; - PRODUCT_NAME = rustdesk; - SUPPORTED_PLATFORMS = macosx; - }; - name = Debug; - }; - CA604B55B260D6691E4C3FF1 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CARGO_XCODE_CARGO_DEP_FILE_NAME = liblibrustdesk.d; - CARGO_XCODE_CARGO_FILE_NAME = liblibrustdesk.dylib; - PRODUCT_NAME = librustdesk; - SUPPORTED_PLATFORMS = macosx; - }; - name = Debug; - }; - CA60583BB9CE12977AAB839F /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CARGO_XCODE_CARGO_DEP_FILE_NAME = liblibrustdesk.d; - CARGO_XCODE_CARGO_FILE_NAME = liblibrustdesk.a; - INSTALL_GROUP = ""; - INSTALL_MODE_FLAG = ""; - INSTALL_OWNER = ""; - PRODUCT_NAME = librustdesk_static; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos appletvsimulator appletvos"; - }; - name = Release; - }; - CA60583BB9CEC858B7409EE3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CARGO_XCODE_CARGO_DEP_FILE_NAME = naming.d; - CARGO_XCODE_CARGO_FILE_NAME = naming; - PRODUCT_NAME = naming; - SUPPORTED_PLATFORMS = macosx; - }; - name = Release; - }; - CA60583BB9CEC9FA710A2219 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CARGO_XCODE_CARGO_DEP_FILE_NAME = rustdesk.d; - CARGO_XCODE_CARGO_FILE_NAME = rustdesk; - PRODUCT_NAME = rustdesk; - SUPPORTED_PLATFORMS = macosx; - }; - name = Release; - }; - CA60583BB9CED6691E4C3FF1 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CARGO_XCODE_CARGO_DEP_FILE_NAME = liblibrustdesk.d; - CARGO_XCODE_CARGO_FILE_NAME = liblibrustdesk.dylib; - PRODUCT_NAME = librustdesk; - SUPPORTED_PLATFORMS = macosx; - }; - name = Release; - }; CA608F3F78EE228BE02872F8 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -387,42 +114,6 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - CA6028B9540B12977AAB839F /* Build configuration list for PBXNativeTarget "librustdesk-staticlib" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CA60583BB9CE12977AAB839F /* Release */, - CA604B55B26012977AAB839F /* Debug */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - CA6028B9540BC858B7409EE3 /* Build configuration list for PBXNativeTarget "naming-bin" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CA60583BB9CEC858B7409EE3 /* Release */, - CA604B55B260C858B7409EE3 /* Debug */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - CA6028B9540BC9FA710A2219 /* Build configuration list for PBXNativeTarget "rustdesk-bin" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CA60583BB9CEC9FA710A2219 /* Release */, - CA604B55B260C9FA710A2219 /* Debug */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - CA6028B9540BD6691E4C3FF1 /* Build configuration list for PBXNativeTarget "librustdesk-cdylib" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CA60583BB9CED6691E4C3FF1 /* Release */, - CA604B55B260D6691E4C3FF1 /* Debug */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; CA603C4309E180E02D6C7F57 /* Build configuration list for PBXProject "rustdesk" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index 432b15b15..738567b22 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -5,253 +5,260 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "49.0.0" + version: "50.0.0" after_layout: dependency: transitive description: name: after_layout - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "5.1.0" + version: "5.2.0" animations: dependency: transitive description: name: animations - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.7" archive: dependency: transitive description: name: archive - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.3.1" + version: "3.3.4" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.1" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.9.0" auto_size_text: dependency: "direct main" description: name: auto_size_text - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.0" back_button_interceptor: dependency: "direct main" description: name: back_button_interceptor - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "6.0.1" + version: "6.0.2" + bot_toast: + dependency: "direct main" + description: + name: bot_toast + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.0.3" build: dependency: transitive description: name: build - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.1" build_config: dependency: transitive description: name: build_config - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.0" + version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.0" build_resolvers: dependency: transitive description: name: build_resolvers - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.10" build_runner: dependency: "direct dev" description: name: build_runner - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.2.1" + version: "2.3.2" build_runner_core: dependency: transitive description: name: build_runner_core - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "7.2.4" + version: "7.2.7" built_collection: dependency: transitive description: name: built_collection - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "5.1.1" built_value: dependency: transitive description: name: built_value - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "8.4.1" + version: "8.4.2" cached_network_image: dependency: transitive description: name: cached_network_image - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.2.1" cached_network_image_platform_interface: dependency: transitive description: name: cached_network_image_platform_interface - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" cached_network_image_web: dependency: transitive description: name: cached_network_image_web - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" charcode: dependency: transitive description: name: charcode - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.1" checked_yaml: dependency: transitive description: name: checked_yaml - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.1" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" code_builder: dependency: transitive description: name: code_builder - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.3.0" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.16.0" contextmenu: dependency: "direct main" description: name: contextmenu - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.0" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.0.2" + version: "3.1.0" cross_file: dependency: transitive description: name: cross_file - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.3.3+2" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.2" csslib: dependency: transitive description: name: csslib - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.17.2" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.5" dart_style: dependency: transitive description: name: dart_style - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.4" dash_chat_2: dependency: "direct main" description: name: dash_chat_2 - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.0.15" desktop_drop: dependency: "direct main" description: name: desktop_drop - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.3.3" desktop_multi_window: dependency: "direct main" description: path: "." - ref: bf278fc8a8ff787e46fa3ab97674373bfaa20f23 - resolved-ref: bf278fc8a8ff787e46fa3ab97674373bfaa20f23 + ref: "8ee8eb59cabf6ac83a13fe002de7d4a231263a58" + resolved-ref: "8ee8eb59cabf6ac83a13fe002de7d4a231263a58" url: "https://github.com/Kingtous/rustdesk_desktop_multi_window" source: git version: "0.1.0" @@ -259,91 +266,91 @@ packages: dependency: "direct main" description: name: device_info_plus - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.1.3" device_info_plus_linux: dependency: transitive description: name: device_info_plus_linux - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.0" device_info_plus_macos: dependency: transitive description: name: device_info_plus_macos - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.0" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.0" device_info_plus_web: dependency: transitive description: name: device_info_plus_web - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.0" device_info_plus_windows: dependency: transitive description: name: device_info_plus_windows - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.1.0" draggable_float_widget: dependency: "direct main" description: name: draggable_float_widget - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.0.2" event_bus: dependency: transitive description: name: event_bus - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" external_path: dependency: "direct main" description: name: external_path - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.3" ffi: dependency: "direct main" description: name: ffi - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.1" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "6.1.4" file_picker: dependency: "direct main" description: name: file_picker - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "5.2.1" + version: "5.2.2" fixnum: dependency: transitive description: name: fixnum - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.1" flutter: @@ -355,29 +362,29 @@ packages: dependency: transitive description: name: flutter_blurhash - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.7.0" flutter_breadcrumb: dependency: "direct main" description: name: flutter_breadcrumb - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.1" flutter_cache_manager: dependency: transitive description: name: flutter_cache_manager - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.3.0" flutter_custom_cursor: dependency: "direct main" description: path: "." - ref: dec2166e881c47d922e1edc484d10d2cd5c2103b - resolved-ref: dec2166e881c47d922e1edc484d10d2cd5c2103b + ref: bfb19c84a8244771488bc05cc5f9c9b5e0324cfd + resolved-ref: bfb19c84a8244771488bc05cc5f9c9b5e0324cfd url: "https://github.com/Kingtous/rustdesk_flutter_custom_cursor" source: git version: "0.0.1" @@ -385,14 +392,14 @@ packages: dependency: "direct main" description: name: flutter_improved_scrolling - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.0.3" flutter_lints: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.1" flutter_localizations: @@ -404,14 +411,14 @@ packages: dependency: transitive description: name: flutter_parsed_text - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.1" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.7" flutter_rust_bridge: @@ -427,9 +434,9 @@ packages: dependency: "direct main" description: name: flutter_svg - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.5" + version: "1.1.6" flutter_web_plugins: dependency: transitive description: flutter @@ -439,408 +446,415 @@ packages: dependency: "direct dev" description: name: freezed - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.1" + version: "2.2.1" freezed_annotation: dependency: "direct main" description: name: freezed_annotation - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.0" + version: "2.2.0" frontend_server_client: dependency: transitive description: name: frontend_server_client - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.3" + version: "3.1.0" get: dependency: "direct main" description: name: get - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.6.5" glob: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.0" + version: "2.1.1" graphs: dependency: transitive description: name: graphs - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.0" + version: "2.2.0" html: dependency: transitive description: name: html - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "0.15.0" + version: "0.15.1" http: dependency: "direct main" description: name: http - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.13.5" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "4.0.1" + version: "4.0.2" icons_launcher: dependency: "direct dev" description: name: icons_launcher - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.4" image: dependency: "direct main" description: name: image - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.2.0" + version: "3.2.2" image_picker: dependency: "direct main" description: name: image_picker - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.8.6" image_picker_android: dependency: transitive description: name: image_picker_android - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.8.5+3" image_picker_for_web: dependency: transitive description: name: image_picker_for_web - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.10" image_picker_ios: dependency: transitive description: name: image_picker_ios - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.8.6+1" image_picker_platform_interface: dependency: transitive description: name: image_picker_platform_interface - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.6.2" intl: dependency: transitive description: name: intl - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.17.0" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.3" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.6.4" json_annotation: dependency: transitive description: name: json_annotation - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.7.0" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.0" + version: "2.0.1" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.12.12" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.1.4" menu_base: dependency: transitive description: name: menu_base - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.1.1" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.7.0" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.2" nested: dependency: transitive description: name: nested - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" octo_image: dependency: transitive description: name: octo_image - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.2" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" package_info_plus: dependency: "direct main" description: name: package_info_plus - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.4.3+1" package_info_plus_linux: dependency: transitive description: name: package_info_plus_linux - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.5" package_info_plus_macos: dependency: transitive description: name: package_info_plus_macos - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.0" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.2" package_info_plus_web: dependency: transitive description: name: package_info_plus_web - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.6" package_info_plus_windows: dependency: transitive description: name: package_info_plus_windows - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" path: dependency: "direct main" description: name: path - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.8.1" path_drawing: dependency: transitive description: name: path_drawing - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.1" path_parsing: dependency: transitive description: name: path_parsing - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.1" path_provider: dependency: "direct main" description: name: path_provider - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.11" path_provider_android: dependency: transitive description: name: path_provider_android - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.20" + version: "2.0.21" path_provider_ios: dependency: transitive description: name: path_provider_ios - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.11" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.7" path_provider_macos: dependency: transitive description: name: path_provider_macos - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.6" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.5" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.3" pedantic: dependency: transitive description: name: pedantic - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.11.1" petitparser: dependency: transitive description: name: petitparser - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "5.0.0" platform: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.3" + pointycastle: + dependency: transitive + description: + name: pointycastle + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.6.2" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.5.1" process: dependency: transitive description: name: process - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.2.4" provider: dependency: "direct main" description: name: provider - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "6.0.3" + version: "6.0.4" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.1" + version: "2.1.3" pubspec_parse: dependency: transitive description: name: pubspec_parse - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.1" qr_code_scanner: dependency: "direct main" description: name: qr_code_scanner - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.1" rxdart: dependency: "direct main" description: name: rxdart - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "0.27.5" + version: "0.27.7" screen_retriever: dependency: transitive description: @@ -854,91 +868,35 @@ packages: dependency: "direct main" description: name: scroll_pos - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.3.0" settings_ui: dependency: "direct main" description: name: settings_ui - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.2" - shared_preferences: - dependency: "direct main" - description: - name: shared_preferences - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.15" - shared_preferences_android: - dependency: transitive - description: - name: shared_preferences_android - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.13" - shared_preferences_ios: - dependency: transitive - description: - name: shared_preferences_ios - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" - shared_preferences_linux: - dependency: transitive - description: - name: shared_preferences_linux - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" - shared_preferences_macos: - dependency: transitive - description: - name: shared_preferences_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.4" - shared_preferences_platform_interface: - dependency: transitive - description: - name: shared_preferences_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - shared_preferences_web: - dependency: transitive - description: - name: shared_preferences_web - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.4" - shared_preferences_windows: - dependency: transitive - description: - name: shared_preferences_windows - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.4.0" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.2" + version: "1.0.3" shortid: dependency: transitive description: name: shortid - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.1.2" sky_engine: @@ -950,84 +908,84 @@ packages: dependency: transitive description: name: source_gen - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.5" + version: "1.2.6" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.9.1" sqflite: dependency: transitive description: name: sqflite - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.3+1" sqflite_common: dependency: transitive description: name: sqflite_common - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.3.0" + version: "2.4.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.1" stream_transform: dependency: transitive description: name: stream_transform - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.1" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.1" synchronized: dependency: transitive description: name: synchronized - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.0+3" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.1" timing: dependency: transitive description: name: timing - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" toggle_switch: dependency: "direct main" description: name: toggle_switch - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.4.0" tray_manager: @@ -1043,232 +1001,234 @@ packages: dependency: "direct main" description: name: tuple - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.1" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.1" uni_links: dependency: "direct main" description: name: uni_links - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.5.1" uni_links_desktop: dependency: "direct main" description: - name: uni_links_desktop - url: "https://pub.dartlang.org" - source: hosted + path: "." + ref: "5be5113d59c753989dbf1106241379e3fd4c9b18" + resolved-ref: "5be5113d59c753989dbf1106241379e3fd4c9b18" + url: "https://github.com/fufesou/uni_links_desktop.git" + source: git version: "0.1.3" uni_links_platform_interface: dependency: transitive description: name: uni_links_platform_interface - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" uni_links_web: dependency: transitive description: name: uni_links_web - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.1.0" universal_io: dependency: transitive description: name: universal_io - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.4" url_launcher: dependency: "direct main" description: name: url_launcher - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "6.1.6" url_launcher_android: dependency: transitive description: name: url_launcher_android - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "6.0.19" + version: "6.0.21" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "6.0.17" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.1" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.1" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.1" url_launcher_web: dependency: transitive description: name: url_launcher_web - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.13" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.1" uuid: dependency: transitive description: name: uuid - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.0.6" + version: "3.0.7" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.2" video_player: dependency: transitive description: name: video_player - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.7" video_player_android: dependency: transitive description: name: video_player_android - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.9" video_player_avfoundation: dependency: transitive description: name: video_player_avfoundation - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.7" video_player_platform_interface: dependency: transitive description: name: video_player_platform_interface - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "5.1.4" video_player_web: dependency: transitive description: name: video_player_web - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.12" visibility_detector: dependency: "direct main" description: name: visibility_detector - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.3.3" wakelock: dependency: "direct main" description: name: wakelock - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.6.2" wakelock_macos: dependency: transitive description: name: wakelock_macos - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.4.0" wakelock_platform_interface: dependency: transitive description: name: wakelock_platform_interface - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.3.0" wakelock_web: dependency: transitive description: name: wakelock_web - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.4.0" wakelock_windows: dependency: transitive description: name: wakelock_windows - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.1" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.1" + version: "1.0.2" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.0" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.0.0" + version: "3.1.1" win32_registry: dependency: transitive description: name: win32_registry - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.2" window_manager: dependency: "direct main" description: path: "." - ref: "88487257cbafc501599ab4f82ec343b46acec020" - resolved-ref: "88487257cbafc501599ab4f82ec343b46acec020" + ref: "32b24c66151b72bba033ef8b954486aa9351d97b" + resolved-ref: "32b24c66151b72bba033ef8b954486aa9351d97b" url: "https://github.com/Kingtous/rustdesk_window_manager" source: git version: "0.2.7" @@ -1285,28 +1245,28 @@ packages: dependency: transitive description: name: xdg_directories - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.0+2" xml: dependency: transitive description: name: xml - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "6.1.0" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.1" zxing2: dependency: "direct main" description: name: zxing2 - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.1.0" sdks: diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index f4b6661b4..f476816ef 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -9,8 +9,10 @@ use std::{ use anyhow::Result; use rand::Rng; +use regex::Regex; use serde as de; use serde_derive::{Deserialize, Serialize}; +use sodiumoxide::base64; use sodiumoxide::crypto::sign; use crate::{ @@ -199,10 +201,7 @@ pub struct PeerConfig { pub show_quality_monitor: bool, // The other scalar value must before this - #[serde( - default, - deserialize_with = "PeerConfig::deserialize_options" - )] + #[serde(default, deserialize_with = "PeerConfig::deserialize_options")] pub options: HashMap, // Various data for flutter ui #[serde(default)] @@ -896,7 +895,17 @@ impl PeerConfig { } fn path(id: &str) -> PathBuf { - let path: PathBuf = [PEERS, id].iter().collect(); + let id_encoded: String; + + //If the id contains invalid chars, encode it + let forbidden_paths = Regex::new(r".*[<>:/\\|\?\*].*").unwrap(); + if forbidden_paths.is_match(id) { + id_encoded = + "base64_".to_string() + base64::encode(id, base64::Variant::Original).as_str(); + } else { + id_encoded = id.to_string(); + } + let path: PathBuf = [PEERS, id_encoded.as_str()].iter().collect(); Config::with_extension(Config::path(path)) } @@ -919,11 +928,22 @@ impl PeerConfig { .map(|p| p.to_str().unwrap_or("")) .unwrap_or("") .to_owned(); - let c = PeerConfig::load(&id); + + let id_decoded_string: String; + if id.starts_with("base64_") && id.len() != 7 { + let id_decoded = base64::decode(&id[7..], base64::Variant::Original) + .unwrap_or(Vec::new()); + id_decoded_string = + String::from_utf8_lossy(&id_decoded).as_ref().to_owned(); + } else { + id_decoded_string = id; + } + + let c = PeerConfig::load(&id_decoded_string); if c.info.platform.is_empty() { fs::remove_file(&p).ok(); } - (id, t, c) + (id_decoded_string, t, c) }) .filter(|p| !p.2.info.platform.is_empty()) .collect(); @@ -934,9 +954,21 @@ impl PeerConfig { Default::default() } - serde_field_string!(default_view_style, deserialize_view_style, "original".to_owned()); - serde_field_string!(default_scroll_style, deserialize_scroll_style, "scrollauto".to_owned()); - serde_field_string!(default_image_quality, deserialize_image_quality, "balanced".to_owned()); + serde_field_string!( + default_view_style, + deserialize_view_style, + "original".to_owned() + ); + serde_field_string!( + default_scroll_style, + deserialize_scroll_style, + "scrollauto".to_owned() + ); + serde_field_string!( + default_image_quality, + deserialize_image_quality, + "balanced".to_owned() + ); fn deserialize_options<'de, D>(deserializer: D) -> Result, D::Error> where diff --git a/libs/hbb_common/src/password_security.rs b/libs/hbb_common/src/password_security.rs index adaafebb3..602906990 100644 --- a/libs/hbb_common/src/password_security.rs +++ b/libs/hbb_common/src/password_security.rs @@ -76,6 +76,12 @@ pub fn approve_mode() -> ApproveMode { } } +pub fn hide_cm() -> bool { + approve_mode() == ApproveMode::Password + && verification_method() == VerificationMethod::OnlyUsePermanentPassword + && !Config::get_option("allow-hide-cm").is_empty() +} + const VERSION_LEN: usize = 2; pub fn encrypt_str_or_original(s: &str, version: &str) -> String { diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index ea33290fe..00f9b51e6 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -1098,6 +1098,10 @@ pub fn version_to_number(v: String) -> i64 { hbb_common::get_version_number(&v) } +pub fn option_synced() -> bool { + crate::ui_interface::option_synced() +} + pub fn main_is_installed() -> SyncReturn { SyncReturn(is_installed()) } diff --git a/src/lang/ca.rs b/src/lang/ca.rs index f5684b4c4..0dd21e168 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -394,5 +394,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 7256c5d1f..a3b3b47c8 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", "使用一次性密码"), ("One-time password length", "一次性密码长度"), ("Request access to your device", "请求访问你的设备"), + ("Hide connection management window", "隐藏连接管理窗口"), + ("hide_cm_tip", "在只允许密码连接并且只用固定密码的情况下才允许隐藏"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 63fac7288..450f3971a 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 4278cdc20..ea7263ac8 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 5d82f84d1..61a25c25e 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -3,7 +3,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = [ ("Status", "Status"), ("Your Desktop", "Ihr Desktop"), - ("desk_tip", "Mit dieser ID und diesem Passwort können Sie auf Ihren Desktop zugreifen."), + ("desk_tip", "Mit dieser ID und diesem Passwort kann auf Ihren Desktop zugegriffen werden."), ("Password", "Passwort"), ("Ready", "Bereit"), ("Established", "Verbunden"), @@ -12,7 +12,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Start Service", "Starte Vermittlungsdienst"), ("Service is running", "Vermittlungsdienst aktiv"), ("Service is not running", "Vermittlungsdienst deaktiviert"), - ("not_ready_status", "Nicht bereit. Bitte überprüfen Sie Ihre Verbindung"), + ("not_ready_status", "Nicht bereit. Bitte überprüfen Sie Ihre Netzwerkverbindung"), ("Control Remote Desktop", "Entfernten PC steuern"), ("Transfer File", "Datei übertragen"), ("Connect", "Verbinden"), @@ -30,9 +30,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("IP Whitelisting", "IP-Whitelist"), ("ID/Relay Server", "ID/Vermittlungsserver"), ("Import Server Config", "Serverkonfiguration importieren"), - ("Export Server Config", ""), + ("Export Server Config", "Serverkonfiguration exportieren"), ("Import server configuration successfully", "Serverkonfiguration erfolgreich importiert"), - ("Export server configuration successfully", ""), + ("Export server configuration successfully", "Serverkonfiguration erfolgreich exportiert"), ("Invalid server configuration", "Ungültige Serverkonfiguration"), ("Clipboard is empty", "Zwischenablage ist leer"), ("Stop service", "Vermittlungsdienst deaktivieren"), @@ -67,12 +67,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...", "Verbinden..."), + ("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...", "Verbunden, warte auf Bild..."), + ("Connected, waiting for image...", "Verbindung hergestellt. Warten auf Bild..."), ("Name", "Name"), ("Type", "Typ"), ("Modified", "Geändert"), @@ -89,15 +89,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Delete", "Löschen"), ("Properties", "Eigenschaften"), ("Multi Select", "Mehrfachauswahl"), - ("Select All", ""), - ("Unselect All", ""), + ("Select All", "Alles auswählen"), + ("Unselect All", "Alles abwählen"), ("Empty Directory", "Leerer Ordner"), ("Not an empty directory", "Ordner ist nicht leer"), ("Are you sure you want to delete this file?", "Sind Sie sicher, dass Sie diese Datei löschen wollen?"), ("Are you sure you want to delete this empty directory?", "Sind Sie sicher, dass Sie diesen leeren Ordner löschen möchten?"), ("Are you sure you want to delete the file of this directory?", "Sind Sie sicher, dass Sie die Datei dieses Ordners löschen möchten?"), ("Do this for all conflicts", "Für alle Konflikte merken"), - ("This is irreversible!", "Dies ist irreversibel!"), + ("This is irreversible!", "Dies kann nicht rückgängig gemacht werden!"), ("Deleting", "Löschen"), ("files", "Dateien"), ("Waiting", "Warten"), @@ -113,14 +113,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stretch", "Strecken"), ("Scrollbar", "Scrollleiste"), ("ScrollAuto", "Automatisch scrollen"), - ("Good image quality", "Qualität"), + ("Good image quality", "Hohe Bildqualität"), ("Balanced", "Ausgeglichen"), ("Optimize reaction time", "Geschwindigkeit"), - ("Custom", ""), + ("Custom", "Individuell"), ("Show remote cursor", "Entfernten Cursor anzeigen"), ("Show quality monitor", "Qualitätsüberwachung anzeigen"), ("Disable clipboard", "Zwischenablage deaktivieren"), - ("Lock after session end", "Sperren nach Sitzungsende"), + ("Lock after session end", "Nach Sitzungsende sperren"), ("Insert", "Einfügen"), ("Insert Lock", "Win+L (Sperren) senden"), ("Refresh", "Aktualisieren"), @@ -136,7 +136,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Failed to make direct connection to remote desktop", "Direkte Verbindung zum entfernten PC fehlgeschlagen"), ("Set Password", "Passwort festlegen"), ("OS Password", "Betriebssystem-Passwort"), - ("install_tip", "Aufgrund der UAC kann RustDesk in manchen Fällen nicht ordnungsgemäß funktionieren. Um UAC zu vermeiden, klicken Sie bitte auf die Schaltfläche unten, um RustDesk auf dem System zu installieren"), + ("install_tip", "Aufgrund der Benutzerkontensteuerung (UAC) kann RustDesk in manchen Fällen nicht ordnungsgemäß funktionieren. Um die Benutzerkontensteuerung zu umgehen, klicken Sie bitte auf die Schaltfläche unten, um RustDesk auf dem System zu installieren"), ("Click to upgrade", "Zum Aktualisieren anklicken"), ("Click to download", "Zum Herunterladen klicken"), ("Click to update", "Zum Aktualisieren klicken"), @@ -161,11 +161,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Action", "Aktion"), ("Add", "Hinzufügen"), ("Local Port", "Lokaler Port"), - ("Local Address", "Lokale ddresse"), + ("Local Address", "Lokale Addresse"), ("Change Local Port", "Lokalen Port ändern"), ("setup_server_tip", "Für eine schnellere Verbindung richten Sie bitte Ihren eigenen Verbindungsserver ein"), ("Too short, at least 6 characters.", "Zu kurz, mindestens 6 Zeichen."), - ("The confirmation is not identical.", "Die Passwörter sind nicht identisch."), + ("The confirmation is not identical.", "Die Passwörter stimmen nicht überein."), ("Permissions", "Berechtigungen"), ("Accept", "Akzeptieren"), ("Dismiss", "Ablehnen"), @@ -181,7 +181,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...", "Anmeldung..."), + ("Logging in...", "Anmelden..."), ("Enable RDP session sharing", "RDP-Sitzungsfreigabe aktivieren"), ("Auto Login", "Automatisch anmelden (nur gültig, wenn Sie \"Sperren nach Sitzungsende\" aktiviert haben)"), ("Enable Direct IP Access", "Direkten IP-Zugang aktivieren"), @@ -209,7 +209,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("whitelist_tip", "Nur IPs auf der Whitelist können zugreifen"), ("Login", "Anmelden"), ("Logout", "Abmelden"), - ("Tags", "Stichworte"), + ("Tags", "Schlagworte"), ("Search ID", "Suche ID"), ("Current Wayland display server is not supported", "Der aktuelle Wayland-Anzeigeserver wird nicht unterstützt"), ("whitelist_sep", "Getrennt durch Komma, Semikolon, Leerzeichen oder Zeilenumbruch"), @@ -220,15 +220,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Username missed", "Benutzername vergessen"), ("Password missed", "Passwort vergessen"), ("Wrong credentials", "Falsche Anmeldedaten"), - ("Edit Tag", "Stichwort bearbeiten"), + ("Edit Tag", "Schlagwort bearbeiten"), ("Unremember Password", "Passwort vergessen"), ("Favorites", "Favoriten"), ("Add to Favorites", "Zu Favoriten hinzufügen"), ("Remove from Favorites", "Aus Favoriten entfernen"), - ("Empty", "Leer"), + ("Empty", "Keine Einträge"), ("Invalid folder name", "Ungültiger Ordnername"), ("Socks5 Proxy", "Socks5 Proxy"), - ("Hostname", "Rechnername"), + ("Hostname", "Hostname"), ("Discovered", "Gefunden"), ("install_daemon_tip", "Um mit System zu starten, muss der Systemdienst installiert sein"), ("Remote ID", "Entfernte ID"), @@ -278,7 +278,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 [Dienst aktivieren] oder aktivieren Sie die Berechtigung [Bildschirmzugr.], um den Bildschirmfreigabedienst zu starten."), - ("Account", "Account"), + ("Account", "Konto"), ("Overwrite", "Überschreiben"), ("This file exists, skip or overwrite this file?", "Diese Datei existiert; überspringen oder überschreiben?"), ("Quit", "Beenden"), @@ -298,10 +298,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Language", "Sprache"), ("Keep RustDesk background service", "RustDesk im Hintergrund ausführen"), ("Ignore Battery Optimizations", "Batterieoptimierung ignorieren"), - ("android_open_battery_optimizations_tip", "Möchten Sie die Batterieopimierungs-Einstellungen öffnen?"), + ("android_open_battery_optimizations_tip", "Möchten Sie die Einstellungen zur Batterieopimierung öffnen?"), ("Connection not allowed", "Verbindung abgelehnt"), ("Legacy mode", "Kompatibilitätsmodus"), - ("Map mode", ""), + ("Map mode", ""), //Muss noch angepasst werden ("Translate mode", "Übersetzungsmodus"), ("Use permanent password", "Dauerhaftes Passwort verwenden"), ("Use both passwords", "Beide Passwörter verwenden"), @@ -332,7 +332,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Adaptiv skalieren"), ("General", "Allgemein"), ("Security", "Sicherheit"), - ("Account", "Account"), + ("Account", "KOnto"), ("Theme", "Farbgebung"), ("Dark Theme", "dunkle Farbgebung"), ("Dark", "Dunkel"), @@ -367,33 +367,35 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", "LAN-Erkennung aktivieren"), ("Deny LAN Discovery", "LAN-Erkennung verbieten"), ("Write a message", "Nachricht schreiben"), - ("Prompt", ""), - ("Please wait for confirmation of UAC...", ""), + ("Prompt", ""), //Aufforderung? + ("Please wait for confirmation of UAC...", "Bitte auf die Bestätigung des Nutzers warten..."), ("elevated_foreground_window_tip", ""), - ("Disconnected", ""), - ("Other", ""), - ("Confirm before closing multiple tabs", ""), - ("Keyboard Settings", ""), - ("Custom", ""), - ("Full Access", ""), - ("Screen Share", ""), + ("Disconnected", "Verbindung abgebrochen"), + ("Other", ""), //Muss noch angepasst werden + ("Confirm before closing multiple tabs", "Bitte vor dem Schließen mehrerer Tabs bestägigen"), + ("Keyboard Settings", "Tastatureinstellungen"), + ("Custom", "Individuell"), + ("Full Access", "Vollzugriff"), + ("Screen Share", "Bildschirmfreigabe"), ("Wayland requires Ubuntu 21.04 or higher version.", "Wayland erfordert Ubuntu 21.04 oder eine höhere Version."), ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland erfordert eine höhere Version der Linux-Distribution. Bitte versuchen Sie den X11-Desktop oder ändern Sie Ihr Betriebssystem."), ("JumpLink", "View"), ("Please Select the screen to be shared(Operate on the peer side).", "Bitte wählen Sie den Bildschirm aus, der freigegeben werden soll (auf der Peer-Seite arbeiten)."), - ("Show RustDesk", ""), - ("This PC", ""), - ("or", ""), - ("Continue with", ""), - ("Elevate", ""), - ("Zoom cursor", ""), - ("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", ""), - ("One-time password length", ""), - ("Request access to your device", ""), + ("Show RustDesk", "RustDesk anzeigen"), + ("This PC", "Dieser PC"), + ("or", "oder"), + ("Continue with", "Fortfahren mit"), + ("Elevate", "Erheben"), + ("Zoom cursor", "Cursor zoomen"), + ("Accept sessions via password", "Sitzung mit Passwort bestätigen"), + ("Accept sessions via click", "Sitzung mit einem Klick bestätigen"), + ("Accept sessions via both", "Sitzung durch beides bestätigen"), + ("Please wait for the remote side to accept your session request...", "Bitte warten Sie auf die Gegenstelle, dass diese Ihre Sitzungsanfrage bestätigt..."), + ("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"), + ("Hide connection management window", "Fenster zur Verwaltung der Verbindung verstecken"), + ("hide_cm_tip", "Verstecken nur erlauben, wenn die Sitzung über ein festes Passwort erstellt wurde"), // Sehr unklar. Muss noch angepasst werden. Original: Allow hiding only if accepting sessions via password and using pernament password ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index ee68d4431..2550135a1 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -33,7 +33,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_foreground_window_tip", "The current window of the remote desktop requires higher privilege to operate, so it's unable to use the mouse and keyboard temporarily. You can request the remote user to minimize the current window, or click elevation button on the connection management window. To avoid this problem, it is recommended to install the software on the remote device."), ("JumpLink", "View"), ("Stop service", "Stop Service"), - ("or", ""), - ("Continue with", ""), + ("hide_cm_tip", "Allow hiding only if accepting sessions via password and using pernament password"), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 3c7ac806a..797eb2bb6 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 5dd471a4b..ca67a68be 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -306,7 +306,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use permanent password", "Usar contraseña permamente"), ("Use both passwords", "Usar ambas contraseñas"), ("Set permanent password", "Establecer contraseña permamente"), - ("Enable Remote Restart", "Activar reinicio remoto"), + ("Enable Remote Restart", "Habilitar reinicio remoto"), ("Allow remote restart", "Permitir reinicio remoto"), ("Restart Remote Device", "Reiniciar dispositivo"), ("Are you sure you want to restart", "Esta Seguro que desea reiniciar?"), @@ -387,13 +387,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Continue with", "Continuar con"), ("Elevate", "Elevar"), ("Zoom cursor", "Ampliar cursor"), - ("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", ""), - ("One-time password length", ""), - ("Request access to your device", ""), + ("Accept sessions via password", "Aceptar sesiones a través de contraseña"), + ("Accept sessions via click", "Aceptar sesiones a través de clic"), + ("Accept sessions via both", "Aceptar sesiones a través de ambos"), + ("Please wait for the remote side to accept your session request...", "Por favor, espere a que el lado remoto acepte su solicitud de sesión"), + ("One-time Password", "Constaseña de un solo uso"), + ("Use one-time password", "Usar contraseña de un solo uso"), + ("One-time password length", "Longitud de la contraseña de un solo uso"), + ("Request access to your device", "Solicitud de acceso a su dispositivo"), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 0ea1f6f55..4dfb22621 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -394,5 +394,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", "استفاده از رمز عبور یکبار مصرف"), ("One-time password length", "طول رمز عبور یکبار مصرف"), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 4b8d0d83e..53c3b3bfa 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -304,14 +304,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Map mode", ""), ("Translate mode", ""), ("Use permanent password", "Utiliser un mot de passe permanent"), - ("Use both passwords", "Utiliser les mots de passe temporaire et permanent"), + ("Use both passwords", "Utiliser les mots de passe unique et permanent"), ("Set permanent password", "Définir le mot de passe permanent"), ("Enable Remote Restart", "Activer le redémarrage à distance"), ("Allow remote restart", "Autoriser le redémarrage à distance"), ("Restart Remote Device", "Redémarrer l'appareil à distance"), ("Are you sure you want to restart", "Êtes-vous sûrs de vouloir redémarrer l'appareil ?"), ("Restarting Remote Device", "Redémarrage de l'appareil distant"), - ("remote_restarting_tip", ""), + ("remote_restarting_tip", "L'appareil distant redémarre, veuillez fermer cette boîte de message et vous reconnecter avec un mot de passe permanent après un certain temps"), ("Copied", "Copié"), ("Exit Fullscreen", "Quitter le mode plein écran"), ("Fullscreen", "Plein écran"), @@ -368,8 +368,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Deny LAN Discovery", "Interdir la découverte réseau local"), ("Write a message", "Ecrire un message"), ("Prompt", ""), - ("Please wait for confirmation of UAC...", ""), - ("elevated_foreground_window_tip", ""), + ("Please wait for confirmation of UAC...", "Veuillez attendre la confirmation de l'UAC..."), + ("elevated_foreground_window_tip", "La fenêtre actuelle que la machine distante nécessite des privilèges plus élevés pour fonctionner, elle ne peut donc pas être atteinte par la souris et le clavier. Vous pouvez demander à l'utilisateur distant de réduire la fenêtre actuelle ou de cliquer sur le bouton d'élévation dans la fenêtre de gestion des connexions. Pour éviter ce problème, il est recommandé d'installer le logiciel sur l'appareil distant."), ("Disconnected", "Déconnecté"), ("Other", "Divers"), ("Confirm before closing multiple tabs", "Confirmer avant de fermer plusieurs onglets"), @@ -387,13 +387,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Continue with", "Continuer avec"), ("Elevate", ""), ("Zoom cursor", ""), - ("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", ""), - ("One-time password length", ""), - ("Request access to your device", ""), + ("Accept sessions via password", "Accepter les sessions via mot de passe"), + ("Accept sessions via click", "Accepter les sessions via clique de confirmation"), + ("Accept sessions via both", "Accepter les sessions via mot de passe ou clique de confirmation"), + ("Please wait for the remote side to accept your session request...", "Veuillez attendre que votre demande de session distante soit accepter ..."), + ("One-time Password", "Mot de passe unique"), + ("Use one-time password", "Utiliser un mot de passe unique"), + ("One-time password length", "Longueur du mot de passe unique"), + ("Request access to your device", "Demande d'accès à votre appareil"), + ("Hide connection management window", "Masquer la fenêtre de gestion des connexions"), + ("hide_cm_tip", "Autoriser le masquage uniquement si vous acceptez des sessions via un mot de passe et utilisez un mot de passe permanent"), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 9802ddb6f..417c83f45 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 002789066..b76bb687d 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 3ca466f22..ef77e18e2 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -394,6 +394,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("One-time Password", "Password monouso"), ("Use one-time password", "Usa password monouso"), ("One-time password length", "Lunghezza password monouso"), - ("Request access to your device", "Richiedi accesso al tuo dispositivo"), + ("Request access to your device", "Richiedi l'accesso al tuo dispositivo"), + ("Hide connection management window", "Nascondi la finestra di gestione delle connessioni"), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index b032fbe7e..8d806416d 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 338fc7ffe..9f8027be7 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 3a343da21..3a8c27cf3 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index b4f760a35..dae77ed88 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -385,15 +385,17 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("This PC", "Ten komputer"), ("or", "albo"), ("Continue with", "Kontynuuj z"), - ("Elevate", ""), - ("Zoom cursor", ""), - ("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", ""), - ("One-time password length", ""), - ("Request access to your device", ""), + ("Elevate", "Podwyższ"), + ("Zoom cursor", "Zoom kursora"), + ("Accept sessions via password", "Akceptuj sesje używając hasła"), + ("Accept sessions via click", "Akceptuj sesję klikając"), + ("Accept sessions via both", "Akceptuj sesjęna dwa sposoby"), + ("Please wait for the remote side to accept your session request...", "Proszę czekać aż zdalny host zaakceptuje Twoją prośbę..."), + ("One-time Password", "Hasło jednorazowe"), + ("Use one-time password", "Użyj hasła jednorazowego"), + ("One-time password length", "Długość hasła jednorazowego"), + ("Request access to your device", "Żądanie dostępu do Twojego urządzenia"), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index dbb5fbbe9..bc5fbbdfd 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 7d9c0b270..0d77eb905 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -385,15 +385,17 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("This PC", "Este PC"), ("or", "ou"), ("Continue with", "Continuar com"), - ("Elevate", ""), - ("Zoom cursor", ""), - ("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", ""), - ("One-time password length", ""), - ("Request access to your device", ""), + ("Elevate", "Elevar"), + ("Zoom cursor", "Aumentar cursor"), + ("Accept sessions via password", "Aceitar sessões via senha"), + ("Accept sessions via click", "Aceitar sessões via clique"), + ("Accept sessions via both", "Aceitar sessões de ambos os modos"), + ("Please wait for the remote side to accept your session request...", "Por favor aguarde enquanto o cliente remoto aceita seu pedido de sessão..."), + ("One-time Password", "Senha de uso único"), + ("Use one-time password", "Usar senha de uso único"), + ("One-time password length", "Comprimento da senha de uso único"), + ("Request access to your device", "Solicitar acesso ao seu dispositivo"), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index ded00af23..e318b7cda 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 8da18e035..33f2be7ab 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index bc9bc95e3..8f855d96a 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 86283557f..a97f832ba 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index cc8f65e1c..4945fd511 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", "使用一次性密碼"), ("One-time password length", "一次性密碼長度"), ("Request access to your device", "請求訪問你的設備"), + ("Hide connection management window", "隱藏連接管理窗口"), + ("hide_cm_tip", "在只允許密碼連接並且只用固定密碼的情況下才允許隱藏"), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 7d14ee7e0..3861f0598 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 3ddacdf8d..8ddeadfca 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -395,5 +395,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use one-time password", ""), ("One-time password length", ""), ("Request access to your device", ""), + ("Hide connection management window", ""), + ("hide_cm_tip", ""), ].iter().cloned().collect(); } diff --git a/src/server/connection.rs b/src/server/connection.rs index 11960be8a..249dadc5e 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -7,6 +7,7 @@ use crate::video_service; #[cfg(any(target_os = "android", target_os = "ios"))] use crate::{common::DEVICE_NAME, flutter::connection_manager::start_channel}; use crate::{ipc, VERSION}; +use cidr_utils::cidr::IpCidr; use hbb_common::{ config::Config, fs, @@ -631,7 +632,7 @@ impl Connection { .is_none() && whitelist .iter() - .filter(|x| x.parse() == Ok(addr.ip())) + .filter(|x| IpCidr::from_str(x).map_or(false, |y| y.contains(addr.ip()))) .next() .is_none() { @@ -1570,17 +1571,18 @@ async fn start_ipc( if let Ok(s) = crate::ipc::connect(1000, "_cm").await { stream = Some(s); } else { + let extra_args = if password::hide_cm() { "--hide" } else { "" }; let run_done; if crate::platform::is_root() { let mut res = Ok(None); for _ in 0..10 { #[cfg(not(target_os = "linux"))] { - res = crate::platform::run_as_user("--cm"); + res = crate::platform::run_as_user(&format!("--cm {}", extra_args)); } #[cfg(target_os = "linux")] { - res = crate::platform::run_as_user("--cm", None); + res = crate::platform::run_as_user(&format!("--cm {}", extra_args), None); } if res.is_ok() { break; @@ -1595,10 +1597,14 @@ async fn start_ipc( run_done = false; } if !run_done { + let mut args = vec!["--cm"]; + if !extra_args.is_empty() { + args.push(&extra_args); + } super::CHILD_PROCESS .lock() .unwrap() - .push(crate::run_me(vec!["--cm"])?); + .push(crate::run_me(args)?); } for _ in 0..10 { sleep(0.3).await; diff --git a/src/server/video_service.rs b/src/server/video_service.rs index 3ccc3af39..db419fc65 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -192,7 +192,7 @@ fn create_capturer( privacy_mode_id: i32, display: Display, use_yuv: bool, - current: usize, + _current: usize, _portable_service_running: bool, ) -> ResultType> { #[cfg(not(windows))] @@ -256,7 +256,7 @@ fn create_capturer( log::debug!("Create capturer dxgi|gdi"); #[cfg(windows)] return crate::portable_service::client::create_capturer( - current, + _current, display, use_yuv, _portable_service_running, diff --git a/src/ui/index.tis b/src/ui/index.tis index 8e2238b2d..9dcd4f4c4 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -395,7 +395,8 @@ class MyIdMenu: Reactor.Component { if (value) { var values = value.split(/[\s,;\n]+/g); for (var ip in values) { - if (!ip.match(/^\d+\.\d+\.\d+\.\d+$/)) { + if (!ip.match(/^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)(\/([1-9]|[1-2][0-9]|3[0-2])){0,1}$/) + && !ip.match(/^(((?:[0-9A-Fa-f]{1,4}))*((?::[0-9A-Fa-f]{1,4}))*::((?:[0-9A-Fa-f]{1,4}))*((?::[0-9A-Fa-f]{1,4}))*|((?:[0-9A-Fa-f]{1,4}))((?::[0-9A-Fa-f]{1,4})){7})(\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])){0,1}$/)) { return translate("Invalid IP") + ": " + ip; } } diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index 5edf53507..26e5e4077 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -784,11 +784,11 @@ pub fn can_elevate() -> bool { return false; } -pub fn elevate_portable(id: i32) { +pub fn elevate_portable(_id: i32) { #[cfg(windows)] { let lock = CLIENTS.read().unwrap(); - if let Some(s) = lock.get(&id) { + if let Some(s) = lock.get(&_id) { allow_err!(s.tx.send(ipc::Data::DataPortableService( ipc::DataPortableService::RequestStart ))); diff --git a/src/ui_interface.rs b/src/ui_interface.rs index e1dc3005e..28ce897bc 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -39,6 +39,7 @@ lazy_static::lazy_static! { static ref OPTIONS : Arc>> = Arc::new(Mutex::new(Config::get_options())); static ref ASYNC_JOB_STATUS : Arc> = Default::default(); static ref TEMPORARY_PASSWD : Arc> = Arc::new(Mutex::new("".to_owned())); + pub static ref OPTION_SYNCED : Arc> = Default::default(); } #[cfg(not(any(target_os = "android", target_os = "ios")))] @@ -924,7 +925,8 @@ async fn check_connect_status_(reconnect: bool, rx: mpsc::UnboundedReceiver { - *OPTIONS.lock().unwrap() = v + *OPTIONS.lock().unwrap() = v; + *OPTION_SYNCED.lock().unwrap() = true; } Ok(Some(ipc::Data::Config((name, Some(value))))) => { if name == "id" { @@ -967,6 +969,11 @@ async fn check_connect_status_(reconnect: bool, rx: mpsc::UnboundedReceiver bool { + OPTION_SYNCED.lock().unwrap().clone() +} + #[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))] #[tokio::main(flavor = "current_thread")] pub(crate) async fn send_to_cm(data: &ipc::Data) { diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 9b00730e5..efc82cbc1 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -200,6 +200,7 @@ impl Session { h265 = h265 && encoding_265; return (h264, h265); } + #[allow(dead_code)] (false, false) }