From 491317bd6fe5cd931e61215a0c40e101a705054b Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Tue, 14 Feb 2023 13:57:33 +0100 Subject: [PATCH 1/5] modernized menu bar --- flutter/assets/actions.svg | 3 + flutter/assets/chat.svg | 3 +- flutter/assets/close.svg | 2 + flutter/assets/display.svg | 2 + flutter/assets/fullscreen.svg | 2 + flutter/assets/fullscreen_exit.svg | 2 + flutter/assets/keyboard.svg | 2 + flutter/assets/pinned.svg | 2 + flutter/assets/rec.svg | 2 + flutter/assets/unpinned.svg | 2 + .../lib/desktop/widgets/remote_menubar.dart | 227 +++++++++--------- 11 files changed, 138 insertions(+), 111 deletions(-) create mode 100644 flutter/assets/actions.svg create mode 100644 flutter/assets/close.svg create mode 100644 flutter/assets/display.svg create mode 100644 flutter/assets/fullscreen.svg create mode 100644 flutter/assets/fullscreen_exit.svg create mode 100644 flutter/assets/keyboard.svg create mode 100644 flutter/assets/pinned.svg create mode 100644 flutter/assets/rec.svg create mode 100644 flutter/assets/unpinned.svg diff --git a/flutter/assets/actions.svg b/flutter/assets/actions.svg new file mode 100644 index 000000000..feaf416cd --- /dev/null +++ b/flutter/assets/actions.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/flutter/assets/chat.svg b/flutter/assets/chat.svg index 03491be6e..830ef0d33 100644 --- a/flutter/assets/chat.svg +++ b/flutter/assets/chat.svg @@ -1 +1,2 @@ - \ No newline at end of file + + \ No newline at end of file diff --git a/flutter/assets/close.svg b/flutter/assets/close.svg new file mode 100644 index 000000000..1e9a30711 --- /dev/null +++ b/flutter/assets/close.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/flutter/assets/display.svg b/flutter/assets/display.svg new file mode 100644 index 000000000..8a87116ff --- /dev/null +++ b/flutter/assets/display.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/flutter/assets/fullscreen.svg b/flutter/assets/fullscreen.svg new file mode 100644 index 000000000..73d79cf0e --- /dev/null +++ b/flutter/assets/fullscreen.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/flutter/assets/fullscreen_exit.svg b/flutter/assets/fullscreen_exit.svg new file mode 100644 index 000000000..f2b3ae27b --- /dev/null +++ b/flutter/assets/fullscreen_exit.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/flutter/assets/keyboard.svg b/flutter/assets/keyboard.svg new file mode 100644 index 000000000..569c68727 --- /dev/null +++ b/flutter/assets/keyboard.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/flutter/assets/pinned.svg b/flutter/assets/pinned.svg new file mode 100644 index 000000000..2563015f7 --- /dev/null +++ b/flutter/assets/pinned.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/flutter/assets/rec.svg b/flutter/assets/rec.svg new file mode 100644 index 000000000..14546b971 --- /dev/null +++ b/flutter/assets/rec.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/flutter/assets/unpinned.svg b/flutter/assets/unpinned.svg new file mode 100644 index 000000000..ba4ab5328 --- /dev/null +++ b/flutter/assets/unpinned.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 6bb49000b..77d687d93 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -405,9 +405,10 @@ class _RemoteMenubarState extends State { Widget _buildMenubar(BuildContext context) { final List menubarItems = []; + final double iconSize = Theme.of(context).iconTheme.size ?? 30.0; if (!isWebDesktop) { - menubarItems.add(_buildPinMenubar(context)); - menubarItems.add(_buildFullscreen(context)); + menubarItems.add(_buildPinMenubar(context, iconSize)); + menubarItems.add(_buildFullscreen(context, iconSize)); if (widget.ffi.ffiModel.isPeerAndroid) { menubarItems.add(IconButton( tooltip: translate('Mobile Actions'), @@ -420,77 +421,84 @@ class _RemoteMenubarState extends State { )); } } - menubarItems.add(_buildMonitor(context)); - menubarItems.add(_buildControl(context)); - menubarItems.add(_buildDisplay(context)); - menubarItems.add(_buildKeyboard(context)); + menubarItems.add(_buildMonitor(context, iconSize)); + menubarItems.add(_buildControl(context, iconSize)); + menubarItems.add(_buildDisplay(context, iconSize)); + menubarItems.add(_buildKeyboard(context, iconSize)); if (!isWeb) { - menubarItems.add(_buildChat(context)); - menubarItems.add(_buildVoiceCall(context)); + menubarItems.add(_buildChat(context, iconSize)); + menubarItems.add(_buildVoiceCall(context, iconSize)); } - menubarItems.add(_buildRecording(context)); - menubarItems.add(_buildClose(context)); + menubarItems.add(_buildRecording(context, iconSize)); + menubarItems.add(_buildClose(context, iconSize)); return PopupMenuTheme( - data: const PopupMenuThemeData( - textStyle: TextStyle(color: _MenubarTheme.commonColor)), - child: Column(mainAxisSize: MainAxisSize.min, children: [ + data: const PopupMenuThemeData( + textStyle: TextStyle(color: _MenubarTheme.commonColor)), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ Container( - decoration: BoxDecoration( - color: Colors.white, - border: Border.all(color: MyTheme.border), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.vertical( + bottom: Radius.circular(10), ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: menubarItems, - )), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: menubarItems, + ), + ), _buildDraggableShowHide(context), - ])); + ], + ), + ); } - Widget _buildPinMenubar(BuildContext context) { - return Obx(() => IconButton( - tooltip: translate(pin ? 'Unpin menubar' : 'Pin menubar'), - onPressed: () { - widget.state.switchPin(); - }, - icon: Obx(() => Transform.rotate( - angle: pin ? math.pi / 4 : 0, - child: Icon( - Icons.push_pin, - color: pin ? _MenubarTheme.commonColor : Colors.grey, - ))), - )); + Widget _buildPinMenubar(BuildContext context, double iconSize) { + return Obx( + () => IconButton( + padding: EdgeInsets.zero, + iconSize: iconSize, + tooltip: translate(pin ? 'Unpin menubar' : 'Pin menubar'), + onPressed: () { + widget.state.switchPin(); + }, + icon: SvgPicture.asset( + pin ? "assets/pinned.svg" : "assets/unpinned.svg", + color: pin ? _MenubarTheme.commonColor : Colors.grey[800], + ), + ), + ); } - Widget _buildFullscreen(BuildContext context) { + Widget _buildFullscreen(BuildContext context, double iconSize) { return IconButton( + padding: EdgeInsets.zero, + iconSize: iconSize, tooltip: translate(isFullscreen ? 'Exit Fullscreen' : 'Fullscreen'), onPressed: () { _setFullscreen(!isFullscreen); }, - icon: isFullscreen - ? const Icon( - Icons.fullscreen_exit, - color: _MenubarTheme.commonColor, - ) - : const Icon( - Icons.fullscreen, - color: _MenubarTheme.commonColor, - ), + icon: SvgPicture.asset( + isFullscreen ? "assets/fullscreen_exit.svg" : "assets/fullscreen.svg", + color: _MenubarTheme.commonColor, + ), ); } - Widget _buildMonitor(BuildContext context) { + Widget _buildMonitor(BuildContext context, double iconSize) { final pi = widget.ffi.ffiModel.pi; return mod_menu.PopupMenuButton( + iconSize: iconSize, tooltip: translate('Select Monitor'), padding: EdgeInsets.zero, position: mod_menu.PopupMenuPosition.under, icon: Stack( alignment: Alignment.center, children: [ - const Icon( - Icons.personal_video, + SvgPicture.asset( + "assets/display.svg", color: _MenubarTheme.commonColor, ), Padding( @@ -499,8 +507,7 @@ class _RemoteMenubarState extends State { RxInt display = CurrentDisplayState.find(widget.id); return Text( '${display.value + 1}/${pi.displays.length}', - style: const TextStyle( - color: _MenubarTheme.commonColor, fontSize: 8), + style: const TextStyle(color: Colors.white, fontSize: 8), ); }), ) @@ -513,23 +520,22 @@ class _RemoteMenubarState extends State { Stack( alignment: Alignment.center, children: [ - const Icon( - Icons.personal_video, - color: _MenubarTheme.commonColor, - ), + SvgPicture.asset("assets/display.svg"), TextButton( child: Container( - alignment: AlignmentDirectional.center, - constraints: - const BoxConstraints(minHeight: _MenubarTheme.height), - child: Padding( - padding: const EdgeInsets.only(bottom: 2.5), - child: Text( - (i + 1).toString(), - style: - const TextStyle(color: _MenubarTheme.commonColor), + alignment: AlignmentDirectional.center, + constraints: + const BoxConstraints(minHeight: _MenubarTheme.height), + child: Padding( + padding: const EdgeInsets.only(bottom: 2.5), + child: Text( + (i + 1).toString(), + style: TextStyle( + color: Theme.of(context).scaffoldBackgroundColor, ), - )), + ), + ), + ), onPressed: () { if (Navigator.canPop(context)) { Navigator.pop(context); @@ -561,11 +567,12 @@ class _RemoteMenubarState extends State { ); } - Widget _buildControl(BuildContext context) { + Widget _buildControl(BuildContext context, double iconSize) { return mod_menu.PopupMenuButton( + iconSize: iconSize, padding: EdgeInsets.zero, - icon: const Icon( - Icons.bolt, + icon: SvgPicture.asset( + "assets/actions.svg", color: _MenubarTheme.commonColor, ), tooltip: translate('Control Actions'), @@ -583,7 +590,7 @@ class _RemoteMenubarState extends State { ); } - Widget _buildDisplay(BuildContext context) { + Widget _buildDisplay(BuildContext context, double iconSize) { return FutureBuilder(future: () async { widget.state.viewStyle.value = await bind.sessionGetViewStyle(id: widget.id) ?? ''; @@ -595,9 +602,10 @@ class _RemoteMenubarState extends State { return Obx(() { final remoteCount = RemoteCountState.find().value; return mod_menu.PopupMenuButton( + iconSize: iconSize, padding: EdgeInsets.zero, - icon: const Icon( - Icons.tv, + icon: SvgPicture.asset( + "assets/display.svg", color: _MenubarTheme.commonColor, ), tooltip: translate('Display Settings'), @@ -622,15 +630,16 @@ class _RemoteMenubarState extends State { }); } - Widget _buildKeyboard(BuildContext context) { + Widget _buildKeyboard(BuildContext context, double iconSize) { FfiModel ffiModel = Provider.of(context); if (ffiModel.permissions['keyboard'] == false) { return Offstage(); } return mod_menu.PopupMenuButton( + iconSize: iconSize, padding: EdgeInsets.zero, - icon: const Icon( - Icons.keyboard, + icon: SvgPicture.asset( + "assets/keyboard.svg", color: _MenubarTheme.commonColor, ), tooltip: translate('Keyboard Settings'), @@ -648,57 +657,54 @@ class _RemoteMenubarState extends State { ); } - Widget _buildRecording(BuildContext context) { + Widget _buildRecording(BuildContext context, double iconSize) { return Consumer(builder: ((context, value, child) { if (value.permissions['recording'] != false) { return Consumer( - builder: (context, value, child) => IconButton( - tooltip: value.start - ? translate('Stop session recording') - : translate('Start session recording'), - onPressed: () => value.toggle(), - icon: value.start - ? Icon( - Icons.pause_circle_filled, - color: _MenubarTheme.commonColor, - ) - : SvgPicture.asset( - "assets/record_screen.svg", - color: _MenubarTheme.commonColor, - width: Theme.of(context).iconTheme.size ?? 22.0, - height: Theme.of(context).iconTheme.size ?? 22.0, - ), - )); + builder: (context, value, child) => IconButton( + padding: EdgeInsets.zero, + iconSize: iconSize, + tooltip: value.start + ? translate('Stop session recording') + : translate('Start session recording'), + onPressed: () => value.toggle(), + icon: SvgPicture.asset( + "assets/rec.svg", + color: value.start ? Colors.red : _MenubarTheme.commonColor, + ), + ), + ); } else { return Offstage(); } })); } - Widget _buildClose(BuildContext context) { + Widget _buildClose(BuildContext context, double iconSize) { return IconButton( + iconSize: iconSize, + padding: EdgeInsets.zero, tooltip: translate('Close'), onPressed: () { clientClose(widget.id, widget.ffi.dialogManager); }, - icon: const Icon( - Icons.close, - color: _MenubarTheme.commonColor, + icon: SvgPicture.asset( + "assets/close.svg", + color: Colors.red, ), ); } final _chatButtonKey = GlobalKey(); - Widget _buildChat(BuildContext context) { + Widget _buildChat(BuildContext context, double iconSize) { FfiModel ffiModel = Provider.of(context); return mod_menu.PopupMenuButton( + iconSize: iconSize, key: _chatButtonKey, padding: EdgeInsets.zero, icon: SvgPicture.asset( "assets/chat.svg", color: _MenubarTheme.commonColor, - width: Theme.of(context).iconTheme.size ?? 24.0, - height: Theme.of(context).iconTheme.size ?? 24.0, ), tooltip: translate('Chat'), position: mod_menu.PopupMenuPosition.under, @@ -719,15 +725,14 @@ class _RemoteMenubarState extends State { switch (widget.ffi.chatModel.voiceCallStatus.value) { case VoiceCallStatus.waitingForResponse: return IconButton( - onPressed: () { - widget.ffi.chatModel.closeVoiceCall(widget.id); - }, - icon: SvgPicture.asset( - "assets/voice_call_waiting.svg", - color: Colors.red, - width: Theme.of(context).iconTheme.size ?? 20.0, - height: Theme.of(context).iconTheme.size ?? 20.0, - )); + onPressed: () { + widget.ffi.chatModel.closeVoiceCall(widget.id); + }, + icon: SvgPicture.asset( + "assets/voice_call_waiting.svg", + color: Colors.red, + ), + ); case VoiceCallStatus.connected: return IconButton( onPressed: () { @@ -736,7 +741,6 @@ class _RemoteMenubarState extends State { icon: Icon( Icons.phone_disabled_rounded, color: Colors.red, - size: Theme.of(context).iconTheme.size ?? 22.0, ), ); default: @@ -755,13 +759,14 @@ class _RemoteMenubarState extends State { } } - Widget _buildVoiceCall(BuildContext context) { + Widget _buildVoiceCall(BuildContext context, double iconSize) { return Obx( () { final tooltipText = _getVoiceCallTooltip(); return tooltipText == null ? const Offstage() : IconButton( + iconSize: iconSize, padding: EdgeInsets.zero, icon: _getVoiceCallIcon(), tooltip: translate(tooltipText), @@ -1748,7 +1753,7 @@ class _DraggableShowHideState extends State<_DraggableShowHide> { child: Icon( Icons.drag_indicator, size: 20, - color: Colors.grey, + color: Colors.grey[800], ), feedback: widget, onDragStarted: (() { @@ -1801,7 +1806,9 @@ class _DraggableShowHideState extends State<_DraggableShowHide> { child: Container( decoration: BoxDecoration( color: Colors.white, - border: Border.all(color: MyTheme.border), + borderRadius: BorderRadius.vertical( + bottom: Radius.circular(5), + ), ), child: SizedBox( height: 20, From c5d39b0c105cf95f987be60bd6d573a7ba89aa03 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Wed, 15 Feb 2023 11:40:17 +0100 Subject: [PATCH 2/5] reworked --- flutter/assets/actions.svg | 3 +- flutter/assets/chat.svg | 2 +- flutter/assets/close.svg | 2 +- flutter/assets/display.svg | 2 +- flutter/assets/fullscreen.svg | 2 +- flutter/assets/fullscreen_exit.svg | 2 +- flutter/assets/keyboard.svg | 2 +- flutter/assets/pinned.svg | 2 +- flutter/assets/rec.svg | 2 +- flutter/assets/unpinned.svg | 2 +- flutter/lib/desktop/pages/remote_page.dart | 2 +- .../lib/desktop/pages/remote_tab_page.dart | 9 ++- .../widgets/material_mod_popup_menu.dart | 9 +-- flutter/lib/desktop/widgets/menu_button.dart | 63 +++++++++++++++++ .../lib/desktop/widgets/remote_menubar.dart | 67 +++++++++++-------- 15 files changed, 125 insertions(+), 46 deletions(-) create mode 100644 flutter/lib/desktop/widgets/menu_button.dart diff --git a/flutter/assets/actions.svg b/flutter/assets/actions.svg index feaf416cd..5403853db 100644 --- a/flutter/assets/actions.svg +++ b/flutter/assets/actions.svg @@ -1,3 +1,2 @@ - - \ No newline at end of file + \ No newline at end of file diff --git a/flutter/assets/chat.svg b/flutter/assets/chat.svg index 830ef0d33..7088107b0 100644 --- a/flutter/assets/chat.svg +++ b/flutter/assets/chat.svg @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/flutter/assets/close.svg b/flutter/assets/close.svg index 1e9a30711..7488acc9f 100644 --- a/flutter/assets/close.svg +++ b/flutter/assets/close.svg @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/flutter/assets/display.svg b/flutter/assets/display.svg index 8a87116ff..b5a88106e 100644 --- a/flutter/assets/display.svg +++ b/flutter/assets/display.svg @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/flutter/assets/fullscreen.svg b/flutter/assets/fullscreen.svg index 73d79cf0e..cd01f93f9 100644 --- a/flutter/assets/fullscreen.svg +++ b/flutter/assets/fullscreen.svg @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/flutter/assets/fullscreen_exit.svg b/flutter/assets/fullscreen_exit.svg index f2b3ae27b..8d4414897 100644 --- a/flutter/assets/fullscreen_exit.svg +++ b/flutter/assets/fullscreen_exit.svg @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/flutter/assets/keyboard.svg b/flutter/assets/keyboard.svg index 569c68727..d5481d7a1 100644 --- a/flutter/assets/keyboard.svg +++ b/flutter/assets/keyboard.svg @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/flutter/assets/pinned.svg b/flutter/assets/pinned.svg index 2563015f7..dd718b96a 100644 --- a/flutter/assets/pinned.svg +++ b/flutter/assets/pinned.svg @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/flutter/assets/rec.svg b/flutter/assets/rec.svg index 14546b971..33a57e9d0 100644 --- a/flutter/assets/rec.svg +++ b/flutter/assets/rec.svg @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/flutter/assets/unpinned.svg b/flutter/assets/unpinned.svg index ba4ab5328..9e9e3de8b 100644 --- a/flutter/assets/unpinned.svg +++ b/flutter/assets/unpinned.svg @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 211d36c39..dac62032f 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -201,7 +201,7 @@ class _RemotePageState extends State Widget buildBody(BuildContext context) { return Scaffold( - backgroundColor: Theme.of(context).backgroundColor, + backgroundColor: Theme.of(context).colorScheme.background, /// the Overlay key will be set with _blockableOverlayState in BlockableOverlay /// see override build() in [BlockableOverlay] diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index 9b00b481f..610a7d1a5 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -22,7 +22,10 @@ import 'package:bot_toast/bot_toast.dart'; import '../../models/platform_model.dart'; class _MenuTheme { - static const Color commonColor = MyTheme.accent; + static const Color blueColor = MyTheme.button; + static const Color hoverBlueColor = MyTheme.accent; + static const Color redColor = Colors.redAccent; + static const Color hoverRedColor = Colors.red; // kMinInteractiveDimension static const double height = 20.0; static const double dividerHeight = 12.0; @@ -134,7 +137,7 @@ class _ConnectionTabPageState extends State { width: stateGlobal.windowBorderWidth.value), ), child: Scaffold( - backgroundColor: Theme.of(context).backgroundColor, + backgroundColor: Theme.of(context).colorScheme.background, body: DesktopTab( controller: tabController, onWindowCloseButton: handleWindowCloseButton, @@ -280,7 +283,7 @@ class _ConnectionTabPageState extends State { .map((entry) => entry.build( context, const MenuConfig( - commonColor: _MenuTheme.commonColor, + commonColor: _MenuTheme.blueColor, height: _MenuTheme.height, dividerHeight: _MenuTheme.dividerHeight, ))) diff --git a/flutter/lib/desktop/widgets/material_mod_popup_menu.dart b/flutter/lib/desktop/widgets/material_mod_popup_menu.dart index 666c9a6e2..05c3059d4 100644 --- a/flutter/lib/desktop/widgets/material_mod_popup_menu.dart +++ b/flutter/lib/desktop/widgets/material_mod_popup_menu.dart @@ -5,6 +5,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_hbb/common.dart'; +import 'package:flutter_hbb/desktop/widgets/menu_button.dart'; // Examples can assume: // enum Commands { heroAndScholar, hurricaneCame } @@ -1391,22 +1393,21 @@ class PopupMenuButtonState extends State> { onTap: widget.enabled ? showButtonMenu : null, onHover: widget.onHover, canRequestFocus: _canRequestFocus, - radius: widget.splashRadius, enableFeedback: enableFeedback, child: widget.child, ), ); } - return IconButton( + return MenuButton( icon: widget.icon ?? Icon(Icons.adaptive.more), - padding: widget.padding, - splashRadius: widget.splashRadius, iconSize: widget.iconSize ?? iconTheme.size ?? _kDefaultIconSize, tooltip: widget.tooltip ?? MaterialLocalizations.of(context).showMenuTooltip, onPressed: widget.enabled ? showButtonMenu : null, enableFeedback: enableFeedback, + color: MyTheme.button, + hoverColor: MyTheme.accent, ); } } diff --git a/flutter/lib/desktop/widgets/menu_button.dart b/flutter/lib/desktop/widgets/menu_button.dart new file mode 100644 index 000000000..ce63dcab1 --- /dev/null +++ b/flutter/lib/desktop/widgets/menu_button.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; + +class MenuButton extends StatefulWidget { + final GestureTapCallback? onPressed; + final Color color; + final Color hoverColor; + final Color? splashColor; + final Widget icon; + final double iconSize; + final String tooltip; + final EdgeInsetsGeometry padding; + final bool enableFeedback; + const MenuButton({ + super.key, + required this.onPressed, + required this.color, + required this.hoverColor, + required this.icon, + required this.iconSize, + required this.tooltip, + this.splashColor, + this.padding = const EdgeInsets.all(5), + this.enableFeedback = true, + }); + + @override + State createState() => _MenuButtonState(); +} + +class _MenuButtonState extends State { + bool _isHover = false; + + @override + Widget build(BuildContext context) { + return Padding( + padding: widget.padding, + child: Tooltip( + message: widget.tooltip, + child: Material( + type: MaterialType.transparency, + child: Ink( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: _isHover ? widget.hoverColor : widget.color, + ), + child: InkWell( + onHover: (val) { + setState(() { + _isHover = val; + }); + }, + borderRadius: BorderRadius.circular(5), + splashColor: widget.splashColor, + enableFeedback: widget.enableFeedback, + onTap: widget.onPressed, + child: widget.icon, + ), + ), + ), + ), + ); + } +} diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 77d687d93..ff586a1f1 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -5,6 +5,7 @@ import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_hbb/desktop/widgets/menu_button.dart'; import 'package:flutter_hbb/models/chat_model.dart'; import 'package:flutter_hbb/models/state_model.dart'; import 'package:flutter_hbb/consts.dart'; @@ -94,7 +95,10 @@ class MenubarState { } class _MenubarTheme { - static const Color commonColor = MyTheme.accent; + static const Color blueColor = MyTheme.button; + static const Color hoverBlueColor = MyTheme.accent; + static const Color redColor = Colors.redAccent; + static const Color hoverRedColor = Colors.red; // kMinInteractiveDimension static const double height = 20.0; static const double dividerHeight = 12.0; @@ -412,7 +416,7 @@ class _RemoteMenubarState extends State { if (widget.ffi.ffiModel.isPeerAndroid) { menubarItems.add(IconButton( tooltip: translate('Mobile Actions'), - color: _MenubarTheme.commonColor, + color: _MenubarTheme.blueColor, icon: const Icon(Icons.build), onPressed: () { widget.ffi.dialogManager @@ -433,7 +437,7 @@ class _RemoteMenubarState extends State { menubarItems.add(_buildClose(context, iconSize)); return PopupMenuTheme( data: const PopupMenuThemeData( - textStyle: TextStyle(color: _MenubarTheme.commonColor)), + textStyle: TextStyle(color: _MenubarTheme.blueColor)), child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -457,8 +461,7 @@ class _RemoteMenubarState extends State { Widget _buildPinMenubar(BuildContext context, double iconSize) { return Obx( - () => IconButton( - padding: EdgeInsets.zero, + () => MenuButton( iconSize: iconSize, tooltip: translate(pin ? 'Unpin menubar' : 'Pin menubar'), onPressed: () { @@ -466,15 +469,16 @@ class _RemoteMenubarState extends State { }, icon: SvgPicture.asset( pin ? "assets/pinned.svg" : "assets/unpinned.svg", - color: pin ? _MenubarTheme.commonColor : Colors.grey[800], + color: Colors.white, ), + color: pin ? _MenubarTheme.blueColor : Colors.grey[800]!, + hoverColor: pin ? _MenubarTheme.hoverBlueColor : Colors.grey[850]!, ), ); } Widget _buildFullscreen(BuildContext context, double iconSize) { - return IconButton( - padding: EdgeInsets.zero, + return MenuButton( iconSize: iconSize, tooltip: translate(isFullscreen ? 'Exit Fullscreen' : 'Fullscreen'), onPressed: () { @@ -482,8 +486,10 @@ class _RemoteMenubarState extends State { }, icon: SvgPicture.asset( isFullscreen ? "assets/fullscreen_exit.svg" : "assets/fullscreen.svg", - color: _MenubarTheme.commonColor, + color: Colors.white, ), + color: _MenubarTheme.blueColor, + hoverColor: _MenubarTheme.hoverBlueColor, ); } @@ -492,14 +498,13 @@ class _RemoteMenubarState extends State { return mod_menu.PopupMenuButton( iconSize: iconSize, tooltip: translate('Select Monitor'), - padding: EdgeInsets.zero, position: mod_menu.PopupMenuPosition.under, icon: Stack( alignment: Alignment.center, children: [ SvgPicture.asset( "assets/display.svg", - color: _MenubarTheme.commonColor, + color: Colors.white, ), Padding( padding: const EdgeInsets.only(bottom: 3.9), @@ -520,7 +525,10 @@ class _RemoteMenubarState extends State { Stack( alignment: Alignment.center, children: [ - SvgPicture.asset("assets/display.svg"), + SvgPicture.asset( + "assets/display.svg", + color: Colors.white, + ), TextButton( child: Container( alignment: AlignmentDirectional.center, @@ -531,7 +539,7 @@ class _RemoteMenubarState extends State { child: Text( (i + 1).toString(), style: TextStyle( - color: Theme.of(context).scaffoldBackgroundColor, + color: Colors.white, ), ), ), @@ -573,7 +581,7 @@ class _RemoteMenubarState extends State { padding: EdgeInsets.zero, icon: SvgPicture.asset( "assets/actions.svg", - color: _MenubarTheme.commonColor, + color: Colors.white, ), tooltip: translate('Control Actions'), position: mod_menu.PopupMenuPosition.under, @@ -581,7 +589,7 @@ class _RemoteMenubarState extends State { .map((entry) => entry.build( context, const MenuConfig( - commonColor: _MenubarTheme.commonColor, + commonColor: _MenubarTheme.blueColor, height: _MenubarTheme.height, dividerHeight: _MenubarTheme.dividerHeight, ))) @@ -606,7 +614,7 @@ class _RemoteMenubarState extends State { padding: EdgeInsets.zero, icon: SvgPicture.asset( "assets/display.svg", - color: _MenubarTheme.commonColor, + color: Colors.white, ), tooltip: translate('Display Settings'), position: mod_menu.PopupMenuPosition.under, @@ -616,7 +624,7 @@ class _RemoteMenubarState extends State { .map((entry) => entry.build( context, const MenuConfig( - commonColor: _MenubarTheme.commonColor, + commonColor: _MenubarTheme.blueColor, height: _MenubarTheme.height, dividerHeight: _MenubarTheme.dividerHeight, ))) @@ -640,7 +648,7 @@ class _RemoteMenubarState extends State { padding: EdgeInsets.zero, icon: SvgPicture.asset( "assets/keyboard.svg", - color: _MenubarTheme.commonColor, + color: Colors.white, ), tooltip: translate('Keyboard Settings'), position: mod_menu.PopupMenuPosition.under, @@ -648,7 +656,7 @@ class _RemoteMenubarState extends State { .map((entry) => entry.build( context, const MenuConfig( - commonColor: _MenubarTheme.commonColor, + commonColor: _MenubarTheme.blueColor, height: _MenubarTheme.height, dividerHeight: _MenubarTheme.dividerHeight, ))) @@ -661,8 +669,7 @@ class _RemoteMenubarState extends State { return Consumer(builder: ((context, value, child) { if (value.permissions['recording'] != false) { return Consumer( - builder: (context, value, child) => IconButton( - padding: EdgeInsets.zero, + builder: (context, value, child) => MenuButton( iconSize: iconSize, tooltip: value.start ? translate('Stop session recording') @@ -670,8 +677,13 @@ class _RemoteMenubarState extends State { onPressed: () => value.toggle(), icon: SvgPicture.asset( "assets/rec.svg", - color: value.start ? Colors.red : _MenubarTheme.commonColor, + color: Colors.white, ), + color: + value.start ? _MenubarTheme.redColor : _MenubarTheme.blueColor, + hoverColor: value.start + ? _MenubarTheme.hoverRedColor + : _MenubarTheme.hoverBlueColor, ), ); } else { @@ -681,17 +693,18 @@ class _RemoteMenubarState extends State { } Widget _buildClose(BuildContext context, double iconSize) { - return IconButton( + return MenuButton( iconSize: iconSize, - padding: EdgeInsets.zero, tooltip: translate('Close'), onPressed: () { clientClose(widget.id, widget.ffi.dialogManager); }, icon: SvgPicture.asset( "assets/close.svg", - color: Colors.red, + color: Colors.white, ), + color: _MenubarTheme.redColor, + hoverColor: _MenubarTheme.hoverRedColor, ); } @@ -704,7 +717,7 @@ class _RemoteMenubarState extends State { padding: EdgeInsets.zero, icon: SvgPicture.asset( "assets/chat.svg", - color: _MenubarTheme.commonColor, + color: Colors.white, ), tooltip: translate('Chat'), position: mod_menu.PopupMenuPosition.under, @@ -712,7 +725,7 @@ class _RemoteMenubarState extends State { .map((entry) => entry.build( context, const MenuConfig( - commonColor: _MenubarTheme.commonColor, + commonColor: _MenubarTheme.blueColor, height: _MenubarTheme.height, dividerHeight: _MenubarTheme.dividerHeight, ))) From 952596080279c8778cd3cd7edd8af6da80fa9089 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Wed, 15 Feb 2023 13:19:15 +0100 Subject: [PATCH 3/5] added new call end/wait icons --- flutter/assets/call_end.svg | 2 + flutter/assets/call_wait.svg | 2 + flutter/lib/desktop/pages/remote_page.dart | 2 +- .../lib/desktop/pages/remote_tab_page.dart | 2 +- .../widgets/material_mod_popup_menu.dart | 1 - flutter/lib/desktop/widgets/menu_button.dart | 6 +- .../lib/desktop/widgets/remote_menubar.dart | 79 +++++++------------ 7 files changed, 38 insertions(+), 56 deletions(-) create mode 100644 flutter/assets/call_end.svg create mode 100644 flutter/assets/call_wait.svg diff --git a/flutter/assets/call_end.svg b/flutter/assets/call_end.svg new file mode 100644 index 000000000..39367c3c5 --- /dev/null +++ b/flutter/assets/call_end.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/flutter/assets/call_wait.svg b/flutter/assets/call_wait.svg new file mode 100644 index 000000000..42a11fe56 --- /dev/null +++ b/flutter/assets/call_wait.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index dac62032f..211d36c39 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -201,7 +201,7 @@ class _RemotePageState extends State Widget buildBody(BuildContext context) { return Scaffold( - backgroundColor: Theme.of(context).colorScheme.background, + backgroundColor: Theme.of(context).backgroundColor, /// the Overlay key will be set with _blockableOverlayState in BlockableOverlay /// see override build() in [BlockableOverlay] diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index 610a7d1a5..7bd2a4126 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -137,7 +137,7 @@ class _ConnectionTabPageState extends State { width: stateGlobal.windowBorderWidth.value), ), child: Scaffold( - backgroundColor: Theme.of(context).colorScheme.background, + backgroundColor: Theme.of(context).backgroundColor, body: DesktopTab( controller: tabController, onWindowCloseButton: handleWindowCloseButton, diff --git a/flutter/lib/desktop/widgets/material_mod_popup_menu.dart b/flutter/lib/desktop/widgets/material_mod_popup_menu.dart index 05c3059d4..47de1be20 100644 --- a/flutter/lib/desktop/widgets/material_mod_popup_menu.dart +++ b/flutter/lib/desktop/widgets/material_mod_popup_menu.dart @@ -1401,7 +1401,6 @@ class PopupMenuButtonState extends State> { return MenuButton( icon: widget.icon ?? Icon(Icons.adaptive.more), - iconSize: widget.iconSize ?? iconTheme.size ?? _kDefaultIconSize, tooltip: widget.tooltip ?? MaterialLocalizations.of(context).showMenuTooltip, onPressed: widget.enabled ? showButtonMenu : null, diff --git a/flutter/lib/desktop/widgets/menu_button.dart b/flutter/lib/desktop/widgets/menu_button.dart index ce63dcab1..b2871e0cd 100644 --- a/flutter/lib/desktop/widgets/menu_button.dart +++ b/flutter/lib/desktop/widgets/menu_button.dart @@ -6,8 +6,7 @@ class MenuButton extends StatefulWidget { final Color hoverColor; final Color? splashColor; final Widget icon; - final double iconSize; - final String tooltip; + final String? tooltip; final EdgeInsetsGeometry padding; final bool enableFeedback; const MenuButton({ @@ -16,9 +15,8 @@ class MenuButton extends StatefulWidget { required this.color, required this.hoverColor, required this.icon, - required this.iconSize, - required this.tooltip, this.splashColor, + this.tooltip = "", this.padding = const EdgeInsets.all(5), this.enableFeedback = true, }); diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index ff586a1f1..5029560b0 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -409,10 +409,9 @@ class _RemoteMenubarState extends State { Widget _buildMenubar(BuildContext context) { final List menubarItems = []; - final double iconSize = Theme.of(context).iconTheme.size ?? 30.0; if (!isWebDesktop) { - menubarItems.add(_buildPinMenubar(context, iconSize)); - menubarItems.add(_buildFullscreen(context, iconSize)); + menubarItems.add(_buildPinMenubar(context)); + menubarItems.add(_buildFullscreen(context)); if (widget.ffi.ffiModel.isPeerAndroid) { menubarItems.add(IconButton( tooltip: translate('Mobile Actions'), @@ -425,16 +424,16 @@ class _RemoteMenubarState extends State { )); } } - menubarItems.add(_buildMonitor(context, iconSize)); - menubarItems.add(_buildControl(context, iconSize)); - menubarItems.add(_buildDisplay(context, iconSize)); - menubarItems.add(_buildKeyboard(context, iconSize)); + menubarItems.add(_buildMonitor(context)); + menubarItems.add(_buildControl(context)); + menubarItems.add(_buildDisplay(context)); + menubarItems.add(_buildKeyboard(context)); if (!isWeb) { - menubarItems.add(_buildChat(context, iconSize)); - menubarItems.add(_buildVoiceCall(context, iconSize)); + menubarItems.add(_buildChat(context)); + menubarItems.add(_buildVoiceCall(context)); } - menubarItems.add(_buildRecording(context, iconSize)); - menubarItems.add(_buildClose(context, iconSize)); + menubarItems.add(_buildRecording(context)); + menubarItems.add(_buildClose(context)); return PopupMenuTheme( data: const PopupMenuThemeData( textStyle: TextStyle(color: _MenubarTheme.blueColor)), @@ -459,10 +458,9 @@ class _RemoteMenubarState extends State { ); } - Widget _buildPinMenubar(BuildContext context, double iconSize) { + Widget _buildPinMenubar(BuildContext context) { return Obx( () => MenuButton( - iconSize: iconSize, tooltip: translate(pin ? 'Unpin menubar' : 'Pin menubar'), onPressed: () { widget.state.switchPin(); @@ -477,9 +475,8 @@ class _RemoteMenubarState extends State { ); } - Widget _buildFullscreen(BuildContext context, double iconSize) { + Widget _buildFullscreen(BuildContext context) { return MenuButton( - iconSize: iconSize, tooltip: translate(isFullscreen ? 'Exit Fullscreen' : 'Fullscreen'), onPressed: () { _setFullscreen(!isFullscreen); @@ -493,10 +490,9 @@ class _RemoteMenubarState extends State { ); } - Widget _buildMonitor(BuildContext context, double iconSize) { + Widget _buildMonitor(BuildContext context) { final pi = widget.ffi.ffiModel.pi; return mod_menu.PopupMenuButton( - iconSize: iconSize, tooltip: translate('Select Monitor'), position: mod_menu.PopupMenuPosition.under, icon: Stack( @@ -575,9 +571,8 @@ class _RemoteMenubarState extends State { ); } - Widget _buildControl(BuildContext context, double iconSize) { + Widget _buildControl(BuildContext context) { return mod_menu.PopupMenuButton( - iconSize: iconSize, padding: EdgeInsets.zero, icon: SvgPicture.asset( "assets/actions.svg", @@ -598,7 +593,7 @@ class _RemoteMenubarState extends State { ); } - Widget _buildDisplay(BuildContext context, double iconSize) { + Widget _buildDisplay(BuildContext context) { return FutureBuilder(future: () async { widget.state.viewStyle.value = await bind.sessionGetViewStyle(id: widget.id) ?? ''; @@ -610,7 +605,6 @@ class _RemoteMenubarState extends State { return Obx(() { final remoteCount = RemoteCountState.find().value; return mod_menu.PopupMenuButton( - iconSize: iconSize, padding: EdgeInsets.zero, icon: SvgPicture.asset( "assets/display.svg", @@ -638,13 +632,12 @@ class _RemoteMenubarState extends State { }); } - Widget _buildKeyboard(BuildContext context, double iconSize) { + Widget _buildKeyboard(BuildContext context) { FfiModel ffiModel = Provider.of(context); if (ffiModel.permissions['keyboard'] == false) { return Offstage(); } return mod_menu.PopupMenuButton( - iconSize: iconSize, padding: EdgeInsets.zero, icon: SvgPicture.asset( "assets/keyboard.svg", @@ -665,12 +658,11 @@ class _RemoteMenubarState extends State { ); } - Widget _buildRecording(BuildContext context, double iconSize) { + Widget _buildRecording(BuildContext context) { return Consumer(builder: ((context, value, child) { if (value.permissions['recording'] != false) { return Consumer( builder: (context, value, child) => MenuButton( - iconSize: iconSize, tooltip: value.start ? translate('Stop session recording') : translate('Start session recording'), @@ -692,9 +684,8 @@ class _RemoteMenubarState extends State { })); } - Widget _buildClose(BuildContext context, double iconSize) { + Widget _buildClose(BuildContext context) { return MenuButton( - iconSize: iconSize, tooltip: translate('Close'), onPressed: () { clientClose(widget.id, widget.ffi.dialogManager); @@ -709,10 +700,9 @@ class _RemoteMenubarState extends State { } final _chatButtonKey = GlobalKey(); - Widget _buildChat(BuildContext context, double iconSize) { + Widget _buildChat(BuildContext context) { FfiModel ffiModel = Provider.of(context); return mod_menu.PopupMenuButton( - iconSize: iconSize, key: _chatButtonKey, padding: EdgeInsets.zero, icon: SvgPicture.asset( @@ -737,24 +727,15 @@ class _RemoteMenubarState extends State { Widget _getVoiceCallIcon() { switch (widget.ffi.chatModel.voiceCallStatus.value) { case VoiceCallStatus.waitingForResponse: - return IconButton( - onPressed: () { - widget.ffi.chatModel.closeVoiceCall(widget.id); - }, - icon: SvgPicture.asset( - "assets/voice_call_waiting.svg", - color: Colors.red, - ), + return SvgPicture.asset( + "assets/call_wait.svg", + color: Colors.white, ); + case VoiceCallStatus.connected: - return IconButton( - onPressed: () { - widget.ffi.chatModel.closeVoiceCall(widget.id); - }, - icon: Icon( - Icons.phone_disabled_rounded, - color: Colors.red, - ), + return SvgPicture.asset( + "assets/call_end.svg", + color: Colors.white, ); default: return const Offstage(); @@ -772,18 +753,18 @@ class _RemoteMenubarState extends State { } } - Widget _buildVoiceCall(BuildContext context, double iconSize) { + Widget _buildVoiceCall(BuildContext context) { return Obx( () { final tooltipText = _getVoiceCallTooltip(); return tooltipText == null ? const Offstage() - : IconButton( - iconSize: iconSize, - padding: EdgeInsets.zero, + : MenuButton( icon: _getVoiceCallIcon(), tooltip: translate(tooltipText), onPressed: () => bind.sessionRequestVoiceCall(id: widget.id), + color: _MenubarTheme.redColor, + hoverColor: _MenubarTheme.hoverRedColor, ); }, ); From 957bb65b9f624d6b00377787033e545cf6423562 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Wed, 15 Feb 2023 13:27:21 +0100 Subject: [PATCH 4/5] adjusted spacing --- flutter/lib/desktop/widgets/menu_button.dart | 2 +- flutter/lib/desktop/widgets/remote_menubar.dart | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/flutter/lib/desktop/widgets/menu_button.dart b/flutter/lib/desktop/widgets/menu_button.dart index b2871e0cd..904195f71 100644 --- a/flutter/lib/desktop/widgets/menu_button.dart +++ b/flutter/lib/desktop/widgets/menu_button.dart @@ -17,7 +17,7 @@ class MenuButton extends StatefulWidget { required this.icon, this.splashColor, this.tooltip = "", - this.padding = const EdgeInsets.all(5), + this.padding = const EdgeInsets.symmetric(horizontal: 2.5, vertical: 5), this.enableFeedback = true, }); diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 5029560b0..afc5b2d9f 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -449,7 +449,11 @@ class _RemoteMenubarState extends State { ), child: Row( mainAxisSize: MainAxisSize.min, - children: menubarItems, + children: [ + SizedBox(width: 2.5), + ...menubarItems, + SizedBox(width: 2.5) + ], ), ), _buildDraggableShowHide(context), From eac6dae3a7aed17b81916b9369c2ed94914f054f Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Wed, 15 Feb 2023 14:14:21 +0100 Subject: [PATCH 5/5] increased margin --- flutter/lib/desktop/widgets/menu_button.dart | 2 +- flutter/lib/desktop/widgets/remote_menubar.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flutter/lib/desktop/widgets/menu_button.dart b/flutter/lib/desktop/widgets/menu_button.dart index 904195f71..7c9fe67eb 100644 --- a/flutter/lib/desktop/widgets/menu_button.dart +++ b/flutter/lib/desktop/widgets/menu_button.dart @@ -17,7 +17,7 @@ class MenuButton extends StatefulWidget { required this.icon, this.splashColor, this.tooltip = "", - this.padding = const EdgeInsets.symmetric(horizontal: 2.5, vertical: 5), + this.padding = const EdgeInsets.symmetric(horizontal: 3, vertical: 6), this.enableFeedback = true, }); diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 189f58f4b..933850c99 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -452,9 +452,9 @@ class _RemoteMenubarState extends State { child: Row( mainAxisSize: MainAxisSize.min, children: [ - SizedBox(width: 2.5), + SizedBox(width: 3), ...menubarItems, - SizedBox(width: 2.5) + SizedBox(width: 3) ], ), ),