Merge remote-tracking branch 'upstream/master' into file-manager-redesign

This commit is contained in:
NicKoehler 2023-02-22 23:01:31 +01:00
parent 922a70adb4
commit 12a33cdfbb
No known key found for this signature in database
GPG Key ID: BAE01394EB51AC58
31 changed files with 488 additions and 282 deletions

View File

@ -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
View 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

View File

@ -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
View 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

View File

@ -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:

View File

@ -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:

View File

@ -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
View File

@ -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",

View File

@ -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"

View File

@ -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
View 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

View File

@ -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/*

View File

@ -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()),
],
);

View File

@ -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));
}
}

View File

@ -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";

View File

@ -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(() {});
}
}

View File

@ -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) {

View File

@ -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();

View File

@ -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!}),

View File

@ -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) {

View File

@ -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:

View File

@ -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.

View File

@ -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"

View File

@ -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;

View File

@ -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();
}
}
};
});
}

View File

@ -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

View File

@ -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)
}

View File

@ -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()) {

View File

@ -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();

View File

@ -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();
}

View File

@ -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());