kopia lustrzana https://gitlab.com/mysocialportal/relatica
141 wiersze
3.8 KiB
Dart
141 wiersze
3.8 KiB
Dart
import 'package:relatica/utils/html_to_edit_text_helper.dart';
|
|
|
|
import '../models/filters/string_filter.dart';
|
|
import '../models/filters/timeline_entry_filter.dart';
|
|
import '../models/timeline_entry.dart';
|
|
|
|
class FilterResult {
|
|
static const show = FilterResult(
|
|
false,
|
|
TimelineEntryFilterAction.warn,
|
|
'',
|
|
);
|
|
final TimelineEntryFilterAction action;
|
|
final bool isFiltered;
|
|
final String trippingFilterName;
|
|
|
|
const FilterResult(
|
|
this.isFiltered,
|
|
this.action,
|
|
this.trippingFilterName,
|
|
);
|
|
|
|
String toActionString() {
|
|
return isFiltered ? action.name : 'show';
|
|
}
|
|
|
|
@override
|
|
bool operator ==(Object other) =>
|
|
identical(this, other) ||
|
|
other is FilterResult &&
|
|
runtimeType == other.runtimeType &&
|
|
action == other.action &&
|
|
isFiltered == other.isFiltered &&
|
|
trippingFilterName == other.trippingFilterName;
|
|
|
|
@override
|
|
int get hashCode =>
|
|
action.hashCode ^ isFiltered.hashCode ^ trippingFilterName.hashCode;
|
|
}
|
|
|
|
FilterResult runFilters(
|
|
TimelineEntry entry,
|
|
List<TimelineEntryFilter> filters,
|
|
) {
|
|
var isFiltered = false;
|
|
var action = TimelineEntryFilterAction.warn;
|
|
var trippingFilterName = '';
|
|
for (final filter in filters.where((f) => f.enabled)) {
|
|
if (filter.isFiltered(entry)) {
|
|
isFiltered = true;
|
|
if (trippingFilterName.isEmpty) {
|
|
trippingFilterName = filter.name;
|
|
}
|
|
|
|
if (filter.action == TimelineEntryFilterAction.hide) {
|
|
action = TimelineEntryFilterAction.hide;
|
|
trippingFilterName = filter.name;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FilterResult(isFiltered, action, trippingFilterName);
|
|
}
|
|
|
|
extension StringFilterOps on StringFilter {
|
|
bool isFiltered(String value) {
|
|
switch (type) {
|
|
case ComparisonType.contains:
|
|
return value.contains(filterString);
|
|
case ComparisonType.containsIgnoreCase:
|
|
final lv = value.toLowerCase();
|
|
final lf = filterString.toLowerCase();
|
|
final c = lv.contains(lf);
|
|
return c;
|
|
case ComparisonType.equals:
|
|
return value == filterString;
|
|
case ComparisonType.equalsIgnoreCase:
|
|
return value.toLowerCase() == filterString.toLowerCase();
|
|
case ComparisonType.endsWithIgnoreCase:
|
|
return value.toLowerCase().endsWith(filterString.toLowerCase());
|
|
}
|
|
}
|
|
}
|
|
|
|
extension TimelineEntryFilterOps on TimelineEntryFilter {
|
|
bool isFiltered(TimelineEntry entry) {
|
|
if (authorFilters.isEmpty &&
|
|
domainFilters.isEmpty &&
|
|
hashtagFilters.isEmpty &&
|
|
keywordFilters.isEmpty) {
|
|
return false;
|
|
}
|
|
|
|
var authorFiltered = authorFilters.isEmpty ? true : false;
|
|
for (final filter in authorFilters) {
|
|
if (filter.isFiltered(entry.authorId) ||
|
|
filter.isFiltered(entry.parentAuthorId)) {
|
|
authorFiltered = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
var hashtagFiltered = hashtagFilters.isEmpty ? true : false;
|
|
for (final filter in hashtagFilters) {
|
|
for (final tag in entry.tags) {
|
|
if (filter.isFiltered(tag)) {
|
|
hashtagFiltered = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
var domainFiltered = domainFilters.isEmpty ? true : false;
|
|
for (final filter in domainFilters) {
|
|
final domain =
|
|
Uri.tryParse(entry.externalLink)?.host ?? entry.externalLink;
|
|
if (filter.isFiltered(domain)) {
|
|
domainFiltered = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
var contentFiltered = keywordFilters.isEmpty ? true : false;
|
|
final simplifiedBody = keywordFilters.isNotEmpty
|
|
? htmlToSimpleText(entry.body).toLowerCase()
|
|
: '';
|
|
for (final filter in keywordFilters) {
|
|
if (filter.isFiltered(simplifiedBody)) {
|
|
contentFiltered = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return authorFiltered &&
|
|
domainFiltered &&
|
|
hashtagFiltered &&
|
|
contentFiltered;
|
|
}
|
|
}
|