chore: refactor row cache with row listener

This commit is contained in:
appflowy 2022-04-16 22:26:34 +08:00
parent 3cc7c8e6de
commit c82754f284
11 changed files with 148 additions and 130 deletions

View File

@ -1,13 +1,10 @@
import 'dart:async'; import 'dart:async';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/protobuf.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'field/grid_listenr.dart';
import 'grid_listener.dart';
import 'grid_service.dart'; import 'grid_service.dart';
import 'row/row_service.dart'; import 'row/row_service.dart';
@ -15,16 +12,12 @@ part 'grid_bloc.freezed.dart';
class GridBloc extends Bloc<GridEvent, GridState> { class GridBloc extends Bloc<GridEvent, GridState> {
final GridService _gridService; final GridService _gridService;
final GridListener _gridListener;
final GridFieldsListener _fieldListener;
final GridFieldCache fieldCache; final GridFieldCache fieldCache;
final GridRowCache rowCache; final GridRowCache rowCache;
GridBloc({required View view}) GridBloc({required View view})
: _fieldListener = GridFieldsListener(gridId: view.id), : _gridService = GridService(gridId: view.id),
_gridService = GridService(gridId: view.id), fieldCache = GridFieldCache(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)) { super(GridState.initial(view.id)) {
on<GridEvent>( on<GridEvent>(
@ -41,7 +34,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
emit(state.copyWith(rows: value.rows, listState: value.listState)); emit(state.copyWith(rows: value.rows, listState: value.listState));
}, },
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
emit(state.copyWith(rows: rowCache.rows, fields: value.fields)); emit(state.copyWith(rows: rowCache.clonedRows, fields: value.fields));
}, },
); );
}, },
@ -51,44 +44,22 @@ class GridBloc extends Bloc<GridEvent, GridState> {
@override @override
Future<void> close() async { Future<void> close() async {
await _gridService.closeGrid(); await _gridService.closeGrid();
await _fieldListener.stop(); await fieldCache.dispose();
await _gridListener.stop(); await rowCache.dispose();
fieldCache.dispose(); fieldCache.dispose();
return super.close(); return super.close();
} }
void _startListening() { void _startListening() {
_fieldListener.updateFieldsNotifier?.addPublishListener((result) { fieldCache.addListener(
result.fold( onChanged: (fields) => add(GridEvent.didReceiveFieldUpdate(fields)),
(changeset) { listenWhen: () => !isClosed,
fieldCache.applyChangeset(changeset); );
rowCache.updateFields(fieldCache.unmodifiableFields);
add(GridEvent.didReceiveFieldUpdate(fieldCache.clonedFields));
},
(err) => Log.error(err),
);
});
_fieldListener.start();
_gridListener.rowsUpdateNotifier.addPublishListener((result) { rowCache.addListener(
result.fold( onChanged: (rows, listState) => add(GridEvent.didReceiveRowUpdate(rowCache.clonedRows, listState)),
(changesets) { listenWhen: () => !isClosed,
for (final changeset in changesets) { );
rowCache
.deleteRows(changeset.deletedRows)
.foldRight(null, (listState, _) => add(GridEvent.didReceiveRowUpdate(rowCache.rows, listState)));
rowCache
.insertRows(changeset.insertedRows)
.foldRight(null, (listState, _) => add(GridEvent.didReceiveRowUpdate(rowCache.rows, listState)));
rowCache.updateRows(changeset.updatedRows);
}
},
(err) => Log.error(err),
);
});
_gridListener.start();
} }
Future<void> _loadGrid(Emitter<GridState> emit) async { Future<void> _loadGrid(Emitter<GridState> emit) async {
@ -106,13 +77,13 @@ class GridBloc extends Bloc<GridEvent, GridState> {
return Future( return Future(
() => result.fold( () => result.fold(
(fields) { (fields) {
fieldCache.clonedFields = fields.items; fieldCache.fields = fields.items;
rowCache.updateWithBlock(grid.blockOrders, fieldCache.unmodifiableFields); rowCache.updateWithBlock(grid.blockOrders, fieldCache.unmodifiableFields);
emit(state.copyWith( emit(state.copyWith(
grid: Some(grid), grid: Some(grid),
fields: fieldCache.clonedFields, fields: fieldCache.clonedFields,
rows: rowCache.rows, rows: rowCache.clonedRows,
loadingState: GridLoadingState.finish(left(unit)), loadingState: GridLoadingState.finish(left(unit)),
)); ));
}, },
@ -126,7 +97,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
class GridEvent with _$GridEvent { class GridEvent with _$GridEvent {
const factory GridEvent.initial() = InitialGrid; const factory GridEvent.initial() = InitialGrid;
const factory GridEvent.createRow() = _CreateRow; const factory GridEvent.createRow() = _CreateRow;
const factory GridEvent.didReceiveRowUpdate(List<GridRow> rows, GridListState listState) = _DidReceiveRowUpdate; const factory GridEvent.didReceiveRowUpdate(List<GridRow> rows, GridRowChangeReason listState) = _DidReceiveRowUpdate;
const factory GridEvent.didReceiveFieldUpdate(List<Field> fields) = _DidReceiveFieldUpdate; const factory GridEvent.didReceiveFieldUpdate(List<Field> fields) = _DidReceiveFieldUpdate;
} }
@ -138,7 +109,7 @@ class GridState with _$GridState {
required List<Field> fields, required List<Field> fields,
required List<GridRow> rows, required List<GridRow> rows,
required GridLoadingState loadingState, required GridLoadingState loadingState,
required GridListState listState, required GridRowChangeReason listState,
}) = _GridState; }) = _GridState;
factory GridState.initial(String gridId) => GridState( factory GridState.initial(String gridId) => GridState(

View File

@ -37,7 +37,6 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
Future<void> _startListening() async { Future<void> _startListening() async {
fieldCache.addListener( fieldCache.addListener(
() {},
onChanged: (fields) => add(GridHeaderEvent.didReceiveFieldUpdate(fields)), onChanged: (fields) => add(GridHeaderEvent.didReceiveFieldUpdate(fields)),
listenWhen: () => !isClosed, listenWhen: () => !isClosed,
); );

View File

@ -7,12 +7,12 @@ import 'dart:async';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:app_flowy/core/notification_helper.dart'; import 'package:app_flowy/core/notification_helper.dart';
class GridListener { class GridRowListener {
final String gridId; final String gridId;
PublishNotifier<Either<List<GridRowsChangeset>, FlowyError>> rowsUpdateNotifier = PublishNotifier(comparable: null); PublishNotifier<Either<List<GridRowsChangeset>, FlowyError>> rowsUpdateNotifier = PublishNotifier(comparable: null);
GridNotificationListener? _listener; GridNotificationListener? _listener;
GridListener({required this.gridId}); GridRowListener({required this.gridId});
void start() { void start() {
_listener = GridNotificationListener( _listener = GridNotificationListener(

View File

@ -1,5 +1,7 @@
import 'package:app_flowy/workspace/application/grid/field/grid_listenr.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.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-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.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'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
@ -50,42 +52,56 @@ class FieldsNotifier extends ChangeNotifier {
} }
class GridFieldCache { class GridFieldCache {
final String gridId;
late final GridFieldsListener _fieldListener;
final FieldsNotifier _fieldNotifier = FieldsNotifier(); final FieldsNotifier _fieldNotifier = FieldsNotifier();
GridFieldCache(); GridFieldCache({required this.gridId}) {
_fieldListener = GridFieldsListener(gridId: gridId);
void applyChangeset(GridFieldChangeset changeset) { _fieldListener.updateFieldsNotifier?.addPublishListener((result) {
_removeFields(changeset.deletedFields); result.fold(
_insertFields(changeset.insertedFields); (changeset) {
_updateFields(changeset.updatedFields); _deleteFields(changeset.deletedFields);
_insertFields(changeset.insertedFields);
_updateFields(changeset.updatedFields);
},
(err) => Log.error(err),
);
});
_fieldListener.start();
} }
Future<void> dispose() async {
await _fieldListener.stop();
_fieldNotifier.dispose();
}
void applyChangeset(GridFieldChangeset changeset) {}
UnmodifiableListView<Field> get unmodifiableFields => UnmodifiableListView(_fieldNotifier.fields); UnmodifiableListView<Field> get unmodifiableFields => UnmodifiableListView(_fieldNotifier.fields);
List<Field> get clonedFields => [..._fieldNotifier.fields]; List<Field> get clonedFields => [..._fieldNotifier.fields];
set clonedFields(List<Field> fields) { set fields(List<Field> fields) {
_fieldNotifier.fields = [...fields]; _fieldNotifier.fields = [...fields];
} }
void listenOnFieldChanged(void Function(List<Field>) onFieldChanged) { void addListener({VoidCallback? listener, void Function(List<Field>)? onChanged, bool Function()? listenWhen}) {
_fieldNotifier.addListener(() => onFieldChanged(clonedFields));
}
void addListener(VoidCallback listener, {void Function(List<Field>)? onChanged, bool Function()? listenWhen}) {
_fieldNotifier.addListener(() { _fieldNotifier.addListener(() {
if (onChanged != null) {
onChanged(clonedFields);
}
if (listenWhen != null && listenWhen() == false) { if (listenWhen != null && listenWhen() == false) {
return; return;
} }
listener(); if (onChanged != null) {
onChanged(clonedFields);
}
if (listener != null) {
listener();
}
}); });
} }
void _removeFields(List<FieldOrder> deletedFields) { void _deleteFields(List<FieldOrder> deletedFields) {
if (deletedFields.isEmpty) { if (deletedFields.isEmpty) {
return; return;
} }
@ -127,8 +143,4 @@ class GridFieldCache {
} }
_fieldNotifier.fields = fields; _fieldNotifier.fields = fields;
} }
void dispose() {
_fieldNotifier.dispose();
}
} }

View File

@ -92,7 +92,7 @@ class RowBloc extends Bloc<RowEvent, RowState> {
); );
_fieldCache.addListener( _fieldCache.addListener(
() => add(const RowEvent.fieldsDidUpdate()), listener: () => add(const RowEvent.fieldsDidUpdate()),
listenWhen: () => !isClosed, listenWhen: () => !isClosed,
); );

View File

@ -1,11 +1,13 @@
import 'dart:collection'; import 'dart:collection';
import 'package:app_flowy/workspace/application/grid/grid_listener.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.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-data-model/grid.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.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:freezed_annotation/freezed_annotation.dart';
part 'row_service.freezed.dart'; part 'row_service.freezed.dart';
@ -60,19 +62,71 @@ class RowService {
} }
} }
class RowsNotifier extends ChangeNotifier {
List<GridRow> _rows = [];
GridRowChangeReason _changeReason = const InitialListState();
void updateRows(List<GridRow> rows, GridRowChangeReason changeReason) {
_rows = rows;
_changeReason = changeReason;
changeReason.map(
insert: (_) => notifyListeners(),
delete: (_) => notifyListeners(),
update: (_) => notifyListeners(),
initial: (_) {},
);
}
List<GridRow> get rows => _rows;
}
class GridRowCache { class GridRowCache {
final String gridId; final String gridId;
late GridRowListener _rowsListener;
final HashMap<String, Row> _rowDataMap = HashMap();
UnmodifiableListView<Field> _fields = UnmodifiableListView([]); UnmodifiableListView<Field> _fields = UnmodifiableListView([]);
HashMap<String, Row> rowDataMap = HashMap(); final RowsNotifier _rowNotifier = RowsNotifier();
List<GridRow> _rows = []; GridRowCache({required this.gridId}) {
_rowsListener = GridRowListener(gridId: gridId);
_rowsListener.rowsUpdateNotifier.addPublishListener((result) {
result.fold(
(changesets) {
for (final changeset in changesets) {
_deleteRows(changeset.deletedRows);
_insertRows(changeset.insertedRows);
_updateRows(changeset.updatedRows);
}
},
(err) => Log.error(err),
);
});
_rowsListener.start();
}
GridRowCache({required this.gridId}); List<GridRow> get clonedRows => [..._rowNotifier.rows];
List<GridRow> get rows => [..._rows]; Future<void> dispose() async {
await _rowsListener.stop();
_rowNotifier.dispose();
}
void addListener({void Function(List<GridRow>, GridRowChangeReason)? onChanged, bool Function()? listenWhen}) {
_rowNotifier.addListener(() {
if (listenWhen != null && listenWhen() == false) {
return;
}
if (onChanged != null) {
onChanged(clonedRows, _rowNotifier._changeReason);
}
});
}
Future<Option<Row>> getRowData(String rowId) async { Future<Option<Row>> getRowData(String rowId) async {
final Row? data = rowDataMap[rowId]; final Row? data = _rowDataMap[rowId];
if (data != null) { if (data != null) {
return Future(() => Some(data)); return Future(() => Some(data));
} }
@ -86,7 +140,7 @@ class GridRowCache {
return result.fold( return result.fold(
(data) { (data) {
data.freeze(); data.freeze();
rowDataMap[data.id] = data; _rowDataMap[data.id] = data;
return Some(data); return Some(data);
}, },
(err) { (err) {
@ -99,73 +153,65 @@ class GridRowCache {
void updateWithBlock(List<GridBlockOrder> blocks, UnmodifiableListView<Field> fields) { void updateWithBlock(List<GridBlockOrder> blocks, UnmodifiableListView<Field> fields) {
_fields = fields; _fields = fields;
_rows = blocks.expand((block) => block.rowOrders).map((rowOrder) { final newRows = blocks.expand((block) => block.rowOrders).map((rowOrder) {
return GridRow.fromBlockRow(gridId, rowOrder, _fields); return GridRow.fromBlockRow(gridId, rowOrder, _fields);
}).toList(); }).toList();
_rowNotifier.updateRows(newRows, const GridRowChangeReason.initial());
} }
void updateFields(UnmodifiableListView<Field> fields) { void _deleteRows(List<RowOrder> deletedRows) {
if (fields.isEmpty) {
return;
}
_fields = fields;
_rows = _rows.map((row) => row.copyWith(fields: fields)).toList();
}
Option<GridListState> deleteRows(List<RowOrder> deletedRows) {
if (deletedRows.isEmpty) { if (deletedRows.isEmpty) {
return none(); return;
} }
final List<GridRow> newRows = []; final List<GridRow> newRows = [];
final DeletedIndex deletedIndex = []; final DeletedIndex deletedIndex = [];
final Map<String, RowOrder> deletedRowMap = {for (var rowOrder in deletedRows) rowOrder.rowId: rowOrder}; final Map<String, RowOrder> deletedRowMap = {for (var rowOrder in deletedRows) rowOrder.rowId: rowOrder};
_rows.asMap().forEach((index, value) {
_rowNotifier.rows.asMap().forEach((index, value) {
if (deletedRowMap[value.rowId] == null) { if (deletedRowMap[value.rowId] == null) {
newRows.add(value); newRows.add(value);
} else { } else {
deletedIndex.add(Tuple2(index, value)); deletedIndex.add(Tuple2(index, value));
} }
}); });
_rows = newRows;
return Some(GridListState.delete(deletedIndex)); _rowNotifier.updateRows(newRows, GridRowChangeReason.delete(deletedIndex));
} }
Option<GridListState> insertRows(List<IndexRowOrder> createdRows) { void _insertRows(List<IndexRowOrder> createdRows) {
if (createdRows.isEmpty) { if (createdRows.isEmpty) {
return none(); return;
} }
InsertedIndexs insertIndexs = []; InsertedIndexs insertIndexs = [];
final List<GridRow> newRows = _rowNotifier.rows;
for (final createdRow in createdRows) { for (final createdRow in createdRows) {
final gridRow = GridRow.fromBlockRow(gridId, createdRow.rowOrder, _fields); final gridRow = GridRow.fromBlockRow(gridId, createdRow.rowOrder, _fields);
insertIndexs.add(Tuple2(createdRow.index, gridRow.rowId)); insertIndexs.add(Tuple2(createdRow.index, gridRow.rowId));
_rows.insert(createdRow.index, gridRow); newRows.insert(createdRow.index, gridRow);
} }
_rowNotifier.updateRows(newRows, GridRowChangeReason.insert(insertIndexs));
return Some(GridListState.insert(insertIndexs));
} }
void updateRows(List<RowOrder> updatedRows) { void _updateRows(List<RowOrder> updatedRows) {
if (updatedRows.isEmpty) { if (updatedRows.isEmpty) {
return; return;
} }
final List<int> updatedIndexs = []; final List<int> updatedIndexs = [];
for (final updatedRow in updatedRows) { final List<GridRow> newRows = _rowNotifier.rows;
final index = _rows.indexWhere((row) => row.rowId == updatedRow.rowId); for (final rowOrder in updatedRows) {
final index = newRows.indexWhere((row) => row.rowId == rowOrder.rowId);
if (index != -1) { if (index != -1) {
_rows.removeAt(index); newRows.removeAt(index);
_rows.insert(index, _toRowData(updatedRow)); newRows.insert(index, GridRow.fromBlockRow(gridId, rowOrder, _fields));
updatedIndexs.add(index); updatedIndexs.add(index);
} }
} }
}
GridRow _toRowData(RowOrder rowOrder) { _rowNotifier.updateRows(newRows, GridRowChangeReason.update(updatedIndexs));
return GridRow.fromBlockRow(gridId, rowOrder, _fields);
} }
} }
@ -204,8 +250,9 @@ typedef InsertedIndexs = List<Tuple2<int, String>>;
typedef DeletedIndex = List<Tuple2<int, GridRow>>; typedef DeletedIndex = List<Tuple2<int, GridRow>>;
@freezed @freezed
class GridListState with _$GridListState { class GridRowChangeReason with _$GridRowChangeReason {
const factory GridListState.insert(InsertedIndexs items) = _Insert; const factory GridRowChangeReason.insert(InsertedIndexs items) = _Insert;
const factory GridListState.delete(DeletedIndex items) = _Delete; const factory GridRowChangeReason.delete(DeletedIndex items) = _Delete;
const factory GridListState.initial() = InitialListState; const factory GridRowChangeReason.update(List<int> indexs) = _Update;
const factory GridRowChangeReason.initial() = InitialListState;
} }

View File

@ -1,5 +1,4 @@
import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
import 'package:app_flowy/workspace/application/grid/field/grid_listenr.dart';
import 'package:app_flowy/workspace/application/grid/grid_service.dart'; import 'package:app_flowy/workspace/application/grid/grid_service.dart';
import 'package:flowy_sdk/log.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-data-model/grid.pb.dart';
@ -11,13 +10,11 @@ part 'property_bloc.freezed.dart';
class GridPropertyBloc extends Bloc<GridPropertyEvent, GridPropertyState> { class GridPropertyBloc extends Bloc<GridPropertyEvent, GridPropertyState> {
final FieldService _service; final FieldService _service;
final GridFieldsListener _fieldListener;
final GridFieldCache _fieldCache; final GridFieldCache _fieldCache;
GridPropertyBloc({required String gridId, required List<Field> fields}) GridPropertyBloc({required String gridId, required List<Field> fields})
: _service = FieldService(gridId: gridId), : _service = FieldService(gridId: gridId),
_fieldListener = GridFieldsListener(gridId: gridId), _fieldCache = GridFieldCache(gridId: gridId),
_fieldCache = GridFieldCache(),
super(GridPropertyState.initial(gridId, fields)) { super(GridPropertyState.initial(gridId, fields)) {
on<GridPropertyEvent>( on<GridPropertyEvent>(
(event, emit) async { (event, emit) async {
@ -45,22 +42,15 @@ class GridPropertyBloc extends Bloc<GridPropertyEvent, GridPropertyState> {
@override @override
Future<void> close() async { Future<void> close() async {
await _fieldListener.stop(); await _fieldCache.dispose();
_fieldCache.dispose();
return super.close(); return super.close();
} }
void _startListening() { void _startListening() {
_fieldListener.updateFieldsNotifier?.addPublishListener((result) { _fieldCache.addListener(
result.fold( onChanged: (fields) => add(GridPropertyEvent.didReceiveFieldUpdate(_fieldCache.clonedFields)),
(changeset) { listenWhen: () => !isClosed,
_fieldCache.applyChangeset(changeset); );
add(GridPropertyEvent.didReceiveFieldUpdate(_fieldCache.clonedFields));
},
(err) => Log.error(err),
);
});
_fieldListener.start();
} }
} }

View File

@ -205,7 +205,8 @@ class _GridRowsState extends State<_GridRows> {
); );
} }
}, },
initial: (updatedIndexs) {}, initial: (_) {},
update: (_) {},
); );
}, },
buildWhen: (previous, current) => false, buildWhen: (previous, current) => false,

View File

@ -5,7 +5,6 @@ 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/button.dart'; import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -1,4 +1,3 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart';

View File

@ -215,7 +215,7 @@ impl GridMetaPad {
|grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) { |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) {
None => Ok(None), None => Ok(None),
Some(index) => { Some(index) => {
debug_assert_eq!(index, from_index); // debug_assert_eq!(index, from_index);
let field_meta = grid_meta.fields.remove(index); let field_meta = grid_meta.fields.remove(index);
grid_meta.fields.insert(to_index, field_meta); grid_meta.fields.insert(to_index, field_meta);
Ok(Some(())) Ok(Some(()))