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..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 @@ -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,63 @@ class ViewDisclosureButton 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.onTap, + required this.child}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Listener( + onPointerDown: (event) => {_handleClick(event, 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)), + ); + }; + + @override + void didRemove() { + onSelected(dartz.none()); + } + + 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; + onTap(); + show(context, anchorOffset: Offset(x, y)); + } + } +} + 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..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 @@ -36,37 +36,57 @@ 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) { - 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, + ), + ), + )); }, ), ); } - 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); @@ -84,7 +104,8 @@ class ViewSectionItem extends StatelessWidget { ); } - void _handleAction(BuildContext context, dartz.Option action) { + void _handleAction( + BuildContext context, dartz.Option action) { action.foldRight({}, (action, previous) { switch (action) { case ViewDisclosureAction.rename: