From 14d390e23f498d28be8daf5ecddf1675dae2ace2 Mon Sep 17 00:00:00 2001 From: csf Date: Sat, 8 Oct 2022 19:28:20 +0900 Subject: [PATCH] opt: address book action more desktop style --- flutter/lib/common/widgets/address_book.dart | 73 +++++++++++------- flutter/lib/common/widgets/peer_card.dart | 76 ++++++++++--------- flutter/lib/consts.dart | 1 + .../lib/desktop/pages/connection_page.dart | 8 +- 4 files changed, 90 insertions(+), 68 deletions(-) diff --git a/flutter/lib/common/widgets/address_book.dart b/flutter/lib/common/widgets/address_book.dart index 6bf6a76c4..8ced1c0e5 100644 --- a/flutter/lib/common/widgets/address_book.dart +++ b/flutter/lib/common/widgets/address_book.dart @@ -1,6 +1,10 @@ import 'package:contextmenu/contextmenu.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_hbb/common/widgets/peer_card.dart'; import 'package:flutter_hbb/common/widgets/peers_view.dart'; +import 'package:flutter_hbb/desktop/widgets/popup_menu.dart'; +import '../../consts.dart'; +import '../../desktop/widgets/material_mod_popup_menu.dart' as mod_menu; import 'package:get/get.dart'; import '../../common.dart'; @@ -102,6 +106,7 @@ class _AddressBookState extends State { } Widget _buildAddressBook(BuildContext context) { + var pos = RelativeRect.fill; return Row( children: [ Card( @@ -120,27 +125,15 @@ class _AddressBookState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - // TODO same style as peer Text(translate('Tags')), - InkWell( - child: PopupMenuButton( - itemBuilder: (context) => [ - PopupMenuItem( - value: 'add-id', - child: Text(translate("Add ID")), - ), - PopupMenuItem( - value: 'add-tag', - child: Text(translate("Add Tag")), - ), - PopupMenuItem( - value: 'unset-all-tag', - child: Text(translate("Unselect all tags")), - ), - ], - onSelected: handleAbOp, - child: const Icon(Icons.more_vert_outlined)), - ) + GestureDetector( + onTapDown: (e) { + final x = e.globalPosition.dx; + final y = e.globalPosition.dy; + pos = RelativeRect.fromLTRB(x, y, x, y); + }, + onTap: () => _showMenu(pos), + child: ActionMore()), ], ), Expanded( @@ -184,15 +177,39 @@ class _AddressBookState extends State { ); } - /// tag operation - void handleAbOp(String value) { - if (value == 'add-id') { - abAddId(); - } else if (value == 'add-tag') { - abAddTag(); - } else if (value == 'unset-all-tag') { - gFFI.abModel.unsetSelectedTags(); + void _showMenu(RelativeRect pos) { + MenuEntryButton getEntry(String title, VoidCallback proc) { + return MenuEntryButton( + childBuilder: (TextStyle? style) => Text( + title, + style: style, + ), + proc: proc, + padding: kDesktopMenuPadding, + dismissOnClicked: true, + ); } + + final items = [ + getEntry(translate("Add ID"), abAddId), + getEntry(translate("Add Tag"), abAddTag), + getEntry(translate("Unselect all tags"), gFFI.abModel.unsetSelectedTags), + ]; + + mod_menu.showMenu( + context: context, + position: pos, + items: items + .map((e) => e.build( + context, + MenuConfig( + commonColor: CustomPopupMenuTheme.commonColor, + height: CustomPopupMenuTheme.height, + dividerHeight: CustomPopupMenuTheme.dividerHeight))) + .expand((i) => i) + .toList(), + elevation: 8, + ); } void abAddId() async { diff --git a/flutter/lib/common/widgets/peer_card.dart b/flutter/lib/common/widgets/peer_card.dart index ce925984e..e4838f40f 100644 --- a/flutter/lib/common/widgets/peer_card.dart +++ b/flutter/lib/common/widgets/peer_card.dart @@ -12,7 +12,7 @@ import '../../models/platform_model.dart'; import '../../desktop/widgets/material_mod_popup_menu.dart' as mod_menu; import '../../desktop/widgets/popup_menu.dart'; -class _PopupMenuTheme { +class CustomPopupMenuTheme { static const Color commonColor = MyTheme.accent; // kMinInteractiveDimension static const double height = 20.0; @@ -46,9 +46,8 @@ class _PeerCard extends StatefulWidget { class _PeerCardState extends State<_PeerCard> with AutomaticKeepAliveClientMixin { var _menuPos = RelativeRect.fill; - final double _cardRadis = 16; + final double _cardRadius = 16; final double _borderWidth = 2; - final RxBool _iconMoreHover = false.obs; @override Widget build(BuildContext context) { @@ -122,23 +121,23 @@ class _PeerCardState extends State<_PeerCard> var deco = Rx(BoxDecoration( border: Border.all(color: Colors.transparent, width: _borderWidth), borderRadius: peerCardUiType.value == PeerUiType.grid - ? BorderRadius.circular(_cardRadis) + ? BorderRadius.circular(_cardRadius) : null)); return MouseRegion( onEnter: (evt) { deco.value = BoxDecoration( border: Border.all( - color: Theme.of(context).colorScheme.secondary, + color: Theme.of(context).colorScheme.primary, width: _borderWidth), borderRadius: peerCardUiType.value == PeerUiType.grid - ? BorderRadius.circular(_cardRadis) + ? BorderRadius.circular(_cardRadius) : null); }, onExit: (evt) { deco.value = BoxDecoration( border: Border.all(color: Colors.transparent, width: _borderWidth), borderRadius: peerCardUiType.value == PeerUiType.grid - ? BorderRadius.circular(_cardRadis) + ? BorderRadius.circular(_cardRadius) : null); }, child: GestureDetector( @@ -221,7 +220,7 @@ class _PeerCardState extends State<_PeerCard> () => Container( foregroundDecoration: deco.value, child: ClipRRect( - borderRadius: BorderRadius.circular(_cardRadis - _borderWidth), + borderRadius: BorderRadius.circular(_cardRadius - _borderWidth), child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, @@ -299,27 +298,7 @@ class _PeerCardState extends State<_PeerCard> _menuPos = RelativeRect.fromLTRB(x, y, x, y); }, onPointerUp: (_) => _showPeerMenu(peer.id), - child: MouseRegion( - onEnter: (_) => _iconMoreHover.value = true, - onExit: (_) => _iconMoreHover.value = false, - child: CircleAvatar( - radius: 14, - backgroundColor: _iconMoreHover.value - ? Theme.of(context).scaffoldBackgroundColor - : Theme.of(context).backgroundColor, - // ? Theme.of(context).scaffoldBackgroundColor! - // : Theme.of(context).backgroundColor!, - child: Icon(Icons.more_vert, - size: 18, - color: _iconMoreHover.value - ? Theme.of(context).textTheme.titleLarge?.color - : Theme.of(context) - .textTheme - .titleLarge - ?.color - ?.withOpacity(0.5))))); - // ? MyTheme.color(context).text - // : MyTheme.color(context).lightText)))); + child: ActionMore()); /// Show the peer menu and handle user's choice. /// User might remove the peer or send a file to the peer. @@ -358,9 +337,9 @@ abstract class BasePeerCard extends StatelessWidget { .map((e) => e.build( context, const MenuConfig( - commonColor: _PopupMenuTheme.commonColor, - height: _PopupMenuTheme.height, - dividerHeight: _PopupMenuTheme.dividerHeight))) + commonColor: CustomPopupMenuTheme.commonColor, + height: CustomPopupMenuTheme.height, + dividerHeight: CustomPopupMenuTheme.dividerHeight))) .expand((i) => i) .toList(); @@ -426,7 +405,7 @@ abstract class BasePeerCard extends StatelessWidget { return MenuEntryButton( childBuilder: (TextStyle? style) => Container( alignment: AlignmentDirectional.center, - height: _PopupMenuTheme.height, + height: CustomPopupMenuTheme.height, child: Row( children: [ Text( @@ -875,7 +854,7 @@ void _rdpDialog(String id) async { text: await bind.mainGetPeerOption(id: id, key: 'rdp_port')); final userController = TextEditingController( text: await bind.mainGetPeerOption(id: id, key: 'rdp_username')); - final passwordContorller = TextEditingController( + final passwordController = TextEditingController( text: await bind.mainGetPeerOption(id: id, key: 'rdp_password')); RxBool secure = true.obs; @@ -886,7 +865,7 @@ void _rdpDialog(String id) async { await bind.mainSetPeerOption( id: id, key: 'rdp_username', value: userController.text); await bind.mainSetPeerOption( - id: id, key: 'rdp_password', value: passwordContorller.text); + id: id, key: 'rdp_password', value: passwordController.text); close(); } @@ -970,7 +949,7 @@ void _rdpDialog(String id) async { icon: Icon(secure.value ? Icons.visibility_off : Icons.visibility))), - controller: passwordContorller, + controller: passwordController, )), ), ], @@ -997,3 +976,28 @@ Widget getOnline(double rightPadding, bool online) { child: CircleAvatar( radius: 3, backgroundColor: online ? Colors.green : kColorWarn))); } + +class ActionMore extends StatelessWidget { + final RxBool _iconMoreHover = false.obs; + + @override + Widget build(BuildContext context) { + return MouseRegion( + onEnter: (_) => _iconMoreHover.value = true, + onExit: (_) => _iconMoreHover.value = false, + child: Obx(() => CircleAvatar( + radius: 14, + backgroundColor: _iconMoreHover.value + ? Theme.of(context).scaffoldBackgroundColor + : Theme.of(context).backgroundColor, + child: Icon(Icons.more_vert, + size: 18, + color: _iconMoreHover.value + ? Theme.of(context).textTheme.titleLarge?.color + : Theme.of(context) + .textTheme + .titleLarge + ?.color + ?.withOpacity(0.5))))); + } +} diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index c8dcbbfba..9e46db0d2 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -32,6 +32,7 @@ const kDefaultMouseWheelThrottleDuration = Duration(milliseconds: 50); const kFullScreenEdgeSize = 0.0; var kWindowEdgeSize = Platform.isWindows ? 1.0 : 5.0; const kWindowBorderWidth = 1.0; +const kDesktopMenuPadding = EdgeInsets.only(left: 12.0, right: 3.0); const kInvalidValueStr = "InvalidValueStr"; diff --git a/flutter/lib/desktop/pages/connection_page.dart b/flutter/lib/desktop/pages/connection_page.dart index 480fd1518..9a606d122 100644 --- a/flutter/lib/desktop/pages/connection_page.dart +++ b/flutter/lib/desktop/pages/connection_page.dart @@ -86,16 +86,16 @@ class _ConnectionPageState extends State ], children: [ RecentPeersView( - menuPadding: EdgeInsets.only(left: 12.0, right: 3.0), + menuPadding: kDesktopMenuPadding, ), FavoritePeersView( - menuPadding: EdgeInsets.only(left: 12.0, right: 3.0), + menuPadding: kDesktopMenuPadding, ), DiscoveredPeersView( - menuPadding: EdgeInsets.only(left: 12.0, right: 3.0), + menuPadding: kDesktopMenuPadding, ), const AddressBook( - menuPadding: EdgeInsets.only(left: 12.0, right: 3.0), + menuPadding: kDesktopMenuPadding, ), ], ).paddingOnly(right: 12.0),