mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-11-27 14:59:02 +08:00
Merge remote-tracking branch 'upstream/master' into file-manager-redesign
This commit is contained in:
parent
922a70adb4
commit
12a33cdfbb
@ -1,19 +1,50 @@
|
||||
FROM debian
|
||||
FROM mcr.microsoft.com/devcontainers/base:ubuntu-22.04
|
||||
ENV HOME=/home/vscode
|
||||
ENV WORKDIR=$HOME/rustdesk
|
||||
|
||||
WORKDIR $HOME
|
||||
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 unzip zip sudo libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
|
||||
WORKDIR /
|
||||
|
||||
RUN git clone https://github.com/microsoft/vcpkg
|
||||
WORKDIR vcpkg
|
||||
RUN git checkout 134505003bb46e20fbace51ccfb69243fbbc5f82
|
||||
RUN /vcpkg/bootstrap-vcpkg.sh -disableMetrics
|
||||
ENV VCPKG_ROOT=/vcpkg
|
||||
RUN $VCPKG_ROOT/vcpkg --disable-metrics install libvpx libyuv opus
|
||||
|
||||
WORKDIR /
|
||||
RUN apt update -y && 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 unzip zip sudo libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
|
||||
RUN wget https://github.com/rustdesk/doc.rustdesk.com/releases/download/console/dep.tar.gz && tar xzf dep.tar.gz
|
||||
|
||||
RUN git clone https://github.com/microsoft/vcpkg && cd vcpkg && git checkout 134505003bb46e20fbace51ccfb69243fbbc5f82
|
||||
RUN /vcpkg/bootstrap-vcpkg.sh -disableMetrics
|
||||
RUN /vcpkg/vcpkg --disable-metrics install libvpx libyuv opus
|
||||
|
||||
RUN groupadd -r user && useradd -r -g user user --home /home/user && mkdir -p /home/user && chown user /home/user && echo "user ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/user
|
||||
WORKDIR /home/user
|
||||
USER vscode
|
||||
WORKDIR $HOME
|
||||
RUN wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
|
||||
USER user
|
||||
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup.sh
|
||||
RUN chmod +x rustup.sh
|
||||
RUN ./rustup.sh -y
|
||||
RUN $HOME/rustup.sh -y
|
||||
RUN $HOME/.cargo/bin/rustup target add aarch64-linux-android
|
||||
RUN $HOME/.cargo/bin/cargo install cargo-ndk
|
||||
|
||||
USER root
|
||||
ENV HOME=/home/user
|
||||
# Install Flutter
|
||||
RUN wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.7.3-stable.tar.xz
|
||||
RUN tar xf flutter_linux_3.7.3-stable.tar.xz && rm flutter_linux_3.7.3-stable.tar.xz
|
||||
ENV PATH="$PATH:$HOME/flutter/bin"
|
||||
RUN dart pub global activate ffigen 5.0.1
|
||||
|
||||
|
||||
# Install packages
|
||||
RUN sudo apt-get install -y libclang-dev
|
||||
RUN sudo apt install -y gcc-multilib
|
||||
|
||||
WORKDIR $WORKDIR
|
||||
ENV ANDROID_NDK_HOME=/opt/android/ndk/22.1.7171670
|
||||
|
||||
# Somehow try to automate flutter pub get
|
||||
# https://rustdesk.com/docs/en/dev/build/android/
|
||||
# Put below steps in entrypoint.sh
|
||||
# cd flutter
|
||||
# wget https://github.com/rustdesk/doc.rustdesk.com/releases/download/console/so.tar.gz
|
||||
# tar xzf so.tar.gz
|
||||
|
||||
# own /opt/android
|
||||
|
75
.devcontainer/build.sh
Executable file
75
.devcontainer/build.sh
Executable file
@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
MODE=${1:---debug}
|
||||
TYPE=${2:-linux}
|
||||
MODE=${MODE/*-/}
|
||||
|
||||
|
||||
build(){
|
||||
pwd
|
||||
$WORKDIR/entrypoint $1
|
||||
}
|
||||
|
||||
build_arm64(){
|
||||
CWD=$(pwd)
|
||||
cd $WORKDIR/flutter
|
||||
flutter pub get
|
||||
cd $WORKDIR
|
||||
$WORKDIR/flutter/ndk_arm64.sh
|
||||
cp $WORKDIR/target/aarch64-linux-android/release/liblibrustdesk.so $WORKDIR/flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so
|
||||
cd $CWD
|
||||
}
|
||||
|
||||
build_apk(){
|
||||
cd $WORKDIR/flutter
|
||||
MODE=$1 $WORKDIR/flutter/build_android.sh
|
||||
cd $WORKDIR
|
||||
}
|
||||
|
||||
key_gen(){
|
||||
if [ ! -f $WORKDIR/flutter/android/key.properties ]
|
||||
then
|
||||
if [ ! -f $HOME/upload-keystore.jks ]
|
||||
then
|
||||
$WORKDIR/.devcontainer/setup.sh key
|
||||
fi
|
||||
read -r -p "enter the password used to generate $HOME/upload-keystore.jks\n" password
|
||||
echo -e "storePassword=${password}\nkeyPassword=${password}\nkeyAlias=upload\nstoreFile=$HOME/upload-keystore.jks" > $WORKDIR/flutter/android/key.properties
|
||||
else
|
||||
echo "Believing storeFile is created ref: $WORKDIR/flutter/android/key.properties"
|
||||
fi
|
||||
}
|
||||
|
||||
android_build(){
|
||||
if [ ! -d $WORKDIR/flutter/android/app/src/main/jniLibs/arm64-v8a ]
|
||||
then
|
||||
$WORKDIR/.devcontainer/setup.sh android
|
||||
fi
|
||||
build_arm64
|
||||
case $1 in
|
||||
debug)
|
||||
build_apk debug
|
||||
;;
|
||||
release)
|
||||
key_gen
|
||||
build_apk release
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
case "$MODE:$TYPE" in
|
||||
"debug:linux")
|
||||
build
|
||||
;;
|
||||
"release:linux")
|
||||
build --release
|
||||
;;
|
||||
"debug:android")
|
||||
android_build debug
|
||||
;;
|
||||
"release:android")
|
||||
android_build release
|
||||
;;
|
||||
esac
|
@ -1,15 +1,18 @@
|
||||
{
|
||||
"name": "rustdesk",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
"args": {
|
||||
"BUILDKIT_INLINE_CACHE": "0"
|
||||
"dockerfile": "./Dockerfile",
|
||||
"context": "."
|
||||
},
|
||||
"workspaceMount": "source=${localWorkspaceFolder},target=/home/vscode/rustdesk,type=bind,consistency=cache",
|
||||
"workspaceFolder": "/home/vscode/rustdesk",
|
||||
"postStartCommand": ".devcontainer/build.sh",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/java:1": {},
|
||||
"ghcr.io/akhildevelops/devcontainer-features/android-cli:latest": {
|
||||
"PACKAGES": "platform-tools,ndk;22.1.7171670"
|
||||
}
|
||||
},
|
||||
"workspaceMount": "source=${localWorkspaceFolder},target=/home/user/rustdesk,type=bind,consistency=cache",
|
||||
"workspaceFolder": "/home/user/rustdesk",
|
||||
"postStartCommand": "./entrypoint",
|
||||
"remoteUser": "user",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
@ -17,7 +20,9 @@
|
||||
"mutantdino.resourcemonitor",
|
||||
"rust-lang.rust-analyzer",
|
||||
"tamasfe.even-better-toml",
|
||||
"serayuzgur.crates"
|
||||
"serayuzgur.crates",
|
||||
"mhutchie.git-graph",
|
||||
"eamodio.gitlens"
|
||||
],
|
||||
"settings": {
|
||||
"files.watcherExclude": {
|
||||
|
23
.devcontainer/setup.sh
Executable file
23
.devcontainer/setup.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
case $1 in
|
||||
android)
|
||||
# install deps
|
||||
cd $WORKDIR/flutter
|
||||
flutter pub get
|
||||
wget https://github.com/rustdesk/doc.rustdesk.com/releases/download/console/so.tar.gz
|
||||
tar xzf so.tar.gz
|
||||
rm so.tar.gz
|
||||
sudo chown -R $(whoami) $ANDROID_HOME
|
||||
echo "Setup is Done."
|
||||
;;
|
||||
linux)
|
||||
echo "Linux Setup"
|
||||
;;
|
||||
key)
|
||||
echo -e "\n$HOME/upload-keystore.jks is not created.\nLet's create it.\nRemember the password you enter in keytool!"
|
||||
keytool -genkey -v -keystore $HOME/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
|
||||
;;
|
||||
esac
|
||||
|
||||
|
4
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
4
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@ -44,7 +44,9 @@ body:
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: Screenshots
|
||||
description: If applicable, please add screenshots to help explain your problem
|
||||
description: Please add screenshots to help explain your problem, if applicable, please upload video.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
|
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
@ -7,6 +7,9 @@ name: CI
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "docs/**"
|
||||
- "README.md"
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
@ -14,6 +17,8 @@ on:
|
||||
- '*'
|
||||
paths-ignore:
|
||||
- ".github/**"
|
||||
- "docs/**"
|
||||
- "README.md"
|
||||
|
||||
jobs:
|
||||
# ensure_cargo_fmt:
|
||||
|
5
.github/workflows/flutter-ci.yml
vendored
5
.github/workflows/flutter-ci.yml
vendored
@ -3,6 +3,9 @@ name: Full Flutter CI
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "docs/**"
|
||||
- "README.md"
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
@ -10,6 +13,8 @@ on:
|
||||
- '*'
|
||||
paths-ignore:
|
||||
- ".github/**"
|
||||
- "docs/**"
|
||||
- "README.md"
|
||||
|
||||
env:
|
||||
LLVM_VERSION: "15.0.6"
|
||||
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -2623,6 +2623,7 @@ dependencies = [
|
||||
"serde_json 1.0.89",
|
||||
"socket2 0.3.19",
|
||||
"sodiumoxide",
|
||||
"sysinfo",
|
||||
"tokio",
|
||||
"tokio-socks",
|
||||
"tokio-util",
|
||||
@ -4887,7 +4888,6 @@ dependencies = [
|
||||
"shutdown_hooks",
|
||||
"simple_rc",
|
||||
"sys-locale",
|
||||
"sysinfo",
|
||||
"system_shutdown",
|
||||
"tao",
|
||||
"tray-icon",
|
||||
|
@ -55,7 +55,6 @@ uuid = { version = "1.0", features = ["v4"] }
|
||||
clap = "3.0"
|
||||
rpassword = "7.0"
|
||||
base64 = "0.13"
|
||||
sysinfo = "0.24"
|
||||
num_cpus = "1.13"
|
||||
bytes = { version = "1.2", features = ["serde"] }
|
||||
default-net = "0.12.0"
|
||||
|
10
README.md
10
README.md
@ -19,7 +19,7 @@ Yet another remote desktop software, written in Rust. Works out of the box, no c
|
||||
|
||||
RustDesk welcomes contribution from everyone. See [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) for help getting started.
|
||||
|
||||
[**How does RustDesk work?**](https://github.com/rustdesk/rustdesk/wiki/How-does-RustDesk-work%3F)
|
||||
[**FAQ**](https://github.com/rustdesk/rustdesk/wiki/FAQ)
|
||||
|
||||
[**BINARY DOWNLOAD**](https://github.com/rustdesk/rustdesk/releases)
|
||||
|
||||
@ -41,6 +41,14 @@ Below are the servers you are using for free, they may change over time. If you
|
||||
| USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8GB RAM |
|
||||
| Ukraine (Kyiv) | dc.volia (2VM) | 2 vCPU / 4GB RAM |
|
||||
|
||||
## Dev Container
|
||||
|
||||
[![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Container&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/rustdesk/rustdesk)
|
||||
|
||||
If you already have VS Code and Docker installed, you can click the badge above to get started. Clicking will cause VS Code to automatically install the Dev Containers extension if needed, clone the source code into a container volume, and spin up a dev container for use.
|
||||
|
||||
Go through [DEVCONTAINER.md](docs/DEVCONTAINER.md) for more info.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Desktop versions use [sciter](https://sciter.com/) or Flutter for GUI, this tutorial is for Sciter only.
|
||||
|
14
docs/DEVCONTAINER.md
Normal file
14
docs/DEVCONTAINER.md
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
After the start of devcontainer in docker container, a linux binary in debug mode is created.
|
||||
|
||||
Currently devcontainer offers linux and android builds in both debug and release mode.
|
||||
|
||||
Below is the table on commands to run from root of the project for creating specific builds.
|
||||
|
||||
Command|Build Type|Mode
|
||||
-|-|-|
|
||||
`.devcontainer/build.sh --debug linux`|Linux|debug
|
||||
`.devcontainer/build.sh --release linux`|Linux|release
|
||||
`.devcontainer/build.sh --debug android`|android-arm64|debug
|
||||
`.devcontainer/build.sh --release android`|android-arm64|debug
|
||||
|
@ -1,8 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
$ANDROID_NDK/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-strip android/app/src/main/jniLibs/arm64-v8a/*
|
||||
flutter build apk --target-platform android-arm64,android-arm --release --obfuscate --split-debug-info ./split-debug-info
|
||||
flutter build apk ---split-per-abi --target-platform android-arm64,android-arm --release --obfuscate --split-debug-info ./split-debug-info
|
||||
flutter build appbundle --target-platform android-arm64,android-arm --release --obfuscate --split-debug-info ./split-debug-info
|
||||
|
||||
MODE=${MODE:=release}
|
||||
$ANDROID_NDK_HOME/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-strip android/app/src/main/jniLibs/arm64-v8a/*
|
||||
flutter build apk --target-platform android-arm64,android-arm --${MODE} --obfuscate --split-debug-info ./split-debug-info
|
||||
flutter build apk --split-per-abi --target-platform android-arm64,android-arm --${MODE} --obfuscate --split-debug-info ./split-debug-info
|
||||
flutter build appbundle --target-platform android-arm64,android-arm --${MODE} --obfuscate --split-debug-info ./split-debug-info
|
||||
|
||||
# build in linux
|
||||
# $ANDROID_NDK/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-strip android/app/src/main/jniLibs/arm64-v8a/*
|
||||
|
@ -44,10 +44,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
if (gFFI.userModel.userName.value.isEmpty) {
|
||||
return Center(
|
||||
child: ElevatedButton(
|
||||
onPressed: loginDialog,
|
||||
child: Text(translate("Login"))
|
||||
)
|
||||
);
|
||||
onPressed: loginDialog, child: Text(translate("Login"))));
|
||||
} else {
|
||||
if (gFFI.abModel.abLoading.value) {
|
||||
return const Center(
|
||||
@ -153,13 +150,13 @@ class _AddressBookState extends State<AddressBook> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(translate('Tags')),
|
||||
GestureDetector(
|
||||
onTapDown: (e) {
|
||||
final x = e.globalPosition.dx;
|
||||
final y = e.globalPosition.dy;
|
||||
Listener(
|
||||
onPointerDown: (e) {
|
||||
final x = e.position.dx;
|
||||
final y = e.position.dy;
|
||||
menuPos = RelativeRect.fromLTRB(x, y, x, y);
|
||||
},
|
||||
onTap: () => _showMenu(menuPos),
|
||||
onPointerUp: (_) => _showMenu(menuPos),
|
||||
child: ActionMore()),
|
||||
],
|
||||
);
|
||||
|
@ -1,8 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
|
||||
import '../../common.dart';
|
||||
import '../../models/input_model.dart';
|
||||
|
||||
class RawKeyFocusScope extends StatelessWidget {
|
||||
@ -20,13 +18,6 @@ class RawKeyFocusScope extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final FocusOnKeyCallback? onKey;
|
||||
if (isAndroid) {
|
||||
onKey = inputModel.handleRawKeyEvent;
|
||||
} else {
|
||||
onKey = stateGlobal.grabKeyboard ? inputModel.handleRawKeyEvent : null;
|
||||
}
|
||||
|
||||
return FocusScope(
|
||||
autofocus: true,
|
||||
child: Focus(
|
||||
@ -34,7 +25,7 @@ class RawKeyFocusScope extends StatelessWidget {
|
||||
canRequestFocus: true,
|
||||
focusNode: focusNode,
|
||||
onFocusChange: onFocusChange,
|
||||
onKey: onKey,
|
||||
onKey: inputModel.handleRawKeyEvent,
|
||||
child: child));
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ const String kAppTypeDesktopPortForward = "port forward";
|
||||
|
||||
const String kWindowMainWindowOnTop = "main_window_on_top";
|
||||
const String kWindowGetWindowInfo = "get_window_info";
|
||||
const String kWindowDisableGrabKeyboard = "disable_grab_keyboard";
|
||||
const String kWindowActionRebuild = "rebuild";
|
||||
const String kWindowEventHide = "hide";
|
||||
const String kWindowEventShow = "show";
|
||||
|
@ -14,6 +14,7 @@ import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart';
|
||||
import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart';
|
||||
import 'package:flutter_hbb/models/platform_model.dart';
|
||||
import 'package:flutter_hbb/models/server_model.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
@ -498,6 +499,10 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
if (watchIsInputMonitoring) {
|
||||
if (bind.mainIsCanInputMonitoring(prompt: false)) {
|
||||
watchIsInputMonitoring = false;
|
||||
// Do not notify for now.
|
||||
// Monitoring may not take effect until the process is restarted.
|
||||
// rustDeskWinManager.call(
|
||||
// WindowType.RemoteDesktop, kWindowDisableGrabKeyboard, '');
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
@ -111,6 +111,8 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
||||
forceRelay: args['forceRelay'],
|
||||
),
|
||||
));
|
||||
} else if (call.method == kWindowDisableGrabKeyboard) {
|
||||
stateGlobal.grabKeyboard = false;
|
||||
} else if (call.method == "onDestroy") {
|
||||
tabController.clear();
|
||||
} else if (call.method == kWindowActionRebuild) {
|
||||
|
@ -650,6 +650,12 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
||||
}
|
||||
|
||||
Widget _buildKeyboard(BuildContext context) {
|
||||
// Do not support peer 1.1.9.
|
||||
if (stateGlobal.grabKeyboard) {
|
||||
bind.sessionSetKeyboardMode(id: widget.id, value: 'map');
|
||||
return Offstage();
|
||||
}
|
||||
|
||||
FfiModel ffiModel = Provider.of<FfiModel>(context);
|
||||
if (ffiModel.permissions['keyboard'] == false) {
|
||||
return Offstage();
|
||||
|
@ -548,13 +548,20 @@ class WindowActionPanelState extends State<WindowActionPanel>
|
||||
if (rustDeskWinManager.getActiveWindows().contains(kMainWindowId)) {
|
||||
await rustDeskWinManager.unregisterActiveWindow(kMainWindowId);
|
||||
}
|
||||
// `hide` must be placed after unregisterActiveWindow, because once all windows are hidden,
|
||||
// flutter closes the application on macOS. We should ensure the post-run logic has ran successfully.
|
||||
// e.g.: saving window position.
|
||||
// macOS specific workaround, the window is not hiding when in fullscreen.
|
||||
if (Platform.isMacOS && await windowManager.isFullScreen()) {
|
||||
await windowManager.setFullScreen(false);
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
}
|
||||
await windowManager.hide();
|
||||
} else {
|
||||
// it's safe to hide the subwindow
|
||||
await WindowController.fromWindowId(kWindowId!).hide();
|
||||
final controller = WindowController.fromWindowId(kWindowId!);
|
||||
if (Platform.isMacOS && await controller.isFullScreen()) {
|
||||
await controller.setFullscreen(false);
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
}
|
||||
await controller.hide();
|
||||
await Future.wait([
|
||||
rustDeskWinManager
|
||||
.call(WindowType.Main, kWindowEventHide, {"id": kWindowId!}),
|
||||
|
@ -58,6 +58,10 @@ class InputModel {
|
||||
InputModel(this.parent);
|
||||
|
||||
KeyEventResult handleRawKeyEvent(FocusNode data, RawKeyEvent e) {
|
||||
if (!stateGlobal.grabKeyboard) {
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
|
||||
// * Currently mobile does not enable map mode
|
||||
if (isDesktop) {
|
||||
bind.sessionGetKeyboardMode(id: id).then((result) {
|
||||
|
@ -325,8 +325,8 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: bc8604a88e52b2b6e64d2661ae49a71450a47af8
|
||||
resolved-ref: bc8604a88e52b2b6e64d2661ae49a71450a47af8
|
||||
ref: f37357ed98a10717576eb9ed8413e92b2ec5d13a
|
||||
resolved-ref: f37357ed98a10717576eb9ed8413e92b2ec5d13a
|
||||
url: "https://github.com/Kingtous/rustdesk_desktop_multi_window"
|
||||
source: git
|
||||
version: "0.1.0"
|
||||
@ -1224,6 +1224,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
texture_rgba_renderer:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: texture_rgba_renderer
|
||||
sha256: fbb09b2c6b4ce71261927f9e7e4ea339af3e2f3f2b175f6fb921de1c66ec848d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.0.8"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -59,7 +59,7 @@ dependencies:
|
||||
desktop_multi_window:
|
||||
git:
|
||||
url: https://github.com/Kingtous/rustdesk_desktop_multi_window
|
||||
ref: bc8604a88e52b2b6e64d2661ae49a71450a47af8
|
||||
ref: f37357ed98a10717576eb9ed8413e92b2ec5d13a
|
||||
freezed_annotation: ^2.0.3
|
||||
flutter_custom_cursor: ^0.0.4
|
||||
window_size:
|
||||
@ -93,7 +93,7 @@ dependencies:
|
||||
flutter_launcher_icons: ^0.11.0
|
||||
flutter_keyboard_visibility: ^5.4.0
|
||||
percent_indicator: ^4.2.2
|
||||
|
||||
texture_rgba_renderer: ^0.0.8
|
||||
|
||||
dev_dependencies:
|
||||
icons_launcher: ^2.0.4
|
||||
@ -119,7 +119,6 @@ flutter_icons:
|
||||
web:
|
||||
generate: true
|
||||
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
@ -145,8 +144,6 @@ flutter:
|
||||
fonts:
|
||||
- asset: assets/peer_searchbar.ttf
|
||||
|
||||
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||
|
||||
|
@ -33,6 +33,7 @@ tokio-socks = { git = "https://github.com/open-trade/tokio-socks" }
|
||||
chrono = "0.4"
|
||||
backtrace = "0.3"
|
||||
libc = "0.2"
|
||||
sysinfo = "0.24"
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
mac_address = "1.1"
|
||||
|
@ -42,6 +42,7 @@ pub use chrono;
|
||||
pub use libc;
|
||||
pub use directories_next;
|
||||
pub mod keyboard;
|
||||
pub use sysinfo;
|
||||
|
||||
#[cfg(feature = "quic")]
|
||||
pub type Stream = quic::Connection;
|
||||
|
@ -317,16 +317,30 @@ pub fn check_config() {
|
||||
}
|
||||
|
||||
pub fn check_config_process(force_reset: bool) {
|
||||
use hbb_common::sysinfo::{ProcessExt, System, SystemExt};
|
||||
|
||||
std::thread::spawn(move || {
|
||||
if force_reset {
|
||||
HwCodecConfig::remove();
|
||||
}
|
||||
if let Ok(exe) = std::env::current_exe() {
|
||||
std::thread::spawn(move || {
|
||||
std::process::Command::new(exe)
|
||||
.arg("--check-hwcodec-config")
|
||||
.status()
|
||||
.ok();
|
||||
HwCodecConfig::refresh();
|
||||
});
|
||||
};
|
||||
if let Some(file_name) = exe.file_name().to_owned() {
|
||||
let s = System::new_all();
|
||||
let arg = "--check-hwcodec-config";
|
||||
for process in s.processes_by_name(&file_name.to_string_lossy().to_string()) {
|
||||
if process.cmd().iter().any(|cmd| cmd.contains(arg)) {
|
||||
log::warn!("already have process {}", arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if let Ok(mut child) = std::process::Command::new(exe).arg(arg).spawn() {
|
||||
let second = 3;
|
||||
std::thread::sleep(std::time::Duration::from_secs(second));
|
||||
// kill: Different platforms have different results
|
||||
child.kill().ok();
|
||||
HwCodecConfig::refresh();
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Version=1.2.0
|
||||
Version=1.5
|
||||
Name=RustDesk
|
||||
GenericName=Remote Desktop
|
||||
Comment=Remote Desktop
|
||||
@ -16,4 +16,4 @@ X-Desktop-File-Install-Version=0.23
|
||||
|
||||
[Desktop Action new-window]
|
||||
Name=Open a New Window
|
||||
|
||||
Exec=rustdesk %u
|
||||
|
@ -1,13 +1,13 @@
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use crate::common::get_default_sound_input;
|
||||
use crate::{
|
||||
client::file_trait::FileManager,
|
||||
common::make_fd_to_json,
|
||||
common::is_keyboard_mode_supported,
|
||||
common::make_fd_to_json,
|
||||
flutter::{self, SESSIONS},
|
||||
flutter::{session_add, session_start_},
|
||||
ui_interface::{self, *},
|
||||
};
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use crate::common::get_default_sound_input;
|
||||
use flutter_rust_bridge::{StreamSink, SyncReturn};
|
||||
use hbb_common::{
|
||||
config::{self, LocalConfig, PeerConfig, ONLINE},
|
||||
@ -1181,6 +1181,9 @@ pub fn main_start_grab_keyboard() -> SyncReturn<bool> {
|
||||
return SyncReturn(false);
|
||||
}
|
||||
crate::keyboard::client::start_grab_loop();
|
||||
if !is_can_input_monitoring(false) {
|
||||
return SyncReturn(false);
|
||||
}
|
||||
SyncReturn(true)
|
||||
}
|
||||
|
||||
|
@ -549,7 +549,7 @@ async fn check_pid(postfix: &str) {
|
||||
file.read_to_string(&mut content).ok();
|
||||
let pid = content.parse::<i32>().unwrap_or(0);
|
||||
if pid > 0 {
|
||||
use sysinfo::{ProcessExt, System, SystemExt};
|
||||
use hbb_common::sysinfo::{ProcessExt, System, SystemExt};
|
||||
let mut sys = System::new();
|
||||
sys.refresh_processes();
|
||||
if let Some(p) = sys.process(pid.into()) {
|
||||
|
@ -11,7 +11,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enable Service", "允许服务"),
|
||||
("Start Service", "启动服务"),
|
||||
("Service is running", "服务正在运行"),
|
||||
("Service is not running", "服务没有启动"),
|
||||
("Service is not running", "服务未运行"),
|
||||
("not_ready_status", "未就绪,请检查网络连接"),
|
||||
("Control Remote Desktop", "控制远程桌面"),
|
||||
("Transfer File", "传输文件"),
|
||||
@ -33,23 +33,23 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Export Server Config", "导出服务器配置"),
|
||||
("Import server configuration successfully", "导入服务器配置信息成功"),
|
||||
("Export server configuration successfully", "导出服务器配置信息成功"),
|
||||
("Invalid server configuration", "无效服务器配置,请修改后重新拷贝配置信息到剪贴板后点击此按钮"),
|
||||
("Clipboard is empty", "拷贝配置信息到剪贴板后点击此按钮,可以自动导入配置"),
|
||||
("Invalid server configuration", "服务器配置无效,请修改后重新复制配置信息到剪贴板,然后点击此按钮"),
|
||||
("Clipboard is empty", "复制配置信息到剪贴板后点击此按钮,可以自动导入配置"),
|
||||
("Stop service", "停止服务"),
|
||||
("Change ID", "改变ID"),
|
||||
("Your new ID", ""),
|
||||
("length %min% to %max%", ""),
|
||||
("starts with a letter", ""),
|
||||
("allowed characters", ""),
|
||||
("Change ID", "更改 ID"),
|
||||
("Your new ID", "你的新 ID"),
|
||||
("length %min% to %max%", "长度在 %min 与 %max 之间"),
|
||||
("starts with a letter", "以字母开头"),
|
||||
("allowed characters", "使用允许的字符"),
|
||||
("id_change_tip", "只可以使用字母 a-z, A-Z, 0-9, _ (下划线)。首字母必须是 a-z, A-Z。长度在 6 与 16 之间。"),
|
||||
("Website", "网站"),
|
||||
("About", "关于"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Privacy Statement", "隐私声明"),
|
||||
("Mute", "静音"),
|
||||
("Build Date", ""),
|
||||
("Version", ""),
|
||||
("Home", ""),
|
||||
("Build Date", "构建日期"),
|
||||
("Version", "版本"),
|
||||
("Home", "主页"),
|
||||
("Audio Input", "音频输入"),
|
||||
("Enhancements", "增强功能"),
|
||||
("Hardware Codec", "硬件编解码"),
|
||||
@ -61,7 +61,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Invalid IP", "无效 IP"),
|
||||
("Invalid format", "无效格式"),
|
||||
("server_not_support", "服务器暂不支持"),
|
||||
("Not available", "已被占用"),
|
||||
("Not available", "不可用"),
|
||||
("Too frequent", "修改太频繁,请稍后再试"),
|
||||
("Cancel", "取消"),
|
||||
("Skip", "跳过"),
|
||||
@ -72,12 +72,12 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Please enter your password", "请输入密码"),
|
||||
("Remember password", "记住密码"),
|
||||
("Wrong Password", "密码错误"),
|
||||
("Do you want to enter again?", "还想输入一次吗?"),
|
||||
("Do you want to enter again?", "是否要再次输入?"),
|
||||
("Connection Error", "连接错误"),
|
||||
("Error", "错误"),
|
||||
("Reset by the peer", "连接被对方关闭"),
|
||||
("Connecting...", "正在连接..."),
|
||||
("Connection in progress. Please wait.", "连接进行中,请稍等。"),
|
||||
("Connection in progress. Please wait.", "正在进行连接,请稍候。"),
|
||||
("Please try 1 minute later", "一分钟后再试"),
|
||||
("Login Error", "登录错误"),
|
||||
("Successful", "成功"),
|
||||
@ -102,14 +102,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Unselect All", "取消全选"),
|
||||
("Empty Directory", "空文件夹"),
|
||||
("Not an empty directory", "这不是一个空文件夹"),
|
||||
("Are you sure you want to delete this file?", "是否删除此文件?"),
|
||||
("Are you sure you want to delete this empty directory?", "是否删除此空文件夹?"),
|
||||
("Are you sure you want to delete the file of this directory?", "是否删除文件夹下的文件?"),
|
||||
("Are you sure you want to delete this file?", "是否删除此文件?"),
|
||||
("Are you sure you want to delete this empty directory?", "是否删除此空文件夹?"),
|
||||
("Are you sure you want to delete the file of this directory?", "是否删除此文件夹下的文件?"),
|
||||
("Do this for all conflicts", "应用于其它冲突"),
|
||||
("This is irreversible!", "此操作不可逆!"),
|
||||
("Deleting", "正在删除"),
|
||||
("files", "文件"),
|
||||
("Waiting", "等待..."),
|
||||
("Waiting", "正在等待..."),
|
||||
("Finished", "完成"),
|
||||
("Speed", "速度"),
|
||||
("Custom Image Quality", "设置画面质量"),
|
||||
@ -122,27 +122,27 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Stretch", "伸展"),
|
||||
("Scrollbar", "滚动条"),
|
||||
("ScrollAuto", "自动滚动"),
|
||||
("Good image quality", "好画质"),
|
||||
("Balanced", "一般画质"),
|
||||
("Optimize reaction time", "优化反应时间"),
|
||||
("Good image quality", "画质最优化"),
|
||||
("Balanced", "平衡"),
|
||||
("Optimize reaction time", "速度最优化"),
|
||||
("Custom", "自定义"),
|
||||
("Show remote cursor", "显示远程光标"),
|
||||
("Show quality monitor", "显示质量监测"),
|
||||
("Disable clipboard", "禁止剪贴板"),
|
||||
("Lock after session end", "断开后锁定远程电脑"),
|
||||
("Disable clipboard", "禁用剪贴板"),
|
||||
("Lock after session end", "会话结束后锁定远程电脑"),
|
||||
("Insert", "插入"),
|
||||
("Insert Lock", "锁定远程电脑"),
|
||||
("Refresh", "刷新画面"),
|
||||
("ID does not exist", "ID 不存在"),
|
||||
("Failed to connect to rendezvous server", "连接注册服务器失败"),
|
||||
("Please try later", "请稍后再试"),
|
||||
("Remote desktop is offline", "远程电脑不在线"),
|
||||
("Key mismatch", "Key不匹配"),
|
||||
("Remote desktop is offline", "远程电脑处于离线状态"),
|
||||
("Key mismatch", "密钥不匹配"),
|
||||
("Timeout", "连接超时"),
|
||||
("Failed to connect to relay server", "无法连接到中继服务器"),
|
||||
("Failed to connect via rendezvous server", "无法通过注册服务器建立连接"),
|
||||
("Failed to connect via relay server", "无法通过中继服务器建立连接"),
|
||||
("Failed to make direct connection to remote desktop", "无法建立直接连接"),
|
||||
("Failed to make direct connection to remote desktop", "无法直接连接到远程桌面"),
|
||||
("Set Password", "设置密码"),
|
||||
("OS Password", "操作系统密码"),
|
||||
("install_tip", "你正在运行未安装版本,由于 UAC 限制,作为被控端,会在某些情况下无法控制鼠标键盘,或者录制屏幕,请点击下面的按钮将 RustDesk 安装到系统,从而规避上述问题。"),
|
||||
@ -152,7 +152,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Configure", "配置"),
|
||||
("config_acc", "为了能够远程控制你的桌面, 请给予 RustDesk \"辅助功能\" 权限。"),
|
||||
("config_screen", "为了能够远程访问你的桌面, 请给予 RustDesk \"屏幕录制\" 权限。"),
|
||||
("Installing ...", "安装 ..."),
|
||||
("Installing ...", "安装中..."),
|
||||
("Install", "安装"),
|
||||
("Installation", "安装"),
|
||||
("Installation Path", "安装路径"),
|
||||
@ -161,7 +161,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("agreement_tip", "开始安装即表示接受许可协议。"),
|
||||
("Accept and Install", "同意并安装"),
|
||||
("End-user license agreement", "用户协议"),
|
||||
("Generating ...", "正在产生 ..."),
|
||||
("Generating ...", "正在生成..."),
|
||||
("Your installation is lower version.", "你安装的版本比当前运行的低。"),
|
||||
("not_close_tcp_tip", "请在使用隧道的时候,不要关闭本窗口"),
|
||||
("Listening ...", "正在等待隧道连接..."),
|
||||
@ -183,7 +183,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Allow using clipboard", "允许使用剪贴板"),
|
||||
("Allow hearing sound", "允许听到声音"),
|
||||
("Allow file copy and paste", "允许复制粘贴文件"),
|
||||
("Connected", "已经连接"),
|
||||
("Connected", "已连接"),
|
||||
("Direct and encrypted connection", "加密直连"),
|
||||
("Relayed and encrypted connection", "加密中继连接"),
|
||||
("Direct and unencrypted connection", "非加密直连"),
|
||||
@ -194,10 +194,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enable RDP session sharing", "允许 RDP 会话共享"),
|
||||
("Auto Login", "自动登录(设置断开后锁定才有效)"),
|
||||
("Enable Direct IP Access", "允许 IP 直接访问"),
|
||||
("Rename", "改名"),
|
||||
("Rename", "重命名"),
|
||||
("Space", "空格"),
|
||||
("Create Desktop Shortcut", "创建桌面快捷方式"),
|
||||
("Change Path", "改变路径"),
|
||||
("Change Path", "更改路径"),
|
||||
("Create Folder", "创建文件夹"),
|
||||
("Please enter the folder name", "请输入文件夹名称"),
|
||||
("Fix it", "修复"),
|
||||
@ -212,16 +212,16 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Invalid port", "无效端口"),
|
||||
("Closed manually by the peer", "被对方手动关闭"),
|
||||
("Enable remote configuration modification", "允许远程修改配置"),
|
||||
("Run without install", "无安装运行"),
|
||||
("Run without install", "不安装直接运行"),
|
||||
("Connect via relay", "中继连接"),
|
||||
("Always connect via relay", "强制走中继连接"),
|
||||
("whitelist_tip", "只有白名单里的ip才能访问我"),
|
||||
("whitelist_tip", "只有白名单里的 IP 才能访问本机"),
|
||||
("Login", "登录"),
|
||||
("Verify", "验证"),
|
||||
("Remember me", "记住我"),
|
||||
("Trust this device", "信任此设备"),
|
||||
("Verification code", "验证码"),
|
||||
("verification_tip", "检测到新设备登录,已向注册邮箱发送了登录验证码,输入验证码继续登录"),
|
||||
("verification_tip", "检测到新设备登录,已向注册邮箱发送了登录验证码,请输入验证码继续登录"),
|
||||
("Logout", "登出"),
|
||||
("Tags", "标签"),
|
||||
("Search ID", "查找 ID"),
|
||||
@ -232,9 +232,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Network error", "网络错误"),
|
||||
("Username missed", "用户名没有填写"),
|
||||
("Password missed", "密码没有填写"),
|
||||
("Wrong credentials", "提供的登入信息错误"),
|
||||
("Wrong credentials", "提供的登录信息错误"),
|
||||
("Edit Tag", "修改标签"),
|
||||
("Unremember Password", "忘掉密码"),
|
||||
("Unremember Password", "忘记密码"),
|
||||
("Favorites", "收藏"),
|
||||
("Add to Favorites", "加入到收藏"),
|
||||
("Remove from Favorites", "从收藏中删除"),
|
||||
@ -246,7 +246,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("install_daemon_tip", "为了开机启动,请安装系统服务。"),
|
||||
("Remote ID", "远程 ID"),
|
||||
("Paste", "粘贴"),
|
||||
("Paste here?", "粘贴到这里?"),
|
||||
("Paste here?", "粘贴到这里?"),
|
||||
("Are you sure to close the connection?", "是否确认关闭连接?"),
|
||||
("Download new version", "下载新版本"),
|
||||
("Touch mode", "触屏模式"),
|
||||
@ -284,7 +284,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Do you accept?", "是否接受?"),
|
||||
("Open System Setting", "打开系统设置"),
|
||||
("How to get Android input permission?", "如何获取安卓的输入权限?"),
|
||||
("android_input_permission_tip1", "为了让远程设备通过鼠标或触屏控制您的安卓设备,你需要允許 RustDesk 使用\"无障碍\"服务。"),
|
||||
("android_input_permission_tip1", "为了让远程设备通过鼠标或触屏控制您的安卓设备,你需要允许 RustDesk 使用\"无障碍\"服务。"),
|
||||
("android_input_permission_tip2", "请在接下来的系统设置页面里,找到并进入 [已安装的服务] 页面,将 [RustDesk Input] 服务开启。"),
|
||||
("android_new_connection_tip", "收到新的连接控制请求,对方想要控制你当前的设备。"),
|
||||
("android_service_will_start_tip", "开启录屏权限将自动开启服务,允许其他设备向此设备请求建立连接。"),
|
||||
@ -293,7 +293,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("android_start_service_tip", "点击 [启动服务] 或打开 [屏幕录制] 权限开启手机屏幕共享服务。"),
|
||||
("Account", "账户"),
|
||||
("Overwrite", "覆盖"),
|
||||
("This file exists, skip or overwrite this file?", "这个文件/文件夹已存在,跳过/覆盖?"),
|
||||
("This file exists, skip or overwrite this file?", "这个文件/文件夹已存在,跳过/覆盖?"),
|
||||
("Quit", "退出"),
|
||||
("doc_mac_permission", "https://rustdesk.com/docs/zh-cn/manual/mac#%E5%90%AF%E7%94%A8%E6%9D%83%E9%99%90"),
|
||||
("Help", "帮助"),
|
||||
@ -358,7 +358,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Direct IP Access", "IP 直接访问"),
|
||||
("Proxy", "代理"),
|
||||
("Apply", "应用"),
|
||||
("Disconnect all devices?", "断开所有远程连接?"),
|
||||
("Disconnect all devices?", "断开所有远程连接?"),
|
||||
("Clear", "清空"),
|
||||
("Audio Input Device", "音频输入设备"),
|
||||
("Deny remote access", "拒绝远程访问"),
|
||||
@ -396,7 +396,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("or", "或"),
|
||||
("Continue with", "使用"),
|
||||
("Elevate", "提权"),
|
||||
("Zoom cursor", "缩放鼠标"),
|
||||
("Zoom cursor", "缩放光标"),
|
||||
("Accept sessions via password", "只允许密码访问"),
|
||||
("Accept sessions via click", "只允许点击访问"),
|
||||
("Accept sessions via both", "允许密码或点击访问"),
|
||||
@ -417,7 +417,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Local keyboard type", "本地键盘类型"),
|
||||
("Select local keyboard type", "请选择本地键盘类型"),
|
||||
("software_render_tip", "如果你使用英伟达显卡, 并且远程窗口在会话建立后会立刻关闭, 那么安装 nouveau 驱动并且选择使用软件渲染可能会有帮助。重启软件后生效。"),
|
||||
("Always use software rendering", "使用软件渲染"),
|
||||
("Always use software rendering", "始终使用软件渲染"),
|
||||
("config_input", "为了能够通过键盘控制远程桌面, 请给予 RustDesk \"输入监控\" 权限。"),
|
||||
("config_microphone", "为了支持通过麦克风进行音频传输,请给予 RustDesk \"录音\"权限。"),
|
||||
("request_elevation_tip", "如果对面有人, 也可以请求提升权限。"),
|
||||
@ -439,19 +439,19 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Medium", "中"),
|
||||
("Strong", "强"),
|
||||
("Switch Sides", "反转访问方向"),
|
||||
("Please confirm if you want to share your desktop?", "请确认要让对方访问你的桌面?"),
|
||||
("Please confirm if you want to share your desktop?", "请确认是否要让对方访问你的桌面?"),
|
||||
("Display", "显示"),
|
||||
("Default View Style", "默认显示方式"),
|
||||
("Default Scroll Style", "默认滚动方式"),
|
||||
("Default Image Quality", "默认图像质量"),
|
||||
("Default Codec", "默认编解码"),
|
||||
("Bitrate", "波特率"),
|
||||
("Bitrate", "码率"),
|
||||
("FPS", "帧率"),
|
||||
("Auto", "自动"),
|
||||
("Other Default Options", "其它默认选项"),
|
||||
("Voice call", "语音通话"),
|
||||
("Text chat", "文字聊天"),
|
||||
("Stop voice call", "停止语音聊天"),
|
||||
("Stop voice call", "停止语音通话"),
|
||||
("relay_hint_tip", "可能无法直连,可以尝试中继连接。\n另外,如果想直接使用中继连接,可以在 ID 后面添加/r,或者在卡片选项里选择强制走中继连接。"),
|
||||
("Reconnect", "重连"),
|
||||
].iter().cloned().collect();
|
||||
|
@ -452,7 +452,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Voice call", "تماس صوتی"),
|
||||
("Text chat", "گفتگو متنی (چت متنی)"),
|
||||
("Stop voice call", "توقف تماس صوتی"),
|
||||
("relay_hint_tip", ""),
|
||||
("Reconnect", ""),
|
||||
("relay_hint_tip", " را به شناسه اضافه کنید یا گزینه \"همیشه از طریق رله متصل شوید\" را در کارت همتا انتخاب کنید. همچنین، اگر میخواهید فوراً از سرور رله استفاده کنید، میتوانید پسوند \"/r\".\n اتصال مستقیم ممکن است امکان پذیر نباشد. در این صورت می توانید سعی کنید از طریق سرور رله متصل شوید"),
|
||||
("Reconnect", "اتصال مجدد"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -558,7 +558,7 @@ pub fn hide_dock() {
|
||||
}
|
||||
|
||||
fn check_main_window() -> bool {
|
||||
use sysinfo::{ProcessExt, System, SystemExt};
|
||||
use hbb_common::sysinfo::{ProcessExt, System, SystemExt};
|
||||
let mut sys = System::new();
|
||||
sys.refresh_processes();
|
||||
let app = format!("/Applications/{}.app", crate::get_app_name());
|
||||
|
Loading…
Reference in New Issue
Block a user