瀏覽代碼

chore: optimize cell focus

appflowy 3 年之前
父節點
當前提交
f972cdd3fb

+ 9 - 0
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart

@@ -44,7 +44,16 @@ class BlankCell extends StatelessWidget {
 abstract class GridCellWidget extends HoverWidget {
   @override
   final ValueNotifier<bool> onFocus = ValueNotifier<bool>(false);
+
+  final GridCellRequestFocusNotifier requestFocus = GridCellRequestFocusNotifier();
+
   GridCellWidget({Key? key}) : super(key: key);
 }
 
+class GridCellRequestFocusNotifier extends ChangeNotifier {
+  void notify() {
+    notifyListeners();
+  }
+}
+
 abstract class GridCellStyle {}

+ 14 - 6
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart

@@ -1,3 +1,4 @@
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
@@ -31,17 +32,20 @@ class CellContainer extends StatelessWidget {
   final GridCellWidget child;
   final Widget? expander;
   final double width;
+  final RegionStateNotifier rowStateNotifier;
   const CellContainer({
     Key? key,
     required this.child,
     required this.width,
+    required this.rowStateNotifier,
     this.expander,
   }) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
-    return ChangeNotifierProvider(
+    return ChangeNotifierProxyProvider<RegionStateNotifier, CellStateNotifier>(
       create: (_) => CellStateNotifier(),
+      update: (_, row, cell) => cell!..onEnter = row.onEnter,
       child: Selector<CellStateNotifier, bool>(
         selector: (context, notifier) => notifier.isFocus,
         builder: (context, isFocus, _) {
@@ -54,11 +58,15 @@ class CellContainer extends StatelessWidget {
             container = _CellEnterRegion(child: container, expander: expander!);
           }
 
-          return Container(
-            constraints: BoxConstraints(maxWidth: width),
-            decoration: _makeBoxDecoration(context, isFocus),
-            padding: GridSize.cellContentInsets,
-            child: container,
+          return GestureDetector(
+            behavior: HitTestBehavior.translucent,
+            onTap: () => child.requestFocus.notify(),
+            child: Container(
+              constraints: BoxConstraints(maxWidth: width),
+              decoration: _makeBoxDecoration(context, isFocus),
+              padding: GridSize.cellContentInsets,
+              child: container,
+            ),
           );
         },
       ),

+ 13 - 0
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart

@@ -24,6 +24,7 @@ class _CheckboxCellState extends State<CheckboxCell> {
   void initState() {
     final cellContext = widget.cellContextBuilder.build();
     _cellBloc = getIt<CheckboxCellBloc>(param1: cellContext)..add(const CheckboxCellEvent.initial());
+    _listenCellRequestFocus();
     super.initState();
   }
 
@@ -48,9 +49,21 @@ class _CheckboxCellState extends State<CheckboxCell> {
     );
   }
 
+  @override
+  void didUpdateWidget(covariant CheckboxCell oldWidget) {
+    _listenCellRequestFocus();
+    super.didUpdateWidget(oldWidget);
+  }
+
   @override
   Future<void> dispose() async {
     _cellBloc.close();
     super.dispose();
   }
+
+  void _listenCellRequestFocus() {
+    widget.requestFocus.addListener(() {
+      _cellBloc.add(const CheckboxCellEvent.select());
+    });
+  }
 }

+ 20 - 0
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart

@@ -23,6 +23,7 @@ class _NumberCellState extends State<NumberCell> {
   late NumberCellBloc _cellBloc;
   late TextEditingController _controller;
   late FocusNode _focusNode;
+  VoidCallback? _focusListener;
   Timer? _delayOperation;
 
   @override
@@ -40,6 +41,7 @@ class _NumberCellState extends State<NumberCell> {
 
   @override
   Widget build(BuildContext context) {
+    _listenCellRequestFocus(context);
     return BlocProvider.value(
       value: _cellBloc,
       child: BlocConsumer<NumberCellBloc, NumberCellState>(
@@ -68,6 +70,9 @@ class _NumberCellState extends State<NumberCell> {
 
   @override
   Future<void> dispose() async {
+    if (_focusListener != null) {
+      widget.requestFocus.removeListener(_focusListener!);
+    }
     _delayOperation?.cancel();
     _cellBloc.close();
     _focusNode.dispose();
@@ -89,4 +94,19 @@ class _NumberCellState extends State<NumberCell> {
       });
     }
   }
+
+  void _listenCellRequestFocus(BuildContext context) {
+    if (_focusListener != null) {
+      widget.requestFocus.removeListener(_focusListener!);
+    }
+
+    focusListener() {
+      if (_focusNode.hasFocus == false && _focusNode.canRequestFocus) {
+        FocusScope.of(context).requestFocus(_focusNode);
+      }
+    }
+
+    _focusListener = focusListener;
+    widget.requestFocus.addListener(focusListener);
+  }
 }

+ 22 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart

@@ -36,7 +36,7 @@ class _GridTextCellState extends State<GridTextCell> {
   late TextCellBloc _cellBloc;
   late TextEditingController _controller;
   late FocusNode _focusNode;
-
+  VoidCallback? _focusListener;
   Timer? _delayOperation;
 
   @override
@@ -50,11 +50,14 @@ class _GridTextCellState extends State<GridTextCell> {
       widget.onFocus.value = _focusNode.hasFocus;
       focusChanged();
     });
+
     super.initState();
   }
 
   @override
   Widget build(BuildContext context) {
+    _listenCellRequestFocus(context);
+
     return BlocProvider.value(
       value: _cellBloc,
       child: BlocConsumer<TextCellBloc, TextCellState>(
@@ -84,8 +87,26 @@ class _GridTextCellState extends State<GridTextCell> {
     );
   }
 
+  void _listenCellRequestFocus(BuildContext context) {
+    if (_focusListener != null) {
+      widget.requestFocus.removeListener(_focusListener!);
+    }
+
+    focusListener() {
+      if (_focusNode.hasFocus == false && _focusNode.canRequestFocus) {
+        FocusScope.of(context).requestFocus(_focusNode);
+      }
+    }
+
+    _focusListener = focusListener;
+    widget.requestFocus.addListener(focusListener);
+  }
+
   @override
   Future<void> dispose() async {
+    if (_focusListener != null) {
+      widget.requestFocus.removeListener(_focusListener!);
+    }
     _delayOperation?.cancel();
     _cellBloc.close();
     _focusNode.dispose();

+ 7 - 6
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart

@@ -88,7 +88,7 @@ class _RowLeading extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return Consumer<_RegionStateNotifier>(
+    return Consumer<RegionStateNotifier>(
       builder: (context, state, _) {
         return SizedBox(width: GridSize.leadingHeaderPadding, child: state.onEnter ? _activeWidget() : null);
       },
@@ -164,13 +164,13 @@ class _RowCells extends StatelessWidget {
         return Row(
           mainAxisSize: MainAxisSize.min,
           mainAxisAlignment: MainAxisAlignment.center,
-          children: _makeCells(state.cellDataMap),
+          children: _makeCells(context, state.cellDataMap),
         );
       },
     );
   }
 
-  List<Widget> _makeCells(GridCellMap gridCellMap) {
+  List<Widget> _makeCells(BuildContext context, GridCellMap gridCellMap) {
     return gridCellMap.values.map(
       (gridCell) {
         Widget? expander;
@@ -181,6 +181,7 @@ class _RowCells extends StatelessWidget {
         return CellContainer(
           width: gridCell.field.width.toDouble(),
           child: buildGridCellWidget(gridCell, cellCache),
+          rowStateNotifier: Provider.of<RegionStateNotifier>(context, listen: false),
           expander: expander,
         );
       },
@@ -188,7 +189,7 @@ class _RowCells extends StatelessWidget {
   }
 }
 
-class _RegionStateNotifier extends ChangeNotifier {
+class RegionStateNotifier extends ChangeNotifier {
   bool _onEnter = false;
 
   set onEnter(bool value) {
@@ -226,11 +227,11 @@ class _RowEnterRegion extends StatefulWidget {
 }
 
 class _RowEnterRegionState extends State<_RowEnterRegion> {
-  late _RegionStateNotifier _rowStateNotifier;
+  late RegionStateNotifier _rowStateNotifier;
 
   @override
   void initState() {
-    _rowStateNotifier = _RegionStateNotifier();
+    _rowStateNotifier = RegionStateNotifier();
     super.initState();
   }