chore: auto reload when field was changed

This commit is contained in:
appflowy 2022-04-24 07:10:09 +08:00
parent be49784f5a
commit af5f42d296
11 changed files with 64 additions and 137 deletions

View File

@ -16,7 +16,6 @@ import 'package:app_flowy/user/presentation/router.dart';
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell;
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
@ -182,19 +181,19 @@ void _resolveGridDeps(GetIt getIt) {
),
);
getIt.registerFactoryParam<NumberCellBloc, GridCellContext<Cell>, void>(
getIt.registerFactoryParam<NumberCellBloc, GridDefaultCellContext, void>(
(context, _) => NumberCellBloc(
cellContext: context,
),
);
getIt.registerFactoryParam<DateCellBloc, GridCellContext<Cell>, void>(
getIt.registerFactoryParam<DateCellBloc, GridDefaultCellContext, void>(
(context, _) => DateCellBloc(
cellContext: context,
),
);
getIt.registerFactoryParam<CheckboxCellBloc, GridCellContext<Cell>, void>(
getIt.registerFactoryParam<CheckboxCellBloc, GridDefaultCellContext, void>(
(cellData, _) => CheckboxCellBloc(
service: CellService(),
cellContext: cellData,

View File

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:collection';
import 'package:dartz/dartz.dart';
@ -6,6 +7,7 @@ import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
import 'package:flutter/foundation.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
@ -13,6 +15,9 @@ import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart';
part 'cell_service.freezed.dart';
typedef GridDefaultCellContext = GridCellContext<Cell>;
typedef GridSelectOptionCellContext = GridCellContext<SelectOptionContext>;
class GridCellContext<T> {
final GridCell gridCell;
final GridCellCache cellCache;
@ -22,6 +27,7 @@ class GridCellContext<T> {
final CellListener _cellListener;
final CellService _cellService = CellService();
final ValueNotifier<dynamic> _cellDataNotifier = ValueNotifier(null);
Timer? _delayOperation;
GridCellContext({
required this.gridCell,
@ -41,6 +47,12 @@ class GridCellContext<T> {
objectId: "$hashCode",
fieldId: gridCell.field.id,
);
if (cellDataLoader.reloadOnFieldChanged) {
cellCache.addListener(cacheKey, () {
reloadCellData();
});
}
}
String get gridId => gridCell.gridId;
@ -73,16 +85,18 @@ class GridCellContext<T> {
_cellService.updateCell(gridId: gridId, fieldId: field.id, rowId: rowId, data: data);
}
void _loadData() {
// It may trigger getCell multiple times. Use cancel operation to fix this.
cellDataLoader.loadData().then((data) {
_cellDataNotifier.value = data;
setCellData(data);
});
void reloadCellData() {
_loadData();
}
void onFieldChanged(VoidCallback callback) {
cellCache.addListener(cacheKey, callback);
void _loadData() {
_delayOperation?.cancel();
_delayOperation = Timer(const Duration(milliseconds: 10), () {
cellDataLoader.loadData().then((data) {
_cellDataNotifier.value = data;
setCellData(data);
});
});
}
void onCellChanged(void Function(T) callback) {
@ -94,13 +108,15 @@ class GridCellContext<T> {
});
}
void removeListener() {
cellCache.removeListener(cacheKey);
void dispose() {
_delayOperation?.cancel();
}
}
abstract class GridCellDataLoader<T> {
Future<T?> loadData();
bool get reloadOnFieldChanged => true;
}
class DefaultCellDataLoader implements GridCellDataLoader<Cell> {
@ -125,6 +141,9 @@ class DefaultCellDataLoader implements GridCellDataLoader<Cell> {
});
});
}
@override
bool get reloadOnFieldChanged => true;
}
// key: rowId

View File

@ -7,13 +7,12 @@ import 'cell_service.dart';
part 'checkbox_cell_bloc.freezed.dart';
class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
final GridCellContext<Cell> _cellContext;
final GridDefaultCellContext cellContext;
CheckboxCellBloc({
required CellService service,
required GridCellContext<Cell> cellContext,
}) : _cellContext = cellContext,
super(CheckboxCellState.initial(cellContext)) {
required this.cellContext,
}) : super(CheckboxCellState.initial(cellContext)) {
on<CheckboxCellEvent>(
(event, emit) async {
await event.map(
@ -33,11 +32,12 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
@override
Future<void> close() async {
cellContext.dispose();
return super.close();
}
void _startListening() {
_cellContext.onCellChanged((cell) {
cellContext.onCellChanged((cell) {
if (!isClosed) {
add(CheckboxCellEvent.didReceiveCellUpdate(cell));
}
@ -45,7 +45,7 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
}
void _updateCellData() {
_cellContext.saveCellData(!state.isSelected ? "Yes" : "No");
cellContext.saveCellData(!state.isSelected ? "Yes" : "No");
}
}

View File

@ -1,5 +1,3 @@
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell, Field;
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
@ -9,12 +7,9 @@ import 'cell_service.dart';
part 'date_cell_bloc.freezed.dart';
class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
final SingleFieldListener _fieldListener;
final GridCellContext<Cell> cellContext;
final GridDefaultCellContext cellContext;
DateCellBloc({required this.cellContext})
: _fieldListener = SingleFieldListener(fieldId: cellContext.fieldId),
super(DateCellState.initial(cellContext)) {
DateCellBloc({required this.cellContext}) : super(DateCellState.initial(cellContext)) {
on<DateCellEvent>(
(event, emit) async {
event.map(
@ -39,7 +34,7 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
@override
Future<void> close() async {
await _fieldListener.stop();
cellContext.dispose();
return super.close();
}
@ -49,14 +44,6 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
add(DateCellEvent.didReceiveCellUpdate(cell));
}
});
_fieldListener.updateFieldNotifier?.addPublishListener((result) {
result.fold(
(field) => add(DateCellEvent.didReceiveFieldUpdate(field)),
(err) => Log.error(err),
);
}, listenWhen: () => !isClosed);
_fieldListener.start();
}
void _updateCellData(DateTime day) {

View File

@ -1,5 +1,3 @@
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
@ -9,13 +7,11 @@ import 'cell_service.dart';
part 'number_cell_bloc.freezed.dart';
class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
final GridCellContext<Cell> cellContext;
final SingleFieldListener _fieldListener;
final GridDefaultCellContext cellContext;
NumberCellBloc({
required this.cellContext,
}) : _fieldListener = SingleFieldListener(fieldId: cellContext.fieldId),
super(NumberCellState.initial(cellContext)) {
}) : super(NumberCellState.initial(cellContext)) {
on<NumberCellEvent>(
(event, emit) async {
await event.map(
@ -40,7 +36,7 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
@override
Future<void> close() async {
await _fieldListener.stop();
cellContext.dispose();
return super.close();
}
@ -50,14 +46,6 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
add(NumberCellEvent.didReceiveCellUpdate(cell));
}
});
_fieldListener.updateFieldNotifier?.addPublishListener((result) {
result.fold(
(field) => cellContext.reloadCellData(),
(err) => Log.error(err),
);
});
_fieldListener.start();
}
}
@ -74,7 +62,8 @@ class NumberCellState with _$NumberCellState {
required String content,
}) = _NumberCellState;
factory NumberCellState.initial(GridCellContext context) {
return NumberCellState(content: context.getCellData().cell?.content ?? "");
factory NumberCellState.initial(GridDefaultCellContext context) {
final cell = context.getCellData();
return NumberCellState(content: cell?.content ?? "");
}
}

View File

@ -27,6 +27,9 @@ class SelectOptionCellDataLoader implements GridCellDataLoader<SelectOptionConte
);
});
}
@override
bool get reloadOnFieldChanged => true;
}
class SelectOptionService {

View File

@ -3,18 +3,15 @@ import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart';
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
part 'selection_cell_bloc.freezed.dart';
class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
final SingleFieldListener _fieldListener;
final GridCellContext<SelectOptionContext> cellContext;
SelectionCellBloc({
required this.cellContext,
}) : _fieldListener = SingleFieldListener(fieldId: cellContext.fieldId),
super(SelectionCellState.initial(cellContext)) {
}) : super(SelectionCellState.initial(cellContext)) {
on<SelectionCellEvent>(
(event, emit) async {
await event.map(
@ -34,8 +31,7 @@ class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
@override
Future<void> close() async {
await _fieldListener.stop();
cellContext.removeListener();
cellContext.dispose();
return super.close();
}
@ -48,8 +44,6 @@ class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
));
}
});
cellContext.onFieldChanged(() => cellContext.reloadCellData());
}
}

View File

@ -1,8 +1,5 @@
import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart';
import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart';
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
@ -14,7 +11,6 @@ part 'selection_editor_bloc.freezed.dart';
class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionEditorState> {
final SelectOptionService _selectOptionService;
final GridCellContext<SelectOptionContext> cellContext;
Timer? _delayOperation;
SelectOptionEditorBloc({
required this.cellContext,
@ -51,8 +47,7 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
@override
Future<void> close() async {
_delayOperation?.cancel();
cellContext.removeListener();
cellContext.dispose();
return super.close();
}
@ -86,27 +81,6 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
}
}
// void _loadOptions() async {
// _delayOperation?.cancel();
// _delayOperation = Timer(
// const Duration(milliseconds: 1),
// () async {
// final result = await _selectOptionService.getOpitonContext();
// if (isClosed) {
// return;
// }
// result.fold(
// (selectOptionContext) => add(SelectOptionEditorEvent.didReceiveOptions(
// selectOptionContext.options,
// selectOptionContext.selectOptions,
// )),
// (err) => Log.error(err),
// );
// },
// );
// }
void _startListening() {
cellContext.onCellChanged((selectOptionContext) {
if (!isClosed) {
@ -116,8 +90,6 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
));
}
});
cellContext.onFieldChanged(() => cellContext.reloadCellData());
}
}

View File

@ -1,22 +1,16 @@
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell;
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
import 'cell_listener.dart';
import 'cell_service.dart';
part 'text_cell_bloc.freezed.dart';
class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
final CellService _service;
final CellListener _cellListener;
final GridCellContext cellContext;
TextCellBloc({
required GridCellContext cellContext,
}) : _service = CellService(),
_cellListener = CellListener(rowId: cellContext.rowId, fieldId: cellContext.fieldId),
super(TextCellState.initial(cellContext.gridCell)) {
required this.cellContext,
}) : super(TextCellState.initial(cellContext.gridCell)) {
on<TextCellEvent>(
(event, emit) async {
await event.map(
@ -24,7 +18,7 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
_startListening();
},
updateText: (_UpdateText value) {
updateCellContent(value.text);
cellContext.saveCellData(value.text);
emit(state.copyWith(content: value.text));
},
didReceiveCellData: (_DidReceiveCellData value) {
@ -46,45 +40,16 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
@override
Future<void> close() async {
await _cellListener.stop();
cellContext.dispose();
return super.close();
}
void updateCellContent(String content) {
final fieldId = state.cellData.field.id;
final gridId = state.cellData.gridId;
final rowId = state.cellData.rowId;
_service.updateCell(
data: content,
fieldId: fieldId,
gridId: gridId,
rowId: rowId,
);
}
void _startListening() {
_cellListener.updateCellNotifier?.addPublishListener((result) {
result.fold(
(notificationData) async => await _loadCellData(),
(err) => Log.error(err),
);
cellContext.onCellChanged((cell) {
if (!isClosed) {
add(TextCellEvent.didReceiveCellUpdate(cell));
}
});
_cellListener.start();
}
Future<void> _loadCellData() async {
final result = await _service.getCell(
gridId: state.cellData.gridId,
fieldId: state.cellData.field.id,
rowId: state.cellData.rowId,
);
if (isClosed) {
return;
}
result.fold(
(cell) => add(TextCellEvent.didReceiveCellUpdate(cell)),
(err) => Log.error(err),
);
}
}

View File

@ -1,7 +1,7 @@
import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart';
import 'package:app_flowy/workspace/application/grid/cell/select_option_service.dart';
import 'package:flowy_infra_ui/style_widget/hover.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell, FieldType;
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show FieldType;
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
import 'package:flutter/widgets.dart';
import 'checkbox_cell.dart';
@ -39,7 +39,7 @@ GridCellContext makeCellContext(GridCell gridCell, GridCellCache cellCache) {
case FieldType.DateTime:
case FieldType.Number:
case FieldType.RichText:
return GridCellContext<Cell>(
return GridDefaultCellContext(
gridCell: gridCell,
cellCache: cellCache,
cellDataLoader: DefaultCellDataLoader(gridCell: gridCell),

View File

@ -1,7 +1,6 @@
import 'dart:collection';
import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart';
import 'package:app_flowy/workspace/application/grid/cell/selection_editor_bloc.dart';
import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart';