mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: cache row data
This commit is contained in:
parent
792f8b95aa
commit
3cc7c8e6de
@ -150,13 +150,6 @@ void _resolveGridDeps(GetIt getIt) {
|
||||
(view, _) => GridBloc(view: view),
|
||||
);
|
||||
|
||||
getIt.registerFactoryParam<RowBloc, RowData, GridFieldCache>(
|
||||
(data, fieldCache) => RowBloc(
|
||||
rowData: data,
|
||||
fieldCache: fieldCache,
|
||||
),
|
||||
);
|
||||
|
||||
getIt.registerFactoryParam<GridHeaderBloc, String, GridFieldCache>(
|
||||
(gridId, fieldCache) => GridHeaderBloc(
|
||||
gridId: gridId,
|
||||
|
@ -58,12 +58,11 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
|
||||
fieldId: state.cellData.field.id,
|
||||
rowId: state.cellData.rowId,
|
||||
);
|
||||
if (isClosed) {
|
||||
return;
|
||||
}
|
||||
result.fold(
|
||||
(cell) {
|
||||
if (!isClosed) {
|
||||
add(CheckboxCellEvent.didReceiveCellUpdate(cell));
|
||||
}
|
||||
},
|
||||
(cell) => add(CheckboxCellEvent.didReceiveCellUpdate(cell)),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
}
|
||||
|
@ -57,19 +57,15 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
|
||||
(notificationData) => _loadCellData(),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
});
|
||||
}, listenWhen: () => !isClosed);
|
||||
_cellListener.start();
|
||||
|
||||
_fieldListener.updateFieldNotifier?.addPublishListener((result) {
|
||||
result.fold(
|
||||
(field) {
|
||||
if (!isClosed) {
|
||||
add(DateCellEvent.didReceiveFieldUpdate(field));
|
||||
}
|
||||
},
|
||||
(field) => add(DateCellEvent.didReceiveFieldUpdate(field)),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
});
|
||||
}, listenWhen: () => !isClosed);
|
||||
_fieldListener.start();
|
||||
}
|
||||
|
||||
@ -79,12 +75,11 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
|
||||
fieldId: state.cellData.field.id,
|
||||
rowId: state.cellData.rowId,
|
||||
);
|
||||
if (isClosed) {
|
||||
return;
|
||||
}
|
||||
result.fold(
|
||||
(cell) {
|
||||
if (!isClosed) {
|
||||
add(DateCellEvent.didReceiveCellUpdate(cell));
|
||||
}
|
||||
},
|
||||
(cell) => add(DateCellEvent.didReceiveCellUpdate(cell)),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
}
|
||||
|
@ -84,12 +84,12 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
|
||||
fieldId: state.cellData.field.id,
|
||||
rowId: state.cellData.rowId,
|
||||
);
|
||||
|
||||
if (isClosed) {
|
||||
return;
|
||||
}
|
||||
result.fold(
|
||||
(cell) {
|
||||
if (!isClosed) {
|
||||
add(NumberCellEvent.didReceiveCellUpdate(cell));
|
||||
}
|
||||
},
|
||||
(cell) => add(NumberCellEvent.didReceiveCellUpdate(cell)),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
}
|
||||
|
@ -49,16 +49,15 @@ class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
|
||||
fieldId: state.cellData.field.id,
|
||||
rowId: state.cellData.rowId,
|
||||
);
|
||||
if (isClosed) {
|
||||
return;
|
||||
}
|
||||
|
||||
result.fold(
|
||||
(selectOptionContext) {
|
||||
if (!isClosed) {
|
||||
add(SelectionCellEvent.didReceiveOptions(
|
||||
selectOptionContext.options,
|
||||
selectOptionContext.selectOptions,
|
||||
));
|
||||
}
|
||||
},
|
||||
(selectOptionContext) => add(SelectionCellEvent.didReceiveOptions(
|
||||
selectOptionContext.options,
|
||||
selectOptionContext.selectOptions,
|
||||
)),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
}
|
||||
|
@ -117,16 +117,15 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
|
||||
fieldId: state.field.id,
|
||||
rowId: state.rowId,
|
||||
);
|
||||
if (isClosed) {
|
||||
return;
|
||||
}
|
||||
|
||||
result.fold(
|
||||
(selectOptionContext) {
|
||||
if (!isClosed) {
|
||||
add(SelectOptionEditorEvent.didReceiveOptions(
|
||||
selectOptionContext.options,
|
||||
selectOptionContext.selectOptions,
|
||||
));
|
||||
}
|
||||
},
|
||||
(selectOptionContext) => add(SelectOptionEditorEvent.didReceiveOptions(
|
||||
selectOptionContext.options,
|
||||
selectOptionContext.selectOptions,
|
||||
)),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
},
|
||||
@ -144,14 +143,10 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
|
||||
|
||||
_fieldListener.updateFieldNotifier?.addPublishListener((result) {
|
||||
result.fold(
|
||||
(field) {
|
||||
if (!isClosed) {
|
||||
add(SelectOptionEditorEvent.didReceiveFieldUpdate(field));
|
||||
}
|
||||
},
|
||||
(field) => add(SelectOptionEditorEvent.didReceiveFieldUpdate(field)),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
});
|
||||
}, listenWhen: () => !isClosed);
|
||||
_fieldListener.start();
|
||||
}
|
||||
}
|
||||
|
@ -47,14 +47,10 @@ class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
|
||||
void _startListening() {
|
||||
_fieldListener.updateFieldNotifier?.addPublishListener((result) {
|
||||
result.fold(
|
||||
(field) {
|
||||
if (!isClosed) {
|
||||
add(FieldCellEvent.didReceiveFieldUpdate(field));
|
||||
}
|
||||
},
|
||||
(field) => add(FieldCellEvent.didReceiveFieldUpdate(field)),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
});
|
||||
}, listenWhen: () => !isClosed);
|
||||
_fieldListener.start();
|
||||
}
|
||||
}
|
||||
|
@ -18,14 +18,14 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
final GridListener _gridListener;
|
||||
final GridFieldsListener _fieldListener;
|
||||
final GridFieldCache fieldCache;
|
||||
final GridRowCache _rowCache;
|
||||
final GridRowCache rowCache;
|
||||
|
||||
GridBloc({required View view})
|
||||
: _fieldListener = GridFieldsListener(gridId: view.id),
|
||||
_gridService = GridService(gridId: view.id),
|
||||
_gridListener = GridListener(gridId: view.id),
|
||||
fieldCache = GridFieldCache(),
|
||||
_rowCache = GridRowCache(gridId: view.id),
|
||||
rowCache = GridRowCache(gridId: view.id),
|
||||
super(GridState.initial(view.id)) {
|
||||
on<GridEvent>(
|
||||
(event, emit) async {
|
||||
@ -41,7 +41,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
emit(state.copyWith(rows: value.rows, listState: value.listState));
|
||||
},
|
||||
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
|
||||
emit(state.copyWith(rows: _rowCache.rows, fields: value.fields));
|
||||
emit(state.copyWith(rows: rowCache.rows, fields: value.fields));
|
||||
},
|
||||
);
|
||||
},
|
||||
@ -62,7 +62,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
result.fold(
|
||||
(changeset) {
|
||||
fieldCache.applyChangeset(changeset);
|
||||
_rowCache.updateFields(fieldCache.unmodifiableFields);
|
||||
rowCache.updateFields(fieldCache.unmodifiableFields);
|
||||
add(GridEvent.didReceiveFieldUpdate(fieldCache.clonedFields));
|
||||
},
|
||||
(err) => Log.error(err),
|
||||
@ -74,15 +74,15 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
result.fold(
|
||||
(changesets) {
|
||||
for (final changeset in changesets) {
|
||||
_rowCache
|
||||
rowCache
|
||||
.deleteRows(changeset.deletedRows)
|
||||
.foldRight(null, (listState, _) => add(GridEvent.didReceiveRowUpdate(_rowCache.rows, listState)));
|
||||
.foldRight(null, (listState, _) => add(GridEvent.didReceiveRowUpdate(rowCache.rows, listState)));
|
||||
|
||||
_rowCache
|
||||
rowCache
|
||||
.insertRows(changeset.insertedRows)
|
||||
.foldRight(null, (listState, _) => add(GridEvent.didReceiveRowUpdate(_rowCache.rows, listState)));
|
||||
.foldRight(null, (listState, _) => add(GridEvent.didReceiveRowUpdate(rowCache.rows, listState)));
|
||||
|
||||
_rowCache.updateRows(changeset.updatedRows);
|
||||
rowCache.updateRows(changeset.updatedRows);
|
||||
}
|
||||
},
|
||||
(err) => Log.error(err),
|
||||
@ -107,12 +107,12 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
() => result.fold(
|
||||
(fields) {
|
||||
fieldCache.clonedFields = fields.items;
|
||||
_rowCache.updateWithBlock(grid.blockOrders, fieldCache.unmodifiableFields);
|
||||
rowCache.updateWithBlock(grid.blockOrders, fieldCache.unmodifiableFields);
|
||||
|
||||
emit(state.copyWith(
|
||||
grid: Some(grid),
|
||||
fields: fieldCache.clonedFields,
|
||||
rows: _rowCache.rows,
|
||||
rows: rowCache.rows,
|
||||
loadingState: GridLoadingState.finish(left(unit)),
|
||||
));
|
||||
},
|
||||
@ -126,7 +126,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
class GridEvent with _$GridEvent {
|
||||
const factory GridEvent.initial() = InitialGrid;
|
||||
const factory GridEvent.createRow() = _CreateRow;
|
||||
const factory GridEvent.didReceiveRowUpdate(List<RowData> rows, GridListState listState) = _DidReceiveRowUpdate;
|
||||
const factory GridEvent.didReceiveRowUpdate(List<GridRow> rows, GridListState listState) = _DidReceiveRowUpdate;
|
||||
const factory GridEvent.didReceiveFieldUpdate(List<Field> fields) = _DidReceiveFieldUpdate;
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ class GridState with _$GridState {
|
||||
required String gridId,
|
||||
required Option<Grid> grid,
|
||||
required List<Field> fields,
|
||||
required List<RowData> rows,
|
||||
required List<GridRow> rows,
|
||||
required GridLoadingState loadingState,
|
||||
required GridListState listState,
|
||||
}) = _GridState;
|
||||
|
@ -36,11 +36,11 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
|
||||
}
|
||||
|
||||
Future<void> _startListening() async {
|
||||
fieldCache.addListener(() {}, onChanged: (fields) {
|
||||
if (!isClosed) {
|
||||
add(GridHeaderEvent.didReceiveFieldUpdate(fields));
|
||||
}
|
||||
});
|
||||
fieldCache.addListener(
|
||||
() {},
|
||||
onChanged: (fields) => add(GridHeaderEvent.didReceiveFieldUpdate(fields)),
|
||||
listenWhen: () => !isClosed,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -5,9 +5,6 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
|
||||
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 'package:app_flowy/workspace/application/grid/row/row_service.dart';
|
||||
|
||||
part 'grid_service.freezed.dart';
|
||||
|
||||
class GridService {
|
||||
final String gridId;
|
||||
@ -74,11 +71,16 @@ class GridFieldCache {
|
||||
_fieldNotifier.addListener(() => onFieldChanged(clonedFields));
|
||||
}
|
||||
|
||||
void addListener(VoidCallback listener, {void Function(List<Field>)? onChanged}) {
|
||||
void addListener(VoidCallback listener, {void Function(List<Field>)? onChanged, bool Function()? listenWhen}) {
|
||||
_fieldNotifier.addListener(() {
|
||||
if (onChanged != null) {
|
||||
onChanged(clonedFields);
|
||||
}
|
||||
|
||||
if (listenWhen != null && listenWhen() == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
listener();
|
||||
});
|
||||
}
|
||||
@ -130,98 +132,3 @@ class GridFieldCache {
|
||||
_fieldNotifier.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class GridRowCache {
|
||||
final String gridId;
|
||||
UnmodifiableListView<Field> _fields = UnmodifiableListView([]);
|
||||
List<RowData> _rows = [];
|
||||
|
||||
GridRowCache({required this.gridId});
|
||||
|
||||
List<RowData> get rows => [..._rows];
|
||||
|
||||
void updateWithBlock(List<GridBlockOrder> blocks, UnmodifiableListView<Field> fields) {
|
||||
_fields = fields;
|
||||
_rows = blocks.expand((block) => block.rowOrders).map((rowOrder) {
|
||||
return RowData.fromBlockRow(gridId, rowOrder, _fields);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
void updateFields(UnmodifiableListView<Field> fields) {
|
||||
if (fields.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
_fields = fields;
|
||||
_rows = _rows.map((row) => row.copyWith(fields: fields)).toList();
|
||||
}
|
||||
|
||||
Option<GridListState> deleteRows(List<RowOrder> deletedRows) {
|
||||
if (deletedRows.isEmpty) {
|
||||
return none();
|
||||
}
|
||||
|
||||
final List<RowData> newRows = [];
|
||||
final DeletedIndex deletedIndex = [];
|
||||
final Map<String, RowOrder> deletedRowMap = {for (var rowOrder in deletedRows) rowOrder.rowId: rowOrder};
|
||||
_rows.asMap().forEach((index, value) {
|
||||
if (deletedRowMap[value.rowId] == null) {
|
||||
newRows.add(value);
|
||||
} else {
|
||||
deletedIndex.add(Tuple2(index, value));
|
||||
}
|
||||
});
|
||||
_rows = newRows;
|
||||
|
||||
return Some(GridListState.delete(deletedIndex));
|
||||
}
|
||||
|
||||
Option<GridListState> insertRows(List<IndexRowOrder> createdRows) {
|
||||
if (createdRows.isEmpty) {
|
||||
return none();
|
||||
}
|
||||
|
||||
InsertedIndexs insertIndexs = [];
|
||||
for (final newRow in createdRows) {
|
||||
if (newRow.hasIndex()) {
|
||||
insertIndexs.add(Tuple2(newRow.index, newRow.rowOrder.rowId));
|
||||
_rows.insert(newRow.index, _toRowData(newRow.rowOrder));
|
||||
} else {
|
||||
insertIndexs.add(Tuple2(newRow.index, newRow.rowOrder.rowId));
|
||||
_rows.add(_toRowData(newRow.rowOrder));
|
||||
}
|
||||
}
|
||||
|
||||
return Some(GridListState.insert(insertIndexs));
|
||||
}
|
||||
|
||||
void updateRows(List<RowOrder> updatedRows) {
|
||||
if (updatedRows.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<int> updatedIndexs = [];
|
||||
for (final updatedRow in updatedRows) {
|
||||
final index = _rows.indexWhere((row) => row.rowId == updatedRow.rowId);
|
||||
if (index != -1) {
|
||||
_rows.removeAt(index);
|
||||
_rows.insert(index, _toRowData(updatedRow));
|
||||
updatedIndexs.add(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowData _toRowData(RowOrder rowOrder) {
|
||||
return RowData.fromBlockRow(gridId, rowOrder, _fields);
|
||||
}
|
||||
}
|
||||
|
||||
typedef InsertedIndexs = List<Tuple2<int, String>>;
|
||||
typedef DeletedIndex = List<Tuple2<int, RowData>>;
|
||||
|
||||
@freezed
|
||||
class GridListState with _$GridListState {
|
||||
const factory GridListState.insert(InsertedIndexs items) = _Insert;
|
||||
const factory GridListState.delete(DeletedIndex items) = _Delete;
|
||||
const factory GridListState.initial() = InitialListState;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ part 'row_action_sheet_bloc.freezed.dart';
|
||||
class RowActionSheetBloc extends Bloc<RowActionSheetEvent, RowActionSheetState> {
|
||||
final RowService _rowService;
|
||||
|
||||
RowActionSheetBloc({required RowData rowData})
|
||||
RowActionSheetBloc({required GridRow rowData})
|
||||
: _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId),
|
||||
super(RowActionSheetState.initial(rowData)) {
|
||||
on<RowActionSheetEvent>(
|
||||
@ -49,10 +49,10 @@ class RowActionSheetEvent with _$RowActionSheetEvent {
|
||||
@freezed
|
||||
class RowActionSheetState with _$RowActionSheetState {
|
||||
const factory RowActionSheetState({
|
||||
required RowData rowData,
|
||||
required GridRow rowData,
|
||||
}) = _RowActionSheetState;
|
||||
|
||||
factory RowActionSheetState.initial(RowData rowData) => RowActionSheetState(
|
||||
factory RowActionSheetState.initial(GridRow rowData) => RowActionSheetState(
|
||||
rowData: rowData,
|
||||
);
|
||||
}
|
||||
|
@ -18,11 +18,16 @@ class RowBloc extends Bloc<RowEvent, RowState> {
|
||||
final RowService _rowService;
|
||||
final RowListener _rowlistener;
|
||||
final GridFieldCache _fieldCache;
|
||||
final GridRowCache _rowCache;
|
||||
|
||||
RowBloc({required RowData rowData, required GridFieldCache fieldCache})
|
||||
: _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId),
|
||||
_fieldCache = fieldCache,
|
||||
RowBloc({
|
||||
required GridRow rowData,
|
||||
required GridFieldCache fieldCache,
|
||||
required GridRowCache rowCache,
|
||||
}) : _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId),
|
||||
_rowlistener = RowListener(rowId: rowData.rowId),
|
||||
_fieldCache = fieldCache,
|
||||
_rowCache = rowCache,
|
||||
super(RowState.initial(rowData)) {
|
||||
on<RowEvent>(
|
||||
(event, emit) async {
|
||||
@ -76,37 +81,30 @@ class RowBloc extends Bloc<RowEvent, RowState> {
|
||||
}
|
||||
|
||||
Future<void> _startListening() async {
|
||||
_rowlistener.updateRowNotifier?.addPublishListener((result) {
|
||||
result.fold(
|
||||
(row) {
|
||||
if (!isClosed) {
|
||||
add(RowEvent.didUpdateRow(row));
|
||||
}
|
||||
},
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
});
|
||||
_rowlistener.updateRowNotifier?.addPublishListener(
|
||||
(result) {
|
||||
result.fold(
|
||||
(row) => add(RowEvent.didUpdateRow(row)),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
},
|
||||
listenWhen: () => !isClosed,
|
||||
);
|
||||
|
||||
_fieldCache.addListener(() {
|
||||
if (!isClosed) {
|
||||
add(const RowEvent.fieldsDidUpdate());
|
||||
}
|
||||
});
|
||||
_fieldCache.addListener(
|
||||
() => add(const RowEvent.fieldsDidUpdate()),
|
||||
listenWhen: () => !isClosed,
|
||||
);
|
||||
|
||||
_rowlistener.start();
|
||||
}
|
||||
|
||||
Future<void> _loadRow(Emitter<RowState> emit) async {
|
||||
_rowService.getRow().then((result) {
|
||||
return result.fold(
|
||||
(row) {
|
||||
if (!isClosed) {
|
||||
add(RowEvent.didLoadRow(row));
|
||||
}
|
||||
},
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
});
|
||||
final data = await _rowCache.getRowData(state.rowData.rowId);
|
||||
if (isClosed) {
|
||||
return;
|
||||
}
|
||||
data.foldRight(null, (data, _) => add(RowEvent.didLoadRow(data)));
|
||||
}
|
||||
|
||||
CellDataMap _makeCellDatas(Row row, List<Field> fields) {
|
||||
@ -137,12 +135,12 @@ class RowEvent with _$RowEvent {
|
||||
@freezed
|
||||
class RowState with _$RowState {
|
||||
const factory RowState({
|
||||
required RowData rowData,
|
||||
required GridRow rowData,
|
||||
required Future<Option<Row>> row,
|
||||
required Option<CellDataMap> cellDataMap,
|
||||
}) = _RowState;
|
||||
|
||||
factory RowState.initial(RowData rowData) => RowState(
|
||||
factory RowState.initial(GridRow rowData) => RowState(
|
||||
rowData: rowData,
|
||||
row: Future(() => none()),
|
||||
cellDataMap: none(),
|
||||
|
@ -1,5 +1,8 @@
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||
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/row_entities.pb.dart';
|
||||
@ -57,6 +60,115 @@ class RowService {
|
||||
}
|
||||
}
|
||||
|
||||
class GridRowCache {
|
||||
final String gridId;
|
||||
UnmodifiableListView<Field> _fields = UnmodifiableListView([]);
|
||||
HashMap<String, Row> rowDataMap = HashMap();
|
||||
|
||||
List<GridRow> _rows = [];
|
||||
|
||||
GridRowCache({required this.gridId});
|
||||
|
||||
List<GridRow> get rows => [..._rows];
|
||||
|
||||
Future<Option<Row>> getRowData(String rowId) async {
|
||||
final Row? data = rowDataMap[rowId];
|
||||
if (data != null) {
|
||||
return Future(() => Some(data));
|
||||
}
|
||||
|
||||
final payload = RowIdentifierPayload.create()
|
||||
..gridId = gridId
|
||||
..rowId = rowId;
|
||||
|
||||
final result = await GridEventGetRow(payload).send();
|
||||
return Future(() {
|
||||
return result.fold(
|
||||
(data) {
|
||||
data.freeze();
|
||||
rowDataMap[data.id] = data;
|
||||
return Some(data);
|
||||
},
|
||||
(err) {
|
||||
Log.error(err);
|
||||
return none();
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void updateWithBlock(List<GridBlockOrder> blocks, UnmodifiableListView<Field> fields) {
|
||||
_fields = fields;
|
||||
_rows = blocks.expand((block) => block.rowOrders).map((rowOrder) {
|
||||
return GridRow.fromBlockRow(gridId, rowOrder, _fields);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
void updateFields(UnmodifiableListView<Field> fields) {
|
||||
if (fields.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
_fields = fields;
|
||||
_rows = _rows.map((row) => row.copyWith(fields: fields)).toList();
|
||||
}
|
||||
|
||||
Option<GridListState> deleteRows(List<RowOrder> deletedRows) {
|
||||
if (deletedRows.isEmpty) {
|
||||
return none();
|
||||
}
|
||||
|
||||
final List<GridRow> newRows = [];
|
||||
final DeletedIndex deletedIndex = [];
|
||||
final Map<String, RowOrder> deletedRowMap = {for (var rowOrder in deletedRows) rowOrder.rowId: rowOrder};
|
||||
_rows.asMap().forEach((index, value) {
|
||||
if (deletedRowMap[value.rowId] == null) {
|
||||
newRows.add(value);
|
||||
} else {
|
||||
deletedIndex.add(Tuple2(index, value));
|
||||
}
|
||||
});
|
||||
_rows = newRows;
|
||||
|
||||
return Some(GridListState.delete(deletedIndex));
|
||||
}
|
||||
|
||||
Option<GridListState> insertRows(List<IndexRowOrder> createdRows) {
|
||||
if (createdRows.isEmpty) {
|
||||
return none();
|
||||
}
|
||||
|
||||
InsertedIndexs insertIndexs = [];
|
||||
for (final createdRow in createdRows) {
|
||||
final gridRow = GridRow.fromBlockRow(gridId, createdRow.rowOrder, _fields);
|
||||
insertIndexs.add(Tuple2(createdRow.index, gridRow.rowId));
|
||||
_rows.insert(createdRow.index, gridRow);
|
||||
}
|
||||
|
||||
return Some(GridListState.insert(insertIndexs));
|
||||
}
|
||||
|
||||
void updateRows(List<RowOrder> updatedRows) {
|
||||
if (updatedRows.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<int> updatedIndexs = [];
|
||||
for (final updatedRow in updatedRows) {
|
||||
final index = _rows.indexWhere((row) => row.rowId == updatedRow.rowId);
|
||||
if (index != -1) {
|
||||
_rows.removeAt(index);
|
||||
_rows.insert(index, _toRowData(updatedRow));
|
||||
updatedIndexs.add(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GridRow _toRowData(RowOrder rowOrder) {
|
||||
return GridRow.fromBlockRow(gridId, rowOrder, _fields);
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class CellData with _$CellData {
|
||||
const factory CellData({
|
||||
@ -68,20 +180,32 @@ class CellData with _$CellData {
|
||||
}
|
||||
|
||||
@freezed
|
||||
class RowData with _$RowData {
|
||||
const factory RowData({
|
||||
class GridRow with _$GridRow {
|
||||
const factory GridRow({
|
||||
required String gridId,
|
||||
required String rowId,
|
||||
required List<Field> fields,
|
||||
required double height,
|
||||
}) = _RowData;
|
||||
required Future<Option<Row>> data,
|
||||
}) = _GridRow;
|
||||
|
||||
factory RowData.fromBlockRow(String gridId, RowOrder row, List<Field> fields) {
|
||||
return RowData(
|
||||
factory GridRow.fromBlockRow(String gridId, RowOrder row, List<Field> fields) {
|
||||
return GridRow(
|
||||
gridId: gridId,
|
||||
rowId: row.rowId,
|
||||
fields: fields,
|
||||
rowId: row.rowId,
|
||||
data: Future(() => none()),
|
||||
height: row.height.toDouble(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
typedef InsertedIndexs = List<Tuple2<int, String>>;
|
||||
typedef DeletedIndex = List<Tuple2<int, GridRow>>;
|
||||
|
||||
@freezed
|
||||
class GridListState with _$GridListState {
|
||||
const factory GridListState.insert(InsertedIndexs items) = _Insert;
|
||||
const factory GridListState.delete(DeletedIndex items) = _Delete;
|
||||
const factory GridListState.initial() = InitialListState;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:app_flowy/workspace/application/grid/grid_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/grid/row/row_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
|
||||
@ -221,14 +222,19 @@ class _GridRowsState extends State<_GridRows> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderRow(BuildContext context, RowData rowData, Animation<double> animation) {
|
||||
final fieldCache = context.read<GridBloc>().fieldCache;
|
||||
Widget _renderRow(BuildContext context, GridRow rowData, Animation<double> animation) {
|
||||
final bloc = context.read<GridBloc>();
|
||||
final fieldCache = bloc.fieldCache;
|
||||
final rowCache = bloc.rowCache;
|
||||
|
||||
return SizeTransition(
|
||||
sizeFactor: animation,
|
||||
child: GridRowWidget(
|
||||
data: rowData,
|
||||
fieldCache: fieldCache,
|
||||
blocBuilder: () => RowBloc(
|
||||
rowData: rowData,
|
||||
fieldCache: fieldCache,
|
||||
rowCache: rowCache,
|
||||
),
|
||||
key: ValueKey(rowData.rowId),
|
||||
),
|
||||
);
|
||||
|
@ -12,9 +12,12 @@ import 'package:provider/provider.dart';
|
||||
import 'row_action_sheet.dart';
|
||||
|
||||
class GridRowWidget extends StatefulWidget {
|
||||
final RowData data;
|
||||
final GridFieldCache fieldCache;
|
||||
const GridRowWidget({required this.data, required this.fieldCache, Key? key}) : super(key: key);
|
||||
final RowBloc Function() blocBuilder;
|
||||
|
||||
const GridRowWidget({
|
||||
required this.blocBuilder,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<GridRowWidget> createState() => _GridRowWidgetState();
|
||||
@ -26,7 +29,8 @@ class _GridRowWidgetState extends State<GridRowWidget> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_rowBloc = getIt<RowBloc>(param1: widget.data, param2: widget.fieldCache)..add(const RowEvent.initial());
|
||||
_rowBloc = widget.blocBuilder();
|
||||
_rowBloc.add(const RowEvent.initial());
|
||||
_rowStateNotifier = _RegionStateNotifier();
|
||||
super.initState();
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class GridRowActionSheet extends StatelessWidget {
|
||||
final RowData rowData;
|
||||
final GridRow rowData;
|
||||
const GridRowActionSheet({required this.rowData, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
@ -31,12 +31,18 @@ class PublishNotifier<T> extends ChangeNotifier {
|
||||
|
||||
T? get currentValue => _value;
|
||||
|
||||
void addPublishListener(void Function(T) callback) {
|
||||
void addPublishListener(void Function(T) callback, {bool Function()? listenWhen}) {
|
||||
super.addListener(
|
||||
() {
|
||||
if (_value != null) {
|
||||
callback(_value!);
|
||||
if (_value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (listenWhen != null && listenWhen() == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(_value!);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user