FilterConditionsBloc<T extends ItemSourceState<ItemClassWithAccessor> > constructor
FilterConditionsBloc<T extends ItemSourceState<ItemClassWithAccessor> > ({})
Attaches to the provided _sourceBloc
in order to dynamically generate
groupings of available conditions that correspond to the
provided _filterProperties
.
Additionally exposes events to add or remove active conditions from the state.
There should be no need to ever manually construct a FilterConditionsBloc.
It should, instead, be retrieved from within the ListManager
in order to construct whatever filtering UI you desire.
Implementation
FilterConditionsBloc({
required List<String> filterProperties,
required Bloc sourceBloc,
}) : _filterProperties = filterProperties,
_sourceBloc = sourceBloc,
super(const ConditionsUninitialized()) {
_sourceSubscription = _sourceBloc.stream.listen((sourceState) {
if (sourceState is! T) {
return;
}
final modifiedFilterConditions = Set.from(_filterProperties);
final booleanProperties = <String>{};
final availableConditions = _generateFilterPropertiesMap();
final availableConditionKeys = <String>{};
for (final item in sourceState.items) {
for (final property in modifiedFilterConditions) {
final value = item[property];
if (value is bool) {
booleanProperties.add(property);
availableConditions[property]!.add('True');
availableConditions[property]!.add('False');
availableConditionKeys.add(generateConditionKey(property, 'True'));
availableConditionKeys.add(generateConditionKey(property, 'False'));
}
if (value is String && value.isNotEmpty) {
final conditionKey = generateConditionKey(property, value);
availableConditions[property]!.add(value);
availableConditionKeys.add(conditionKey);
}
}
// We don't want to repeatedly loop through boolean properties that
// have already been parsed. Nor do we want to sort them (below).
if (booleanProperties.isNotEmpty) {
modifiedFilterConditions.removeWhere(booleanProperties.contains);
booleanProperties.clear();
}
}
final currentState = state;
final activeAndConditions = currentState is ConditionsInitialized
? currentState.activeAndConditions
: <String>{};
final activeOrConditions = currentState is ConditionsInitialized
? currentState.activeOrConditions
: <String>{};
for (final property in modifiedFilterConditions) {
// Ensure only unique entries are present and that entries are sorted.
// Removing duplicates before sorting will save a few cycles.
availableConditions[property] =
availableConditions[property]!.toSet().toList()..sort();
}
_conditionKeyTracker
.removeWhere((key, _) => !availableConditionKeys.contains(key));
add(RefreshConditions(
activeAndConditions:
activeAndConditions.intersection(availableConditionKeys),
activeOrConditions:
activeOrConditions.intersection(availableConditionKeys),
availableConditions: availableConditions,
));
});
on<RefreshConditions>((event, emit) => emit(ConditionsInitialized(
activeAndConditions: event.activeAndConditions,
activeOrConditions: event.activeOrConditions,
availableConditions: event.availableConditions,
)));
on<AddCondition>(
(event, emit) => emit(_addConditionToActiveConditions(event)));
on<RemoveCondition>(
(event, emit) => emit(_removeConditionFromActiveConditions(event)));
}