save pin option on remote menubar

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2022-11-10 14:32:22 +08:00
parent ac3c7a1fa8
commit 0cf2bfb5ef
4 changed files with 97 additions and 21 deletions

View File

@ -28,14 +28,14 @@ class RemotePage extends StatefulWidget {
RemotePage({
Key? key,
required this.id,
required this.menubarState,
}) : super(key: key);
final String id;
final MenubarState menubarState;
final SimpleWrapper<State<RemotePage>?> _lastState = SimpleWrapper(null);
FFI get ffi => (_lastState.value! as _RemotePageState)._ffi;
RxBool get showMenubar =>
(_lastState.value! as _RemotePageState)._showMenubar;
@override
State<RemotePage> createState() {
@ -50,7 +50,6 @@ class _RemotePageState extends State<RemotePage>
Timer? _timer;
String keyboardMode = "legacy";
final _cursorOverImage = false.obs;
final _showMenubar = false.obs;
late RxBool _showRemoteCursor;
late RxBool _remoteCursorMoved;
late RxBool _keyboardEnabled;
@ -239,7 +238,7 @@ class _RemotePageState extends State<RemotePage>
paints.add(RemoteMenubar(
id: widget.id,
ffi: _ffi,
show: _showMenubar,
state: widget.menubarState,
onEnterOrLeaveImageSetter: (func) => _onEnterOrLeaveImage4Menubar = func,
onEnterOrLeaveImageCleaner: () => _onEnterOrLeaveImage4Menubar = null,
));

View File

@ -9,6 +9,7 @@ import 'package:flutter_hbb/common/shared_state.dart';
import 'package:flutter_hbb/consts.dart';
import 'package:flutter_hbb/models/state_model.dart';
import 'package:flutter_hbb/desktop/pages/remote_page.dart';
import 'package:flutter_hbb/desktop/widgets/remote_menubar.dart';
import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
import 'package:flutter_hbb/desktop/widgets/material_mod_popup_menu.dart'
as mod_menu;
@ -43,9 +44,12 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
static const IconData selectedIcon = Icons.desktop_windows_sharp;
static const IconData unselectedIcon = Icons.desktop_windows_outlined;
late MenubarState _menubarState;
var connectionMap = RxList<Widget>.empty(growable: true);
_ConnectionTabPageState(Map<String, dynamic> params) {
_menubarState = MenubarState();
RemoteCountState.init();
final peerId = params['id'];
if (peerId != null) {
@ -59,6 +63,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
page: RemotePage(
key: ValueKey(peerId),
id: peerId,
menubarState: _menubarState,
),
));
_update_remote_count();
@ -88,7 +93,11 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
selectedIcon: selectedIcon,
unselectedIcon: unselectedIcon,
onTabCloseButton: () => tabController.closeBy(id),
page: RemotePage(key: ValueKey(id), id: id),
page: RemotePage(
key: ValueKey(id),
id: id,
menubarState: _menubarState,
),
));
} else if (call.method == "onDestroy") {
tabController.clear();
@ -99,6 +108,12 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
});
}
@override
void dispose() {
super.dispose();
_menubarState.save();
}
@override
Widget build(BuildContext context) {
final tabWidget = Container(
@ -177,7 +192,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
);
}
// to-do: some dup code to ../widgets/remote_menubar
// Note: Some dup code to ../widgets/remote_menubar
Widget _tabMenuBuilder(String key, CancelFunc cancelFunc) {
final List<MenuEntryBase<String>> menu = [];
const EdgeInsets padding = EdgeInsets.only(left: 8.0, right: 5.0);
@ -187,7 +202,6 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
final ffi = remotePage.ffi;
final pi = ffi.ffiModel.pi;
final perms = ffi.ffiModel.permissions;
final showMenuBar = remotePage.showMenubar;
menu.addAll([
MenuEntryButton<String>(
childBuilder: (TextStyle? style) => Text(
@ -202,11 +216,12 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
),
MenuEntryButton<String>(
childBuilder: (TextStyle? style) => Obx(() => Text(
translate(showMenuBar.isTrue ? 'Hide Menubar' : 'Show Menubar'),
translate(
_menubarState.show.isTrue ? 'Hide Menubar' : 'Show Menubar'),
style: style,
)),
proc: () {
showMenuBar.value = !showMenuBar.value;
_menubarState.switchShow();
cancelFunc();
},
padding: padding,

View File

@ -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:shared_preferences/shared_preferences.dart';
import 'package:get/get.dart';
import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart' as rxdart;
@ -21,6 +22,69 @@ import '../../common/shared_state.dart';
import './popup_menu.dart';
import './material_mod_popup_menu.dart' as mod_menu;
class MenubarState {
final kStoreKey = "remoteMenubarState";
late RxBool show;
late RxBool _pin;
MenubarState() {
final s = Get.find<SharedPreferences>().getString(kStoreKey);
if (s == null) {
_initSet(false, false);
}
try {
final m = jsonDecode(s!);
if (m == null) {
_initSet(false, false);
} else {
_initSet(m['pin'] ?? false, m['pin'] ?? false);
}
} catch (e) {
debugPrint('Failed to decode menubar state ${e.toString()}');
_initSet(false, false);
}
}
_initSet(bool s, bool p) {
show = RxBool(s);
_pin = RxBool(p);
}
bool get pin => _pin.value;
switchShow() async {
show.value = !show.value;
}
setShow(bool v) async {
if (show.value != v) {
show.value = v;
}
}
switchPin() async {
_pin.value = !_pin.value;
// Save everytime changed, as this func will not be called frequently
await save();
}
setPin(bool v) async {
if (_pin.value != v) {
_pin.value = v;
// Save everytime changed, as this func will not be called frequently
await save();
}
}
save() async {
final success = await Get.find<SharedPreferences>()
.setString(kStoreKey, jsonEncode({'pin': _pin.value}.toString()));
if (!success) {
debugPrint('Failed to save remote menu bar state');
}
}
}
class _MenubarTheme {
static const Color commonColor = MyTheme.accent;
// kMinInteractiveDimension
@ -31,7 +95,7 @@ class _MenubarTheme {
class RemoteMenubar extends StatefulWidget {
final String id;
final FFI ffi;
final RxBool show;
final MenubarState state;
final Function(Function(bool)) onEnterOrLeaveImageSetter;
final Function() onEnterOrLeaveImageCleaner;
@ -39,7 +103,7 @@ class RemoteMenubar extends StatefulWidget {
Key? key,
required this.id,
required this.ffi,
required this.show,
required this.state,
required this.onEnterOrLeaveImageSetter,
required this.onEnterOrLeaveImageCleaner,
}) : super(key: key);
@ -51,7 +115,6 @@ class RemoteMenubar extends StatefulWidget {
class _RemoteMenubarState extends State<RemoteMenubar> {
final Rx<Color> _hideColor = Colors.white12.obs;
final _rxHideReplay = rxdart.ReplaySubject<int>();
final _pinMenubar = false.obs;
bool _isCursorOverImage = false;
window_size.Screen? _screen;
@ -63,7 +126,8 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
setState(() {});
}
RxBool get show => widget.show;
RxBool get show => widget.state.show;
bool get pin => widget.state.pin;
@override
initState() {
@ -82,7 +146,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
.throttleTime(const Duration(milliseconds: 5000),
trailing: true, leading: false)
.listen((int v) {
if (_pinMenubar.isFalse && show.isTrue && _isCursorOverImage) {
if (!pin && show.isTrue && _isCursorOverImage) {
show.value = false;
}
});
@ -196,18 +260,15 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
Widget _buildPinMenubar(BuildContext context) {
return Obx(() => IconButton(
tooltip:
translate(_pinMenubar.isTrue ? 'Unpin menubar' : 'Pin menubar'),
tooltip: translate(pin ? 'Unpin menubar' : 'Pin menubar'),
onPressed: () {
_pinMenubar.value = !_pinMenubar.value;
widget.state.switchPin();
},
icon: Obx(() => Transform.rotate(
angle: _pinMenubar.isTrue ? math.pi / 4 : 0,
angle: pin ? math.pi / 4 : 0,
child: Icon(
Icons.push_pin,
color: _pinMenubar.isTrue
? _MenubarTheme.commonColor
: Colors.grey,
color: pin ? _MenubarTheme.commonColor : Colors.grey,
))),
));
}

View File

@ -8,6 +8,7 @@ class StateGlobal {
bool _fullscreen = false;
final RxBool _showTabBar = true.obs;
final RxDouble _resizeEdgeSize = 8.0.obs;
final RxBool showRemoteMenuBar = false.obs;
int get windowId => _windowId;
bool get fullscreen => _fullscreen;