mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor: add GridCellState and GridFocusNodeCellState
This commit is contained in:
parent
81efee557c
commit
4887885aae
@ -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
|
@override
|
||||||
final ValueNotifier<bool> isFocus = ValueNotifier<bool>(false);
|
final ValueNotifier<bool> isFocus = ValueNotifier<bool>(false);
|
||||||
|
|
||||||
@ -59,6 +61,72 @@ abstract class GridCellWidget implements AccessoryWidget, CellContainerFocustabl
|
|||||||
final GridCellRequestBeginFocus requestBeginFocus = GridCellRequestBeginFocus();
|
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 {
|
class GridCellRequestBeginFocus extends ChangeNotifier {
|
||||||
VoidCallback? _listener;
|
VoidCallback? _listener;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import 'package:flutter/widgets.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'cell_builder.dart';
|
import 'cell_builder.dart';
|
||||||
|
|
||||||
class CheckboxCell extends StatefulWidget with GridCellWidget {
|
class CheckboxCell extends GridCellWidget {
|
||||||
final GridCellContextBuilder cellContextBuilder;
|
final GridCellContextBuilder cellContextBuilder;
|
||||||
CheckboxCell({
|
CheckboxCell({
|
||||||
required this.cellContextBuilder,
|
required this.cellContextBuilder,
|
||||||
@ -14,17 +14,17 @@ class CheckboxCell extends StatefulWidget with GridCellWidget {
|
|||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CheckboxCell> createState() => _CheckboxCellState();
|
GridCellState<CheckboxCell> createState() => _CheckboxCellState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CheckboxCellState extends State<CheckboxCell> {
|
class _CheckboxCellState extends GridCellState<CheckboxCell> {
|
||||||
late CheckboxCellBloc _cellBloc;
|
late CheckboxCellBloc _cellBloc;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
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());
|
||||||
_handleRequestFocus();
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,22 +49,14 @@ class _CheckboxCellState extends State<CheckboxCell> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void didUpdateWidget(covariant CheckboxCell oldWidget) {
|
|
||||||
_handleRequestFocus();
|
|
||||||
super.didUpdateWidget(oldWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
widget.requestBeginFocus.removeAllListener();
|
|
||||||
_cellBloc.close();
|
_cellBloc.close();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleRequestFocus() {
|
@override
|
||||||
widget.requestBeginFocus.setListener(() {
|
void requestBeginFocus() {
|
||||||
_cellBloc.add(const CheckboxCellEvent.select());
|
_cellBloc.add(const CheckboxCellEvent.select());
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ abstract class GridCellDelegate {
|
|||||||
GridCellDelegate get delegate;
|
GridCellDelegate get delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DateCell extends StatefulWidget with GridCellWidget {
|
class DateCell extends GridCellWidget {
|
||||||
final GridCellContextBuilder cellContextBuilder;
|
final GridCellContextBuilder cellContextBuilder;
|
||||||
late final DateCellStyle? cellStyle;
|
late final DateCellStyle? cellStyle;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
|
|
||||||
import 'cell_builder.dart';
|
import 'cell_builder.dart';
|
||||||
|
|
||||||
class NumberCell extends StatefulWidget with GridCellWidget {
|
class NumberCell extends GridCellWidget {
|
||||||
final GridCellContextBuilder cellContextBuilder;
|
final GridCellContextBuilder cellContextBuilder;
|
||||||
|
|
||||||
NumberCell({
|
NumberCell({
|
||||||
@ -16,13 +16,12 @@ class NumberCell extends StatefulWidget with GridCellWidget {
|
|||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<NumberCell> createState() => _NumberCellState();
|
GridFocusNodeCellState<NumberCell> createState() => _NumberCellState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _NumberCellState extends State<NumberCell> {
|
class _NumberCellState extends GridFocusNodeCellState<NumberCell> {
|
||||||
late NumberCellBloc _cellBloc;
|
late NumberCellBloc _cellBloc;
|
||||||
late TextEditingController _controller;
|
late TextEditingController _controller;
|
||||||
late SingleListenrFocusNode _focusNode;
|
|
||||||
Timer? _delayOperation;
|
Timer? _delayOperation;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -30,14 +29,11 @@ class _NumberCellState extends State<NumberCell> {
|
|||||||
final cellContext = widget.cellContextBuilder.build();
|
final cellContext = widget.cellContextBuilder.build();
|
||||||
_cellBloc = getIt<NumberCellBloc>(param1: cellContext)..add(const NumberCellEvent.initial());
|
_cellBloc = getIt<NumberCellBloc>(param1: cellContext)..add(const NumberCellEvent.initial());
|
||||||
_controller = TextEditingController(text: contentFromState(_cellBloc.state));
|
_controller = TextEditingController(text: contentFromState(_cellBloc.state));
|
||||||
_focusNode = SingleListenrFocusNode();
|
|
||||||
_listenOnFocusNodeChanged();
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
_handleCellRequestFocus(context);
|
|
||||||
return BlocProvider.value(
|
return BlocProvider.value(
|
||||||
value: _cellBloc,
|
value: _cellBloc,
|
||||||
child: MultiBlocListener(
|
child: MultiBlocListener(
|
||||||
@ -49,8 +45,8 @@ class _NumberCellState extends State<NumberCell> {
|
|||||||
],
|
],
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
focusNode: _focusNode,
|
focusNode: focusNode,
|
||||||
onEditingComplete: () => _focusNode.unfocus(),
|
onEditingComplete: () => focusNode.unfocus(),
|
||||||
maxLines: null,
|
maxLines: null,
|
||||||
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
|
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
@ -65,20 +61,12 @@ class _NumberCellState extends State<NumberCell> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
widget.requestBeginFocus.removeAllListener();
|
|
||||||
_delayOperation?.cancel();
|
_delayOperation?.cancel();
|
||||||
_cellBloc.close();
|
_cellBloc.close();
|
||||||
_focusNode.removeAllListener();
|
|
||||||
_focusNode.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didUpdateWidget(covariant NumberCell oldWidget) {
|
|
||||||
_listenOnFocusNodeChanged();
|
|
||||||
super.didUpdateWidget(oldWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> focusChanged() async {
|
Future<void> focusChanged() async {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
_delayOperation?.cancel();
|
_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) {
|
String contentFromState(NumberCellState state) {
|
||||||
return state.content.fold((l) => l, (r) => "");
|
return state.content.fold((l) => l, (r) => "");
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ class SelectOptionCellStyle extends GridCellStyle {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class SingleSelectCell extends StatefulWidget with GridCellWidget {
|
class SingleSelectCell extends GridCellWidget {
|
||||||
final GridCellContextBuilder cellContextBuilder;
|
final GridCellContextBuilder cellContextBuilder;
|
||||||
late final SelectOptionCellStyle? cellStyle;
|
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;
|
final GridCellContextBuilder cellContextBuilder;
|
||||||
late final SelectOptionCellStyle? cellStyle;
|
late final SelectOptionCellStyle? cellStyle;
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ class GridTextCellStyle extends GridCellStyle {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridTextCell extends StatefulWidget with GridCellWidget {
|
class GridTextCell extends GridCellWidget {
|
||||||
final GridCellContextBuilder cellContextBuilder;
|
final GridCellContextBuilder cellContextBuilder;
|
||||||
late final GridTextCellStyle? cellStyle;
|
late final GridTextCellStyle? cellStyle;
|
||||||
GridTextCell({
|
GridTextCell({
|
||||||
@ -29,13 +29,12 @@ class GridTextCell extends StatefulWidget with GridCellWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<GridTextCell> createState() => _GridTextCellState();
|
GridFocusNodeCellState<GridTextCell> createState() => _GridTextCellState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _GridTextCellState extends State<GridTextCell> {
|
class _GridTextCellState extends GridFocusNodeCellState<GridTextCell> {
|
||||||
late TextCellBloc _cellBloc;
|
late TextCellBloc _cellBloc;
|
||||||
late TextEditingController _controller;
|
late TextEditingController _controller;
|
||||||
late SingleListenrFocusNode _focusNode;
|
|
||||||
Timer? _delayOperation;
|
Timer? _delayOperation;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -44,10 +43,6 @@ class _GridTextCellState extends State<GridTextCell> {
|
|||||||
_cellBloc = getIt<TextCellBloc>(param1: cellContext);
|
_cellBloc = getIt<TextCellBloc>(param1: cellContext);
|
||||||
_cellBloc.add(const TextCellEvent.initial());
|
_cellBloc.add(const TextCellEvent.initial());
|
||||||
_controller = TextEditingController(text: _cellBloc.state.content);
|
_controller = TextEditingController(text: _cellBloc.state.content);
|
||||||
_focusNode = SingleListenrFocusNode();
|
|
||||||
|
|
||||||
_listenOnFocusNodeChanged();
|
|
||||||
_listenRequestFocus(context);
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,9 +58,9 @@ class _GridTextCellState extends State<GridTextCell> {
|
|||||||
},
|
},
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
focusNode: _focusNode,
|
focusNode: focusNode,
|
||||||
onChanged: (value) => focusChanged(),
|
onChanged: (value) => focusChanged(),
|
||||||
onEditingComplete: () => _focusNode.unfocus(),
|
onEditingComplete: () => focusNode.unfocus(),
|
||||||
maxLines: null,
|
maxLines: null,
|
||||||
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
|
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
@ -81,39 +76,12 @@ class _GridTextCellState extends State<GridTextCell> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
widget.requestBeginFocus.removeAllListener();
|
|
||||||
_delayOperation?.cancel();
|
_delayOperation?.cancel();
|
||||||
_cellBloc.close();
|
_cellBloc.close();
|
||||||
_focusNode.removeAllListener();
|
|
||||||
_focusNode.dispose();
|
|
||||||
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@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 {
|
Future<void> focusChanged() async {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
_delayOperation?.cancel();
|
_delayOperation?.cancel();
|
||||||
|
@ -30,7 +30,7 @@ enum GridURLCellAccessoryType {
|
|||||||
copyURL,
|
copyURL,
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridURLCell extends StatefulWidget with GridCellWidget {
|
class GridURLCell extends GridCellWidget {
|
||||||
final GridCellContextBuilder cellContextBuilder;
|
final GridCellContextBuilder cellContextBuilder;
|
||||||
late final GridURLCellStyle? cellStyle;
|
late final GridURLCellStyle? cellStyle;
|
||||||
GridURLCell({
|
GridURLCell({
|
||||||
@ -46,7 +46,7 @@ class GridURLCell extends StatefulWidget with GridCellWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<GridURLCell> createState() => _GridURLCellState();
|
GridCellState<GridURLCell> createState() => _GridURLCellState();
|
||||||
|
|
||||||
GridCellAccessory accessoryFromType(GridURLCellAccessoryType ty, GridCellAccessoryBuildContext buildContext) {
|
GridCellAccessory accessoryFromType(GridURLCellAccessoryType ty, GridCellAccessoryBuildContext buildContext) {
|
||||||
switch (ty) {
|
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;
|
late URLCellBloc _cellBloc;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -86,7 +86,6 @@ class _GridURLCellState extends State<GridURLCell> {
|
|||||||
final cellContext = widget.cellContextBuilder.build() as GridURLCellContext;
|
final cellContext = widget.cellContextBuilder.build() as GridURLCellContext;
|
||||||
_cellBloc = URLCellBloc(cellContext: cellContext);
|
_cellBloc = URLCellBloc(cellContext: cellContext);
|
||||||
_cellBloc.add(const URLCellEvent.initial());
|
_cellBloc.add(const URLCellEvent.initial());
|
||||||
_handleRequestFocus();
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,17 +124,10 @@ class _GridURLCellState extends State<GridURLCell> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
widget.requestBeginFocus.removeAllListener();
|
|
||||||
_cellBloc.close();
|
_cellBloc.close();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void didUpdateWidget(covariant GridURLCell oldWidget) {
|
|
||||||
_handleRequestFocus();
|
|
||||||
super.didUpdateWidget(oldWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _openUrlOrEdit(String url) async {
|
Future<void> _openUrlOrEdit(String url) async {
|
||||||
final uri = Uri.parse(url);
|
final uri = Uri.parse(url);
|
||||||
if (url.isNotEmpty && await canLaunchUrl(uri)) {
|
if (url.isNotEmpty && await canLaunchUrl(uri)) {
|
||||||
@ -146,10 +138,9 @@ class _GridURLCellState extends State<GridURLCell> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleRequestFocus() {
|
@override
|
||||||
widget.requestBeginFocus.setListener(() {
|
void requestBeginFocus() {
|
||||||
_openUrlOrEdit(_cellBloc.state.url);
|
_openUrlOrEdit(_cellBloc.state.url);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user