diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart index 65bff03ecf..05708e6198 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart @@ -48,7 +48,9 @@ class BlankCell extends StatelessWidget { } } -abstract class GridCellWidget implements AccessoryWidget, CellContainerFocustable { +abstract class GridCellWidget extends StatefulWidget implements AccessoryWidget, CellContainerFocustable { + GridCellWidget({Key? key}) : super(key: key); + @override final ValueNotifier isFocus = ValueNotifier(false); @@ -59,6 +61,72 @@ abstract class GridCellWidget implements AccessoryWidget, CellContainerFocustabl final GridCellRequestBeginFocus requestBeginFocus = GridCellRequestBeginFocus(); } +abstract class GridCellState extends State { + @override + void initState() { + widget.requestBeginFocus.setListener(() => requestBeginFocus()); + super.initState(); + } + + @override + void didUpdateWidget(covariant T oldWidget) { + if (oldWidget != this) { + widget.requestBeginFocus.setListener(() => requestBeginFocus()); + } + super.didUpdateWidget(oldWidget); + } + + @override + void dispose() { + widget.requestBeginFocus.removeAllListener(); + super.dispose(); + } + + void requestBeginFocus(); +} + +abstract class GridFocusNodeCellState extends GridCellState { + SingleListenrFocusNode focusNode = SingleListenrFocusNode(); + + @override + void initState() { + _listenOnFocusNodeChanged(); + super.initState(); + } + + @override + void didUpdateWidget(covariant T oldWidget) { + if (oldWidget != this) { + _listenOnFocusNodeChanged(); + } + super.didUpdateWidget(oldWidget); + } + + @override + void dispose() { + focusNode.removeAllListener(); + focusNode.dispose(); + super.dispose(); + } + + @override + void requestBeginFocus() { + if (focusNode.hasFocus == false && focusNode.canRequestFocus) { + FocusScope.of(context).requestFocus(focusNode); + } + } + + void _listenOnFocusNodeChanged() { + widget.isFocus.value = focusNode.hasFocus; + focusNode.setListener(() { + widget.isFocus.value = focusNode.hasFocus; + focusChanged(); + }); + } + + Future focusChanged() async {} +} + class GridCellRequestBeginFocus extends ChangeNotifier { VoidCallback? _listener; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart index 78910348b3..6f22a7d977 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart @@ -6,7 +6,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'cell_builder.dart'; -class CheckboxCell extends StatefulWidget with GridCellWidget { +class CheckboxCell extends GridCellWidget { final GridCellContextBuilder cellContextBuilder; CheckboxCell({ required this.cellContextBuilder, @@ -14,17 +14,17 @@ class CheckboxCell extends StatefulWidget with GridCellWidget { }) : super(key: key); @override - State createState() => _CheckboxCellState(); + GridCellState createState() => _CheckboxCellState(); } -class _CheckboxCellState extends State { +class _CheckboxCellState extends GridCellState { late CheckboxCellBloc _cellBloc; @override void initState() { final cellContext = widget.cellContextBuilder.build(); _cellBloc = getIt(param1: cellContext)..add(const CheckboxCellEvent.initial()); - _handleRequestFocus(); + super.initState(); } @@ -49,22 +49,14 @@ class _CheckboxCellState extends State { ); } - @override - void didUpdateWidget(covariant CheckboxCell oldWidget) { - _handleRequestFocus(); - super.didUpdateWidget(oldWidget); - } - @override Future dispose() async { - widget.requestBeginFocus.removeAllListener(); _cellBloc.close(); super.dispose(); } - void _handleRequestFocus() { - widget.requestBeginFocus.setListener(() { - _cellBloc.add(const CheckboxCellEvent.select()); - }); + @override + void requestBeginFocus() { + _cellBloc.add(const CheckboxCellEvent.select()); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart index 9855b98bf5..eed45464bf 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart @@ -18,7 +18,7 @@ abstract class GridCellDelegate { GridCellDelegate get delegate; } -class DateCell extends StatefulWidget with GridCellWidget { +class DateCell extends GridCellWidget { final GridCellContextBuilder cellContextBuilder; late final DateCellStyle? cellStyle; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart index 64fff54c47..88aaf5cb3b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart @@ -7,7 +7,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'cell_builder.dart'; -class NumberCell extends StatefulWidget with GridCellWidget { +class NumberCell extends GridCellWidget { final GridCellContextBuilder cellContextBuilder; NumberCell({ @@ -16,13 +16,12 @@ class NumberCell extends StatefulWidget with GridCellWidget { }) : super(key: key); @override - State createState() => _NumberCellState(); + GridFocusNodeCellState createState() => _NumberCellState(); } -class _NumberCellState extends State { +class _NumberCellState extends GridFocusNodeCellState { late NumberCellBloc _cellBloc; late TextEditingController _controller; - late SingleListenrFocusNode _focusNode; Timer? _delayOperation; @override @@ -30,14 +29,11 @@ class _NumberCellState extends State { final cellContext = widget.cellContextBuilder.build(); _cellBloc = getIt(param1: cellContext)..add(const NumberCellEvent.initial()); _controller = TextEditingController(text: contentFromState(_cellBloc.state)); - _focusNode = SingleListenrFocusNode(); - _listenOnFocusNodeChanged(); super.initState(); } @override Widget build(BuildContext context) { - _handleCellRequestFocus(context); return BlocProvider.value( value: _cellBloc, child: MultiBlocListener( @@ -49,8 +45,8 @@ class _NumberCellState extends State { ], child: TextField( controller: _controller, - focusNode: _focusNode, - onEditingComplete: () => _focusNode.unfocus(), + focusNode: focusNode, + onEditingComplete: () => focusNode.unfocus(), maxLines: null, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), decoration: const InputDecoration( @@ -65,20 +61,12 @@ class _NumberCellState extends State { @override Future dispose() async { - widget.requestBeginFocus.removeAllListener(); _delayOperation?.cancel(); _cellBloc.close(); - _focusNode.removeAllListener(); - _focusNode.dispose(); super.dispose(); } @override - void didUpdateWidget(covariant NumberCell oldWidget) { - _listenOnFocusNodeChanged(); - super.didUpdateWidget(oldWidget); - } - Future focusChanged() async { if (mounted) { _delayOperation?.cancel(); @@ -90,22 +78,6 @@ class _NumberCellState extends State { } } - void _listenOnFocusNodeChanged() { - widget.isFocus.value = _focusNode.hasFocus; - _focusNode.setListener(() { - widget.isFocus.value = _focusNode.hasFocus; - focusChanged(); - }); - } - - void _handleCellRequestFocus(BuildContext context) { - widget.requestBeginFocus.setListener(() { - if (_focusNode.hasFocus == false && _focusNode.canRequestFocus) { - FocusScope.of(context).requestFocus(_focusNode); - } - }); - } - String contentFromState(NumberCellState state) { return state.content.fold((l) => l, (r) => ""); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_cell.dart index aa780263b5..294a87976f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_cell.dart @@ -20,7 +20,7 @@ class SelectOptionCellStyle extends GridCellStyle { }); } -class SingleSelectCell extends StatefulWidget with GridCellWidget { +class SingleSelectCell extends GridCellWidget { final GridCellContextBuilder cellContextBuilder; late final SelectOptionCellStyle? cellStyle; @@ -74,7 +74,7 @@ class _SingleSelectCellState extends State { } //---------------------------------------------------------------- -class MultiSelectCell extends StatefulWidget with GridCellWidget { +class MultiSelectCell extends GridCellWidget { final GridCellContextBuilder cellContextBuilder; late final SelectOptionCellStyle? cellStyle; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart index b2eda288a1..7e1333fff0 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart @@ -13,7 +13,7 @@ class GridTextCellStyle extends GridCellStyle { }); } -class GridTextCell extends StatefulWidget with GridCellWidget { +class GridTextCell extends GridCellWidget { final GridCellContextBuilder cellContextBuilder; late final GridTextCellStyle? cellStyle; GridTextCell({ @@ -29,13 +29,12 @@ class GridTextCell extends StatefulWidget with GridCellWidget { } @override - State createState() => _GridTextCellState(); + GridFocusNodeCellState createState() => _GridTextCellState(); } -class _GridTextCellState extends State { +class _GridTextCellState extends GridFocusNodeCellState { late TextCellBloc _cellBloc; late TextEditingController _controller; - late SingleListenrFocusNode _focusNode; Timer? _delayOperation; @override @@ -44,10 +43,6 @@ class _GridTextCellState extends State { _cellBloc = getIt(param1: cellContext); _cellBloc.add(const TextCellEvent.initial()); _controller = TextEditingController(text: _cellBloc.state.content); - _focusNode = SingleListenrFocusNode(); - - _listenOnFocusNodeChanged(); - _listenRequestFocus(context); super.initState(); } @@ -63,9 +58,9 @@ class _GridTextCellState extends State { }, child: TextField( controller: _controller, - focusNode: _focusNode, + focusNode: focusNode, onChanged: (value) => focusChanged(), - onEditingComplete: () => _focusNode.unfocus(), + onEditingComplete: () => focusNode.unfocus(), maxLines: null, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), decoration: InputDecoration( @@ -81,39 +76,12 @@ class _GridTextCellState extends State { @override Future dispose() async { - widget.requestBeginFocus.removeAllListener(); _delayOperation?.cancel(); _cellBloc.close(); - _focusNode.removeAllListener(); - _focusNode.dispose(); - super.dispose(); } @override - void didUpdateWidget(covariant GridTextCell oldWidget) { - if (oldWidget != widget) { - _listenOnFocusNodeChanged(); - } - super.didUpdateWidget(oldWidget); - } - - void _listenOnFocusNodeChanged() { - widget.isFocus.value = _focusNode.hasFocus; - _focusNode.setListener(() { - widget.isFocus.value = _focusNode.hasFocus; - focusChanged(); - }); - } - - void _listenRequestFocus(BuildContext context) { - widget.requestBeginFocus.setListener(() { - if (_focusNode.hasFocus == false && _focusNode.canRequestFocus) { - FocusScope.of(context).requestFocus(_focusNode); - } - }); - } - Future focusChanged() async { if (mounted) { _delayOperation?.cancel(); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart index 56f0b421a5..5caa014df0 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart @@ -30,7 +30,7 @@ enum GridURLCellAccessoryType { copyURL, } -class GridURLCell extends StatefulWidget with GridCellWidget { +class GridURLCell extends GridCellWidget { final GridCellContextBuilder cellContextBuilder; late final GridURLCellStyle? cellStyle; GridURLCell({ @@ -46,7 +46,7 @@ class GridURLCell extends StatefulWidget with GridCellWidget { } @override - State createState() => _GridURLCellState(); + GridCellState createState() => _GridURLCellState(); GridCellAccessory accessoryFromType(GridURLCellAccessoryType ty, GridCellAccessoryBuildContext buildContext) { switch (ty) { @@ -78,7 +78,7 @@ class GridURLCell extends StatefulWidget with GridCellWidget { }; } -class _GridURLCellState extends State { +class _GridURLCellState extends GridCellState { late URLCellBloc _cellBloc; @override @@ -86,7 +86,6 @@ class _GridURLCellState extends State { final cellContext = widget.cellContextBuilder.build() as GridURLCellContext; _cellBloc = URLCellBloc(cellContext: cellContext); _cellBloc.add(const URLCellEvent.initial()); - _handleRequestFocus(); super.initState(); } @@ -125,17 +124,10 @@ class _GridURLCellState extends State { @override Future dispose() async { - widget.requestBeginFocus.removeAllListener(); _cellBloc.close(); super.dispose(); } - @override - void didUpdateWidget(covariant GridURLCell oldWidget) { - _handleRequestFocus(); - super.didUpdateWidget(oldWidget); - } - Future _openUrlOrEdit(String url) async { final uri = Uri.parse(url); if (url.isNotEmpty && await canLaunchUrl(uri)) { @@ -146,10 +138,9 @@ class _GridURLCellState extends State { } } - void _handleRequestFocus() { - widget.requestBeginFocus.setListener(() { - _openUrlOrEdit(_cellBloc.state.url); - }); + @override + void requestBeginFocus() { + _openUrlOrEdit(_cellBloc.state.url); } }