Merge pull request #2299 from fufesou/refact_remote_menubar

hide zoom-cursor if view-style is original
This commit is contained in:
RustDesk 2022-11-24 11:31:07 +08:00 committed by GitHub
commit 93e0533c84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 92 additions and 52 deletions

View File

@ -70,6 +70,30 @@ const kMouseControlDistance = 12;
/// [kMouseControlTimeoutMSec] indicates the timeout (in milliseconds) that self-side can get control of mouse. /// [kMouseControlTimeoutMSec] indicates the timeout (in milliseconds) that self-side can get control of mouse.
const kMouseControlTimeoutMSec = 1000; const kMouseControlTimeoutMSec = 1000;
/// [kRemoteViewStyleOriginal] Show remote image without scaling.
const kRemoteViewStyleOriginal = 'original';
/// [kRemoteViewStyleAdaptive] Show remote image scaling by ratio factor.
const kRemoteViewStyleAdaptive = 'adaptive';
/// [kRemoteScrollStyleAuto] Scroll image auto by position.
const kRemoteScrollStyleAuto = 'scrollauto';
/// [kRemoteScrollStyleBar] Scroll image with scroll bar.
const kRemoteScrollStyleBar = 'scrollbar';
/// [kRemoteImageQualityBest] Best image quality.
const kRemoteImageQualityBest = 'best';
/// [kRemoteImageQualityBalanced] Balanced image quality, mid performance.
const kRemoteImageQualityBalanced = 'balanced';
/// [kRemoteImageQualityLow] Low image quality, better performance.
const kRemoteImageQualityLow = 'low';
/// [kRemoteImageQualityCustom] Custom image quality.
const kRemoteImageQualityCustom = 'custom';
/// flutter/packages/flutter/lib/src/services/keyboard_key.dart -> _keyLabels /// flutter/packages/flutter/lib/src/services/keyboard_key.dart -> _keyLabels
/// see [LogicalKeyboardKey.keyLabel] /// see [LogicalKeyboardKey.keyLabel]
const Map<int, String> logicalKeyMap = <int, String>{ const Map<int, String> logicalKeyMap = <int, String>{

View File

@ -236,12 +236,12 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
optionsGetter: () => [ optionsGetter: () => [
MenuEntryRadioOption( MenuEntryRadioOption(
text: translate('Scale original'), text: translate('Scale original'),
value: 'original', value: kRemoteViewStyleOriginal,
dismissOnClicked: true, dismissOnClicked: true,
), ),
MenuEntryRadioOption( MenuEntryRadioOption(
text: translate('Scale adaptive'), text: translate('Scale adaptive'),
value: 'adaptive', value: kRemoteViewStyleAdaptive,
dismissOnClicked: true, dismissOnClicked: true,
), ),
], ],
@ -249,8 +249,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
// null means peer id is not found, which there's no need to care about // null means peer id is not found, which there's no need to care about
await bind.sessionGetViewStyle(id: key) ?? '', await bind.sessionGetViewStyle(id: key) ?? '',
optionSetter: (String oldValue, String newValue) async { optionSetter: (String oldValue, String newValue) async {
await bind.sessionSetViewStyle( await bind.sessionSetViewStyle(id: key, value: newValue);
id: key, value: newValue);
ffi.canvasModel.updateViewStyle(); ffi.canvasModel.updateViewStyle();
cancelFunc(); cancelFunc();
}, },

View File

@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_hbb/models/chat_model.dart'; import 'package:flutter_hbb/models/chat_model.dart';
import 'package:flutter_hbb/models/state_model.dart'; import 'package:flutter_hbb/models/state_model.dart';
import 'package:flutter_hbb/consts.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart' as rxdart; import 'package:rxdart/rxdart.dart' as rxdart;
@ -25,6 +26,7 @@ class MenubarState {
final kStoreKey = 'remoteMenubarState'; final kStoreKey = 'remoteMenubarState';
late RxBool show; late RxBool show;
late RxBool _pin; late RxBool _pin;
RxString viewStyle = RxString(kRemoteViewStyleOriginal);
MenubarState() { MenubarState() {
final s = bind.getLocalFlutterConfig(k: kStoreKey); final s = bind.getLocalFlutterConfig(k: kStoreKey);
@ -67,21 +69,25 @@ class MenubarState {
switchPin() async { switchPin() async {
_pin.value = !_pin.value; _pin.value = !_pin.value;
// Save everytime changed, as this func will not be called frequently // Save everytime changed, as this func will not be called frequently
await save(); await _savePin();
} }
setPin(bool v) async { setPin(bool v) async {
if (_pin.value != v) { if (_pin.value != v) {
_pin.value = v; _pin.value = v;
// Save everytime changed, as this func will not be called frequently // Save everytime changed, as this func will not be called frequently
await save(); await _savePin();
} }
} }
save() async { _savePin() async {
bind.setLocalFlutterConfig( bind.setLocalFlutterConfig(
k: kStoreKey, v: jsonEncode({'pin': _pin.value})); k: kStoreKey, v: jsonEncode({'pin': _pin.value}));
} }
save() async {
await _savePin();
}
} }
class _MenubarTheme { class _MenubarTheme {
@ -404,6 +410,8 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
Widget _buildDisplay(BuildContext context) { Widget _buildDisplay(BuildContext context) {
return FutureBuilder(future: () async { return FutureBuilder(future: () async {
widget.state.viewStyle.value =
await bind.sessionGetViewStyle(id: widget.id) ?? '';
final supportedHwcodec = final supportedHwcodec =
await bind.sessionSupportedHwcodec(id: widget.id); await bind.sessionSupportedHwcodec(id: widget.id);
return {'supportedHwcodec': supportedHwcodec}; return {'supportedHwcodec': supportedHwcodec};
@ -719,20 +727,24 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
optionsGetter: () => [ optionsGetter: () => [
MenuEntryRadioOption( MenuEntryRadioOption(
text: translate('Scale original'), text: translate('Scale original'),
value: 'original', value: kRemoteViewStyleOriginal,
dismissOnClicked: true, dismissOnClicked: true,
), ),
MenuEntryRadioOption( MenuEntryRadioOption(
text: translate('Scale adaptive'), text: translate('Scale adaptive'),
value: 'adaptive', value: kRemoteViewStyleAdaptive,
dismissOnClicked: true, dismissOnClicked: true,
), ),
], ],
curOptionGetter: () async => curOptionGetter: () async {
// null means peer id is not found, which there's no need to care about // null means peer id is not found, which there's no need to care about
await bind.sessionGetViewStyle(id: widget.id) ?? '', final viewStyle = await bind.sessionGetViewStyle(id: widget.id) ?? '';
widget.state.viewStyle.value = viewStyle;
return viewStyle;
},
optionSetter: (String oldValue, String newValue) async { optionSetter: (String oldValue, String newValue) async {
await bind.sessionSetViewStyle(id: widget.id, value: newValue); await bind.sessionSetViewStyle(id: widget.id, value: newValue);
widget.state.viewStyle.value = newValue;
widget.ffi.canvasModel.updateViewStyle(); widget.ffi.canvasModel.updateViewStyle();
}, },
padding: padding, padding: padding,
@ -744,12 +756,12 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
optionsGetter: () => [ optionsGetter: () => [
MenuEntryRadioOption( MenuEntryRadioOption(
text: translate('ScrollAuto'), text: translate('ScrollAuto'),
value: 'scrollauto', value: kRemoteScrollStyleAuto,
dismissOnClicked: true, dismissOnClicked: true,
), ),
MenuEntryRadioOption( MenuEntryRadioOption(
text: translate('Scrollbar'), text: translate('Scrollbar'),
value: 'scrollbar', value: kRemoteScrollStyleBar,
dismissOnClicked: true, dismissOnClicked: true,
), ),
], ],
@ -769,22 +781,22 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
optionsGetter: () => [ optionsGetter: () => [
MenuEntryRadioOption( MenuEntryRadioOption(
text: translate('Good image quality'), text: translate('Good image quality'),
value: 'best', value: kRemoteImageQualityBest,
dismissOnClicked: true, dismissOnClicked: true,
), ),
MenuEntryRadioOption( MenuEntryRadioOption(
text: translate('Balanced'), text: translate('Balanced'),
value: 'balanced', value: kRemoteImageQualityBalanced,
dismissOnClicked: true, dismissOnClicked: true,
), ),
MenuEntryRadioOption( MenuEntryRadioOption(
text: translate('Optimize reaction time'), text: translate('Optimize reaction time'),
value: 'low', value: kRemoteImageQualityLow,
dismissOnClicked: true, dismissOnClicked: true,
), ),
MenuEntryRadioOption( MenuEntryRadioOption(
text: translate('Custom'), text: translate('Custom'),
value: 'custom', value: kRemoteImageQualityCustom,
dismissOnClicked: true), dismissOnClicked: true),
], ],
curOptionGetter: () async => curOptionGetter: () async =>
@ -821,7 +833,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
} }
} }
if (newValue == 'custom') { if (newValue == kRemoteImageQualityCustom) {
final btnClose = msgBoxButton(translate('Close'), () async { final btnClose = msgBoxButton(translate('Close'), () async {
await setCustomValues(); await setCustomValues();
widget.ffi.dialogManager.dismissAll(); widget.ffi.dialogManager.dismissAll();
@ -1089,7 +1101,8 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
); );
}()); }());
/// Show remote cursor /// Show remote cursor scaling with image
if (widget.state.viewStyle.value != kRemoteViewStyleOriginal) {
displayMenu.add(() { displayMenu.add(() {
final opt = 'zoom-cursor'; final opt = 'zoom-cursor';
final state = PeerBoolOption.find(widget.id, opt); final state = PeerBoolOption.find(widget.id, opt);
@ -1107,6 +1120,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
dismissOnClicked: true, dismissOnClicked: true,
); );
}()); }());
}
/// Show quality monitor /// Show quality monitor
displayMenu.add(MenuEntrySwitch<String>( displayMenu.add(MenuEntrySwitch<String>(
@ -1179,7 +1193,6 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
optionSetter: (String oldValue, String newValue) async { optionSetter: (String oldValue, String newValue) async {
await bind.sessionSetKeyboardMode( await bind.sessionSetKeyboardMode(
id: widget.id, keyboardMode: newValue); id: widget.id, keyboardMode: newValue);
widget.ffi.canvasModel.updateViewStyle();
}, },
) )
]; ];

View File

@ -4,6 +4,7 @@ import 'dart:ui' as ui;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_hbb/consts.dart';
import 'package:flutter_hbb/mobile/widgets/gesture_help.dart'; import 'package:flutter_hbb/mobile/widgets/gesture_help.dart';
import 'package:flutter_hbb/models/chat_model.dart'; import 'package:flutter_hbb/models/chat_model.dart';
import 'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart'; import 'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart';
@ -642,7 +643,7 @@ class _RemotePageState extends State<RemotePage> {
// FIXME: // FIXME:
// null means no session of id // null means no session of id
// empty string means no password // empty string means no password
var password = await bind.sessionGetOption(id: id, arg: "os-password"); var password = await bind.sessionGetOption(id: id, arg: 'os-password');
if (password != null) { if (password != null) {
bind.sessionInputOsPassword(id: widget.id, value: password); bind.sessionInputOsPassword(id: widget.id, value: password);
} else { } else {
@ -908,13 +909,13 @@ class ImagePainter extends CustomPainter {
void showOptions( void showOptions(
BuildContext context, String id, OverlayDialogManager dialogManager) async { BuildContext context, String id, OverlayDialogManager dialogManager) async {
String quality = await bind.sessionGetImageQuality(id: id) ?? 'balanced'; String quality =
if (quality == '') quality = 'balanced'; await bind.sessionGetImageQuality(id: id) ?? kRemoteImageQualityBalanced;
if (quality == '') quality = kRemoteImageQualityBalanced;
String codec = String codec =
await bind.sessionGetOption(id: id, arg: 'codec-preference') ?? 'auto'; await bind.sessionGetOption(id: id, arg: 'codec-preference') ?? 'auto';
if (codec == '') codec = 'auto'; if (codec == '') codec = 'auto';
String viewStyle = String viewStyle = await bind.sessionGetViewStyle(id: id) ?? '';
await bind.sessionGetOption(id: id, arg: 'view-style') ?? '';
var displays = <Widget>[]; var displays = <Widget>[];
final pi = gFFI.ffiModel.pi; final pi = gFFI.ffiModel.pi;
@ -1017,12 +1018,16 @@ void showOptions(
} }
final radios = [ final radios = [
getRadio('Scale original', 'original', viewStyle, setViewStyle), getRadio(
getRadio('Scale adaptive', 'adaptive', viewStyle, setViewStyle), 'Scale original', kRemoteViewStyleOriginal, viewStyle, setViewStyle),
getRadio(
'Scale adaptive', kRemoteViewStyleAdaptive, viewStyle, setViewStyle),
const Divider(color: MyTheme.border), const Divider(color: MyTheme.border),
getRadio('Good image quality', 'best', quality, setQuality), getRadio(
getRadio('Balanced', 'balanced', quality, setQuality), 'Good image quality', kRemoteImageQualityBest, quality, setQuality),
getRadio('Optimize reaction time', 'low', quality, setQuality), getRadio('Balanced', kRemoteImageQualityBalanced, quality, setQuality),
getRadio('Optimize reaction time', kRemoteImageQualityLow, quality,
setQuality),
const Divider(color: MyTheme.border) const Divider(color: MyTheme.border)
]; ];

View File

@ -565,7 +565,7 @@ class CanvasModel with ChangeNotifier {
updateScrollStyle() async { updateScrollStyle() async {
final style = await bind.sessionGetScrollStyle(id: id); final style = await bind.sessionGetScrollStyle(id: id);
if (style == 'scrollbar') { if (style == kRemoteScrollStyleBar) {
_scrollStyle = ScrollStyle.scrollbar; _scrollStyle = ScrollStyle.scrollbar;
_scrollX = 0.0; _scrollX = 0.0;
_scrollY = 0.0; _scrollY = 0.0;

View File

@ -1,6 +1,5 @@
use std::{ use std::{
collections::HashMap, collections::HashMap,
ffi::{OsStr, OsString},
fs, fs,
net::{IpAddr, Ipv4Addr, SocketAddr}, net::{IpAddr, Ipv4Addr, SocketAddr},
path::{Path, PathBuf}, path::{Path, PathBuf},
@ -896,13 +895,13 @@ impl PeerConfig {
} }
fn path(id: &str) -> PathBuf { fn path(id: &str) -> PathBuf {
let mut id_encoded: String; let id_encoded: String;
//If the id contains invalid chars, encode it //If the id contains invalid chars, encode it
let forbidden_paths = Regex::new(r".*[<>:/\\|\?\*].*").unwrap(); let forbidden_paths = Regex::new(r".*[<>:/\\|\?\*].*").unwrap();
if forbidden_paths.is_match(id) { if forbidden_paths.is_match(id) {
id_encoded = id_encoded =
("base64_".to_string() + base64::encode(id, base64::Variant::Original).as_str()) "base64_".to_string() + base64::encode(id, base64::Variant::Original).as_str();
} else { } else {
id_encoded = id.to_string(); id_encoded = id.to_string();
} }