chore: add fitler bloc test

This commit is contained in:
nathan
2022-11-15 23:17:01 +08:00
parent f1ac38dd59
commit 0ee27097ce
31 changed files with 578 additions and 92 deletions

View File

@ -39,7 +39,7 @@ class GroupController {
void startListening() {
_listener.start(onGroupChanged: (result) {
result.fold(
(GroupChangesetPB changeset) {
(GroupRowsNotificationPB changeset) {
for (final deletedRow in changeset.deletedRows) {
group.rows.removeWhere((rowPB) => rowPB.id == deletedRow);
delegate.removeRow(group, deletedRow);

View File

@ -8,7 +8,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/group_changeset.pb.dart';
typedef UpdateGroupNotifiedValue = Either<GroupChangesetPB, FlowyError>;
typedef UpdateGroupNotifiedValue = Either<GroupRowsNotificationPB, FlowyError>;
class GroupListener {
final GroupPB group;
@ -34,7 +34,7 @@ class GroupListener {
case GridNotification.DidUpdateGroup:
result.fold(
(payload) => _groupNotifier?.value =
left(GroupChangesetPB.fromBuffer(payload)),
left(GroupRowsNotificationPB.fromBuffer(payload)),
(error) => _groupNotifier?.value = right(error),
);
break;

View File

@ -0,0 +1,206 @@
import 'package:app_flowy/plugins/grid/application/filter/filter_listener.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_filter.pbenum.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_filter.pbenum.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/number_filter.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pbserver.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/util.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
import 'filter_service.dart';
part 'filter_bloc.freezed.dart';
class GridFilterBloc extends Bloc<GridFilterEvent, GridFilterState> {
final String viewId;
final FilterFFIService _ffiService;
final FilterListener _listener;
GridFilterBloc({required this.viewId})
: _ffiService = FilterFFIService(viewId: viewId),
_listener = FilterListener(viewId: viewId),
super(GridFilterState.initial()) {
on<GridFilterEvent>(
(event, emit) async {
event.when(
initial: () async {
_startListening();
await _loadFilters();
},
deleteFilter: (
String fieldId,
String filterId,
FieldType fieldType,
) {
_ffiService.deleteFilter(
fieldId: fieldId,
filterId: filterId,
fieldType: fieldType,
);
},
didReceiveFilters: (filters) {
emit(state.copyWith(filters: filters));
},
createCheckboxFilter: (
String fieldId,
CheckboxFilterCondition condition,
) {
_ffiService.createCheckboxFilter(
fieldId: fieldId,
condition: condition,
);
},
createNumberFilter: (
String fieldId,
NumberFilterCondition condition,
String content,
) {
_ffiService.createNumberFilter(
fieldId: fieldId,
condition: condition,
content: content,
);
},
createTextFilter: (
String fieldId,
TextFilterCondition condition,
String content,
) {
_ffiService.createTextFilter(
fieldId: fieldId,
condition: condition,
);
},
createDateFilter: (
String fieldId,
DateFilterCondition condition,
int timestamp,
) {
_ffiService.createDateFilter(
fieldId: fieldId,
condition: condition,
timestamp: timestamp,
);
},
createDateFilterInRange: (
String fieldId,
DateFilterCondition condition,
int start,
int end,
) {
_ffiService.createDateFilter(
fieldId: fieldId,
condition: condition,
start: start,
end: end,
);
},
);
},
);
}
void _startListening() {
_listener.start(onFilterChanged: (result) {
result.fold(
(changeset) {
final List<FilterPB> filters = List.from(state.filters);
// Deletes the filters
final deleteFilterIds =
changeset.deleteFilters.map((e) => e.id).toList();
filters.retainWhere(
(element) => !deleteFilterIds.contains(element.id),
);
// Inserts the new fitler if it's not exist
for (final newFilter in changeset.insertFilters) {
final index =
filters.indexWhere((element) => element.id == newFilter.id);
if (index == -1) {
filters.add(newFilter);
}
}
if (!isClosed) {
add(GridFilterEvent.didReceiveFilters(filters));
}
},
(err) => Log.error(err),
);
});
}
Future<void> _loadFilters() async {
final result = await _ffiService.getAllFilters();
result.fold(
(filters) {
if (!isClosed) {
add(GridFilterEvent.didReceiveFilters(filters));
}
},
(err) => Log.error(err),
);
}
@override
Future<void> close() async {
await _listener.stop();
return super.close();
}
}
@freezed
class GridFilterEvent with _$GridFilterEvent {
const factory GridFilterEvent.initial() = _Initial;
const factory GridFilterEvent.didReceiveFilters(List<FilterPB> filters) =
_DidReceiveFilters;
const factory GridFilterEvent.deleteFilter({
required String fieldId,
required String filterId,
required FieldType fieldType,
}) = _DeleteFilter;
const factory GridFilterEvent.createTextFilter({
required String fieldId,
required TextFilterCondition condition,
required String content,
}) = _CreateTextFilter;
const factory GridFilterEvent.createCheckboxFilter({
required String fieldId,
required CheckboxFilterCondition condition,
}) = _CreateCheckboxFilter;
const factory GridFilterEvent.createNumberFilter({
required String fieldId,
required NumberFilterCondition condition,
required String content,
}) = _CreateCheckboxFitler;
const factory GridFilterEvent.createDateFilter({
required String fieldId,
required DateFilterCondition condition,
required int start,
}) = _CreateDateFitler;
const factory GridFilterEvent.createDateFilterInRange({
required String fieldId,
required DateFilterCondition condition,
required int start,
required int end,
}) = _CreateDateFitlerInRange;
}
@freezed
class GridFilterState with _$GridFilterState {
const factory GridFilterState({
required List<FilterPB> filters,
}) = _GridFilterState;
factory GridFilterState.initial() => const GridFilterState(
filters: [],
);
}

View File

@ -0,0 +1,53 @@
import 'dart:typed_data';
import 'package:app_flowy/core/grid_notification.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/filter_changeset.pb.dart';
import 'package:dartz/dartz.dart';
typedef UpdateFilterNotifiedValue
= Either<FilterChangesetNotificationPB, FlowyError>;
class FilterListener {
final String viewId;
PublishNotifier<UpdateFilterNotifiedValue>? _filterNotifier =
PublishNotifier();
GridNotificationListener? _listener;
FilterListener({required this.viewId});
void start({
required void Function(UpdateFilterNotifiedValue) onFilterChanged,
}) {
_filterNotifier?.addPublishListener(onFilterChanged);
_listener = GridNotificationListener(
objectId: viewId,
handler: _handler,
);
}
void _handler(
GridNotification ty,
Either<Uint8List, FlowyError> result,
) {
switch (ty) {
case GridNotification.DidUpdateFilter:
result.fold(
(payload) => _filterNotifier?.value =
left(FilterChangesetNotificationPB.fromBuffer(payload)),
(error) => _filterNotifier?.value = right(error),
);
break;
default:
break;
}
}
Future<void> stop() async {
await _listener?.stop();
_filterNotifier?.dispose();
_filterNotifier = null;
}
}

View File

@ -1,9 +1,11 @@
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/checkbox_filter.pbserver.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_filter.pbserver.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/number_filter.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/select_option_filter.pbserver.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart';
@ -15,6 +17,17 @@ class FilterFFIService {
final String viewId;
const FilterFFIService({required this.viewId});
Future<Either<List<FilterPB>, FlowyError>> getAllFilters() {
final payload = GridIdPB()..value = viewId;
return GridEventGetAllFilters(payload).send().then((result) {
return result.fold(
(repeated) => left(repeated.items),
(r) => right(r),
);
});
}
Future<Either<Unit, FlowyError>> createTextFilter({
required String fieldId,
required TextFilterCondition condition,
@ -150,6 +163,40 @@ class FilterFFIService {
final payload = GridSettingChangesetPB.create()
..gridId = viewId
..insertFilter = insertFilterPayload;
return GridEventUpdateGridSetting(payload).send();
return GridEventUpdateGridSetting(payload).send().then((result) {
return result.fold(
(l) => left(l),
(err) {
Log.error(err);
return right(err);
},
);
});
}
Future<Either<Unit, FlowyError>> deleteFilter({
required String fieldId,
required String filterId,
required FieldType fieldType,
}) {
TextFilterCondition.DoesNotContain.value;
final deleteFilterPayload = DeleteFilterPayloadPB.create()
..fieldId = fieldId
..filterId = filterId
..fieldType = fieldType;
final payload = GridSettingChangesetPB.create()
..gridId = viewId
..deleteFilter = deleteFilterPayload;
return GridEventUpdateGridSetting(payload).send().then((result) {
return result.fold(
(l) => left(l),
(err) {
Log.error(err);
return right(err);
},
);
});
}
}