mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-11-13 00:48:20 +00:00
chore: optimize cell focus
This commit is contained in:
parent
d0b4abb0c8
commit
f972cdd3fb
@ -44,7 +44,16 @@ class BlankCell extends StatelessWidget {
|
|||||||
abstract class GridCellWidget extends HoverWidget {
|
abstract class GridCellWidget extends HoverWidget {
|
||||||
@override
|
@override
|
||||||
final ValueNotifier<bool> onFocus = ValueNotifier<bool>(false);
|
final ValueNotifier<bool> onFocus = ValueNotifier<bool>(false);
|
||||||
|
|
||||||
|
final GridCellRequestFocusNotifier requestFocus = GridCellRequestFocusNotifier();
|
||||||
|
|
||||||
GridCellWidget({Key? key}) : super(key: key);
|
GridCellWidget({Key? key}) : super(key: key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GridCellRequestFocusNotifier extends ChangeNotifier {
|
||||||
|
void notify() {
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
abstract class GridCellStyle {}
|
abstract class GridCellStyle {}
|
||||||
|
|||||||
@ -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:flowy_infra/theme.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@ -31,17 +32,20 @@ class CellContainer extends StatelessWidget {
|
|||||||
final GridCellWidget child;
|
final GridCellWidget child;
|
||||||
final Widget? expander;
|
final Widget? expander;
|
||||||
final double width;
|
final double width;
|
||||||
|
final RegionStateNotifier rowStateNotifier;
|
||||||
const CellContainer({
|
const CellContainer({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.child,
|
required this.child,
|
||||||
required this.width,
|
required this.width,
|
||||||
|
required this.rowStateNotifier,
|
||||||
this.expander,
|
this.expander,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ChangeNotifierProvider(
|
return ChangeNotifierProxyProvider<RegionStateNotifier, CellStateNotifier>(
|
||||||
create: (_) => CellStateNotifier(),
|
create: (_) => CellStateNotifier(),
|
||||||
|
update: (_, row, cell) => cell!..onEnter = row.onEnter,
|
||||||
child: Selector<CellStateNotifier, bool>(
|
child: Selector<CellStateNotifier, bool>(
|
||||||
selector: (context, notifier) => notifier.isFocus,
|
selector: (context, notifier) => notifier.isFocus,
|
||||||
builder: (context, isFocus, _) {
|
builder: (context, isFocus, _) {
|
||||||
@ -54,11 +58,15 @@ class CellContainer extends StatelessWidget {
|
|||||||
container = _CellEnterRegion(child: container, expander: expander!);
|
container = _CellEnterRegion(child: container, expander: expander!);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Container(
|
return GestureDetector(
|
||||||
|
behavior: HitTestBehavior.translucent,
|
||||||
|
onTap: () => child.requestFocus.notify(),
|
||||||
|
child: Container(
|
||||||
constraints: BoxConstraints(maxWidth: width),
|
constraints: BoxConstraints(maxWidth: width),
|
||||||
decoration: _makeBoxDecoration(context, isFocus),
|
decoration: _makeBoxDecoration(context, isFocus),
|
||||||
padding: GridSize.cellContentInsets,
|
padding: GridSize.cellContentInsets,
|
||||||
child: container,
|
child: container,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@ -24,6 +24,7 @@ class _CheckboxCellState extends State<CheckboxCell> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
final cellContext = widget.cellContextBuilder.build();
|
final cellContext = widget.cellContextBuilder.build();
|
||||||
_cellBloc = getIt<CheckboxCellBloc>(param1: cellContext)..add(const CheckboxCellEvent.initial());
|
_cellBloc = getIt<CheckboxCellBloc>(param1: cellContext)..add(const CheckboxCellEvent.initial());
|
||||||
|
_listenCellRequestFocus();
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,9 +49,21 @@ class _CheckboxCellState extends State<CheckboxCell> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant CheckboxCell oldWidget) {
|
||||||
|
_listenCellRequestFocus();
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
_cellBloc.close();
|
_cellBloc.close();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _listenCellRequestFocus() {
|
||||||
|
widget.requestFocus.addListener(() {
|
||||||
|
_cellBloc.add(const CheckboxCellEvent.select());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,7 @@ class _NumberCellState extends State<NumberCell> {
|
|||||||
late NumberCellBloc _cellBloc;
|
late NumberCellBloc _cellBloc;
|
||||||
late TextEditingController _controller;
|
late TextEditingController _controller;
|
||||||
late FocusNode _focusNode;
|
late FocusNode _focusNode;
|
||||||
|
VoidCallback? _focusListener;
|
||||||
Timer? _delayOperation;
|
Timer? _delayOperation;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -40,6 +41,7 @@ class _NumberCellState extends State<NumberCell> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
_listenCellRequestFocus(context);
|
||||||
return BlocProvider.value(
|
return BlocProvider.value(
|
||||||
value: _cellBloc,
|
value: _cellBloc,
|
||||||
child: BlocConsumer<NumberCellBloc, NumberCellState>(
|
child: BlocConsumer<NumberCellBloc, NumberCellState>(
|
||||||
@ -68,6 +70,9 @@ class _NumberCellState extends State<NumberCell> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
|
if (_focusListener != null) {
|
||||||
|
widget.requestFocus.removeListener(_focusListener!);
|
||||||
|
}
|
||||||
_delayOperation?.cancel();
|
_delayOperation?.cancel();
|
||||||
_cellBloc.close();
|
_cellBloc.close();
|
||||||
_focusNode.dispose();
|
_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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ class _GridTextCellState extends State<GridTextCell> {
|
|||||||
late TextCellBloc _cellBloc;
|
late TextCellBloc _cellBloc;
|
||||||
late TextEditingController _controller;
|
late TextEditingController _controller;
|
||||||
late FocusNode _focusNode;
|
late FocusNode _focusNode;
|
||||||
|
VoidCallback? _focusListener;
|
||||||
Timer? _delayOperation;
|
Timer? _delayOperation;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -50,11 +50,14 @@ class _GridTextCellState extends State<GridTextCell> {
|
|||||||
widget.onFocus.value = _focusNode.hasFocus;
|
widget.onFocus.value = _focusNode.hasFocus;
|
||||||
focusChanged();
|
focusChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
_listenCellRequestFocus(context);
|
||||||
|
|
||||||
return BlocProvider.value(
|
return BlocProvider.value(
|
||||||
value: _cellBloc,
|
value: _cellBloc,
|
||||||
child: BlocConsumer<TextCellBloc, TextCellState>(
|
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
|
@override
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
|
if (_focusListener != null) {
|
||||||
|
widget.requestFocus.removeListener(_focusListener!);
|
||||||
|
}
|
||||||
_delayOperation?.cancel();
|
_delayOperation?.cancel();
|
||||||
_cellBloc.close();
|
_cellBloc.close();
|
||||||
_focusNode.dispose();
|
_focusNode.dispose();
|
||||||
|
|||||||
@ -88,7 +88,7 @@ class _RowLeading extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer<_RegionStateNotifier>(
|
return Consumer<RegionStateNotifier>(
|
||||||
builder: (context, state, _) {
|
builder: (context, state, _) {
|
||||||
return SizedBox(width: GridSize.leadingHeaderPadding, child: state.onEnter ? _activeWidget() : null);
|
return SizedBox(width: GridSize.leadingHeaderPadding, child: state.onEnter ? _activeWidget() : null);
|
||||||
},
|
},
|
||||||
@ -164,13 +164,13 @@ class _RowCells extends StatelessWidget {
|
|||||||
return Row(
|
return Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
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(
|
return gridCellMap.values.map(
|
||||||
(gridCell) {
|
(gridCell) {
|
||||||
Widget? expander;
|
Widget? expander;
|
||||||
@ -181,6 +181,7 @@ class _RowCells extends StatelessWidget {
|
|||||||
return CellContainer(
|
return CellContainer(
|
||||||
width: gridCell.field.width.toDouble(),
|
width: gridCell.field.width.toDouble(),
|
||||||
child: buildGridCellWidget(gridCell, cellCache),
|
child: buildGridCellWidget(gridCell, cellCache),
|
||||||
|
rowStateNotifier: Provider.of<RegionStateNotifier>(context, listen: false),
|
||||||
expander: expander,
|
expander: expander,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -188,7 +189,7 @@ class _RowCells extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _RegionStateNotifier extends ChangeNotifier {
|
class RegionStateNotifier extends ChangeNotifier {
|
||||||
bool _onEnter = false;
|
bool _onEnter = false;
|
||||||
|
|
||||||
set onEnter(bool value) {
|
set onEnter(bool value) {
|
||||||
@ -226,11 +227,11 @@ class _RowEnterRegion extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _RowEnterRegionState extends State<_RowEnterRegion> {
|
class _RowEnterRegionState extends State<_RowEnterRegion> {
|
||||||
late _RegionStateNotifier _rowStateNotifier;
|
late RegionStateNotifier _rowStateNotifier;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_rowStateNotifier = _RegionStateNotifier();
|
_rowStateNotifier = RegionStateNotifier();
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user