import 'package:nc_photos/account.dart'; import 'package:nc_photos/ci_string.dart'; import 'package:nc_photos/entity/file.dart'; import 'package:nc_photos/entity/sqlite_table_extension.dart' as sql; import 'package:nc_photos/iterable_extension.dart'; class SearchCriteria { const SearchCriteria(this.keywords, this.filters); SearchCriteria copyWith({ Set? keywords, List? filters, }) => SearchCriteria( keywords ?? Set.of(this.keywords), filters ?? List.of(this.filters), ); @override toString() => "$runtimeType {" "keywords: ${keywords.toReadableString()}, " "filters: ${filters.toReadableString()}, " "}"; final Set keywords; final List filters; } abstract class SearchFilter { void apply(sql.FilesQueryBuilder query); } enum SearchFileType { image, video, } extension on SearchFileType { String toSqlPattern() { switch (this) { case SearchFileType.image: return "image/%"; case SearchFileType.video: return "video/%"; } } } class SearchFileTypeFilter implements SearchFilter { const SearchFileTypeFilter(this.type); @override apply(sql.FilesQueryBuilder query) { query.byMimePattern(type.toSqlPattern()); } @override toString() => "$runtimeType {" "type: ${type.name}, " "}"; final SearchFileType type; } class SearchFavoriteFilter implements SearchFilter { const SearchFavoriteFilter(this.value); @override apply(sql.FilesQueryBuilder query) { query.byFavorite(value); } @override toString() => "$runtimeType {" "value: $value, " "}"; final bool value; } class SearchRepo { const SearchRepo(this.dataSrc); Future> list(Account account, SearchCriteria criteria) => dataSrc.list(account, criteria); final SearchDataSource dataSrc; } abstract class SearchDataSource { /// List all results from a given search criteria Future> list(Account account, SearchCriteria criteria); }