From 1cca7acf1b7ea304aac609c172c0d68b11db8e7c Mon Sep 17 00:00:00 2001 From: Aryman Date: Tue, 9 Aug 2022 01:43:04 +0530 Subject: [PATCH 1/5] perf: added right click context menu functionality --- .../menu/app/section/disclosure_action.dart | 64 ++++++++++++++++--- .../home/menu/app/section/item.dart | 45 +++++++++---- 2 files changed, 87 insertions(+), 22 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart index c9a02a9de7..83b652eb8b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart @@ -3,6 +3,7 @@ import 'package:dartz/dartz.dart' as dartz; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flowy_infra/theme.dart'; import 'package:provider/provider.dart'; @@ -11,10 +12,13 @@ import 'item.dart'; // [[Widget: LifeCycle]] // https://flutterbyexample.com/lesson/stateful-widget-lifecycle -class ViewDisclosureButton extends StatelessWidget with ActionList, FlowyOverlayDelegate { +class ViewDisclosureButton extends StatelessWidget + with ActionList, FlowyOverlayDelegate { final Function() onTap; final Function(dartz.Option) onSelected; - final _items = ViewDisclosureAction.values.map((action) => ViewDisclosureActionWrapper(action)).toList(); + final _items = ViewDisclosureAction.values + .map((action) => ViewDisclosureActionWrapper(action)) + .toList(); ViewDisclosureButton({ Key? key, @@ -40,12 +44,13 @@ class ViewDisclosureButton extends StatelessWidget with ActionList get items => _items; @override - void Function(dartz.Option p1) get selectCallback => (result) { - result.fold( - () => onSelected(dartz.none()), - (wrapper) => onSelected(dartz.some(wrapper.inner)), - ); - }; + void Function(dartz.Option p1) + get selectCallback => (result) { + result.fold( + () => onSelected(dartz.none()), + (wrapper) => onSelected(dartz.some(wrapper.inner)), + ); + }; @override FlowyOverlayDelegate? get delegate => this; @@ -56,6 +61,49 @@ class ViewDisclosureButton extends StatelessWidget with ActionList, FlowyOverlayDelegate { + final Widget child; + final Function(dartz.Option) onSelected; + final _items = ViewDisclosureAction.values + .map((action) => ViewDisclosureActionWrapper(action)) + .toList(); + + ViewDisclosureRegion( + {Key? key, required this.onSelected, required this.child}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Listener( + onPointerDown: (event) => { + if (event.kind == PointerDeviceKind.mouse && + event.buttons == kSecondaryMouseButton) + { + print("IN LISTENER RN"), + show(context), + } + }, + child: child, + ); + } + + @override + FlowyOverlayDelegate? get delegate => this; + + @override + List get items => _items; + + @override + void Function(dartz.Option p1) + get selectCallback => (result) { + result.fold( + () => onSelected(dartz.none()), + (wrapper) => onSelected(dartz.some(wrapper.inner)), + ); + }; +} + class ViewDisclosureActionWrapper extends ActionItem { final ViewDisclosureAction inner; diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart index 97ae1dae52..93855c3fa2 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart @@ -36,7 +36,9 @@ class ViewSectionItem extends StatelessWidget { final theme = context.watch(); return MultiBlocProvider( providers: [ - BlocProvider(create: (ctx) => getIt(param1: view)..add(const ViewEvent.initial())), + BlocProvider( + create: (ctx) => + getIt(param1: view)..add(const ViewEvent.initial())), ], child: BlocBuilder( builder: (context, state) { @@ -46,7 +48,8 @@ class ViewSectionItem extends StatelessWidget { onTap: () => onSelected(context.read().state.view), child: FlowyHover( style: HoverStyle(hoverColor: theme.bg3), - builder: (_, onHover) => _render(context, onHover, state, theme.iconColor), + builder: (_, onHover) => + _render(context, onHover, state, theme.iconColor), setSelected: () => state.isEditing || isSelected, ), ), @@ -56,17 +59,24 @@ class ViewSectionItem extends StatelessWidget { ); } - Widget _render(BuildContext context, bool onHover, ViewState state, Color iconColor) { + Widget _render( + BuildContext context, bool onHover, ViewState state, Color iconColor) { List children = [ - SizedBox(width: 16, height: 16, child: state.view.renderThumbnail(iconColor: iconColor)), + SizedBox( + width: 16, + height: 16, + child: state.view.renderThumbnail(iconColor: iconColor)), const HSpace(2), - Expanded(child: FlowyText.regular(state.view.name, fontSize: 12, overflow: TextOverflow.clip)), + Expanded( + child: FlowyText.regular(state.view.name, + fontSize: 12, overflow: TextOverflow.clip)), ]; if (onHover || state.isEditing) { children.add( ViewDisclosureButton( - onTap: () => context.read().add(const ViewEvent.setIsEditing(true)), + onTap: () => + context.read().add(const ViewEvent.setIsEditing(true)), onSelected: (action) { context.read().add(const ViewEvent.setIsEditing(false)); _handleAction(context, action); @@ -75,16 +85,23 @@ class ViewSectionItem extends StatelessWidget { ); } - return SizedBox( - height: 26, - child: Row(children: children).padding( - left: MenuAppSizes.expandedPadding, - right: MenuAppSizes.headerPadding, - ), - ); + return ViewDisclosureRegion( + // context.read().add(const ViewEvent.setIsEditing(true)), + onSelected: (action) { + context.read().add(const ViewEvent.setIsEditing(false)); + _handleAction(context, action); + }, + child: SizedBox( + height: 26, + child: Row(children: children).padding( + left: MenuAppSizes.expandedPadding, + right: MenuAppSizes.headerPadding, + ), + )); } - void _handleAction(BuildContext context, dartz.Option action) { + void _handleAction( + BuildContext context, dartz.Option action) { action.foldRight({}, (action, previous) { switch (action) { case ViewDisclosureAction.rename: From c8d5769b1140c58e8ff736bd068b1fdd9ac8710e Mon Sep 17 00:00:00 2001 From: Aryman Date: Tue, 9 Aug 2022 01:45:56 +0530 Subject: [PATCH 2/5] refactor: remove print statement --- .../presentation/home/menu/app/section/disclosure_action.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart index 83b652eb8b..7fe02bab1a 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart @@ -80,7 +80,6 @@ class ViewDisclosureRegion extends StatelessWidget if (event.kind == PointerDeviceKind.mouse && event.buttons == kSecondaryMouseButton) { - print("IN LISTENER RN"), show(context), } }, From ab4a2e8b07af72bd9efbba5027e8b164707b224b Mon Sep 17 00:00:00 2001 From: Aryman Date: Wed, 10 Aug 2022 03:23:37 +0530 Subject: [PATCH 3/5] fix: menu displayed at mouse location --- .../menu/app/section/disclosure_action.dart | 19 ++++++++++++------- .../home/menu/app/section/item.dart | 1 - 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart index 7fe02bab1a..7375f6a113 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart @@ -76,13 +76,7 @@ class ViewDisclosureRegion extends StatelessWidget @override Widget build(BuildContext context) { return Listener( - onPointerDown: (event) => { - if (event.kind == PointerDeviceKind.mouse && - event.buttons == kSecondaryMouseButton) - { - show(context), - } - }, + onPointerDown: (event) => {_handleClick(event, context)}, child: child, ); } @@ -101,6 +95,17 @@ class ViewDisclosureRegion extends StatelessWidget (wrapper) => onSelected(dartz.some(wrapper.inner)), ); }; + + void _handleClick(PointerDownEvent event, BuildContext context) { + if (event.kind == PointerDeviceKind.mouse && + event.buttons == kSecondaryMouseButton) { + RenderBox box = context.findRenderObject() as RenderBox; + Offset position = box.localToGlobal(Offset.zero); + double x = event.position.dx - position.dx - box.size.width; + double y = event.position.dy - position.dy - box.size.height; + show(context, anchorOffset: Offset(x, y)); + } + } } class ViewDisclosureActionWrapper extends ActionItem { diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart index 93855c3fa2..3ca8577d8c 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart @@ -86,7 +86,6 @@ class ViewSectionItem extends StatelessWidget { } return ViewDisclosureRegion( - // context.read().add(const ViewEvent.setIsEditing(true)), onSelected: (action) { context.read().add(const ViewEvent.setIsEditing(false)); _handleAction(context, action); From e095a176832f644eb22b387887ac7b386e9c0dfd Mon Sep 17 00:00:00 2001 From: Aryman Date: Wed, 10 Aug 2022 14:46:39 +0530 Subject: [PATCH 4/5] fix: bug where context menu options wouldn't work unless page was selcted --- .../home/menu/app/section/disclosure_action.dart | 12 +++++++++++- .../presentation/home/menu/app/section/item.dart | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart index 7375f6a113..019f674b01 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart @@ -64,13 +64,17 @@ class ViewDisclosureButton extends StatelessWidget class ViewDisclosureRegion extends StatelessWidget with ActionList, FlowyOverlayDelegate { final Widget child; + final Function() onTap; final Function(dartz.Option) onSelected; final _items = ViewDisclosureAction.values .map((action) => ViewDisclosureActionWrapper(action)) .toList(); ViewDisclosureRegion( - {Key? key, required this.onSelected, required this.child}) + {Key? key, + required this.onSelected, + required this.onTap, + required this.child}) : super(key: key); @override @@ -96,6 +100,11 @@ class ViewDisclosureRegion extends StatelessWidget ); }; + @override + void didRemove() { + onSelected(dartz.none()); + } + void _handleClick(PointerDownEvent event, BuildContext context) { if (event.kind == PointerDeviceKind.mouse && event.buttons == kSecondaryMouseButton) { @@ -103,6 +112,7 @@ class ViewDisclosureRegion extends StatelessWidget Offset position = box.localToGlobal(Offset.zero); double x = event.position.dx - position.dx - box.size.width; double y = event.position.dy - position.dy - box.size.height; + onTap(); show(context, anchorOffset: Offset(x, y)); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart index 3ca8577d8c..bfc51f4bf9 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart @@ -86,6 +86,8 @@ class ViewSectionItem extends StatelessWidget { } return ViewDisclosureRegion( + onTap: () => + context.read().add(const ViewEvent.setIsEditing(true)), onSelected: (action) { context.read().add(const ViewEvent.setIsEditing(false)); _handleAction(context, action); From 72c5c937ae8c85ee7c1c8016b1530b6625778a9a Mon Sep 17 00:00:00 2001 From: Aryaman Date: Wed, 10 Aug 2022 17:03:01 +0530 Subject: [PATCH 5/5] fix: context menu now opens behind the icon as well --- .../home/menu/app/section/item.dart | 55 ++++++++++--------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart index bfc51f4bf9..cb3146a70c 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart @@ -42,18 +42,28 @@ class ViewSectionItem extends StatelessWidget { ], child: BlocBuilder( builder: (context, state) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 4), - child: InkWell( - onTap: () => onSelected(context.read().state.view), - child: FlowyHover( - style: HoverStyle(hoverColor: theme.bg3), - builder: (_, onHover) => - _render(context, onHover, state, theme.iconColor), - setSelected: () => state.isEditing || isSelected, - ), - ), - ); + return ViewDisclosureRegion( + onTap: () => context + .read() + .add(const ViewEvent.setIsEditing(true)), + onSelected: (action) { + context + .read() + .add(const ViewEvent.setIsEditing(false)); + _handleAction(context, action); + }, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: InkWell( + onTap: () => onSelected(context.read().state.view), + child: FlowyHover( + style: HoverStyle(hoverColor: theme.bg3), + builder: (_, onHover) => + _render(context, onHover, state, theme.iconColor), + setSelected: () => state.isEditing || isSelected, + ), + ), + )); }, ), ); @@ -85,20 +95,13 @@ class ViewSectionItem extends StatelessWidget { ); } - return ViewDisclosureRegion( - onTap: () => - context.read().add(const ViewEvent.setIsEditing(true)), - onSelected: (action) { - context.read().add(const ViewEvent.setIsEditing(false)); - _handleAction(context, action); - }, - child: SizedBox( - height: 26, - child: Row(children: children).padding( - left: MenuAppSizes.expandedPadding, - right: MenuAppSizes.headerPadding, - ), - )); + return SizedBox( + height: 26, + child: Row(children: children).padding( + left: MenuAppSizes.expandedPadding, + right: MenuAppSizes.headerPadding, + ), + ); } void _handleAction(