fix: add event after bloc close

This commit is contained in:
appflowy 2022-03-26 21:03:54 +08:00
parent 16598650ff
commit b65b4796d2
8 changed files with 91 additions and 66 deletions

View file

@ -112,7 +112,7 @@ class ApplicationBlocObserver extends BlocObserver {
// ignore: unnecessary_overrides // ignore: unnecessary_overrides
void onTransition(Bloc bloc, Transition transition) { void onTransition(Bloc bloc, Transition transition) {
// Log.debug("[current]: ${transition.currentState} \n\n[next]: ${transition.nextState}"); // Log.debug("[current]: ${transition.currentState} \n\n[next]: ${transition.nextState}");
Log.debug("${transition.nextState}"); // Log.debug("${transition.nextState}");
super.onTransition(bloc, transition); super.onTransition(bloc, transition);
} }

View file

@ -15,8 +15,6 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
required this.service, required this.service,
required FutureCellData cellData, required FutureCellData cellData,
}) : super(CheckboxCellState.initial()) { }) : super(CheckboxCellState.initial()) {
cellData.then((a) {});
on<CheckboxCellEvent>( on<CheckboxCellEvent>(
(event, emit) async { (event, emit) async {
await event.map( await event.map(

View file

@ -12,13 +12,7 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
TextCellBloc({ TextCellBloc({
required this.service, required this.service,
required FutureCellData cellData, required FutureCellData cellData,
}) : super(TextCellState.initial()) { }) : super(TextCellState.initial(cellData)) {
cellData.then((cellData) {
if (cellData != null) {
add(TextCellEvent.didReceiveCellData(cellData));
}
});
on<TextCellEvent>( on<TextCellEvent>(
(event, emit) async { (event, emit) async {
await event.map( await event.map(
@ -69,8 +63,11 @@ class TextCellEvent with _$TextCellEvent {
class TextCellState with _$TextCellState { class TextCellState with _$TextCellState {
const factory TextCellState({ const factory TextCellState({
required String content, required String content,
GridCellData? cellData, required FutureCellData cellData,
}) = _TextCellState; }) = _TextCellState;
factory TextCellState.initial() => const TextCellState(content: ""); factory TextCellState.initial(FutureCellData cellData) => TextCellState(
content: cellData?.cell?.content ?? "",
cellData: cellData,
);
} }

View file

@ -50,12 +50,11 @@ class RowBloc extends Bloc<RowEvent, RowState> {
emit(state.copyWith(fields: value.fields)); emit(state.copyWith(fields: value.fields));
add(const RowEvent.didUpdateCell()); add(const RowEvent.didUpdateCell());
}, },
didUpdateCell: (_DidUpdateCell value) { didUpdateCell: (_DidUpdateCell value) async {
final Future<CellDataMap> cellDataMap = state.row.then( final optionRow = await state.row;
(someRow) => someRow.fold( final CellDataMap cellDataMap = optionRow.fold(
() => HashMap.identity(), () => HashMap.identity(),
(row) => _makeCellDatas(row), (row) => _makeCellDatas(row),
),
); );
emit(state.copyWith(cellDataMap: cellDataMap)); emit(state.copyWith(cellDataMap: cellDataMap));
}, },
@ -147,7 +146,7 @@ class RowState with _$RowState {
required double rowHeight, required double rowHeight,
required List<Field> fields, required List<Field> fields,
required Future<Option<Row>> row, required Future<Option<Row>> row,
required Future<CellDataMap> cellDataMap, required CellDataMap? cellDataMap,
}) = _RowState; }) = _RowState;
factory RowState.initial(GridRowData data) => RowState( factory RowState.initial(GridRowData data) => RowState(
@ -156,6 +155,6 @@ class RowState with _$RowState {
rowHeight: data.height, rowHeight: data.height,
fields: data.fields, fields: data.fields,
row: Future(() => none()), row: Future(() => none()),
cellDataMap: Future(() => CellDataMap.identity()), cellDataMap: null,
); );
} }

View file

@ -29,7 +29,7 @@ class RowService {
} }
} }
typedef FutureCellData = Future<GridCellData?>; typedef FutureCellData = GridCellData?;
class GridCellData extends Equatable { class GridCellData extends Equatable {
final String gridId; final String gridId;

View file

@ -1,4 +1,5 @@
import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'checkbox_cell.dart'; import 'checkbox_cell.dart';
@ -7,20 +8,24 @@ import 'number_cell.dart';
import 'selection_cell.dart'; import 'selection_cell.dart';
import 'text_cell.dart'; import 'text_cell.dart';
Widget buildGridCell(FieldType fieldType, FutureCellData cellData) { Widget buildGridCell(String rowId, Field field, FutureCellData cellData) {
switch (fieldType) { if (cellData == null) {
return const SizedBox();
}
final key = ValueKey(field.id + rowId);
switch (field.fieldType) {
case FieldType.Checkbox: case FieldType.Checkbox:
return CheckboxCell(cellData: cellData, key: ObjectKey(cellData)); return CheckboxCell(cellData: cellData, key: key);
case FieldType.DateTime: case FieldType.DateTime:
return DateCell(cellData: cellData, key: ObjectKey(cellData)); return DateCell(cellData: cellData, key: key);
case FieldType.MultiSelect: case FieldType.MultiSelect:
return MultiSelectCell(cellData: cellData, key: ObjectKey(cellData)); return MultiSelectCell(cellData: cellData, key: key);
case FieldType.Number: case FieldType.Number:
return NumberCell(cellData: cellData, key: ObjectKey(cellData)); return NumberCell(cellData: cellData, key: key);
case FieldType.RichText: case FieldType.RichText:
return GridTextCell(cellData: cellData, key: ObjectKey(cellData)); return GridTextCell(cellData: cellData, key: key);
case FieldType.SingleSelect: case FieldType.SingleSelect:
return SingleSelectCell(cellData: cellData, key: ObjectKey(cellData)); return SingleSelectCell(cellData: cellData, key: key);
default: default:
throw UnimplementedError; throw UnimplementedError;
} }

View file

@ -4,38 +4,61 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.d
import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'cell_builder.dart'; import 'cell_builder.dart';
import 'cell_container.dart'; import 'cell_container.dart';
class GridRowWidget extends StatelessWidget { class GridRowWidget extends StatefulWidget {
final GridRowData data; final GridRowData data;
const GridRowWidget({required this.data, Key? key}) : super(key: key); const GridRowWidget({required this.data, Key? key}) : super(key: key);
@override
State<GridRowWidget> createState() => _GridRowWidgetState();
}
class _GridRowWidgetState extends State<GridRowWidget> {
late RowBloc _rowBloc;
@override
void initState() {
_rowBloc = getIt<RowBloc>(param1: widget.data)..add(const RowEvent.initial());
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider.value(
create: (context) => getIt<RowBloc>(param1: data)..add(const RowEvent.initial()), value: _rowBloc,
child: BlocBuilder<RowBloc, RowState>( child: MouseRegion(
buildWhen: (p, c) => p.rowHeight != c.rowHeight, cursor: SystemMouseCursors.click,
builder: (context, state) { onEnter: (p) => _rowBloc.add(const RowEvent.activeRow()),
return SizedBox( onExit: (p) => _rowBloc.add(const RowEvent.disactiveRow()),
height: state.rowHeight, child: BlocBuilder<RowBloc, RowState>(
child: Row( buildWhen: (p, c) => p.rowHeight != c.rowHeight,
crossAxisAlignment: CrossAxisAlignment.stretch, builder: (context, state) {
children: const [ return SizedBox(
_RowLeading(), height: _rowBloc.state.rowHeight,
_RowCells(), child: Row(
_RowTrailing(), crossAxisAlignment: CrossAxisAlignment.stretch,
], children: const [
), _RowLeading(),
); _RowCells(),
}, _RowTrailing(),
],
),
);
},
),
), ),
); );
} }
@override
Future<void> dispose() async {
_rowBloc.close();
super.dispose();
}
} }
class _RowLeading extends StatelessWidget { class _RowLeading extends StatelessWidget {
@ -92,18 +115,20 @@ class _RowCells extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<RowBloc, RowState>( return BlocBuilder<RowBloc, RowState>(
buildWhen: (previous, current) => previous.cellDataMap != current.cellDataMap,
builder: (context, state) { builder: (context, state) {
return Row(children: [ final children = state.fields
...state.fields.map( .map((field) => CellContainer(
(field) { width: field.width.toDouble(),
final cellData = state.cellDataMap.then((fut) => fut[field.id]); child: buildGridCell(
return CellContainer( state.rowId,
width: field.width.toDouble(), field,
child: buildGridCell(field.fieldType, cellData), state.cellDataMap?[field.id],
); ),
}, ))
), .toList();
]);
return Row(children: children);
}, },
); );
} }

View file

@ -22,12 +22,12 @@ class _GridTextCellState extends State<GridTextCell> {
late TextEditingController _controller; late TextEditingController _controller;
Timer? _delayOperation; Timer? _delayOperation;
final _focusNode = FocusNode(); final _focusNode = FocusNode();
TextCellBloc? _cellBloc; late TextCellBloc _cellBloc;
@override @override
void initState() { void initState() {
_cellBloc = getIt<TextCellBloc>(param1: widget.cellData); _cellBloc = getIt<TextCellBloc>(param1: widget.cellData);
_controller = TextEditingController(text: _cellBloc!.state.content); _controller = TextEditingController(text: _cellBloc.state.content);
_focusNode.addListener(save); _focusNode.addListener(save);
super.initState(); super.initState();
} }
@ -35,7 +35,7 @@ class _GridTextCellState extends State<GridTextCell> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider.value( return BlocProvider.value(
value: _cellBloc!, value: _cellBloc,
child: BlocConsumer<TextCellBloc, TextCellState>( child: BlocConsumer<TextCellBloc, TextCellState>(
listener: (context, state) { listener: (context, state) {
if (_controller.text != state.content) { if (_controller.text != state.content) {
@ -71,8 +71,7 @@ class _GridTextCellState extends State<GridTextCell> {
@override @override
Future<void> dispose() async { Future<void> dispose() async {
_cellBloc?.close(); _cellBloc.close();
_cellBloc = null;
_focusNode.removeListener(save); _focusNode.removeListener(save);
_focusNode.dispose(); _focusNode.dispose();
super.dispose(); super.dispose();
@ -80,8 +79,10 @@ class _GridTextCellState extends State<GridTextCell> {
Future<void> save() async { Future<void> save() async {
_delayOperation?.cancel(); _delayOperation?.cancel();
_delayOperation = Timer(const Duration(seconds: 2), () { _delayOperation = Timer(const Duration(milliseconds: 300), () {
_cellBloc?.add(TextCellEvent.updateText(_controller.text)); if (_cellBloc.isClosed == false) {
_cellBloc.add(TextCellEvent.updateText(_controller.text));
}
}); });
// and later, before the timer goes off... // and later, before the timer goes off...
} }