feat: search filter feature

This commit is contained in:
kodjomoustapha 2023-11-23 19:56:55 +01:00
parent 8440b25935
commit 09b002be8b
12 changed files with 1536 additions and 39 deletions

1034
lib/eval/bridge/filter.dart Normal file

File diff suppressed because it is too large Load diff

View file

@ -2,12 +2,14 @@ import 'dart:convert';
import 'package:dart_eval/dart_eval.dart';
import 'package:dart_eval/dart_eval_bridge.dart';
import 'package:dart_eval/stdlib/core.dart';
import 'package:mangayomi/eval/bridge/filter.dart';
import 'package:mangayomi/eval/bridge/m_source.dart';
import 'package:mangayomi/eval/bridge/m_manga.dart';
import 'package:mangayomi/eval/bridge/m_pages.dart';
import 'package:mangayomi/eval/bridge/m_status.dart';
import 'package:mangayomi/eval/bridge/m_track.dart';
import 'package:mangayomi/eval/bridge/m_video.dart';
import 'package:mangayomi/eval/model/filter.dart';
import 'package:mangayomi/eval/model/m_bridge.dart';
import 'package:mangayomi/eval/model/m_pages.dart';
import 'package:mangayomi/eval/model/m_source.dart';
@ -127,6 +129,9 @@ class $MProvider extends MProvider with $Bridge<MProvider> {
false,
),
])),
'getFilterList': BridgeMethodDef(BridgeFunctionDef(
returns: BridgeTypeAnnotation(BridgeTypeRef(
CoreTypes.future, [BridgeTypeRef(CoreTypes.dynamic)])))),
'cryptoHandler': BridgeMethodDef(
BridgeFunctionDef(
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
@ -963,9 +968,14 @@ class $MProvider extends MProvider with $Bridge<MProvider> {
await $_invoke('getPopular', [$MSource.wrap(source), $int(page)]);
@override
Future<MPages> search(MSource source, String query, int page) async =>
await $_invoke(
'search', [$MSource.wrap(source), $String(query), $int(page)]);
Future<MPages> search(MSource source, String query, int page,
FilterList filterList) async =>
await $_invoke('search', [
$MSource.wrap(source),
$String(query),
$int(page),
$FilterList.wrap(FilterList(_toValueList(filterList.filters)))
]);
@override
Future<List<String>> getPageList(MSource source, String url) async {
@ -977,6 +987,15 @@ class $MProvider extends MProvider with $Bridge<MProvider> {
return res;
}
@override
List getFilterList() {
final res = $_invoke('getFilterList', []);
if (res is $List) {
return res.$reified;
}
return res;
}
@override
Future<List<Video>> getVideoList(MSource source, String url) async {
final res =
@ -1000,4 +1019,35 @@ class $MProvider extends MProvider with $Bridge<MProvider> {
: e.audios!
.map((t) => $MTrack.wrap(Track(file: t.file, label: t.label)))
.toList()));
_toValueList(List filters) {
return (filters).map((e) {
if (e is SelectFilter) {
return $SelectFilter
.wrap(SelectFilter(e.type, e.name, e.state, _toValueList(e.values)));
} else if (e is TextFilter) {
return $TextFilter.wrap(e);
} else if (e is HeaderFilter) {
return $HeaderFilter.wrap(e);
} else if (e is CheckBoxFilter) {
return $CheckBoxFilter.wrap(e);
} else if (e is TriStateFilter) {
return $TriStateFilter.wrap(e);
} else if (e is SeparatorFilter) {
return $SeparatorFilter.wrap(e);
} else if (e is SortFilter) {
return $SortFilter
.wrap(SortFilter(e.type, e.name, e.state, _toValueList(e.values)));
} else if (e is SortState) {
return $SortState.wrap(e);
} else if (e is CheckBoxFilter) {
return $CheckBoxFilter.wrap(e);
} else if (e is SelectFilterOption) {
return $SelectFilterOption.wrap(e);
} else if (e is GroupFilter) {
return $GroupFilter
.wrap(GroupFilter(e.type, e.name, _toValueList(e.state)));
}
return e;
}).toList();
}
}

View file

@ -0,0 +1,92 @@
class FilterList {
List<dynamic> filters;
FilterList(this.filters);
}
class SelectFilter {
String? type;
String name;
int state;
List<dynamic> values;
SelectFilter(this.type, this.name, this.state, this.values);
}
class SelectFilterOption {
String name;
String value;
SelectFilterOption(this.name, this.value);
}
class SeparatorFilter {
String? type;
SeparatorFilter({this.type = ''});
}
class HeaderFilter {
String? type;
String name;
HeaderFilter(this.name, {this.type = ''});
}
class TextFilter {
String? type;
String name;
String state;
TextFilter(this.type, this.name, {this.state = ""});
}
class SortFilter {
String? type;
String name;
SortState state;
List<dynamic> values;
SortFilter(this.type, this.name, this.state, this.values);
}
class SortState {
int index;
bool ascending;
SortState(this.index, this.ascending);
}
class TriStateFilter {
String? type;
String name;
String value;
int state;
factory TriStateFilter.fromJson(Map<String, dynamic> json) {
return TriStateFilter(json['type'], json['name'], json['value']);
}
TriStateFilter(this.type, this.name, this.value, {this.state = 0});
}
extension TriStateFilterExtension on TriStateFilter {
bool get ignored => state == 0;
bool get included => state == 1;
bool get excluded => state == 2;
}
class GroupFilter {
String? type;
String name;
List<dynamic> state;
GroupFilter(this.type, this.name, this.state);
}
class CheckBoxFilter {
String? type;
String name;
String value;
bool state;
factory CheckBoxFilter.fromJson(Map<String, dynamic> json) {
return CheckBoxFilter(json['type'], json['name'], json['value']);
}
CheckBoxFilter(this.type, this.name, this.value, {this.state = false});
}

View file

@ -1,3 +1,4 @@
import 'package:mangayomi/eval/model/filter.dart';
import 'package:mangayomi/eval/model/m_pages.dart';
import 'package:mangayomi/eval/model/m_source.dart';
import 'package:mangayomi/eval/model/m_manga.dart';
@ -10,7 +11,8 @@ abstract class MProvider {
Future<MPages> getPopular(MSource source, int page);
Future<MPages> search(MSource source, String query, int page);
Future<MPages> search(
MSource source, String query, int page, FilterList filterList);
Future<MManga> getDetail(MSource source, String url);
@ -18,5 +20,5 @@ abstract class MProvider {
Future<List<Video>> getVideoList(MSource source, String url);
// FilterList getFilterList();
List<dynamic> getFilterList();
}

View file

@ -1,6 +1,7 @@
import 'package:dart_eval/dart_eval.dart';
import 'package:dart_eval/dart_eval_bridge.dart';
import 'package:mangayomi/eval/bridge/m_chapter.dart';
import 'package:mangayomi/eval/bridge/filter.dart';
import 'package:mangayomi/eval/bridge/m_pages.dart';
import 'package:mangayomi/eval/bridge/m_status.dart';
import 'package:mangayomi/eval/bridge/m_provider.dart';
@ -23,6 +24,18 @@ class MEvalPlugin extends EvalPlugin {
registry.defineBridgeClass($MChapter.$declaration);
registry.defineBridgeClass($MManga.$declaration);
registry.defineBridgeEnum($MStatus.$declaration);
//Filter
registry.defineBridgeClass($FilterList.$declaration);
registry.defineBridgeClass($SelectFilter.$declaration);
registry.defineBridgeClass($SeparatorFilter.$declaration);
registry.defineBridgeClass($HeaderFilter.$declaration);
registry.defineBridgeClass($TextFilter.$declaration);
registry.defineBridgeClass($SortFilter.$declaration);
registry.defineBridgeClass($TriStateFilter.$declaration);
registry.defineBridgeClass($GroupFilter.$declaration);
registry.defineBridgeClass($CheckBoxFilter.$declaration);
registry.defineBridgeClass($SortState.$declaration);
registry.defineBridgeClass($SelectFilterOption.$declaration);
}
@override
@ -44,5 +57,28 @@ class MEvalPlugin extends EvalPlugin {
'package:mangayomi/bridge_lib.dart', 'MTrack.', $MTrack.$new);
runtime.registerBridgeEnumValues(
'package:mangayomi/bridge_lib.dart', 'MStatus', $MStatus.$values);
//Filter
runtime.registerBridgeFunc(
'package:mangayomi/bridge_lib.dart', 'FilterList.', $FilterList.$new);
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
'SelectFilter.', $SelectFilter.$new);
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
'SeparatorFilter.', $SeparatorFilter.$new);
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
'HeaderFilter.', $HeaderFilter.$new);
runtime.registerBridgeFunc(
'package:mangayomi/bridge_lib.dart', 'TextFilter.', $TextFilter.$new);
runtime.registerBridgeFunc(
'package:mangayomi/bridge_lib.dart', 'SortFilter.', $SortFilter.$new);
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
'TriStateFilter.', $TriStateFilter.$new);
runtime.registerBridgeFunc(
'package:mangayomi/bridge_lib.dart', 'GroupFilter.', $GroupFilter.$new);
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
'CheckBoxFilter.', $CheckBoxFilter.$new);
runtime.registerBridgeFunc(
'package:mangayomi/bridge_lib.dart', 'SortState.', $SortState.$new);
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
'SelectFilterOption.', $SelectFilterOption.$new);
}
}

View file

@ -112,11 +112,8 @@ class SourceSearchScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final l10n = l10nLocalizations(context)!;
final search = ref.watch(searchProvider(
source: source,
page: 1,
query: query,
));
final search = ref.watch(
searchProvider(source: source, page: 1, query: query, filterList: []));
return Scaffold(
body: SizedBox(
height: 260,

View file

@ -5,7 +5,10 @@ import 'package:go_router/go_router.dart';
import 'package:mangayomi/eval/model/m_manga.dart';
import 'package:mangayomi/eval/model/m_pages.dart';
import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/modules/manga/home/widget/filter_widget.dart';
import 'package:mangayomi/modules/widgets/progress_center.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/services/get_filter_list.dart';
import 'package:mangayomi/services/get_latest_updates.dart';
import 'package:mangayomi/services/get_popular.dart';
import 'package:mangayomi/services/search.dart';
@ -45,6 +48,7 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
int _fullDataLength = 50;
int _page = 1;
late int _selectedIndex = widget.isSearch ? 2 : 0;
List<dynamic> filters = [];
List<TypeMangaSelector> _types(BuildContext context) {
final l10n = l10nLocalizations(context)!;
return [
@ -72,12 +76,15 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
source: widget.source,
page: _page + 1,
).future);
} else if (_selectedIndex == 2 && _isSearch && _query.isNotEmpty) {
} else if (_selectedIndex == 2 &&
_isSearch &&
(_query.isNotEmpty || _isFiltering)) {
mangaResList = await ref.watch(searchProvider(
source: widget.source,
query: _query,
page: _page + 1,
).future);
source: widget.source,
query: _query,
page: _page + 1,
filterList: filters)
.future);
}
}
if (mounted) {
@ -94,11 +101,15 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
late bool _isSearch = widget.isSearch;
AsyncValue<MPages?>? _getManga;
int _length = 0;
bool _isFiltering = false;
@override
Widget build(BuildContext context) {
if (_selectedIndex == 2 && _isSearch && _query.isNotEmpty) {
_getManga = ref
.watch(searchProvider(source: widget.source, query: _query, page: 1));
final filterList = getFilterList(source: widget.source);
if (_selectedIndex == 2 &&
_isSearch &&
(_query.isNotEmpty || _isFiltering)) {
_getManga = ref.watch(searchProvider(
source: widget.source, query: _query, page: 1, filterList: filters));
} else if (_selectedIndex == 1 && !_isSearch && _query.isEmpty) {
_getManga =
ref.watch(getLatestUpdatesProvider(source: widget.source, page: 1));
@ -138,6 +149,7 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
if (_textEditingController.text.isEmpty) {
_isSearch = false;
_query = "";
_isFiltering = false;
_selectedIndex = 0;
_page = 1;
_textEditingController.clear();
@ -189,11 +201,75 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
icon: _types(context)[index].icon,
selected: _selectedIndex == index,
text: _types(context)[index].title,
onPressed: () {
setState(() {
_selectedIndex = index;
_page = 1;
});
onPressed: () async {
if (filters.isEmpty) {
filters = filterList;
}
if (filters.isNotEmpty && index == 2) {
final result = await showModalBottomSheet(
context: context,
builder: (context) =>
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
TextButton(
onPressed: () {
setState(() {
filters = getFilterList(
source: widget.source);
});
},
child: Text(l10n.reset),
),
const Spacer(),
ElevatedButton(
onPressed: () {
Navigator.pop(context, 'filter');
},
child: Text(l10n.filter),
),
],
),
),
const Divider(),
Expanded(
child: FilterWidget(
filterList: filters,
onChanged: (values) {
setState(() {
filters = values;
});
},
),
),
],
);
}),
);
if (result == 'filter') {
setState(() {
_selectedIndex = 2;
_isFiltering = true;
_isSearch = true;
_page = 1;
});
_getManga = ref.refresh(searchProvider(
source: widget.source,
query: _query,
page: 1,
filterList: filters));
}
} else if (index != 2) {
setState(() {
_selectedIndex = index;
_isFiltering = false;
_page = 1;
});
}
},
);
},
@ -215,6 +291,9 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
},
child: _getManga!.when(
data: (data) {
if (_getManga!.isLoading) {
return const ProgressCenter();
}
Widget buildProgressIndicator() {
return !(data!.list.isNotEmpty && (data.hasNextPage))
? Container()
@ -334,11 +413,12 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
onPressed: () {
if (_selectedIndex == 2 &&
_isSearch &&
_query.isNotEmpty) {
(_query.isNotEmpty || _isFiltering)) {
ref.invalidate(searchProvider(
source: widget.source,
query: _query,
page: 1));
page: 1,
filterList: filters));
} else if (_selectedIndex == 1 &&
!_isSearch &&
_query.isEmpty) {

View file

@ -0,0 +1,163 @@
import 'package:flutter/material.dart';
import 'package:mangayomi/eval/model/filter.dart';
import 'package:mangayomi/utils/colors.dart';
class FilterWidget extends StatelessWidget {
final List<dynamic> filterList;
final Function(List<dynamic>) onChanged;
const FilterWidget(
{super.key, required this.onChanged, required this.filterList});
@override
Widget build(BuildContext context) {
return ListView.builder(
padding: const EdgeInsets.all(0),
itemCount: filterList.length,
primary: false,
shrinkWrap: true,
itemBuilder: (context, idx) {
final filterState = filterList[idx];
Widget? widget;
if (filterState is TextFilter) {
widget = Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
onChanged: (val) {
filterList[idx] = filterState..state = val;
onChanged(filterList);
},
decoration: InputDecoration(
isDense: true,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: secondaryColor(context)),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: primaryColor(context)),
),
border: const OutlineInputBorder(borderSide: BorderSide()),
labelText: filterState.name,
),
),
);
} else if (filterState is HeaderFilter) {
widget = ListTile(dense: true, title: Text(filterState.name));
} else if (filterState is SeparatorFilter) {
widget = const Divider();
} else if (filterState is TriStateFilter) {
final state = filterState.state;
widget = CheckboxListTile(
dense: true,
value: state == 0
? false
: state == 1
? true
: null,
onChanged: (value) {
filterList[idx] = filterState
..state = value == null
? 2
: value == true
? 1
: 0;
onChanged(filterList);
},
title: Text(filterState.name),
controlAffinity: ListTileControlAffinity.leading,
tristate: true,
);
} else if (filterState is CheckBoxFilter) {
widget = CheckboxListTile(
dense: true,
value: filterState.state,
onChanged: (value) {
filterList[idx] = filterState..state = value!;
onChanged(filterList);
},
title: Text(filterState.name),
controlAffinity: ListTileControlAffinity.leading,
);
} else if (filterState is GroupFilter) {
widget = ExpansionTile(
title: Text(filterState.name, style: const TextStyle(fontSize: 13)),
children: [
FilterWidget(
filterList: filterState.state,
onChanged: (values) {
filterState.state = values;
onChanged(filterList);
},
)
],
);
} else if (filterState is SortFilter) {
final ascending = filterState.state.ascending;
widget = ExpansionTile(
title: Text(filterState.name, style: const TextStyle(fontSize: 13)),
children: filterState.values.map((e) {
final selected = filterState.values[filterState.state.index] == e;
return ListTile(
dense: true,
leading: Icon(
ascending
? Icons.arrow_upward_rounded
: Icons.arrow_downward_rounded,
color: selected ? null : Colors.transparent),
title: Text(e.name),
onTap: () {
if (selected) {
filterState.state.ascending = !ascending;
} else {
filterState.state.index = filterState.values
.indexWhere((element) => element == e);
}
filterList[idx] = filterState;
onChanged(filterList);
},
);
}).toList(),
);
} else if (filterState is SelectFilter) {
widget = Row(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: ListTile(
dense: true,
title: Text(filterState.name),
),
),
Expanded(
child: DropdownButtonHideUnderline(
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 25),
child: DropdownButton(
icon: const Icon(Icons.keyboard_arrow_down),
isExpanded: true,
value: filterState.values[filterState.state],
hint: Text(filterState.name,
style: const TextStyle(fontSize: 13)),
items: filterState.values
.map((e) => DropdownMenuItem(
value: e,
child: Text(e.name,
style: const TextStyle(fontSize: 13)),
))
.toList(),
onChanged: (value) {
filterState.state = filterState.values
.indexWhere((element) => element == value);
onChanged(filterList);
},
),
),
),
),
],
);
}
return widget ?? const SizedBox.shrink();
},
);
}
}

View file

@ -6,11 +6,11 @@ part of 'auto_backup.dart';
// RiverpodGenerator
// **************************************************************************
String _$checkAndBackupHash() => r'039aea77df04d1925a25ad8839177cf9ee96aa65';
String _$checkAndBackupHash() => r'fad714bbc0d37442d4f72fd98d91fcaf72166284';
/// See also [checkAndBackup].
@ProviderFor(checkAndBackup)
final checkAndBackupProvider = AutoDisposeProvider<void>.internal(
final checkAndBackupProvider = AutoDisposeFutureProvider<void>.internal(
checkAndBackup,
name: r'checkAndBackupProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
@ -20,7 +20,7 @@ final checkAndBackupProvider = AutoDisposeProvider<void>.internal(
allTransitiveDependencies: null,
);
typedef CheckAndBackupRef = AutoDisposeProviderRef<void>;
typedef CheckAndBackupRef = AutoDisposeFutureProviderRef<void>;
String _$backupFrequencyStateHash() =>
r'2e73e3fe54456978ff92f49cdc67e84f2af6de7c';
@ -39,7 +39,7 @@ final backupFrequencyStateProvider =
typedef _$BackupFrequencyState = AutoDisposeNotifier<int>;
String _$backupFrequencyOptionsStateHash() =>
r'98c9a7014b56b3a2ec243f82efa3c2b5aade03fc';
r'79d93411a02867c8882d2d0f2143f5da6c107075';
/// See also [BackupFrequencyOptionsState].
@ProviderFor(BackupFrequencyOptionsState)
@ -56,7 +56,7 @@ final backupFrequencyOptionsStateProvider = AutoDisposeNotifierProvider<
typedef _$BackupFrequencyOptionsState = AutoDisposeNotifier<List<int>>;
String _$autoBackupLocationStateHash() =>
r'0ec954361736e570e3bc6fa4e7895fc79070cb33';
r'87feb5475d47a77da4e87fa62e551b785fa1e7ba';
/// See also [AutoBackupLocationState].
@ProviderFor(AutoBackupLocationState)

View file

@ -0,0 +1,27 @@
import 'package:dart_eval/dart_eval_bridge.dart';
import 'package:mangayomi/eval/compiler/compiler.dart';
import 'package:mangayomi/eval/model/m_provider.dart';
import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/eval/runtime/runtime.dart';
import 'package:mangayomi/sources/source_test.dart';
List<dynamic> getFilterList({required Source source}) {
List<dynamic> filterList = [];
try {
final bytecode =
compilerEval(useTestSourceCode ? testSourceCode : source.sourceCode!);
final runtime = runtimeEval(bytecode);
var res = runtime.executeLib('package:mangayomi/main.dart', 'main');
filterList = (res as MProvider)
.getFilterList()
.map((e) => e is $Value ? e.$reified : e)
.toList();
} catch (_) {
return [];
}
return filterList;
}

View file

@ -1,3 +1,4 @@
import 'package:mangayomi/eval/model/filter.dart';
import 'package:mangayomi/eval/model/m_pages.dart';
import 'package:mangayomi/eval/compiler/compiler.dart';
import 'package:mangayomi/eval/model/m_provider.dart';
@ -8,12 +9,11 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'search.g.dart';
@riverpod
Future<MPages?> search(
SearchRef ref, {
required Source source,
required String query,
required int page,
}) async {
Future<MPages?> search(SearchRef ref,
{required Source source,
required String query,
required int page,
required List<dynamic> filterList}) async {
MPages? manga;
final bytecode =
compilerEval(useTestSourceCode ? testSourceCode : source.sourceCode!);
@ -21,7 +21,7 @@ Future<MPages?> search(
var res = runtime.executeLib('package:mangayomi/main.dart', 'main');
try {
manga = await (res as MProvider)
.search(source.toMSource(), query, page);
.search(source.toMSource(), query, page, FilterList(filterList));
} catch (e) {
throw Exception(e);
}

View file

@ -6,7 +6,7 @@ part of 'search.dart';
// RiverpodGenerator
// **************************************************************************
String _$searchHash() => r'a387d6ddc86044bba9c8264c8bec6c1c29393ac5';
String _$searchHash() => r'b2683242cc45e83f3946339d3490cad6488dd847';
/// Copied from Dart SDK
class _SystemHash {
@ -43,11 +43,13 @@ class SearchFamily extends Family<AsyncValue<MPages?>> {
required Source source,
required String query,
required int page,
required List<dynamic> filterList,
}) {
return SearchProvider(
source: source,
query: query,
page: page,
filterList: filterList,
);
}
@ -59,6 +61,7 @@ class SearchFamily extends Family<AsyncValue<MPages?>> {
source: provider.source,
query: provider.query,
page: provider.page,
filterList: provider.filterList,
);
}
@ -84,12 +87,14 @@ class SearchProvider extends AutoDisposeFutureProvider<MPages?> {
required Source source,
required String query,
required int page,
required List<dynamic> filterList,
}) : this._internal(
(ref) => search(
ref as SearchRef,
source: source,
query: query,
page: page,
filterList: filterList,
),
from: searchProvider,
name: r'searchProvider',
@ -102,6 +107,7 @@ class SearchProvider extends AutoDisposeFutureProvider<MPages?> {
source: source,
query: query,
page: page,
filterList: filterList,
);
SearchProvider._internal(
@ -114,11 +120,13 @@ class SearchProvider extends AutoDisposeFutureProvider<MPages?> {
required this.source,
required this.query,
required this.page,
required this.filterList,
}) : super.internal();
final Source source;
final String query;
final int page;
final List<dynamic> filterList;
@override
Override overrideWith(
@ -136,6 +144,7 @@ class SearchProvider extends AutoDisposeFutureProvider<MPages?> {
source: source,
query: query,
page: page,
filterList: filterList,
),
);
}
@ -150,7 +159,8 @@ class SearchProvider extends AutoDisposeFutureProvider<MPages?> {
return other is SearchProvider &&
other.source == source &&
other.query == query &&
other.page == page;
other.page == page &&
other.filterList == filterList;
}
@override
@ -159,6 +169,7 @@ class SearchProvider extends AutoDisposeFutureProvider<MPages?> {
hash = _SystemHash.combine(hash, source.hashCode);
hash = _SystemHash.combine(hash, query.hashCode);
hash = _SystemHash.combine(hash, page.hashCode);
hash = _SystemHash.combine(hash, filterList.hashCode);
return _SystemHash.finish(hash);
}
@ -173,6 +184,9 @@ mixin SearchRef on AutoDisposeFutureProviderRef<MPages?> {
/// The parameter `page` of this provider.
int get page;
/// The parameter `filterList` of this provider.
List<dynamic> get filterList;
}
class _SearchProviderElement extends AutoDisposeFutureProviderElement<MPages?>
@ -185,6 +199,8 @@ class _SearchProviderElement extends AutoDisposeFutureProviderElement<MPages?>
String get query => (origin as SearchProvider).query;
@override
int get page => (origin as SearchProvider).page;
@override
List<dynamic> get filterList => (origin as SearchProvider).filterList;
}
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member