feat, mouse wheel and touchpad scroll mode, default or reverse

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou
2023-09-10 14:14:57 +08:00
parent 405363da59
commit eb0a0662a3
7 changed files with 217 additions and 58 deletions

View File

@@ -138,6 +138,11 @@ const kRemoteScrollStyleAuto = 'scrollauto';
/// [kRemoteScrollStyleBar] Scroll image with scroll bar.
const kRemoteScrollStyleBar = 'scrollbar';
/// [kScrollModeDefault] Mouse or touchpad, the default scroll mode.
const kScrollModeDefault = 'default';
/// [kScrollModeReverse] Mouse or touchpad, the reverse scroll mode.
const kScrollModeReverse = 'reverse';
/// [kRemoteImageQualityBest] Best image quality.
const kRemoteImageQualityBest = 'best';

View File

@@ -105,6 +105,7 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
_TabInfo('Network', Icons.link_outlined, Icons.link),
_TabInfo(
'Display', Icons.desktop_windows_outlined, Icons.desktop_windows),
_TabInfo('Input', Icons.keyboard_outlined, Icons.keyboard),
_TabInfo('Account', Icons.person_outline, Icons.person),
_TabInfo('About', Icons.info_outline, Icons.info)
];
@@ -121,6 +122,7 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
_Safety(),
_Network(),
_Display(),
_Input(),
_Account(),
_About(),
];
@@ -1220,6 +1222,50 @@ class _DisplayState extends State<_Display> {
}
}
class _Input extends StatefulWidget {
const _Input({Key? key}) : super(key: key);
@override
State<_Input> createState() => _InputState();
}
class _InputState extends State<_Input> {
@override
Widget build(BuildContext context) {
final scrollController = ScrollController();
return DesktopScrollWrapper(
scrollController: scrollController,
child: ListView(
controller: scrollController,
physics: DraggableNeverScrollableScrollPhysics(),
children: [
scrollMode(context),
]).marginOnly(bottom: _kListViewBottomMargin));
}
Widget scrollMode(BuildContext context) {
final key = 'scroll_mode';
onChanged(String value) async {
await bind.mainSetUserDefaultOption(key: key, value: value);
setState(() {});
}
final groupValue = bind.mainGetUserDefaultOption(key: key);
return _Card(title: 'Default Scroll Mode', children: [
_Radio(context,
value: kScrollModeDefault,
groupValue: groupValue,
label: 'Default scroll',
onChanged: onChanged),
_Radio(context,
value: kScrollModeReverse,
groupValue: groupValue,
label: 'Reverse scroll',
onChanged: onChanged),
]);
}
}
class _Account extends StatefulWidget {
const _Account({Key? key}) : super(key: key);

View File

@@ -101,7 +101,7 @@ class ToolbarState {
class _ToolbarTheme {
static const Color blueColor = MyTheme.button;
static const Color hoverBlueColor = MyTheme.accent;
static Color inactiveColor = Colors.grey[800]!;
static Color inactiveColor = Colors.grey[800]!;
static Color hoverInactiveColor = Colors.grey[850]!;
static const Color redColor = Colors.redAccent;
@@ -546,9 +546,11 @@ class _PinMenu extends StatelessWidget {
assetName: state.pin ? "assets/pinned.svg" : "assets/unpinned.svg",
tooltip: state.pin ? 'Unpin Toolbar' : 'Pin Toolbar',
onPressed: state.switchPin,
color: state.pin ? _ToolbarTheme.blueColor : _ToolbarTheme.inactiveColor,
hoverColor:
state.pin ? _ToolbarTheme.hoverBlueColor : _ToolbarTheme.hoverInactiveColor,
color:
state.pin ? _ToolbarTheme.blueColor : _ToolbarTheme.inactiveColor,
hoverColor: state.pin
? _ToolbarTheme.hoverBlueColor
: _ToolbarTheme.hoverInactiveColor,
),
);
}
@@ -561,15 +563,18 @@ class _MobileActionMenu extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (!ffi.ffiModel.isPeerAndroid) return Offstage();
return Obx(()=>_IconMenuButton(
assetName: 'assets/actions_mobile.svg',
tooltip: 'Mobile Actions',
onPressed: () => ffi.dialogManager.toggleMobileActionsOverlay(ffi: ffi),
color: ffi.dialogManager.mobileActionsOverlayVisible.isTrue
? _ToolbarTheme.blueColor : _ToolbarTheme.inactiveColor,
hoverColor: ffi.dialogManager.mobileActionsOverlayVisible.isTrue
? _ToolbarTheme.hoverBlueColor : _ToolbarTheme.hoverInactiveColor,
));
return Obx(() => _IconMenuButton(
assetName: 'assets/actions_mobile.svg',
tooltip: 'Mobile Actions',
onPressed: () =>
ffi.dialogManager.toggleMobileActionsOverlay(ffi: ffi),
color: ffi.dialogManager.mobileActionsOverlayVisible.isTrue
? _ToolbarTheme.blueColor
: _ToolbarTheme.inactiveColor,
hoverColor: ffi.dialogManager.mobileActionsOverlayVisible.isTrue
? _ToolbarTheme.hoverBlueColor
: _ToolbarTheme.hoverInactiveColor,
));
}
}
@@ -1304,23 +1309,25 @@ class _KeyboardMenu extends StatelessWidget {
color: _ToolbarTheme.blueColor,
hoverColor: _ToolbarTheme.hoverBlueColor,
menuChildren: [
mode(modeOnly),
keyboardMode(modeOnly),
localKeyboardType(),
Divider(),
view_mode(),
viewMode(),
Divider(),
scrollMode(),
]);
}
mode(String? modeOnly) {
keyboardMode(String? modeOnly) {
return futureBuilder(future: () async {
return await bind.sessionGetKeyboardMode(sessionId: ffi.sessionId) ??
_kKeyLegacyMode;
}(), hasData: (data) {
final groupValue = data as String;
List<KeyboardModeMenu> modes = [
KeyboardModeMenu(key: _kKeyLegacyMode, menu: 'Legacy mode'),
KeyboardModeMenu(key: _kKeyMapMode, menu: 'Map mode'),
KeyboardModeMenu(key: _kKeyTranslateMode, menu: 'Translate mode'),
List<InputModeMenu> modes = [
InputModeMenu(key: _kKeyLegacyMode, menu: 'Legacy mode'),
InputModeMenu(key: _kKeyMapMode, menu: 'Map mode'),
InputModeMenu(key: _kKeyTranslateMode, menu: 'Translate mode'),
];
List<RdoMenuButton> list = [];
final enabled = !ffi.ffiModel.viewOnly;
@@ -1330,7 +1337,7 @@ class _KeyboardMenu extends StatelessWidget {
sessionId: ffi.sessionId, value: value);
}
for (KeyboardModeMenu mode in modes) {
for (InputModeMenu mode in modes) {
if (modeOnly != null && mode.key != modeOnly) {
continue;
} else if (!bind.sessionIsKeyboardModeSupported(
@@ -1379,7 +1386,7 @@ class _KeyboardMenu extends StatelessWidget {
);
}
view_mode() {
viewMode() {
final ffiModel = ffi.ffiModel;
final enabled = version_cmp(pi.version, '1.2.0') >= 0 && ffiModel.keyboard;
return CkbMenuButton(
@@ -1395,6 +1402,40 @@ class _KeyboardMenu extends StatelessWidget {
ffi: ffi,
child: Text(translate('View Mode')));
}
scrollMode() {
return futureBuilder(future: () async {
final mode = await bind.sessionGetScrollMode(sessionId: ffi.sessionId);
if (mode != null) {
return mode;
}
return bind.mainGetUserDefaultOption(key: 'scroll_mode');
}(), hasData: (data) {
final groupValue = data as String;
List<InputModeMenu> modes = [
InputModeMenu(key: kScrollModeDefault, menu: 'Default mode'),
InputModeMenu(key: kScrollModeReverse, menu: 'Reverse mode'),
];
List<RdoMenuButton> list = [];
final enabled = !ffi.ffiModel.viewOnly;
onChanged(String? value) async {
if (value == null) return;
await bind.sessionSetScrollMode(sessionId: ffi.sessionId, value: value);
}
for (InputModeMenu mode in modes) {
var text = translate(mode.menu);
list.add(RdoMenuButton<String>(
child: Text(text),
value: mode.key,
groupValue: groupValue,
onChanged: enabled ? onChanged : null,
ffi: ffi,
));
}
return Column(children: list);
});
}
}
class _ChatMenu extends StatefulWidget {
@@ -1592,26 +1633,26 @@ class _IconMenuButtonState extends State<_IconMenuButton> {
width: _ToolbarTheme.buttonSize,
height: _ToolbarTheme.buttonSize,
child: MenuItemButton(
style: ButtonStyle(
backgroundColor: MaterialStatePropertyAll(Colors.transparent),
padding: MaterialStatePropertyAll(EdgeInsets.zero),
overlayColor: MaterialStatePropertyAll(Colors.transparent)),
onHover: (value) => setState(() {
hover = value;
}),
onPressed: widget.onPressed,
child: Tooltip(
message: translate(widget.tooltip),
child: Material(
type: MaterialType.transparency,
child: Ink(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(_ToolbarTheme.iconRadius),
color: hover ? widget.hoverColor : widget.color,
),
child: icon)),
)
),
style: ButtonStyle(
backgroundColor: MaterialStatePropertyAll(Colors.transparent),
padding: MaterialStatePropertyAll(EdgeInsets.zero),
overlayColor: MaterialStatePropertyAll(Colors.transparent)),
onHover: (value) => setState(() {
hover = value;
}),
onPressed: widget.onPressed,
child: Tooltip(
message: translate(widget.tooltip),
child: Material(
type: MaterialType.transparency,
child: Ink(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(_ToolbarTheme.iconRadius),
color: hover ? widget.hoverColor : widget.color,
),
child: icon)),
)),
).marginSymmetric(
horizontal: widget.hMargin ?? _ToolbarTheme.buttonHMargin,
vertical: widget.vMargin ?? _ToolbarTheme.buttonVMargin);
@@ -1675,18 +1716,17 @@ class _IconSubmenuButtonState extends State<_IconSubmenuButton> {
onHover: (value) => setState(() {
hover = value;
}),
child: Tooltip(
message: translate(widget.tooltip),
child: Material(
child: Tooltip(
message: translate(widget.tooltip),
child: Material(
type: MaterialType.transparency,
child: Ink(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(_ToolbarTheme.iconRadius),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(_ToolbarTheme.iconRadius),
color: hover ? widget.hoverColor : widget.color,
),
child: icon))
),
),
child: icon))),
menuChildren: widget.menuChildren
.map((e) => _buildPointerTrackWidget(e, widget.ffi))
.toList()));
@@ -1973,11 +2013,11 @@ class _DraggableShowHideState extends State<_DraggableShowHide> {
}
}
class KeyboardModeMenu {
class InputModeMenu {
final String key;
final String menu;
KeyboardModeMenu({required this.key, required this.menu});
InputModeMenu({required this.key, required this.menu});
}
_menuDismissCallback(FFI ffi) => ffi.inputModel.refreshMousePos();