mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-11-29 16:49:10 +08:00
Merge branch 'rustdesk:master' into master
This commit is contained in:
commit
082f851d4b
@ -43,7 +43,7 @@
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode|navigation"
|
||||
android:exported="true"
|
||||
android:hardwareAccelerated="true"
|
||||
android:launchMode="singleTop"
|
||||
|
@ -310,19 +310,19 @@ class ImageModel with ChangeNotifier {
|
||||
}
|
||||
|
||||
double get maxScale {
|
||||
if (_image == null) return 1.0;
|
||||
if (_image == null) return 1.5;
|
||||
final size = MediaQueryData.fromWindow(ui.window).size;
|
||||
final xscale = size.width / _image!.width;
|
||||
final yscale = size.height / _image!.height;
|
||||
return max(1.0, max(xscale, yscale));
|
||||
return max(1.5, max(xscale, yscale));
|
||||
}
|
||||
|
||||
double get minScale {
|
||||
if (_image == null) return 1.0;
|
||||
if (_image == null) return 1.5;
|
||||
final size = MediaQueryData.fromWindow(ui.window).size;
|
||||
final xscale = size.width / _image!.width;
|
||||
final yscale = size.height / _image!.height;
|
||||
return min(xscale, yscale);
|
||||
return min(xscale, yscale) / 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
@ -724,13 +724,17 @@ class FFI {
|
||||
|
||||
static void inputKey(String name, {bool? down, bool? press}) {
|
||||
if (!ffiModel.keyboard()) return;
|
||||
setByName(
|
||||
'input_key',
|
||||
json.encode(modify({
|
||||
'name': name,
|
||||
'down': (down ?? false).toString(),
|
||||
'press': (press ?? true).toString()
|
||||
})));
|
||||
final Map<String, String> out = Map();
|
||||
out['name'] = name;
|
||||
// default: down = false
|
||||
if (down == true) {
|
||||
out['down'] = "true";
|
||||
}
|
||||
// default: press = true
|
||||
if (press != false) {
|
||||
out['press'] = "true";
|
||||
}
|
||||
setByName('input_key', json.encode(modify(out)));
|
||||
}
|
||||
|
||||
static void moveMouse(double x, double y) {
|
||||
|
@ -343,9 +343,14 @@ class _RemotePageState extends State<RemotePage> {
|
||||
onKey: (data, e) {
|
||||
final key = e.logicalKey;
|
||||
if (e is RawKeyDownEvent) {
|
||||
if (e.repeat) {
|
||||
if (e.repeat &&
|
||||
!e.isAltPressed &&
|
||||
!e.isControlPressed &&
|
||||
!e.isShiftPressed &&
|
||||
!e.isMetaPressed) {
|
||||
sendRawKey(e, press: true);
|
||||
} else {
|
||||
sendRawKey(e, down: true);
|
||||
if (e.isAltPressed && !FFI.alt) {
|
||||
FFI.alt = true;
|
||||
} else if (e.isControlPressed && !FFI.ctrl) {
|
||||
@ -355,7 +360,6 @@ class _RemotePageState extends State<RemotePage> {
|
||||
} else if (e.isMetaPressed && !FFI.command) {
|
||||
FFI.command = true;
|
||||
}
|
||||
sendRawKey(e, down: true);
|
||||
}
|
||||
}
|
||||
// [!_showEdit] workaround for soft-keyboard's control_key like Backspace / Enter
|
||||
@ -481,6 +485,7 @@ class _RemotePageState extends State<RemotePage> {
|
||||
/// DoubleFiner -> right click
|
||||
/// HoldDrag -> left drag
|
||||
|
||||
Offset _cacheLongPressPosition = Offset(0, 0);
|
||||
Widget getBodyForMobileWithGesture() {
|
||||
final touchMode = FFI.ffiModel.touchMode;
|
||||
return getMixinGestureDetector(
|
||||
@ -504,10 +509,14 @@ class _RemotePageState extends State<RemotePage> {
|
||||
},
|
||||
onLongPressDown: (d) {
|
||||
if (touchMode) {
|
||||
FFI.cursorModel.move(d.localPosition.dx, d.localPosition.dy);
|
||||
_cacheLongPressPosition = d.localPosition;
|
||||
}
|
||||
},
|
||||
onLongPress: () {
|
||||
if (touchMode) {
|
||||
FFI.cursorModel
|
||||
.move(_cacheLongPressPosition.dx, _cacheLongPressPosition.dy);
|
||||
}
|
||||
FFI.tap(MouseButtons.right);
|
||||
},
|
||||
onDoubleFinerTap: (d) {
|
||||
@ -534,6 +543,15 @@ class _RemotePageState extends State<RemotePage> {
|
||||
if (touchMode) {
|
||||
FFI.cursorModel.move(d.localPosition.dx, d.localPosition.dy);
|
||||
FFI.sendMouse('down', MouseButtons.left);
|
||||
} else {
|
||||
final cursorX = FFI.cursorModel.x;
|
||||
final cursorY = FFI.cursorModel.y;
|
||||
final visible =
|
||||
FFI.cursorModel.getVisibleRect().inflate(1); // extend edges
|
||||
final size = MediaQueryData.fromWindow(ui.window).size;
|
||||
if (!visible.contains(Offset(cursorX, cursorY))) {
|
||||
FFI.cursorModel.move(size.width / 2, size.height / 2);
|
||||
}
|
||||
}
|
||||
},
|
||||
onOneFingerPanUpdate: (d) {
|
||||
|
@ -2,7 +2,7 @@ import 'dart:async';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
enum CustomTouchGestureState {
|
||||
enum GestureState {
|
||||
none,
|
||||
oneFingerPan,
|
||||
twoFingerScale,
|
||||
@ -35,64 +35,41 @@ class CustomTouchGestureRecognizer extends ScaleGestureRecognizer {
|
||||
GestureDragUpdateCallback? onThreeFingerVerticalDragUpdate;
|
||||
GestureDragEndCallback? onThreeFingerVerticalDragEnd;
|
||||
|
||||
var _currentState = CustomTouchGestureState.none;
|
||||
Timer? _startEventDebounceTimer;
|
||||
var _currentState = GestureState.none;
|
||||
Timer? _debounceTimer;
|
||||
|
||||
void _init() {
|
||||
debugPrint("CustomTouchGestureRecognizer init");
|
||||
onStart = (d) {
|
||||
_startEventDebounceTimer?.cancel();
|
||||
if (d.pointerCount == 1) {
|
||||
_currentState = CustomTouchGestureState.oneFingerPan;
|
||||
if (onOneFingerPanStart != null) {
|
||||
onOneFingerPanStart!(DragStartDetails(
|
||||
localPosition: d.localFocalPoint, globalPosition: d.focalPoint));
|
||||
}
|
||||
debugPrint("start oneFingerPan");
|
||||
} else if (d.pointerCount == 2) {
|
||||
if (_currentState == CustomTouchGestureState.threeFingerVerticalDrag) {
|
||||
// 3 -> 2 debounce
|
||||
_startEventDebounceTimer = Timer(Duration(milliseconds: 200), () {
|
||||
_currentState = CustomTouchGestureState.twoFingerScale;
|
||||
if (onTwoFingerScaleStart != null) {
|
||||
onTwoFingerScaleStart!(ScaleStartDetails(
|
||||
localFocalPoint: d.localFocalPoint,
|
||||
focalPoint: d.focalPoint));
|
||||
}
|
||||
debugPrint("debounce start twoFingerScale success");
|
||||
});
|
||||
}
|
||||
_currentState = CustomTouchGestureState.twoFingerScale;
|
||||
// startWatchTimer();
|
||||
if (onTwoFingerScaleStart != null) {
|
||||
onTwoFingerScaleStart!(ScaleStartDetails(
|
||||
localFocalPoint: d.localFocalPoint, focalPoint: d.focalPoint));
|
||||
}
|
||||
debugPrint("start twoFingerScale");
|
||||
} else if (d.pointerCount == 3) {
|
||||
_currentState = CustomTouchGestureState.threeFingerVerticalDrag;
|
||||
// onStart = (d) {};
|
||||
onUpdate = (d) {
|
||||
_debounceTimer?.cancel();
|
||||
if (d.pointerCount == 1 && _currentState != GestureState.oneFingerPan) {
|
||||
onOneFingerStartDebounce(d);
|
||||
} else if (d.pointerCount == 2 &&
|
||||
_currentState != GestureState.twoFingerScale) {
|
||||
onTwoFingerStartDebounce(d);
|
||||
} else if (d.pointerCount == 3 &&
|
||||
_currentState != GestureState.threeFingerVerticalDrag) {
|
||||
_currentState = GestureState.threeFingerVerticalDrag;
|
||||
if (onThreeFingerVerticalDragStart != null) {
|
||||
onThreeFingerVerticalDragStart!(
|
||||
DragStartDetails(globalPosition: d.localFocalPoint));
|
||||
}
|
||||
debugPrint("start threeFingerScale");
|
||||
// _reset();
|
||||
}
|
||||
};
|
||||
onUpdate = (d) {
|
||||
if (_currentState != CustomTouchGestureState.none) {
|
||||
if (_currentState != GestureState.none) {
|
||||
switch (_currentState) {
|
||||
case CustomTouchGestureState.oneFingerPan:
|
||||
case GestureState.oneFingerPan:
|
||||
if (onOneFingerPanUpdate != null) {
|
||||
onOneFingerPanUpdate!(_getDragUpdateDetails(d));
|
||||
}
|
||||
break;
|
||||
case CustomTouchGestureState.twoFingerScale:
|
||||
case GestureState.twoFingerScale:
|
||||
if (onTwoFingerScaleUpdate != null) {
|
||||
onTwoFingerScaleUpdate!(d);
|
||||
}
|
||||
break;
|
||||
case CustomTouchGestureState.threeFingerVerticalDrag:
|
||||
case GestureState.threeFingerVerticalDrag:
|
||||
if (onThreeFingerVerticalDragUpdate != null) {
|
||||
onThreeFingerVerticalDragUpdate!(_getDragUpdateDetails(d));
|
||||
}
|
||||
@ -105,21 +82,22 @@ class CustomTouchGestureRecognizer extends ScaleGestureRecognizer {
|
||||
};
|
||||
onEnd = (d) {
|
||||
debugPrint("ScaleGestureRecognizer onEnd");
|
||||
_debounceTimer?.cancel();
|
||||
// end
|
||||
switch (_currentState) {
|
||||
case CustomTouchGestureState.oneFingerPan:
|
||||
case GestureState.oneFingerPan:
|
||||
debugPrint("TwoFingerState.pan onEnd");
|
||||
if (onOneFingerPanEnd != null) {
|
||||
onOneFingerPanEnd!(_getDragEndDetails(d));
|
||||
}
|
||||
break;
|
||||
case CustomTouchGestureState.twoFingerScale:
|
||||
case GestureState.twoFingerScale:
|
||||
debugPrint("TwoFingerState.scale onEnd");
|
||||
if (onTwoFingerScaleEnd != null) {
|
||||
onTwoFingerScaleEnd!(d);
|
||||
}
|
||||
break;
|
||||
case CustomTouchGestureState.threeFingerVerticalDrag:
|
||||
case GestureState.threeFingerVerticalDrag:
|
||||
debugPrint("ThreeFingerState.vertical onEnd");
|
||||
if (onThreeFingerVerticalDragEnd != null) {
|
||||
onThreeFingerVerticalDragEnd!(_getDragEndDetails(d));
|
||||
@ -128,10 +106,50 @@ class CustomTouchGestureRecognizer extends ScaleGestureRecognizer {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_currentState = CustomTouchGestureState.none;
|
||||
_debounceTimer = Timer(Duration(milliseconds: 200), () {
|
||||
_currentState = GestureState.none;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
void onOneFingerStartDebounce(ScaleUpdateDetails d) {
|
||||
final start = (ScaleUpdateDetails d) {
|
||||
_currentState = GestureState.oneFingerPan;
|
||||
if (onOneFingerPanStart != null) {
|
||||
onOneFingerPanStart!(DragStartDetails(
|
||||
localPosition: d.localFocalPoint, globalPosition: d.focalPoint));
|
||||
}
|
||||
};
|
||||
if (_currentState != GestureState.none) {
|
||||
_debounceTimer = Timer(Duration(milliseconds: 200), () {
|
||||
start(d);
|
||||
debugPrint("debounce start oneFingerPan");
|
||||
});
|
||||
} else {
|
||||
start(d);
|
||||
debugPrint("start oneFingerPan");
|
||||
}
|
||||
}
|
||||
|
||||
void onTwoFingerStartDebounce(ScaleUpdateDetails d) {
|
||||
final start = (ScaleUpdateDetails d) {
|
||||
_currentState = GestureState.twoFingerScale;
|
||||
if (onTwoFingerScaleStart != null) {
|
||||
onTwoFingerScaleStart!(ScaleStartDetails(
|
||||
localFocalPoint: d.localFocalPoint, focalPoint: d.focalPoint));
|
||||
}
|
||||
};
|
||||
if (_currentState == GestureState.threeFingerVerticalDrag) {
|
||||
_debounceTimer = Timer(Duration(milliseconds: 200), () {
|
||||
start(d);
|
||||
debugPrint("debounce start twoFingerScale");
|
||||
});
|
||||
} else {
|
||||
start(d);
|
||||
debugPrint("start twoFingerScale");
|
||||
}
|
||||
}
|
||||
|
||||
DragUpdateDetails _getDragUpdateDetails(ScaleUpdateDetails d) =>
|
||||
DragUpdateDetails(
|
||||
globalPosition: d.focalPoint,
|
||||
|
@ -47,7 +47,7 @@ case "$1" in
|
||||
;;
|
||||
2)
|
||||
# for upgrade
|
||||
service rustdesk stop || true
|
||||
systemctl stop rustdesk || true
|
||||
;;
|
||||
esac
|
||||
|
||||
@ -61,10 +61,26 @@ systemctl start rustdesk
|
||||
update-desktop-database
|
||||
|
||||
%preun
|
||||
systemctl stop rustdesk || true
|
||||
systemctl disable rustdesk || true
|
||||
rm /etc/systemd/system/rustdesk.service || true
|
||||
case "$1" in
|
||||
0)
|
||||
# for uninstall
|
||||
systemctl stop rustdesk || true
|
||||
systemctl disable rustdesk || true
|
||||
rm /etc/systemd/system/rustdesk.service || true
|
||||
;;
|
||||
1)
|
||||
# for upgrade
|
||||
;;
|
||||
esac
|
||||
|
||||
%postun
|
||||
rm /usr/share/applications/rustdesk.desktop || true
|
||||
update-desktop-database
|
||||
case "$1" in
|
||||
0)
|
||||
# for uninstall
|
||||
rm /usr/share/applications/rustdesk.desktop || true
|
||||
update-desktop-database
|
||||
;;
|
||||
1)
|
||||
# for upgrade
|
||||
;;
|
||||
esac
|
||||
|
28
rpm.spec
28
rpm.spec
@ -48,7 +48,7 @@ case "$1" in
|
||||
;;
|
||||
2)
|
||||
# for upgrade
|
||||
service rustdesk stop || true
|
||||
systemctl stop rustdesk || true
|
||||
;;
|
||||
esac
|
||||
|
||||
@ -62,10 +62,26 @@ systemctl start rustdesk
|
||||
update-desktop-database
|
||||
|
||||
%preun
|
||||
systemctl stop rustdesk || true
|
||||
systemctl disable rustdesk || true
|
||||
rm /etc/systemd/system/rustdesk.service || true
|
||||
case "$1" in
|
||||
0)
|
||||
# for uninstall
|
||||
systemctl stop rustdesk || true
|
||||
systemctl disable rustdesk || true
|
||||
rm /etc/systemd/system/rustdesk.service || true
|
||||
;;
|
||||
1)
|
||||
# for upgrade
|
||||
;;
|
||||
esac
|
||||
|
||||
%postun
|
||||
rm /usr/share/applications/rustdesk.desktop || true
|
||||
update-desktop-database
|
||||
case "$1" in
|
||||
0)
|
||||
# for uninstall
|
||||
rm /usr/share/applications/rustdesk.desktop || true
|
||||
update-desktop-database
|
||||
;;
|
||||
1)
|
||||
# for upgrade
|
||||
;;
|
||||
esac
|
||||
|
26
src/lang.rs
26
src/lang.rs
@ -1,21 +1,43 @@
|
||||
use serde_json::{json, value::Value};
|
||||
use std::ops::Deref;
|
||||
|
||||
mod cn;
|
||||
mod cs;
|
||||
mod da;
|
||||
mod sk;
|
||||
mod de;
|
||||
mod en;
|
||||
mod es;
|
||||
mod eo;
|
||||
mod es;
|
||||
mod fr;
|
||||
mod id;
|
||||
mod it;
|
||||
mod ptbr;
|
||||
mod ru;
|
||||
mod sk;
|
||||
mod tr;
|
||||
mod tw;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref LANGS: Value =
|
||||
json!(vec![
|
||||
("en", "English"),
|
||||
("it", "Italiano"),
|
||||
("fr", "Français"),
|
||||
("de", "Deutsch"),
|
||||
("cn", "简体中文"),
|
||||
("tw", "繁體中文"),
|
||||
("pt", "Português"),
|
||||
("es", "Español"),
|
||||
("ru", "Русский"),
|
||||
("sk", "Slovenčina"),
|
||||
("id", "Indonesia"),
|
||||
("cs", "Čeština"),
|
||||
("da", "Dansk"),
|
||||
("eo", "Esperanto"),
|
||||
("tr", "Türkçe"),
|
||||
]);
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub fn translate(name: String) -> String {
|
||||
let locale = sys_locale::get_locale().unwrap_or_default().to_lowercase();
|
||||
|
@ -279,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", "退出"),
|
||||
("In privacy mode", "进入隐私模式"),
|
||||
("Out privacy mode", "退出隐私模式"),
|
||||
("Language", "语言"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -279,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", "Vypnutý"),
|
||||
("In privacy mode", "v režimu soukromí"),
|
||||
("Out privacy mode", "mimo režim soukromí"),
|
||||
("Language", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -279,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", "Slukket"),
|
||||
("In privacy mode", "I databeskyttelsestilstand"),
|
||||
("Out privacy mode", "Databeskyttelsestilstand fra"),
|
||||
("Language", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -279,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", "Ausgeschaltet"),
|
||||
("In privacy mode", "im Datenschutzmodus"),
|
||||
("Out privacy mode", "Datenschutzmodus aus"),
|
||||
("Language", "Sprache"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -279,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", ""),
|
||||
("In privacy mode", ""),
|
||||
("Out privacy mode", ""),
|
||||
("Language", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -279,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", "Apagado"),
|
||||
("In privacy mode", "En modo de privacidad"),
|
||||
("Out privacy mode", "Fuera del modo de privacidad"),
|
||||
("Language", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -279,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", "Éteindre"),
|
||||
("In privacy mode", "en mode privé"),
|
||||
("Out privacy mode", "hors mode de confidentialité"),
|
||||
("Language", "Langue"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -158,7 +158,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Allow using clipboard", "Izinkan menggunakan papan klip"),
|
||||
("Allow hearing sound", "Izinkan mendengarkan suara"),
|
||||
("Allow file copy and paste", "Izinkan penyalinan dan tempel file"),
|
||||
("File transfer", "Transfer file"),
|
||||
("Connected", "Terkoneksi"),
|
||||
("Direct and encrypted connection", "Koneksi langsung dan terenkripsi"),
|
||||
("Relayed and encrypted connection", "Koneksi relai dan terenkripsi"),
|
||||
@ -280,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", "Matikan"),
|
||||
("In privacy mode", "Dalam mode privasi"),
|
||||
("Out privacy mode", "Keluar dari mode privasi"),
|
||||
("Language", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -279,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", "Spegni"),
|
||||
("In privacy mode", "In modalità privacy"),
|
||||
("Out privacy mode", "Fuori modalità privacy"),
|
||||
("Language", "Linguaggio"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -279,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", "Desligado"),
|
||||
("In privacy mode", "No modo de privacidade"),
|
||||
("Out privacy mode", "Fora do modo de privacidade"),
|
||||
("Language", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -263,9 +263,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("android_version_audio_tip", "Текущая версия Android не поддерживает захват звука, обновите ее до Android 10 или выше."),
|
||||
("android_start_service_tip", "Нажмите [Запуск промежуточного сервера] или ОТКРЫТЬ разрешение [Захват экрана], чтобы запустить службу демонстрации экрана."),
|
||||
("Account", "Аккаунт"),
|
||||
("Quit", "Выйти"),
|
||||
("Overwrite", "Перезаписать"),
|
||||
("This file exists, skip or overwrite this file?", "Этот файл существует, пропустить или перезаписать этот файл?"),
|
||||
("Quit", "Выйти"),
|
||||
("doc_mac_permission", "https://rustdesk.com/docs/ru/manual/mac/#включение-разрешений"),
|
||||
("Help", "Помощь"),
|
||||
("Failed", "Неуспешный"),
|
||||
@ -279,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", "Выключен"),
|
||||
("In privacy mode", "В режиме конфиденциальности"),
|
||||
("Out privacy mode", "Выход из режима конфиденциальности"),
|
||||
("Language", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -279,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", "Vypnutý"),
|
||||
("In privacy mode", "V režime súkromia"),
|
||||
("Out privacy mode", "Mimo režimu súkromia"),
|
||||
("Language", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -264,7 +264,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", ""),
|
||||
("Help", ""),
|
||||
@ -279,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", ""),
|
||||
("In privacy mode", ""),
|
||||
("Out privacy mode", ""),
|
||||
("Language", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -279,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", "Kapalı"),
|
||||
("In privacy mode", "Gizlilik modunda"),
|
||||
("Out privacy mode", "Gizlilik modu dışında"),
|
||||
("Language", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -262,13 +262,12 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("android_stop_service_tip", "關閉服務將自動關閉所有已建立的連接。"),
|
||||
("android_version_audio_tip", "目前的 Android 版本不支持音訊錄製,請升級至 Android 10 或以上版本。"),
|
||||
("android_start_service_tip", "點擊 「啟動服務」 或啟用 「畫面錄製」 權限以開啟手機畫面共享服務。"),
|
||||
("Account", "帳號"),
|
||||
("Quit", "退出"),
|
||||
("Account", "帳戶"),
|
||||
("Overwrite", "覆寫"),
|
||||
("This file exists, skip or overwrite this file?", "此檔案/資料夾已存在,要跳過或是覆寫此檔案嗎?"),
|
||||
("Quit", "退出"),
|
||||
("doc_mac_permission", "https://rustdesk.com/docs/zh-tw/manual/mac/#啟用權限"),
|
||||
("Help", "幫助"),
|
||||
("Account", "帳戶"),
|
||||
("Failed", "失敗"),
|
||||
("Succeeded", "成功"),
|
||||
("Someone turns on privacy mode, exit", "其他用戶開啟隱私模式,退出"),
|
||||
@ -280,5 +279,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Turned off", "退出"),
|
||||
("In privacy mode", "開啟隱私模式"),
|
||||
("Out privacy mode", "退出隱私模式"),
|
||||
("Language", "語言"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -1059,6 +1059,7 @@ sc start {app_name}
|
||||
sc stop {app_name}
|
||||
sc delete {app_name}
|
||||
{after_install}
|
||||
{sleep}
|
||||
",
|
||||
uninstall_str=uninstall_str,
|
||||
path=path,
|
||||
@ -1081,6 +1082,11 @@ sc delete {app_name}
|
||||
config_path=Config::file().to_str().unwrap_or(""),
|
||||
lic=register_licence(),
|
||||
after_install=get_after_install(&exe),
|
||||
sleep=if debug {
|
||||
"timeout 300"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
);
|
||||
run_cmds(cmds, debug, "install")?;
|
||||
std::thread::sleep(std::time::Duration::from_millis(2000));
|
||||
|
@ -3,9 +3,9 @@ mod cm;
|
||||
mod inline;
|
||||
#[cfg(target_os = "macos")]
|
||||
mod macos;
|
||||
pub mod remote;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub mod win_privacy;
|
||||
pub mod remote;
|
||||
use crate::common::SOFTWARE_UPDATE_URL;
|
||||
use crate::ipc;
|
||||
use hbb_common::{
|
||||
@ -702,7 +702,7 @@ impl UI {
|
||||
let p = "explorer";
|
||||
#[cfg(target_os = "macos")]
|
||||
let p = "open";
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(target_os = "linux")]
|
||||
let p = if std::path::Path::new("/usr/bin/firefox").exists() {
|
||||
"firefox"
|
||||
} else {
|
||||
@ -753,6 +753,10 @@ impl UI {
|
||||
self.get_option_("custom-rendezvous-server"),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_langs(&self) -> String {
|
||||
crate::lang::LANGS.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl sciter::EventHandler for UI {
|
||||
@ -829,6 +833,7 @@ impl sciter::EventHandler for UI {
|
||||
fn discover();
|
||||
fn get_lan_peers();
|
||||
fn get_uuid();
|
||||
fn get_langs();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,8 +163,43 @@ class AudioInputs: Reactor.Component {
|
||||
}
|
||||
this.toggleMenuState();
|
||||
}
|
||||
};
|
||||
|
||||
class Languages: Reactor.Component {
|
||||
function render() {
|
||||
var langs = JSON.parse(handler.get_langs());
|
||||
var me = this;
|
||||
self.timer(1ms, function() { me.toggleMenuState() });
|
||||
return <li>{translate('Language')}
|
||||
<menu #languages key={langs.length}>
|
||||
<li id="default"><span>{svg_checkmark}</span>Default</li>
|
||||
<div .separator />
|
||||
{langs.map(function(lang) {
|
||||
return <li id={lang[0]}><span>{svg_checkmark}</span>{lang[1]}</li>;
|
||||
})}
|
||||
</menu>
|
||||
</li>;
|
||||
}
|
||||
|
||||
|
||||
function toggleMenuState() {
|
||||
var cur = handler.get_local_option("lang") || "default";
|
||||
for (var el in this.$$(menu#languages>li)) {
|
||||
var selected = cur == el.id;
|
||||
el.attributes.toggleClass("selected", selected);
|
||||
}
|
||||
}
|
||||
|
||||
event click $(menu#languages>li) (_, me) {
|
||||
var v = me.id;
|
||||
if (v == "default") v = "";
|
||||
handler.set_local_option("lang", v);
|
||||
app.update();
|
||||
this.toggleMenuState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getUserName() {
|
||||
try {
|
||||
return JSON.parse(handler.get_local_option("user_info")).name;
|
||||
@ -222,7 +257,7 @@ class MyIdMenu: Reactor.Component {
|
||||
{handler.is_ok_change_id() && key_confirmed ? <li #change-id>{translate('Change ID')}</li> : ""}
|
||||
<div .separator />
|
||||
<li #allow-darktheme><span>{svg_checkmark}</span>{translate('Dark Theme')}</li>
|
||||
<div .separator />
|
||||
<Languages />
|
||||
<li #about>{translate('About')} {" "}{handler.get_app_name()}</li>
|
||||
</menu>
|
||||
</popup>;
|
||||
|
@ -1956,11 +1956,11 @@ impl Remote {
|
||||
let mut config: PeerConfig = self.handler.load_config();
|
||||
let mut transfer_metas = TransferSerde::default();
|
||||
for job in self.read_jobs.iter() {
|
||||
let json_str = serde_json::to_string(&job.gen_meta()).unwrap();
|
||||
let json_str = serde_json::to_string(&job.gen_meta()).unwrap_or_default();
|
||||
transfer_metas.read_jobs.push(json_str);
|
||||
}
|
||||
for job in self.write_jobs.iter() {
|
||||
let json_str = serde_json::to_string(&job.gen_meta()).unwrap();
|
||||
let json_str = serde_json::to_string(&job.gen_meta()).unwrap_or_default();
|
||||
transfer_metas.write_jobs.push(json_str);
|
||||
}
|
||||
log::info!("meta: {:?}", transfer_metas);
|
||||
@ -2371,7 +2371,7 @@ impl Remote {
|
||||
}
|
||||
back_notification::PrivacyModeState::OffSucceeded => {
|
||||
self.handler
|
||||
.msgbox("custom-nocancel", "Privacy mode", "Out privacy mode");
|
||||
.msgbox("custom-nocancel", "Privacy mode", "Out privacy mode");
|
||||
self.update_privacy_mode(false);
|
||||
}
|
||||
back_notification::PrivacyModeState::OffByPeer => {
|
||||
|
Loading…
Reference in New Issue
Block a user