refactor: add GridCellState and GridFocusNodeCellState

This commit is contained in:
appflowy 2022-06-03 12:05:47 +08:00
parent 81efee557c
commit 4887885aae
7 changed files with 95 additions and 104 deletions

View File

@ -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<bool> isFocus = ValueNotifier<bool>(false);
@ -59,6 +61,72 @@ abstract class GridCellWidget implements AccessoryWidget, CellContainerFocustabl
final GridCellRequestBeginFocus requestBeginFocus = GridCellRequestBeginFocus();
}
abstract class GridCellState<T extends GridCellWidget> extends State<T> {
@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<T extends GridCellWidget> extends GridCellState<T> {
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<void> focusChanged() async {}
}
class GridCellRequestBeginFocus extends ChangeNotifier {
VoidCallback? _listener;

View File

@ -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<CheckboxCell> createState() => _CheckboxCellState();
GridCellState<CheckboxCell> createState() => _CheckboxCellState();
}
class _CheckboxCellState extends State<CheckboxCell> {
class _CheckboxCellState extends GridCellState<CheckboxCell> {
late CheckboxCellBloc _cellBloc;
@override
void initState() {
final cellContext = widget.cellContextBuilder.build();
_cellBloc = getIt<CheckboxCellBloc>(param1: cellContext)..add(const CheckboxCellEvent.initial());
_handleRequestFocus();
super.initState();
}
@ -49,22 +49,14 @@ class _CheckboxCellState extends State<CheckboxCell> {
);
}
@override
void didUpdateWidget(covariant CheckboxCell oldWidget) {
_handleRequestFocus();
super.didUpdateWidget(oldWidget);
}
@override
Future<void> 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());
}
}

View File

@ -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;

View File

@ -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<NumberCell> createState() => _NumberCellState();
GridFocusNodeCellState<NumberCell> createState() => _NumberCellState();
}
class _NumberCellState extends State<NumberCell> {
class _NumberCellState extends GridFocusNodeCellState<NumberCell> {
late NumberCellBloc _cellBloc;
late TextEditingController _controller;
late SingleListenrFocusNode _focusNode;
Timer? _delayOperation;
@override
@ -30,14 +29,11 @@ class _NumberCellState extends State<NumberCell> {
final cellContext = widget.cellContextBuilder.build();
_cellBloc = getIt<NumberCellBloc>(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<NumberCell> {
],
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<NumberCell> {
@override
Future<void> 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<void> focusChanged() async {
if (mounted) {
_delayOperation?.cancel();
@ -90,22 +78,6 @@ class _NumberCellState extends State<NumberCell> {
}
}
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) => "");
}

View File

@ -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<SingleSelectCell> {
}
//----------------------------------------------------------------
class MultiSelectCell extends StatefulWidget with GridCellWidget {
class MultiSelectCell extends GridCellWidget {
final GridCellContextBuilder cellContextBuilder;
late final SelectOptionCellStyle? cellStyle;

View File

@ -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<GridTextCell> createState() => _GridTextCellState();
GridFocusNodeCellState<GridTextCell> createState() => _GridTextCellState();
}
class _GridTextCellState extends State<GridTextCell> {
class _GridTextCellState extends GridFocusNodeCellState<GridTextCell> {
late TextCellBloc _cellBloc;
late TextEditingController _controller;
late SingleListenrFocusNode _focusNode;
Timer? _delayOperation;
@override
@ -44,10 +43,6 @@ class _GridTextCellState extends State<GridTextCell> {
_cellBloc = getIt<TextCellBloc>(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<GridTextCell> {
},
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<GridTextCell> {
@override
Future<void> 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<void> focusChanged() async {
if (mounted) {
_delayOperation?.cancel();

View File

@ -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<GridURLCell> createState() => _GridURLCellState();
GridCellState<GridURLCell> createState() => _GridURLCellState();
GridCellAccessory accessoryFromType(GridURLCellAccessoryType ty, GridCellAccessoryBuildContext buildContext) {
switch (ty) {
@ -78,7 +78,7 @@ class GridURLCell extends StatefulWidget with GridCellWidget {
};
}
class _GridURLCellState extends State<GridURLCell> {
class _GridURLCellState extends GridCellState<GridURLCell> {
late URLCellBloc _cellBloc;
@override
@ -86,7 +86,6 @@ class _GridURLCellState extends State<GridURLCell> {
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<GridURLCell> {
@override
Future<void> dispose() async {
widget.requestBeginFocus.removeAllListener();
_cellBloc.close();
super.dispose();
}
@override
void didUpdateWidget(covariant GridURLCell oldWidget) {
_handleRequestFocus();
super.didUpdateWidget(oldWidget);
}
Future<void> _openUrlOrEdit(String url) async {
final uri = Uri.parse(url);
if (url.isNotEmpty && await canLaunchUrl(uri)) {
@ -146,10 +138,9 @@ class _GridURLCellState extends State<GridURLCell> {
}
}
void _handleRequestFocus() {
widget.requestBeginFocus.setListener(() {
_openUrlOrEdit(_cellBloc.state.url);
});
@override
void requestBeginFocus() {
_openUrlOrEdit(_cellBloc.state.url);
}
}