mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: refactor rowbloc
This commit is contained in:
parent
b3a99be7f8
commit
f40e0c18e6
@ -168,32 +168,32 @@ void _resolveGridDeps(GetIt getIt) {
|
||||
),
|
||||
);
|
||||
|
||||
getIt.registerFactoryParam<TextCellBloc, GridCellIdentifier, void>(
|
||||
getIt.registerFactoryParam<TextCellBloc, GridCell, void>(
|
||||
(cellData, _) => TextCellBloc(
|
||||
service: CellService(),
|
||||
cellData: cellData,
|
||||
),
|
||||
);
|
||||
|
||||
getIt.registerFactoryParam<SelectionCellBloc, GridCellIdentifier, void>(
|
||||
getIt.registerFactoryParam<SelectionCellBloc, GridCell, void>(
|
||||
(cellData, _) => SelectionCellBloc(
|
||||
cellData: cellData,
|
||||
),
|
||||
);
|
||||
|
||||
getIt.registerFactoryParam<NumberCellBloc, GridCellIdentifier, void>(
|
||||
getIt.registerFactoryParam<NumberCellBloc, GridCell, void>(
|
||||
(cellData, _) => NumberCellBloc(
|
||||
cellData: cellData,
|
||||
),
|
||||
);
|
||||
|
||||
getIt.registerFactoryParam<DateCellBloc, GridCellIdentifier, void>(
|
||||
getIt.registerFactoryParam<DateCellBloc, GridCell, void>(
|
||||
(cellData, _) => DateCellBloc(
|
||||
cellIdentifier: cellData,
|
||||
),
|
||||
);
|
||||
|
||||
getIt.registerFactoryParam<CheckboxCellBloc, GridCellIdentifier, void>(
|
||||
getIt.registerFactoryParam<CheckboxCellBloc, GridCell, void>(
|
||||
(cellData, _) => CheckboxCellBloc(
|
||||
service: CellService(),
|
||||
cellData: cellData,
|
||||
|
@ -44,7 +44,7 @@ class CellCache {
|
||||
|
||||
CellCache() : _cellService = CellService();
|
||||
|
||||
Future<Option<Cell>> getCellData(GridCellIdentifier identifier) async {
|
||||
Future<Option<Cell>> getCellData(GridCell identifier) async {
|
||||
final cellId = _cellId(identifier);
|
||||
final Cell? data = _cellDataMap[cellId];
|
||||
if (data != null) {
|
||||
@ -69,7 +69,7 @@ class CellCache {
|
||||
);
|
||||
}
|
||||
|
||||
String _cellId(GridCellIdentifier identifier) {
|
||||
String _cellId(GridCell identifier) {
|
||||
return "${identifier.rowId}/${identifier.field.id}";
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
|
||||
|
||||
CheckboxCellBloc({
|
||||
required CellService service,
|
||||
required GridCellIdentifier cellData,
|
||||
required GridCell cellData,
|
||||
}) : _service = service,
|
||||
_listener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
||||
super(CheckboxCellState.initial(cellData)) {
|
||||
@ -87,11 +87,11 @@ class CheckboxCellEvent with _$CheckboxCellEvent {
|
||||
@freezed
|
||||
class CheckboxCellState with _$CheckboxCellState {
|
||||
const factory CheckboxCellState({
|
||||
required GridCellIdentifier cellData,
|
||||
required GridCell cellData,
|
||||
required bool isSelected,
|
||||
}) = _CheckboxCellState;
|
||||
|
||||
factory CheckboxCellState.initial(GridCellIdentifier cellData) {
|
||||
factory CheckboxCellState.initial(GridCell cellData) {
|
||||
return CheckboxCellState(cellData: cellData, isSelected: _isSelected(cellData.cell));
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
|
||||
final CellListener _cellListener;
|
||||
final SingleFieldListener _fieldListener;
|
||||
|
||||
DateCellBloc({required GridCellIdentifier cellIdentifier})
|
||||
DateCellBloc({required GridCell cellIdentifier})
|
||||
: _service = CellService(),
|
||||
_cellListener = CellListener(rowId: cellIdentifier.rowId, fieldId: cellIdentifier.field.id),
|
||||
_fieldListener = SingleFieldListener(fieldId: cellIdentifier.field.id),
|
||||
@ -106,13 +106,13 @@ class DateCellEvent with _$DateCellEvent {
|
||||
@freezed
|
||||
class DateCellState with _$DateCellState {
|
||||
const factory DateCellState({
|
||||
required GridCellIdentifier cellData,
|
||||
required GridCell cellData,
|
||||
required String content,
|
||||
required Field field,
|
||||
DateTime? selectedDay,
|
||||
}) = _DateCellState;
|
||||
|
||||
factory DateCellState.initial(GridCellIdentifier cellData) => DateCellState(
|
||||
factory DateCellState.initial(GridCell cellData) => DateCellState(
|
||||
cellData: cellData,
|
||||
field: cellData.field,
|
||||
content: cellData.cell?.content ?? "",
|
||||
|
@ -16,7 +16,7 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
|
||||
final SingleFieldListener _fieldListener;
|
||||
|
||||
NumberCellBloc({
|
||||
required GridCellIdentifier cellData,
|
||||
required GridCell cellData,
|
||||
}) : _service = CellService(),
|
||||
_cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
||||
_fieldListener = SingleFieldListener(fieldId: cellData.field.id),
|
||||
@ -105,11 +105,11 @@ class NumberCellEvent with _$NumberCellEvent {
|
||||
@freezed
|
||||
class NumberCellState with _$NumberCellState {
|
||||
const factory NumberCellState({
|
||||
required GridCellIdentifier cellData,
|
||||
required GridCell cellData,
|
||||
required String content,
|
||||
}) = _NumberCellState;
|
||||
|
||||
factory NumberCellState.initial(GridCellIdentifier cellData) {
|
||||
factory NumberCellState.initial(GridCell cellData) {
|
||||
return NumberCellState(cellData: cellData, content: cellData.cell?.content ?? "");
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
|
||||
final SingleFieldListener _fieldListener;
|
||||
|
||||
SelectionCellBloc({
|
||||
required GridCellIdentifier cellData,
|
||||
required GridCell cellData,
|
||||
}) : _service = SelectOptionService(),
|
||||
_cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
||||
_fieldListener = SingleFieldListener(fieldId: cellData.field.id),
|
||||
@ -93,12 +93,12 @@ class SelectionCellEvent with _$SelectionCellEvent {
|
||||
@freezed
|
||||
class SelectionCellState with _$SelectionCellState {
|
||||
const factory SelectionCellState({
|
||||
required GridCellIdentifier cellData,
|
||||
required GridCell cellData,
|
||||
required List<SelectOption> options,
|
||||
required List<SelectOption> selectedOptions,
|
||||
}) = _SelectionCellState;
|
||||
|
||||
factory SelectionCellState.initial(GridCellIdentifier cellData) => SelectionCellState(
|
||||
factory SelectionCellState.initial(GridCell cellData) => SelectionCellState(
|
||||
cellData: cellData,
|
||||
options: [],
|
||||
selectedOptions: [],
|
||||
|
@ -18,7 +18,7 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
|
||||
Timer? _delayOperation;
|
||||
|
||||
SelectOptionEditorBloc({
|
||||
required GridCellIdentifier cellData,
|
||||
required GridCell cellData,
|
||||
required List<SelectOption> options,
|
||||
required List<SelectOption> selectedOptions,
|
||||
}) : _selectOptionService = SelectOptionService(),
|
||||
@ -174,7 +174,7 @@ class SelectOptionEditorState with _$SelectOptionEditorState {
|
||||
}) = _SelectOptionEditorState;
|
||||
|
||||
factory SelectOptionEditorState.initial(
|
||||
GridCellIdentifier cellData,
|
||||
GridCell cellData,
|
||||
List<SelectOption> options,
|
||||
List<SelectOption> selectedOptions,
|
||||
) {
|
||||
|
@ -11,7 +11,7 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
|
||||
|
||||
TextCellBloc({
|
||||
required this.service,
|
||||
required GridCellIdentifier cellData,
|
||||
required GridCell cellData,
|
||||
}) : super(TextCellState.initial(cellData)) {
|
||||
on<TextCellEvent>(
|
||||
(event, emit) async {
|
||||
@ -53,7 +53,7 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
|
||||
@freezed
|
||||
class TextCellEvent with _$TextCellEvent {
|
||||
const factory TextCellEvent.initial() = _InitialCell;
|
||||
const factory TextCellEvent.didReceiveCellData(GridCellIdentifier cellData) = _DidReceiveCellData;
|
||||
const factory TextCellEvent.didReceiveCellData(GridCell cellData) = _DidReceiveCellData;
|
||||
const factory TextCellEvent.updateText(String text) = _UpdateText;
|
||||
}
|
||||
|
||||
@ -61,10 +61,10 @@ class TextCellEvent with _$TextCellEvent {
|
||||
class TextCellState with _$TextCellState {
|
||||
const factory TextCellState({
|
||||
required String content,
|
||||
required GridCellIdentifier cellData,
|
||||
required GridCell cellData,
|
||||
}) = _TextCellState;
|
||||
|
||||
factory TextCellState.initial(GridCellIdentifier cellData) => TextCellState(
|
||||
factory TextCellState.initial(GridCell cellData) => TextCellState(
|
||||
content: cellData.cell?.content ?? "",
|
||||
cellData: cellData,
|
||||
);
|
||||
|
@ -13,13 +13,17 @@ part 'grid_bloc.freezed.dart';
|
||||
class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
final GridService _gridService;
|
||||
final GridFieldCache fieldCache;
|
||||
final GridRowCache rowCache;
|
||||
late final GridRowCache rowCache;
|
||||
|
||||
GridBloc({required View view})
|
||||
: _gridService = GridService(gridId: view.id),
|
||||
fieldCache = GridFieldCache(gridId: view.id),
|
||||
rowCache = GridRowCache(gridId: view.id),
|
||||
super(GridState.initial(view.id)) {
|
||||
rowCache = GridRowCache(
|
||||
gridId: view.id,
|
||||
dataDelegate: GridRowDataDelegateAdaptor(fieldCache),
|
||||
);
|
||||
|
||||
on<GridEvent>(
|
||||
(event, emit) async {
|
||||
await event.map(
|
||||
@ -77,7 +81,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
() => result.fold(
|
||||
(fields) {
|
||||
fieldCache.fields = fields.items;
|
||||
rowCache.updateWithBlock(grid.blockOrders, fieldCache.unmodifiableFields);
|
||||
rowCache.updateWithBlock(grid.blockOrders);
|
||||
|
||||
emit(state.copyWith(
|
||||
grid: Some(grid),
|
||||
|
@ -8,6 +8,8 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import 'row/row_service.dart';
|
||||
|
||||
class GridService {
|
||||
final String gridId;
|
||||
GridService({
|
||||
@ -152,3 +154,44 @@ class GridFieldCache {
|
||||
_fieldNotifier.fields = fields;
|
||||
}
|
||||
}
|
||||
|
||||
class GridRowDataDelegateAdaptor extends GridRowDataDelegate {
|
||||
final GridFieldCache _cache;
|
||||
|
||||
GridRowDataDelegateAdaptor(GridFieldCache cache) : _cache = cache;
|
||||
@override
|
||||
UnmodifiableListView<Field> get fields => _cache.unmodifiableFields;
|
||||
|
||||
@override
|
||||
GridRow buildGridRow(RowOrder rowOrder) {
|
||||
return GridRow(
|
||||
gridId: _cache.gridId,
|
||||
fields: _cache.unmodifiableFields,
|
||||
rowId: rowOrder.rowId,
|
||||
height: rowOrder.height.toDouble(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onFieldChanged(FieldDidUpdateCallback callback) {
|
||||
_cache.addListener(listener: () {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
CellDataMap buildCellDataMap(Row rowData) {
|
||||
var map = CellDataMap.new();
|
||||
for (final field in fields) {
|
||||
if (field.visibility) {
|
||||
map[field.id] = GridCell(
|
||||
rowId: rowData.id,
|
||||
gridId: _cache.gridId,
|
||||
cell: rowData.cellByFieldId[field.id],
|
||||
field: field,
|
||||
);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,4 @@
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:app_flowy/workspace/application/grid/grid_service.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';
|
||||
import 'dart:async';
|
||||
@ -10,21 +7,15 @@ import 'package:dartz/dartz.dart';
|
||||
|
||||
part 'row_bloc.freezed.dart';
|
||||
|
||||
typedef CellDataMap = LinkedHashMap<String, GridCellIdentifier>;
|
||||
|
||||
class RowBloc extends Bloc<RowEvent, RowState> {
|
||||
final RowService _rowService;
|
||||
final GridFieldCache _fieldCache;
|
||||
final GridRowCache _rowCache;
|
||||
void Function()? _rowListenCallback;
|
||||
void Function()? _fieldListenCallback;
|
||||
void Function()? _rowListenFn;
|
||||
|
||||
RowBloc({
|
||||
required GridRow rowData,
|
||||
required GridFieldCache fieldCache,
|
||||
required GridRowCache rowCache,
|
||||
}) : _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId),
|
||||
_fieldCache = fieldCache,
|
||||
_rowCache = rowCache,
|
||||
super(RowState.initial(rowData)) {
|
||||
on<RowEvent>(
|
||||
@ -37,92 +28,45 @@ class RowBloc extends Bloc<RowEvent, RowState> {
|
||||
createRow: (_CreateRow value) {
|
||||
_rowService.createRow();
|
||||
},
|
||||
didUpdateRow: (_DidUpdateRow value) async {
|
||||
_handleRowUpdate(value.row, emit);
|
||||
},
|
||||
fieldsDidUpdate: (_FieldsDidUpdate value) async {
|
||||
await _handleFieldUpdate(emit);
|
||||
},
|
||||
didLoadRow: (_DidLoadRow value) {
|
||||
_handleRowUpdate(value.row, emit);
|
||||
didReceiveCellDatas: (_DidReceiveCellDatas value) async {
|
||||
emit(state.copyWith(cellDataMap: Some(value.cellData)));
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _handleRowUpdate(Row row, Emitter<RowState> emit) {
|
||||
final CellDataMap cellDataMap = _makeCellDatas(row, state.rowData.fields);
|
||||
emit(state.copyWith(cellDataMap: Some(cellDataMap)));
|
||||
}
|
||||
|
||||
Future<void> _handleFieldUpdate(Emitter<RowState> emit) async {
|
||||
final data = state.rowData.data;
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final CellDataMap cellDataMap = _makeCellDatas(data, state.rowData.fields);
|
||||
emit(state.copyWith(cellDataMap: Some(cellDataMap)));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
if (_rowListenCallback != null) {
|
||||
_rowCache.removeRowListener(_rowListenCallback!);
|
||||
}
|
||||
|
||||
if (_fieldListenCallback != null) {
|
||||
_fieldCache.removeListener(_fieldListenCallback!);
|
||||
if (_rowListenFn != null) {
|
||||
_rowCache.removeRowListener(_rowListenFn!);
|
||||
}
|
||||
return super.close();
|
||||
}
|
||||
|
||||
Future<void> _startListening() async {
|
||||
_fieldListenCallback = _fieldCache.addListener(
|
||||
listener: () => add(const RowEvent.fieldsDidUpdate()),
|
||||
listenWhen: () => !isClosed,
|
||||
);
|
||||
|
||||
_rowListenCallback = _rowCache.addRowListener(
|
||||
_rowListenFn = _rowCache.addRowListener(
|
||||
rowId: state.rowData.rowId,
|
||||
onUpdated: (row) => add(RowEvent.didUpdateRow(row)),
|
||||
onUpdated: (cellDatas) => add(RowEvent.didReceiveCellDatas(cellDatas)),
|
||||
listenWhen: () => !isClosed,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _loadRow(Emitter<RowState> emit) async {
|
||||
final data = _rowCache.loadRow(state.rowData.rowId);
|
||||
data.foldRight(null, (data, _) {
|
||||
final data = _rowCache.loadCellData(state.rowData.rowId);
|
||||
data.foldRight(null, (cellDatas, _) {
|
||||
if (!isClosed) {
|
||||
add(RowEvent.didLoadRow(data));
|
||||
add(RowEvent.didReceiveCellDatas(cellDatas));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
CellDataMap _makeCellDatas(Row row, List<Field> fields) {
|
||||
var map = CellDataMap.new();
|
||||
for (final field in fields) {
|
||||
if (field.visibility) {
|
||||
map[field.id] = GridCellIdentifier(
|
||||
rowId: row.id,
|
||||
gridId: _rowService.gridId,
|
||||
cell: row.cellByFieldId[field.id],
|
||||
field: field,
|
||||
);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class RowEvent with _$RowEvent {
|
||||
const factory RowEvent.initial() = _InitialRow;
|
||||
const factory RowEvent.createRow() = _CreateRow;
|
||||
const factory RowEvent.fieldsDidUpdate() = _FieldsDidUpdate;
|
||||
const factory RowEvent.didLoadRow(Row row) = _DidLoadRow;
|
||||
const factory RowEvent.didUpdateRow(Row row) = _DidUpdateRow;
|
||||
const factory RowEvent.didReceiveCellDatas(CellDataMap cellData) = _DidReceiveCellDatas;
|
||||
}
|
||||
|
||||
@freezed
|
||||
|
@ -8,31 +8,36 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import 'package:app_flowy/workspace/application/grid/grid_listener.dart';
|
||||
|
||||
part 'row_service.freezed.dart';
|
||||
|
||||
typedef RowUpdateCallback = void Function();
|
||||
typedef FieldDidUpdateCallback = void Function();
|
||||
typedef CellDataMap = LinkedHashMap<String, GridCell>;
|
||||
|
||||
abstract class GridRowDataDelegate {
|
||||
UnmodifiableListView<Field> get fields;
|
||||
GridRow buildGridRow(RowOrder rowOrder);
|
||||
CellDataMap buildCellDataMap(Row rowData);
|
||||
void onFieldChanged(FieldDidUpdateCallback callback);
|
||||
}
|
||||
|
||||
class GridRowCache {
|
||||
final String gridId;
|
||||
final RowsNotifier _rowNotifier;
|
||||
final GridRowListener _rowsListener;
|
||||
late final _RowsNotifier _rowNotifier;
|
||||
UnmodifiableListView<Field> _fields = UnmodifiableListView([]);
|
||||
final GridRowDataDelegate _dataDelegate;
|
||||
|
||||
List<GridRow> get clonedRows => _rowNotifier.clonedRows;
|
||||
|
||||
GridRowCache({required this.gridId}) : _rowsListener = GridRowListener(gridId: gridId) {
|
||||
_rowNotifier = _RowsNotifier(
|
||||
rowBuilder: (rowOrder) {
|
||||
return GridRow(
|
||||
gridId: gridId,
|
||||
fields: _fields,
|
||||
rowId: rowOrder.rowId,
|
||||
height: rowOrder.height.toDouble(),
|
||||
);
|
||||
},
|
||||
);
|
||||
GridRowCache({required this.gridId, required GridRowDataDelegate dataDelegate})
|
||||
: _rowNotifier = RowsNotifier(rowBuilder: dataDelegate.buildGridRow),
|
||||
_rowsListener = GridRowListener(gridId: gridId),
|
||||
_dataDelegate = dataDelegate {
|
||||
//
|
||||
dataDelegate.onFieldChanged(() => _rowNotifier.fieldDidChange());
|
||||
|
||||
// listen on the row update
|
||||
_rowsListener.rowsUpdateNotifier.addPublishListener((result) {
|
||||
result.fold(
|
||||
(changesets) {
|
||||
@ -68,9 +73,9 @@ class GridRowCache {
|
||||
});
|
||||
}
|
||||
|
||||
VoidCallback addRowListener({
|
||||
RowUpdateCallback addRowListener({
|
||||
required String rowId,
|
||||
void Function(Row)? onUpdated,
|
||||
void Function(CellDataMap)? onUpdated,
|
||||
bool Function()? listenWhen,
|
||||
}) {
|
||||
listenrHandler() {
|
||||
@ -82,12 +87,22 @@ class GridRowCache {
|
||||
return;
|
||||
}
|
||||
|
||||
_rowNotifier._changeReason.whenOrNull(update: (indexs) {
|
||||
notify() {
|
||||
final row = _rowNotifier.rowDataWithId(rowId);
|
||||
if (indexs[rowId] != null && row != null) {
|
||||
onUpdated(row);
|
||||
if (row != null) {
|
||||
final cellDataMap = _dataDelegate.buildCellDataMap(row);
|
||||
onUpdated(cellDataMap);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_rowNotifier._changeReason.whenOrNull(
|
||||
update: (indexs) {
|
||||
if (indexs[rowId] != null) {
|
||||
notify();
|
||||
}
|
||||
},
|
||||
fieldDidChange: () => notify(),
|
||||
);
|
||||
}
|
||||
|
||||
_rowNotifier.addListener(listenrHandler);
|
||||
@ -98,10 +113,10 @@ class GridRowCache {
|
||||
_rowNotifier.removeListener(callback);
|
||||
}
|
||||
|
||||
Option<Row> loadRow(String rowId) {
|
||||
Option<CellDataMap> loadCellData(String rowId) {
|
||||
final Row? data = _rowNotifier.rowDataWithId(rowId);
|
||||
if (data != null) {
|
||||
return Some(data);
|
||||
return Some(_dataDelegate.buildCellDataMap(data));
|
||||
}
|
||||
|
||||
final payload = RowIdentifierPayload.create()
|
||||
@ -117,8 +132,7 @@ class GridRowCache {
|
||||
return none();
|
||||
}
|
||||
|
||||
void updateWithBlock(List<GridBlockOrder> blocks, UnmodifiableListView<Field> fields) {
|
||||
_fields = fields;
|
||||
void updateWithBlock(List<GridBlockOrder> blocks) {
|
||||
final rowOrders = blocks.expand((block) => block.rowOrders).toList();
|
||||
_rowNotifier.reset(rowOrders);
|
||||
}
|
||||
@ -136,13 +150,13 @@ class GridRowCache {
|
||||
}
|
||||
}
|
||||
|
||||
class _RowsNotifier extends ChangeNotifier {
|
||||
class RowsNotifier extends ChangeNotifier {
|
||||
List<GridRow> _rows = [];
|
||||
HashMap<String, Row> _rowDataMap = HashMap();
|
||||
GridRowChangeReason _changeReason = const InitialListState();
|
||||
final GridRow Function(RowOrder) rowBuilder;
|
||||
|
||||
_RowsNotifier({
|
||||
RowsNotifier({
|
||||
required this.rowBuilder,
|
||||
});
|
||||
|
||||
@ -199,9 +213,10 @@ class _RowsNotifier extends ChangeNotifier {
|
||||
final index = newRows.indexWhere((row) => row.rowId == rowOrder.rowId);
|
||||
if (index != -1) {
|
||||
newRows.removeAt(index);
|
||||
// Remove the cache data
|
||||
// Remove the old row data, the data will be filled if the loadRow method gets called.
|
||||
_rowDataMap.remove(rowOrder.rowId);
|
||||
newRows.insert(index, rowBuilder(rowOrder));
|
||||
|
||||
updatedIndexs[rowOrder.rowId] = UpdatedIndex(index: index, rowId: rowOrder.rowId);
|
||||
}
|
||||
}
|
||||
@ -209,14 +224,19 @@ class _RowsNotifier extends ChangeNotifier {
|
||||
_update(newRows, GridRowChangeReason.update(updatedIndexs));
|
||||
}
|
||||
|
||||
void _update(List<GridRow> rows, GridRowChangeReason changeReason) {
|
||||
_rows = rows;
|
||||
_changeReason = changeReason;
|
||||
void fieldDidChange() {
|
||||
_update(_rows, const GridRowChangeReason.fieldDidChange());
|
||||
}
|
||||
|
||||
changeReason.map(
|
||||
void _update(List<GridRow> rows, GridRowChangeReason reason) {
|
||||
_rows = rows;
|
||||
_changeReason = reason;
|
||||
|
||||
_changeReason.map(
|
||||
insert: (_) => notifyListeners(),
|
||||
delete: (_) => notifyListeners(),
|
||||
update: (_) => notifyListeners(),
|
||||
fieldDidChange: (_) => notifyListeners(),
|
||||
initial: (_) {},
|
||||
);
|
||||
}
|
||||
@ -227,13 +247,17 @@ class _RowsNotifier extends ChangeNotifier {
|
||||
_rowDataMap[rowData.id] = rowData;
|
||||
final index = _rows.indexWhere((row) => row.rowId == rowData.id);
|
||||
if (index != -1) {
|
||||
// update the corresponding row in _rows if they are not the same
|
||||
if (_rows[index].data != rowData) {
|
||||
final row = _rows.removeAt(index).copyWith(data: rowData);
|
||||
_rows.insert(index, row);
|
||||
|
||||
// Calculate the update index
|
||||
final UpdatedIndexs updatedIndexs = UpdatedIndexs();
|
||||
updatedIndexs[row.rowId] = UpdatedIndex(index: index, rowId: row.rowId);
|
||||
_changeReason = GridRowChangeReason.update(updatedIndexs);
|
||||
|
||||
//
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
@ -296,16 +320,6 @@ class RowService {
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class GridCellIdentifier with _$GridCellIdentifier {
|
||||
const factory GridCellIdentifier({
|
||||
required String gridId,
|
||||
required String rowId,
|
||||
required Field field,
|
||||
Cell? cell,
|
||||
}) = _GridCellIdentifier;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class GridRow with _$GridRow {
|
||||
const factory GridRow({
|
||||
@ -317,13 +331,32 @@ class GridRow with _$GridRow {
|
||||
}) = _GridRow;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class GridCell with _$GridCell {
|
||||
const factory GridCell({
|
||||
required String gridId,
|
||||
required String rowId,
|
||||
required Field field,
|
||||
Cell? cell,
|
||||
}) = _GridCell;
|
||||
}
|
||||
|
||||
typedef InsertedIndexs = List<InsertedIndex>;
|
||||
typedef DeletedIndexs = List<DeletedIndex>;
|
||||
typedef UpdatedIndexs = LinkedHashMap<String, UpdatedIndex>;
|
||||
|
||||
@freezed
|
||||
class GridRowChangeReason with _$GridRowChangeReason {
|
||||
const factory GridRowChangeReason.insert(InsertedIndexs items) = _Insert;
|
||||
const factory GridRowChangeReason.delete(DeletedIndexs items) = _Delete;
|
||||
const factory GridRowChangeReason.update(UpdatedIndexs indexs) = _Update;
|
||||
const factory GridRowChangeReason.fieldDidChange() = _FieldDidChange;
|
||||
const factory GridRowChangeReason.initial() = InitialListState;
|
||||
}
|
||||
|
||||
class InsertedIndex {
|
||||
int index;
|
||||
String rowId;
|
||||
final int index;
|
||||
final String rowId;
|
||||
InsertedIndex({
|
||||
required this.index,
|
||||
required this.rowId,
|
||||
@ -331,8 +364,8 @@ class InsertedIndex {
|
||||
}
|
||||
|
||||
class DeletedIndex {
|
||||
int index;
|
||||
GridRow row;
|
||||
final int index;
|
||||
final GridRow row;
|
||||
DeletedIndex({
|
||||
required this.index,
|
||||
required this.row,
|
||||
@ -340,18 +373,10 @@ class DeletedIndex {
|
||||
}
|
||||
|
||||
class UpdatedIndex {
|
||||
int index;
|
||||
String rowId;
|
||||
final int index;
|
||||
final String rowId;
|
||||
UpdatedIndex({
|
||||
required this.index,
|
||||
required this.rowId,
|
||||
});
|
||||
}
|
||||
|
||||
@freezed
|
||||
class GridRowChangeReason with _$GridRowChangeReason {
|
||||
const factory GridRowChangeReason.insert(InsertedIndexs items) = _Insert;
|
||||
const factory GridRowChangeReason.delete(DeletedIndexs items) = _Delete;
|
||||
const factory GridRowChangeReason.update(UpdatedIndexs indexs) = _Update;
|
||||
const factory GridRowChangeReason.initial() = InitialListState;
|
||||
}
|
||||
|
@ -227,16 +227,12 @@ class _GridRowsState extends State<_GridRows> {
|
||||
GridRow rowData,
|
||||
Animation<double> animation,
|
||||
) {
|
||||
final bloc = context.read<GridBloc>();
|
||||
final fieldCache = bloc.fieldCache;
|
||||
final rowCache = bloc.rowCache;
|
||||
|
||||
final rowCache = context.read<GridBloc>().rowCache;
|
||||
return SizeTransition(
|
||||
sizeFactor: animation,
|
||||
child: GridRowWidget(
|
||||
blocBuilder: () => RowBloc(
|
||||
rowData: rowData,
|
||||
fieldCache: fieldCache,
|
||||
rowCache: rowCache,
|
||||
),
|
||||
key: ValueKey(rowData.rowId),
|
||||
|
@ -7,7 +7,7 @@ import 'number_cell.dart';
|
||||
import 'selection_cell/selection_cell.dart';
|
||||
import 'text_cell.dart';
|
||||
|
||||
Widget buildGridCell(GridCellIdentifier cellData) {
|
||||
Widget buildGridCell(GridCell cellData) {
|
||||
final key = ValueKey(cellData.field.id + cellData.rowId);
|
||||
switch (cellData.field.fieldType) {
|
||||
case FieldType.Checkbox:
|
||||
|
@ -55,8 +55,8 @@ class CellContainer extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class GridCell extends StatefulWidget {
|
||||
const GridCell({Key? key}) : super(key: key);
|
||||
abstract class GridCellWidget extends StatefulWidget {
|
||||
const GridCellWidget({Key? key}) : super(key: key);
|
||||
|
||||
void setFocus(BuildContext context, bool value) {
|
||||
Provider.of<CellStateNotifier>(context, listen: false).isFocus = value;
|
||||
|
@ -6,7 +6,7 @@ import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class CheckboxCell extends StatefulWidget {
|
||||
final GridCellIdentifier cellData;
|
||||
final GridCell cellData;
|
||||
|
||||
const CheckboxCell({
|
||||
required this.cellData,
|
||||
|
@ -8,8 +8,8 @@ import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:table_calendar/table_calendar.dart';
|
||||
|
||||
class DateCell extends GridCell {
|
||||
final GridCellIdentifier cellData;
|
||||
class DateCell extends GridCellWidget {
|
||||
final GridCell cellData;
|
||||
|
||||
const DateCell({
|
||||
required this.cellData,
|
||||
|
@ -6,8 +6,8 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/c
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class NumberCell extends GridCell {
|
||||
final GridCellIdentifier cellData;
|
||||
class NumberCell extends GridCellWidget {
|
||||
final GridCell cellData;
|
||||
|
||||
const NumberCell({
|
||||
required this.cellData,
|
||||
|
@ -7,8 +7,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'extension.dart';
|
||||
import 'selection_editor.dart';
|
||||
|
||||
class SingleSelectCell extends GridCell {
|
||||
final GridCellIdentifier cellData;
|
||||
class SingleSelectCell extends GridCellWidget {
|
||||
final GridCell cellData;
|
||||
|
||||
const SingleSelectCell({
|
||||
required this.cellData,
|
||||
@ -63,8 +63,8 @@ class _SingleSelectCellState extends State<SingleSelectCell> {
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
class MultiSelectCell extends GridCell {
|
||||
final GridCellIdentifier cellData;
|
||||
class MultiSelectCell extends GridCellWidget {
|
||||
final GridCell cellData;
|
||||
|
||||
const MultiSelectCell({
|
||||
required this.cellData,
|
||||
|
@ -25,7 +25,7 @@ import 'text_field.dart';
|
||||
const double _editorPannelWidth = 300;
|
||||
|
||||
class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
|
||||
final GridCellIdentifier cellData;
|
||||
final GridCell cellData;
|
||||
final List<SelectOption> options;
|
||||
final List<SelectOption> selectedOptions;
|
||||
final VoidCallback onDismissed;
|
||||
@ -66,7 +66,7 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
|
||||
|
||||
static void show(
|
||||
BuildContext context,
|
||||
GridCellIdentifier cellData,
|
||||
GridCell cellData,
|
||||
List<SelectOption> options,
|
||||
List<SelectOption> selectedOptions,
|
||||
VoidCallback onDismissed,
|
||||
|
@ -5,8 +5,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'cell_container.dart';
|
||||
|
||||
class GridTextCell extends GridCell {
|
||||
final GridCellIdentifier cellData;
|
||||
class GridTextCell extends GridCellWidget {
|
||||
final GridCell cellData;
|
||||
const GridTextCell({
|
||||
required this.cellData,
|
||||
Key? key,
|
||||
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class NumberCell extends StatefulWidget {
|
||||
final GridCellIdentifier cellData;
|
||||
final GridCell cellData;
|
||||
|
||||
const NumberCell({
|
||||
required this.cellData,
|
||||
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class NumberCell extends StatefulWidget {
|
||||
final GridCellIdentifier cellData;
|
||||
final GridCell cellData;
|
||||
|
||||
const NumberCell({
|
||||
required this.cellData,
|
||||
|
Loading…
Reference in New Issue
Block a user