mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-04-25 07:07:32 -04:00
fix: add event after bloc close
This commit is contained in:
parent
16598650ff
commit
b65b4796d2
8 changed files with 91 additions and 66 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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...
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue