Merge pull request #2299 from fufesou/refact_remote_menubar
hide zoom-cursor if view-style is original
This commit is contained in:
commit
93e0533c84
@ -70,6 +70,30 @@ const kMouseControlDistance = 12;
|
||||
/// [kMouseControlTimeoutMSec] indicates the timeout (in milliseconds) that self-side can get control of mouse.
|
||||
const kMouseControlTimeoutMSec = 1000;
|
||||
|
||||
/// [kRemoteViewStyleOriginal] Show remote image without scaling.
|
||||
const kRemoteViewStyleOriginal = 'original';
|
||||
|
||||
/// [kRemoteViewStyleAdaptive] Show remote image scaling by ratio factor.
|
||||
const kRemoteViewStyleAdaptive = 'adaptive';
|
||||
|
||||
/// [kRemoteScrollStyleAuto] Scroll image auto by position.
|
||||
const kRemoteScrollStyleAuto = 'scrollauto';
|
||||
|
||||
/// [kRemoteScrollStyleBar] Scroll image with scroll bar.
|
||||
const kRemoteScrollStyleBar = 'scrollbar';
|
||||
|
||||
/// [kRemoteImageQualityBest] Best image quality.
|
||||
const kRemoteImageQualityBest = 'best';
|
||||
|
||||
/// [kRemoteImageQualityBalanced] Balanced image quality, mid performance.
|
||||
const kRemoteImageQualityBalanced = 'balanced';
|
||||
|
||||
/// [kRemoteImageQualityLow] Low image quality, better performance.
|
||||
const kRemoteImageQualityLow = 'low';
|
||||
|
||||
/// [kRemoteImageQualityCustom] Custom image quality.
|
||||
const kRemoteImageQualityCustom = 'custom';
|
||||
|
||||
/// flutter/packages/flutter/lib/src/services/keyboard_key.dart -> _keyLabels
|
||||
/// see [LogicalKeyboardKey.keyLabel]
|
||||
const Map<int, String> logicalKeyMap = <int, String>{
|
||||
|
@ -236,12 +236,12 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
||||
optionsGetter: () => [
|
||||
MenuEntryRadioOption(
|
||||
text: translate('Scale original'),
|
||||
value: 'original',
|
||||
value: kRemoteViewStyleOriginal,
|
||||
dismissOnClicked: true,
|
||||
),
|
||||
MenuEntryRadioOption(
|
||||
text: translate('Scale adaptive'),
|
||||
value: 'adaptive',
|
||||
value: kRemoteViewStyleAdaptive,
|
||||
dismissOnClicked: true,
|
||||
),
|
||||
],
|
||||
@ -249,8 +249,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
||||
// null means peer id is not found, which there's no need to care about
|
||||
await bind.sessionGetViewStyle(id: key) ?? '',
|
||||
optionSetter: (String oldValue, String newValue) async {
|
||||
await bind.sessionSetViewStyle(
|
||||
id: key, value: newValue);
|
||||
await bind.sessionSetViewStyle(id: key, value: newValue);
|
||||
ffi.canvasModel.updateViewStyle();
|
||||
cancelFunc();
|
||||
},
|
||||
|
@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hbb/models/chat_model.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
import 'package:flutter_hbb/consts.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:rxdart/rxdart.dart' as rxdart;
|
||||
@ -25,6 +26,7 @@ class MenubarState {
|
||||
final kStoreKey = 'remoteMenubarState';
|
||||
late RxBool show;
|
||||
late RxBool _pin;
|
||||
RxString viewStyle = RxString(kRemoteViewStyleOriginal);
|
||||
|
||||
MenubarState() {
|
||||
final s = bind.getLocalFlutterConfig(k: kStoreKey);
|
||||
@ -67,21 +69,25 @@ class MenubarState {
|
||||
switchPin() async {
|
||||
_pin.value = !_pin.value;
|
||||
// Save everytime changed, as this func will not be called frequently
|
||||
await save();
|
||||
await _savePin();
|
||||
}
|
||||
|
||||
setPin(bool v) async {
|
||||
if (_pin.value != v) {
|
||||
_pin.value = v;
|
||||
// Save everytime changed, as this func will not be called frequently
|
||||
await save();
|
||||
await _savePin();
|
||||
}
|
||||
}
|
||||
|
||||
save() async {
|
||||
_savePin() async {
|
||||
bind.setLocalFlutterConfig(
|
||||
k: kStoreKey, v: jsonEncode({'pin': _pin.value}));
|
||||
}
|
||||
|
||||
save() async {
|
||||
await _savePin();
|
||||
}
|
||||
}
|
||||
|
||||
class _MenubarTheme {
|
||||
@ -404,6 +410,8 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
||||
|
||||
Widget _buildDisplay(BuildContext context) {
|
||||
return FutureBuilder(future: () async {
|
||||
widget.state.viewStyle.value =
|
||||
await bind.sessionGetViewStyle(id: widget.id) ?? '';
|
||||
final supportedHwcodec =
|
||||
await bind.sessionSupportedHwcodec(id: widget.id);
|
||||
return {'supportedHwcodec': supportedHwcodec};
|
||||
@ -719,20 +727,24 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
||||
optionsGetter: () => [
|
||||
MenuEntryRadioOption(
|
||||
text: translate('Scale original'),
|
||||
value: 'original',
|
||||
value: kRemoteViewStyleOriginal,
|
||||
dismissOnClicked: true,
|
||||
),
|
||||
MenuEntryRadioOption(
|
||||
text: translate('Scale adaptive'),
|
||||
value: 'adaptive',
|
||||
value: kRemoteViewStyleAdaptive,
|
||||
dismissOnClicked: true,
|
||||
),
|
||||
],
|
||||
curOptionGetter: () async =>
|
||||
// null means peer id is not found, which there's no need to care about
|
||||
await bind.sessionGetViewStyle(id: widget.id) ?? '',
|
||||
curOptionGetter: () async {
|
||||
// null means peer id is not found, which there's no need to care about
|
||||
final viewStyle = await bind.sessionGetViewStyle(id: widget.id) ?? '';
|
||||
widget.state.viewStyle.value = viewStyle;
|
||||
return viewStyle;
|
||||
},
|
||||
optionSetter: (String oldValue, String newValue) async {
|
||||
await bind.sessionSetViewStyle(id: widget.id, value: newValue);
|
||||
widget.state.viewStyle.value = newValue;
|
||||
widget.ffi.canvasModel.updateViewStyle();
|
||||
},
|
||||
padding: padding,
|
||||
@ -744,12 +756,12 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
||||
optionsGetter: () => [
|
||||
MenuEntryRadioOption(
|
||||
text: translate('ScrollAuto'),
|
||||
value: 'scrollauto',
|
||||
value: kRemoteScrollStyleAuto,
|
||||
dismissOnClicked: true,
|
||||
),
|
||||
MenuEntryRadioOption(
|
||||
text: translate('Scrollbar'),
|
||||
value: 'scrollbar',
|
||||
value: kRemoteScrollStyleBar,
|
||||
dismissOnClicked: true,
|
||||
),
|
||||
],
|
||||
@ -769,22 +781,22 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
||||
optionsGetter: () => [
|
||||
MenuEntryRadioOption(
|
||||
text: translate('Good image quality'),
|
||||
value: 'best',
|
||||
value: kRemoteImageQualityBest,
|
||||
dismissOnClicked: true,
|
||||
),
|
||||
MenuEntryRadioOption(
|
||||
text: translate('Balanced'),
|
||||
value: 'balanced',
|
||||
value: kRemoteImageQualityBalanced,
|
||||
dismissOnClicked: true,
|
||||
),
|
||||
MenuEntryRadioOption(
|
||||
text: translate('Optimize reaction time'),
|
||||
value: 'low',
|
||||
value: kRemoteImageQualityLow,
|
||||
dismissOnClicked: true,
|
||||
),
|
||||
MenuEntryRadioOption(
|
||||
text: translate('Custom'),
|
||||
value: 'custom',
|
||||
value: kRemoteImageQualityCustom,
|
||||
dismissOnClicked: true),
|
||||
],
|
||||
curOptionGetter: () async =>
|
||||
@ -821,7 +833,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
||||
}
|
||||
}
|
||||
|
||||
if (newValue == 'custom') {
|
||||
if (newValue == kRemoteImageQualityCustom) {
|
||||
final btnClose = msgBoxButton(translate('Close'), () async {
|
||||
await setCustomValues();
|
||||
widget.ffi.dialogManager.dismissAll();
|
||||
@ -1089,24 +1101,26 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
||||
);
|
||||
}());
|
||||
|
||||
/// Show remote cursor
|
||||
displayMenu.add(() {
|
||||
final opt = 'zoom-cursor';
|
||||
final state = PeerBoolOption.find(widget.id, opt);
|
||||
return MenuEntrySwitch2<String>(
|
||||
switchType: SwitchType.scheckbox,
|
||||
text: translate('Zoom cursor'),
|
||||
getter: () {
|
||||
return state;
|
||||
},
|
||||
setter: (bool v) async {
|
||||
state.value = v;
|
||||
await bind.sessionToggleOption(id: widget.id, value: opt);
|
||||
},
|
||||
padding: padding,
|
||||
dismissOnClicked: true,
|
||||
);
|
||||
}());
|
||||
/// Show remote cursor scaling with image
|
||||
if (widget.state.viewStyle.value != kRemoteViewStyleOriginal) {
|
||||
displayMenu.add(() {
|
||||
final opt = 'zoom-cursor';
|
||||
final state = PeerBoolOption.find(widget.id, opt);
|
||||
return MenuEntrySwitch2<String>(
|
||||
switchType: SwitchType.scheckbox,
|
||||
text: translate('Zoom cursor'),
|
||||
getter: () {
|
||||
return state;
|
||||
},
|
||||
setter: (bool v) async {
|
||||
state.value = v;
|
||||
await bind.sessionToggleOption(id: widget.id, value: opt);
|
||||
},
|
||||
padding: padding,
|
||||
dismissOnClicked: true,
|
||||
);
|
||||
}());
|
||||
}
|
||||
|
||||
/// Show quality monitor
|
||||
displayMenu.add(MenuEntrySwitch<String>(
|
||||
@ -1179,7 +1193,6 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
||||
optionSetter: (String oldValue, String newValue) async {
|
||||
await bind.sessionSetKeyboardMode(
|
||||
id: widget.id, keyboardMode: newValue);
|
||||
widget.ffi.canvasModel.updateViewStyle();
|
||||
},
|
||||
)
|
||||
];
|
||||
|
@ -4,6 +4,7 @@ import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hbb/consts.dart';
|
||||
import 'package:flutter_hbb/mobile/widgets/gesture_help.dart';
|
||||
import 'package:flutter_hbb/models/chat_model.dart';
|
||||
import 'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart';
|
||||
@ -642,7 +643,7 @@ class _RemotePageState extends State<RemotePage> {
|
||||
// FIXME:
|
||||
// null means no session of id
|
||||
// empty string means no password
|
||||
var password = await bind.sessionGetOption(id: id, arg: "os-password");
|
||||
var password = await bind.sessionGetOption(id: id, arg: 'os-password');
|
||||
if (password != null) {
|
||||
bind.sessionInputOsPassword(id: widget.id, value: password);
|
||||
} else {
|
||||
@ -908,13 +909,13 @@ class ImagePainter extends CustomPainter {
|
||||
|
||||
void showOptions(
|
||||
BuildContext context, String id, OverlayDialogManager dialogManager) async {
|
||||
String quality = await bind.sessionGetImageQuality(id: id) ?? 'balanced';
|
||||
if (quality == '') quality = 'balanced';
|
||||
String quality =
|
||||
await bind.sessionGetImageQuality(id: id) ?? kRemoteImageQualityBalanced;
|
||||
if (quality == '') quality = kRemoteImageQualityBalanced;
|
||||
String codec =
|
||||
await bind.sessionGetOption(id: id, arg: 'codec-preference') ?? 'auto';
|
||||
if (codec == '') codec = 'auto';
|
||||
String viewStyle =
|
||||
await bind.sessionGetOption(id: id, arg: 'view-style') ?? '';
|
||||
String viewStyle = await bind.sessionGetViewStyle(id: id) ?? '';
|
||||
|
||||
var displays = <Widget>[];
|
||||
final pi = gFFI.ffiModel.pi;
|
||||
@ -1017,12 +1018,16 @@ void showOptions(
|
||||
}
|
||||
|
||||
final radios = [
|
||||
getRadio('Scale original', 'original', viewStyle, setViewStyle),
|
||||
getRadio('Scale adaptive', 'adaptive', viewStyle, setViewStyle),
|
||||
getRadio(
|
||||
'Scale original', kRemoteViewStyleOriginal, viewStyle, setViewStyle),
|
||||
getRadio(
|
||||
'Scale adaptive', kRemoteViewStyleAdaptive, viewStyle, setViewStyle),
|
||||
const Divider(color: MyTheme.border),
|
||||
getRadio('Good image quality', 'best', quality, setQuality),
|
||||
getRadio('Balanced', 'balanced', quality, setQuality),
|
||||
getRadio('Optimize reaction time', 'low', quality, setQuality),
|
||||
getRadio(
|
||||
'Good image quality', kRemoteImageQualityBest, quality, setQuality),
|
||||
getRadio('Balanced', kRemoteImageQualityBalanced, quality, setQuality),
|
||||
getRadio('Optimize reaction time', kRemoteImageQualityLow, quality,
|
||||
setQuality),
|
||||
const Divider(color: MyTheme.border)
|
||||
];
|
||||
|
||||
|
@ -565,7 +565,7 @@ class CanvasModel with ChangeNotifier {
|
||||
|
||||
updateScrollStyle() async {
|
||||
final style = await bind.sessionGetScrollStyle(id: id);
|
||||
if (style == 'scrollbar') {
|
||||
if (style == kRemoteScrollStyleBar) {
|
||||
_scrollStyle = ScrollStyle.scrollbar;
|
||||
_scrollX = 0.0;
|
||||
_scrollY = 0.0;
|
||||
|
@ -1,6 +1,5 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ffi::{OsStr, OsString},
|
||||
fs,
|
||||
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||
path::{Path, PathBuf},
|
||||
@ -896,13 +895,13 @@ impl PeerConfig {
|
||||
}
|
||||
|
||||
fn path(id: &str) -> PathBuf {
|
||||
let mut id_encoded: String;
|
||||
let id_encoded: String;
|
||||
|
||||
//If the id contains invalid chars, encode it
|
||||
let forbidden_paths = Regex::new(r".*[<>:/\\|\?\*].*").unwrap();
|
||||
if forbidden_paths.is_match(id) {
|
||||
id_encoded =
|
||||
("base64_".to_string() + base64::encode(id, base64::Variant::Original).as_str())
|
||||
"base64_".to_string() + base64::encode(id, base64::Variant::Original).as_str();
|
||||
} else {
|
||||
id_encoded = id.to_string();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user