diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/desktop_row_detail/desktop_row_detail_checklist_cell.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/desktop_row_detail/desktop_row_detail_checklist_cell.dart index 255dbdd38b..3c4576e4c3 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/desktop_row_detail/desktop_row_detail_checklist_cell.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/desktop_row_detail/desktop_row_detail_checklist_cell.dart @@ -10,7 +10,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:provider/provider.dart'; import '../editable_cell_skeleton/checklist.dart'; @@ -113,40 +113,34 @@ class _ChecklistItemsState extends State { ), const VSpace(4), ...children, - const ChecklistItemControl(), + ChecklistItemControl(cellNotifer: widget.cellContainerNotifier), ], ), ); } } -class ChecklistItemControl extends StatefulWidget { - const ChecklistItemControl({super.key}); +class ChecklistItemControl extends StatelessWidget { + const ChecklistItemControl({super.key, required this.cellNotifer}); - @override - State createState() => _ChecklistItemControlState(); -} - -class _ChecklistItemControlState extends State { - bool _isHover = false; + final CellContainerNotifier cellNotifer; @override Widget build(BuildContext context) { - return MouseRegion( - onHover: (_) => setState(() => _isHover = true), - onExit: (_) => setState(() => _isHover = false), - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () => context - .read() - .add(const ChecklistCellEvent.createNewTask("")), - child: Padding( - padding: const EdgeInsets.fromLTRB(8.0, 4.0, 8.0, 0), - child: SizedBox( + return ChangeNotifierProvider.value( + value: cellNotifer, + child: Consumer( + builder: (buildContext, notifier, _) => GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () => context + .read() + .add(const ChecklistCellEvent.createNewTask("")), + child: Container( + margin: const EdgeInsets.fromLTRB(8.0, 4.0, 8.0, 0), height: 12, child: AnimatedSwitcher( duration: const Duration(milliseconds: 150), - child: _isHover + child: notifier.isHover ? FlowyTooltip( message: LocaleKeys.grid_checklist_addNew.tr(), child: Row( diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_builder.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_builder.dart index a5e190400e..e49347eeaf 100755 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_builder.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_builder.dart @@ -190,11 +190,9 @@ class EditableCellBuilder { } abstract class CellEditable { - RequestFocusListener get requestFocus; + SingleListenerChangeNotifier get requestFocus; CellContainerNotifier get cellContainerNotifier; - - // ValueNotifier get onCellEditing; } typedef AccessoryBuilder = List Function( @@ -204,9 +202,6 @@ typedef AccessoryBuilder = List Function( abstract class CellAccessory extends Widget { const CellAccessory({super.key}); - // The hover will show if the isHover's value is true - ValueNotifier? get onAccessoryHover; - AccessoryBuilder? get accessoryBuilder; } @@ -217,20 +212,11 @@ abstract class EditableCellWidget extends StatefulWidget @override final CellContainerNotifier cellContainerNotifier = CellContainerNotifier(); - // When the cell is focused, we assume that the accessory also be hovered. @override - ValueNotifier get onAccessoryHover => ValueNotifier(false); - - // @override - // final ValueNotifier onCellEditing = ValueNotifier(false); + AccessoryBuilder? get accessoryBuilder => null; @override - List Function( - GridCellAccessoryBuildContext buildContext, - )? get accessoryBuilder => null; - - @override - final RequestFocusListener requestFocus = RequestFocusListener(); + final requestFocus = SingleListenerChangeNotifier(); @override final Map shortcutHandlers = {}; @@ -240,28 +226,25 @@ abstract class GridCellState extends State { @override void initState() { super.initState(); - - widget.requestFocus.setListener(requestBeginFocus); + widget.requestFocus.addListener(onRequestFocus); } @override void didUpdateWidget(covariant T oldWidget) { if (oldWidget != this) { - widget.requestFocus.setListener(requestBeginFocus); + widget.requestFocus.addListener(onRequestFocus); } super.didUpdateWidget(oldWidget); } @override void dispose() { - widget.onAccessoryHover.dispose(); - widget.requestFocus.removeAllListener(); widget.requestFocus.dispose(); super.dispose(); } /// Subclass can override this method to request focus. - void requestBeginFocus(); + void onRequestFocus(); String? onCopy() => null; } @@ -287,7 +270,7 @@ abstract class GridEditableTextCell } @override - void requestBeginFocus() { + void onRequestFocus() { if (!focusNode.hasFocus && focusNode.canRequestFocus) { FocusScope.of(context).requestFocus(focusNode); } @@ -304,28 +287,25 @@ abstract class GridEditableTextCell Future focusChanged() async {} } -class RequestFocusListener extends ChangeNotifier { +class SingleListenerChangeNotifier extends ChangeNotifier { VoidCallback? _listener; - void setListener(VoidCallback listener) { + @override + void addListener(VoidCallback listener) { if (_listener != null) { removeListener(_listener!); } - _listener = listener; - addListener(listener); + super.addListener(listener); } - void removeAllListener() { - if (_listener != null) { - removeListener(_listener!); - _listener = null; - } + @override + void dispose() { + _listener = null; + super.dispose(); } - void notify() { - notifyListeners(); - } + void notify() => notifyListeners(); } class SingleListenerFocusNode extends FocusNode { @@ -374,7 +354,7 @@ class EditableCellSkinMap { FieldType.Checklist => checklistSkin != null, FieldType.CreatedTime || FieldType.LastEditedTime => - throw timestampSkin != null, + timestampSkin != null, FieldType.DateTime => dateSkin != null, FieldType.MultiSelect || FieldType.SingleSelect => diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/checkbox.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/checkbox.dart index 41d7e22ed6..4b7bd2c442 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/checkbox.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/checkbox.dart @@ -80,9 +80,7 @@ class _CheckboxCellState extends GridCellState { } @override - void requestBeginFocus() { - cellBloc.add(const CheckboxCellEvent.select()); - } + void onRequestFocus() => cellBloc.add(const CheckboxCellEvent.select()); @override String? onCopy() { diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/checklist.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/checklist.dart index 434cd19e8f..2f3407aea6 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/checklist.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/checklist.dart @@ -85,7 +85,7 @@ class GridChecklistCellState extends GridCellState { } @override - void requestBeginFocus() { + void onRequestFocus() { if (widget.skin is DesktopGridChecklistCellSkin) { _popover.show(); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/date.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/date.dart index bfabe0e97f..d6c2ae8434 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/date.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/date.dart @@ -84,7 +84,7 @@ class _DateCellState extends GridCellState { } @override - void requestBeginFocus() { + void onRequestFocus() { _popover.show(); widget.cellContainerNotifier.isFocus = true; } diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/number.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/number.dart index bf5f887a9f..689b411550 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/number.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/number.dart @@ -96,7 +96,7 @@ class _NumberCellState extends GridEditableTextCell { SingleListenerFocusNode focusNode = SingleListenerFocusNode(); @override - void requestBeginFocus() { + void onRequestFocus() { focusNode.requestFocus(); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/select_option.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/select_option.dart index 08f6c1c750..de3908e585 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/select_option.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/select_option.dart @@ -92,5 +92,5 @@ class _SelectOptionCellState extends GridCellState { } @override - void requestBeginFocus() => _popover.show(); + void onRequestFocus() => _popover.show(); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/text.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/text.dart index 8e3c06edca..622b6a471d 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/text.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/text.dart @@ -97,7 +97,7 @@ class _TextCellState extends GridEditableTextCell { SingleListenerFocusNode focusNode = SingleListenerFocusNode(); @override - void requestBeginFocus() { + void onRequestFocus() { focusNode.requestFocus(); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/timestamp.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/timestamp.dart index 7391971775..5296ec7943 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/timestamp.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/editable_cell_skeleton/timestamp.dart @@ -83,7 +83,7 @@ class _TimestampCellState extends GridCellState { } @override - void requestBeginFocus() { + void onRequestFocus() { widget.cellContainerNotifier.isFocus = true; } diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/row/cells/cell_container.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/row/cells/cell_container.dart index 82ff1cce08..a878192106 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/row/cells/cell_container.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/row/cells/cell_container.dart @@ -98,7 +98,7 @@ class _GridCellEnterRegion extends StatelessWidget { return Selector2( selector: (context, regionNotifier, cellNotifier) => !cellNotifier.isFocus && - (cellNotifier.onEnter || regionNotifier.onEnter && isPrimary), + (cellNotifier.isHover || regionNotifier.onEnter && isPrimary), builder: (context, showAccessory, _) { final List children = [child]; @@ -113,9 +113,9 @@ class _GridCellEnterRegion extends StatelessWidget { return MouseRegion( cursor: SystemMouseCursors.click, onEnter: (p) => - CellContainerNotifier.of(context, listen: false).onEnter = true, + CellContainerNotifier.of(context, listen: false).isHover = true, onExit: (p) => - CellContainerNotifier.of(context, listen: false).onEnter = false, + CellContainerNotifier.of(context, listen: false).isHover = false, child: Stack( alignment: AlignmentDirectional.center, fit: StackFit.expand, @@ -138,7 +138,7 @@ class CellContainerNotifier extends ChangeNotifier { } } - set onEnter(bool value) { + set isHover(bool value) { if (_onEnter != value) { _onEnter = value; notifyListeners(); @@ -147,7 +147,7 @@ class CellContainerNotifier extends ChangeNotifier { bool get isFocus => _isFocus; - bool get onEnter => _onEnter; + bool get isHover => _onEnter; static CellContainerNotifier of(BuildContext context, {bool listen = true}) { return Provider.of(context, listen: listen); diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/row/row_property.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/row/row_property.dart index 1718d3a67e..a5b92ab9cb 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/row/row_property.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/row/row_property.dart @@ -189,8 +189,14 @@ class _PropertyCellState extends State<_PropertyCell> { margin: const EdgeInsets.only(bottom: 8), constraints: const BoxConstraints(minHeight: 30), child: MouseRegion( - onEnter: (event) => _isFieldHover.value = true, - onExit: (event) => _isFieldHover.value = false, + onEnter: (event) { + _isFieldHover.value = true; + cell.cellContainerNotifier.isHover = true; + }, + onExit: (event) { + _isFieldHover.value = false; + cell.cellContainerNotifier.isHover = false; + }, child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [