chore: fix some bugs

This commit is contained in:
appflowy 2022-04-14 18:11:28 +08:00
parent fd9e13bf4b
commit b606c5ba7b
13 changed files with 72 additions and 81 deletions

View File

@ -157,9 +157,10 @@ void _resolveGridDeps(GetIt getIt) {
), ),
); );
getIt.registerFactoryParam<GridHeaderBloc, String, List<Field>>( getIt.registerFactoryParam<GridHeaderBloc, String, GridFieldCache>(
(gridId, fields) => GridHeaderBloc( (gridId, fieldCache) => GridHeaderBloc(
data: GridHeaderData(gridId: gridId, fields: fields), gridId: gridId,
fieldCache: fieldCache,
), ),
); );

View File

@ -113,7 +113,7 @@ class ApplicationBlocObserver extends BlocObserver {
// ignore: unnecessary_overrides // ignore: unnecessary_overrides
void onTransition(Bloc bloc, Transition transition) { void onTransition(Bloc bloc, Transition transition) {
// Log.debug("[current]: ${transition.currentState} \n\n[next]: ${transition.nextState}"); // Log.debug("[current]: ${transition.currentState} \n\n[next]: ${transition.nextState}");
// Log.debug("${transition.nextState}"); Log.debug("${transition.nextState}");
super.onTransition(bloc, transition); super.onTransition(bloc, transition);
} }
@ -123,9 +123,9 @@ class ApplicationBlocObserver extends BlocObserver {
super.onError(bloc, error, stackTrace); super.onError(bloc, error, stackTrace);
} }
// @override @override
// void onEvent(Bloc bloc, Object? event) { void onEvent(Bloc bloc, Object? event) {
// Log.debug("$event"); // Log.debug("$event");
// super.onEvent(bloc, event); super.onEvent(bloc, event);
// } }
} }

View File

@ -62,7 +62,11 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
_fieldListener.updateFieldNotifier.addPublishListener((result) { _fieldListener.updateFieldNotifier.addPublishListener((result) {
result.fold( result.fold(
(field) => add(DateCellEvent.didReceiveFieldUpdate(field)), (field) {
if (!isClosed) {
add(DateCellEvent.didReceiveFieldUpdate(field));
}
},
(err) => Log.error(err), (err) => Log.error(err),
); );
}); });

View File

@ -144,7 +144,11 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
_fieldListener.updateFieldNotifier.addPublishListener((result) { _fieldListener.updateFieldNotifier.addPublishListener((result) {
result.fold( result.fold(
(field) => add(SelectOptionEditorEvent.didReceiveFieldUpdate(field)), (field) {
if (!isClosed) {
add(SelectOptionEditorEvent.didReceiveFieldUpdate(field));
}
},
(err) => Log.error(err), (err) => Log.error(err),
); );
}); });

View File

@ -1,8 +0,0 @@
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
class GridHeaderData {
final String gridId;
final List<Field> fields;
GridHeaderData({required this.gridId, required this.fields});
}

View File

@ -47,7 +47,11 @@ class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
void _startListening() { void _startListening() {
_fieldListener.updateFieldNotifier.addPublishListener((result) { _fieldListener.updateFieldNotifier.addPublishListener((result) {
result.fold( result.fold(
(field) => add(FieldCellEvent.didReceiveFieldUpdate(field)), (field) {
if (!isClosed) {
add(FieldCellEvent.didReceiveFieldUpdate(field));
}
},
(err) => Log.error(err), (err) => Log.error(err),
); );
}); });

View File

@ -41,10 +41,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( emit(state.copyWith(rows: _rowCache.rows, fields: value.fields));
rows: _rowCache.rows,
fields: value.fields,
));
}, },
); );
}, },
@ -56,19 +53,17 @@ class GridBloc extends Bloc<GridEvent, GridState> {
await _gridService.closeGrid(); await _gridService.closeGrid();
await _fieldListener.stop(); await _fieldListener.stop();
await _gridListener.stop(); await _gridListener.stop();
fieldCache.dispose();
return super.close(); return super.close();
} }
void _startListening() { void _startListening() {
fieldCache.addListener((fields) {
_rowCache.updateFields(fields);
});
_fieldListener.updateFieldsNotifier.addPublishListener((result) { _fieldListener.updateFieldsNotifier.addPublishListener((result) {
result.fold( result.fold(
(changeset) { (changeset) {
fieldCache.applyChangeset(changeset); fieldCache.applyChangeset(changeset);
add(GridEvent.didReceiveFieldUpdate(List.from(fieldCache.fields))); _rowCache.updateFields(fieldCache.unmodifiableFields);
add(GridEvent.didReceiveFieldUpdate(fieldCache.clonedFields));
}, },
(err) => Log.error(err), (err) => Log.error(err),
); );
@ -111,12 +106,12 @@ class GridBloc extends Bloc<GridEvent, GridState> {
return Future( return Future(
() => result.fold( () => result.fold(
(fields) { (fields) {
fieldCache.fields = fields.items; fieldCache.clonedFields = fields.items;
_rowCache.updateWithBlock(grid.blockOrders); _rowCache.updateWithBlock(grid.blockOrders, fieldCache.unmodifiableFields);
emit(state.copyWith( emit(state.copyWith(
grid: Some(grid), grid: Some(grid),
fields: fieldCache.fields, fields: fieldCache.clonedFields,
rows: _rowCache.rows, rows: _rowCache.rows,
loadingState: GridLoadingState.finish(left(unit)), loadingState: GridLoadingState.finish(left(unit)),
)); ));

View File

@ -1,6 +1,3 @@
import 'package:app_flowy/workspace/application/grid/data.dart';
import 'package:app_flowy/workspace/application/grid/field/grid_listenr.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';
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';
@ -12,17 +9,13 @@ part 'grid_header_bloc.freezed.dart';
class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> { class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
final FieldService _fieldService; final FieldService _fieldService;
final GridFieldCache _fieldCache; final GridFieldCache fieldCache;
final GridFieldsListener _fieldListener;
GridHeaderBloc({ GridHeaderBloc({
required GridHeaderData data, required String gridId,
}) : _fieldListener = GridFieldsListener(gridId: data.gridId), required this.fieldCache,
_fieldService = FieldService(gridId: data.gridId), }) : _fieldService = FieldService(gridId: gridId),
_fieldCache = GridFieldCache(), super(GridHeaderState.initial(fieldCache.clonedFields)) {
super(GridHeaderState.initial(data.fields)) {
_fieldCache.fields = data.fields;
on<GridHeaderEvent>( on<GridHeaderEvent>(
(event, emit) async { (event, emit) async {
await event.map( await event.map(
@ -30,7 +23,6 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
_startListening(); _startListening();
}, },
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
value.fields.retainWhere((field) => field.visibility);
emit(state.copyWith(fields: value.fields)); emit(state.copyWith(fields: value.fields));
}, },
); );
@ -39,22 +31,15 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
} }
Future<void> _startListening() async { Future<void> _startListening() async {
_fieldListener.updateFieldsNotifier.addPublishListener((result) { fieldCache.listenOnFieldChanged((fields) {
result.fold( if (!isClosed) {
(changeset) { add(GridHeaderEvent.didReceiveFieldUpdate(fields));
_fieldCache.applyChangeset(changeset); }
add(GridHeaderEvent.didReceiveFieldUpdate(List.from(_fieldCache.fields)));
},
(err) => Log.error(err),
);
}); });
_fieldListener.start();
} }
@override @override
Future<void> close() async { Future<void> close() async {
await _fieldListener.stop();
return super.close(); return super.close();
} }
} }
@ -70,7 +55,8 @@ class GridHeaderState with _$GridHeaderState {
const factory GridHeaderState({required List<Field> fields}) = _GridHeaderState; const factory GridHeaderState({required List<Field> fields}) = _GridHeaderState;
factory GridHeaderState.initial(List<Field> fields) { factory GridHeaderState.initial(List<Field> fields) {
fields.retainWhere((field) => field.visibility); // final List<Field> newFields = List.from(fields);
// newFields.retainWhere((field) => field.visibility);
return GridHeaderState(fields: fields); return GridHeaderState(fields: fields);
} }
} }

View File

@ -62,25 +62,23 @@ class GridFieldCache {
_updateFields(changeset.updatedFields); _updateFields(changeset.updatedFields);
} }
List<Field> get fields => _fieldNotifier.fields; UnmodifiableListView<Field> get unmodifiableFields => UnmodifiableListView(_fieldNotifier.fields);
set fields(List<Field> fields) { List<Field> get clonedFields => [..._fieldNotifier.fields];
_fieldNotifier.fields = fields;
set clonedFields(List<Field> fields) {
_fieldNotifier.fields = [...fields];
} }
set onFieldChanged(void Function(List<Field>) onChanged) { void listenOnFieldChanged(void Function(List<Field>) onFieldChanged) {
_fieldNotifier.addListener(() => onChanged(fields)); _fieldNotifier.addListener(() => onFieldChanged(clonedFields));
}
void addListener(void Function(List<Field>) onFieldChanged) {
_fieldNotifier.addListener(() => onFieldChanged(fields));
} }
void _removeFields(List<FieldOrder> deletedFields) { void _removeFields(List<FieldOrder> deletedFields) {
if (deletedFields.isEmpty) { if (deletedFields.isEmpty) {
return; return;
} }
final List<Field> fields = List.from(_fieldNotifier.fields); final List<Field> fields = _fieldNotifier.fields;
final Map<String, FieldOrder> deletedFieldMap = { final Map<String, FieldOrder> deletedFieldMap = {
for (var fieldOrder in deletedFields) fieldOrder.fieldId: fieldOrder for (var fieldOrder in deletedFields) fieldOrder.fieldId: fieldOrder
}; };
@ -93,7 +91,7 @@ class GridFieldCache {
if (insertedFields.isEmpty) { if (insertedFields.isEmpty) {
return; return;
} }
final List<Field> fields = List.from(_fieldNotifier.fields); final List<Field> fields = _fieldNotifier.fields;
for (final indexField in insertedFields) { for (final indexField in insertedFields) {
if (fields.length > indexField.index) { if (fields.length > indexField.index) {
fields.removeAt(indexField.index); fields.removeAt(indexField.index);
@ -109,7 +107,7 @@ class GridFieldCache {
if (updatedFields.isEmpty) { if (updatedFields.isEmpty) {
return; return;
} }
final List<Field> fields = List.from(_fieldNotifier.fields); final List<Field> fields = _fieldNotifier.fields;
for (final updatedField in updatedFields) { for (final updatedField in updatedFields) {
final index = fields.indexWhere((field) => field.id == updatedField.id); final index = fields.indexWhere((field) => field.id == updatedField.id);
if (index != -1) { if (index != -1) {
@ -119,24 +117,29 @@ class GridFieldCache {
} }
_fieldNotifier.fields = fields; _fieldNotifier.fields = fields;
} }
void dispose() {
_fieldNotifier.dispose();
}
} }
class GridRowCache { class GridRowCache {
final String gridId; final String gridId;
List<Field> _fields = []; UnmodifiableListView<Field> _fields = UnmodifiableListView([]);
List<RowData> _rows = []; List<RowData> _rows = [];
GridRowCache({required this.gridId}); GridRowCache({required this.gridId});
List<RowData> get rows => _rows; List<RowData> get rows => _rows;
void updateWithBlock(List<GridBlockOrder> blocks) { void updateWithBlock(List<GridBlockOrder> blocks, UnmodifiableListView<Field> fields) {
_fields = fields;
_rows = blocks.expand((block) => block.rowOrders).map((rowOrder) { _rows = blocks.expand((block) => block.rowOrders).map((rowOrder) {
return RowData.fromBlockRow(gridId, rowOrder, _fields); return RowData.fromBlockRow(gridId, rowOrder, _fields);
}).toList(); }).toList();
} }
void updateFields(List<Field> fields) { void updateFields(UnmodifiableListView<Field> fields) {
if (fields.isEmpty) { if (fields.isEmpty) {
return; return;
} }

View File

@ -2,7 +2,6 @@ export 'grid_bloc.dart';
export 'row/row_bloc.dart'; export 'row/row_bloc.dart';
export 'row/row_service.dart'; export 'row/row_service.dart';
export 'grid_service.dart'; export 'grid_service.dart';
export 'data.dart';
export 'grid_header_bloc.dart'; export 'grid_header_bloc.dart';
// Field // Field

View File

@ -80,9 +80,9 @@ class RowBloc extends Bloc<RowEvent, RowState> {
); );
}); });
_fieldCache.addListener((fields) { _fieldCache.listenOnFieldChanged((fields) {
if (!isClosed) { if (!isClosed) {
add(RowEvent.didReceiveFieldUpdate(fields)); // add(RowEvent.didReceiveFieldUpdate(fields));
} }
}); });

View File

@ -77,7 +77,7 @@ class FlowyGrid extends StatelessWidget {
final child = _wrapScrollView( final child = _wrapScrollView(
state.fields, state.fields,
[ [
_GridHeader(gridId: state.gridId, fields: List.from(state.fields)), _GridHeader(gridId: state.gridId, fields: state.fields),
_GridRows(), _GridRows(),
const _GridFooter(), const _GridFooter(),
], ],
@ -150,7 +150,8 @@ class _GridHeader extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GridHeaderSliverAdaptor(gridId: gridId, fields: fields); final fieldCache = context.read<GridBloc>().fieldCache;
return GridHeaderSliverAdaptor(gridId: gridId, fieldCache: fieldCache);
} }
} }

View File

@ -14,18 +14,19 @@ import 'field_cell.dart';
class GridHeaderSliverAdaptor extends StatelessWidget { class GridHeaderSliverAdaptor extends StatelessWidget {
final String gridId; final String gridId;
final List<Field> fields; final GridFieldCache fieldCache;
const GridHeaderSliverAdaptor({required this.gridId, required this.fields, Key? key}) : super(key: key); const GridHeaderSliverAdaptor({required this.gridId, required this.fieldCache, Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => getIt<GridHeaderBloc>(param1: gridId, param2: fields)..add(const GridHeaderEvent.initial()), create: (context) =>
getIt<GridHeaderBloc>(param1: gridId, param2: fieldCache)..add(const GridHeaderEvent.initial()),
child: BlocBuilder<GridHeaderBloc, GridHeaderState>( child: BlocBuilder<GridHeaderBloc, GridHeaderState>(
builder: (context, state) { builder: (context, state) {
return SliverPersistentHeader( return SliverPersistentHeader(
delegate: SliverHeaderDelegateImplementation(gridId: gridId, fields: fields), delegate: SliverHeaderDelegateImplementation(gridId: gridId, fields: state.fields),
floating: true, floating: true,
pinned: true, pinned: true,
); );
@ -77,6 +78,7 @@ class _GridHeader extends StatelessWidget {
return BlocBuilder<GridHeaderBloc, GridHeaderState>( return BlocBuilder<GridHeaderBloc, GridHeaderState>(
builder: (context, state) { builder: (context, state) {
final cells = state.fields final cells = state.fields
.where((field) => field.visibility)
.map((field) => GridFieldCellContext(gridId: gridId, field: field)) .map((field) => GridFieldCellContext(gridId: gridId, field: field))
.map((ctx) => GridFieldCell(ctx, key: ValueKey(ctx.field.id))) .map((ctx) => GridFieldCell(ctx, key: ValueKey(ctx.field.id)))
.toList(); .toList();