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.dart';
import 'package:dart_eval/dart_eval_bridge.dart'; import 'package:dart_eval/dart_eval_bridge.dart';
import 'package:dart_eval/stdlib/core.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_source.dart';
import 'package:mangayomi/eval/bridge/m_manga.dart'; import 'package:mangayomi/eval/bridge/m_manga.dart';
import 'package:mangayomi/eval/bridge/m_pages.dart'; import 'package:mangayomi/eval/bridge/m_pages.dart';
import 'package:mangayomi/eval/bridge/m_status.dart'; import 'package:mangayomi/eval/bridge/m_status.dart';
import 'package:mangayomi/eval/bridge/m_track.dart'; import 'package:mangayomi/eval/bridge/m_track.dart';
import 'package:mangayomi/eval/bridge/m_video.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_bridge.dart';
import 'package:mangayomi/eval/model/m_pages.dart'; import 'package:mangayomi/eval/model/m_pages.dart';
import 'package:mangayomi/eval/model/m_source.dart'; import 'package:mangayomi/eval/model/m_source.dart';
@ -127,6 +129,9 @@ class $MProvider extends MProvider with $Bridge<MProvider> {
false, false,
), ),
])), ])),
'getFilterList': BridgeMethodDef(BridgeFunctionDef(
returns: BridgeTypeAnnotation(BridgeTypeRef(
CoreTypes.future, [BridgeTypeRef(CoreTypes.dynamic)])))),
'cryptoHandler': BridgeMethodDef( 'cryptoHandler': BridgeMethodDef(
BridgeFunctionDef( BridgeFunctionDef(
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
@ -963,9 +968,14 @@ class $MProvider extends MProvider with $Bridge<MProvider> {
await $_invoke('getPopular', [$MSource.wrap(source), $int(page)]); await $_invoke('getPopular', [$MSource.wrap(source), $int(page)]);
@override @override
Future<MPages> search(MSource source, String query, int page) async => Future<MPages> search(MSource source, String query, int page,
await $_invoke( FilterList filterList) async =>
'search', [$MSource.wrap(source), $String(query), $int(page)]); await $_invoke('search', [
$MSource.wrap(source),
$String(query),
$int(page),
$FilterList.wrap(FilterList(_toValueList(filterList.filters)))
]);
@override @override
Future<List<String>> getPageList(MSource source, String url) async { Future<List<String>> getPageList(MSource source, String url) async {
@ -977,6 +987,15 @@ class $MProvider extends MProvider with $Bridge<MProvider> {
return res; return res;
} }
@override
List getFilterList() {
final res = $_invoke('getFilterList', []);
if (res is $List) {
return res.$reified;
}
return res;
}
@override @override
Future<List<Video>> getVideoList(MSource source, String url) async { Future<List<Video>> getVideoList(MSource source, String url) async {
final res = final res =
@ -1000,4 +1019,35 @@ class $MProvider extends MProvider with $Bridge<MProvider> {
: e.audios! : e.audios!
.map((t) => $MTrack.wrap(Track(file: t.file, label: t.label))) .map((t) => $MTrack.wrap(Track(file: t.file, label: t.label)))
.toList())); .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_pages.dart';
import 'package:mangayomi/eval/model/m_source.dart'; import 'package:mangayomi/eval/model/m_source.dart';
import 'package:mangayomi/eval/model/m_manga.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> 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); Future<MManga> getDetail(MSource source, String url);
@ -18,5 +20,5 @@ abstract class MProvider {
Future<List<Video>> getVideoList(MSource source, String url); 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.dart';
import 'package:dart_eval/dart_eval_bridge.dart'; import 'package:dart_eval/dart_eval_bridge.dart';
import 'package:mangayomi/eval/bridge/m_chapter.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_pages.dart';
import 'package:mangayomi/eval/bridge/m_status.dart'; import 'package:mangayomi/eval/bridge/m_status.dart';
import 'package:mangayomi/eval/bridge/m_provider.dart'; import 'package:mangayomi/eval/bridge/m_provider.dart';
@ -23,6 +24,18 @@ class MEvalPlugin extends EvalPlugin {
registry.defineBridgeClass($MChapter.$declaration); registry.defineBridgeClass($MChapter.$declaration);
registry.defineBridgeClass($MManga.$declaration); registry.defineBridgeClass($MManga.$declaration);
registry.defineBridgeEnum($MStatus.$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 @override
@ -44,5 +57,28 @@ class MEvalPlugin extends EvalPlugin {
'package:mangayomi/bridge_lib.dart', 'MTrack.', $MTrack.$new); 'package:mangayomi/bridge_lib.dart', 'MTrack.', $MTrack.$new);
runtime.registerBridgeEnumValues( runtime.registerBridgeEnumValues(
'package:mangayomi/bridge_lib.dart', 'MStatus', $MStatus.$values); '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 @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final l10n = l10nLocalizations(context)!; final l10n = l10nLocalizations(context)!;
final search = ref.watch(searchProvider( final search = ref.watch(
source: source, searchProvider(source: source, page: 1, query: query, filterList: []));
page: 1,
query: query,
));
return Scaffold( return Scaffold(
body: SizedBox( body: SizedBox(
height: 260, 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_manga.dart';
import 'package:mangayomi/eval/model/m_pages.dart'; import 'package:mangayomi/eval/model/m_pages.dart';
import 'package:mangayomi/models/source.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/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_latest_updates.dart';
import 'package:mangayomi/services/get_popular.dart'; import 'package:mangayomi/services/get_popular.dart';
import 'package:mangayomi/services/search.dart'; import 'package:mangayomi/services/search.dart';
@ -45,6 +48,7 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
int _fullDataLength = 50; int _fullDataLength = 50;
int _page = 1; int _page = 1;
late int _selectedIndex = widget.isSearch ? 2 : 0; late int _selectedIndex = widget.isSearch ? 2 : 0;
List<dynamic> filters = [];
List<TypeMangaSelector> _types(BuildContext context) { List<TypeMangaSelector> _types(BuildContext context) {
final l10n = l10nLocalizations(context)!; final l10n = l10nLocalizations(context)!;
return [ return [
@ -72,12 +76,15 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
source: widget.source, source: widget.source,
page: _page + 1, page: _page + 1,
).future); ).future);
} else if (_selectedIndex == 2 && _isSearch && _query.isNotEmpty) { } else if (_selectedIndex == 2 &&
_isSearch &&
(_query.isNotEmpty || _isFiltering)) {
mangaResList = await ref.watch(searchProvider( mangaResList = await ref.watch(searchProvider(
source: widget.source, source: widget.source,
query: _query, query: _query,
page: _page + 1, page: _page + 1,
).future); filterList: filters)
.future);
} }
} }
if (mounted) { if (mounted) {
@ -94,11 +101,15 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
late bool _isSearch = widget.isSearch; late bool _isSearch = widget.isSearch;
AsyncValue<MPages?>? _getManga; AsyncValue<MPages?>? _getManga;
int _length = 0; int _length = 0;
bool _isFiltering = false;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (_selectedIndex == 2 && _isSearch && _query.isNotEmpty) { final filterList = getFilterList(source: widget.source);
_getManga = ref if (_selectedIndex == 2 &&
.watch(searchProvider(source: widget.source, query: _query, page: 1)); _isSearch &&
(_query.isNotEmpty || _isFiltering)) {
_getManga = ref.watch(searchProvider(
source: widget.source, query: _query, page: 1, filterList: filters));
} else if (_selectedIndex == 1 && !_isSearch && _query.isEmpty) { } else if (_selectedIndex == 1 && !_isSearch && _query.isEmpty) {
_getManga = _getManga =
ref.watch(getLatestUpdatesProvider(source: widget.source, page: 1)); ref.watch(getLatestUpdatesProvider(source: widget.source, page: 1));
@ -138,6 +149,7 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
if (_textEditingController.text.isEmpty) { if (_textEditingController.text.isEmpty) {
_isSearch = false; _isSearch = false;
_query = ""; _query = "";
_isFiltering = false;
_selectedIndex = 0; _selectedIndex = 0;
_page = 1; _page = 1;
_textEditingController.clear(); _textEditingController.clear();
@ -189,11 +201,75 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
icon: _types(context)[index].icon, icon: _types(context)[index].icon,
selected: _selectedIndex == index, selected: _selectedIndex == index,
text: _types(context)[index].title, text: _types(context)[index].title,
onPressed: () { onPressed: () async {
setState(() { if (filters.isEmpty) {
_selectedIndex = index; filters = filterList;
_page = 1; }
}); 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( child: _getManga!.when(
data: (data) { data: (data) {
if (_getManga!.isLoading) {
return const ProgressCenter();
}
Widget buildProgressIndicator() { Widget buildProgressIndicator() {
return !(data!.list.isNotEmpty && (data.hasNextPage)) return !(data!.list.isNotEmpty && (data.hasNextPage))
? Container() ? Container()
@ -334,11 +413,12 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
onPressed: () { onPressed: () {
if (_selectedIndex == 2 && if (_selectedIndex == 2 &&
_isSearch && _isSearch &&
_query.isNotEmpty) { (_query.isNotEmpty || _isFiltering)) {
ref.invalidate(searchProvider( ref.invalidate(searchProvider(
source: widget.source, source: widget.source,
query: _query, query: _query,
page: 1)); page: 1,
filterList: filters));
} else if (_selectedIndex == 1 && } else if (_selectedIndex == 1 &&
!_isSearch && !_isSearch &&
_query.isEmpty) { _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 // RiverpodGenerator
// ************************************************************************** // **************************************************************************
String _$checkAndBackupHash() => r'039aea77df04d1925a25ad8839177cf9ee96aa65'; String _$checkAndBackupHash() => r'fad714bbc0d37442d4f72fd98d91fcaf72166284';
/// See also [checkAndBackup]. /// See also [checkAndBackup].
@ProviderFor(checkAndBackup) @ProviderFor(checkAndBackup)
final checkAndBackupProvider = AutoDisposeProvider<void>.internal( final checkAndBackupProvider = AutoDisposeFutureProvider<void>.internal(
checkAndBackup, checkAndBackup,
name: r'checkAndBackupProvider', name: r'checkAndBackupProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
@ -20,7 +20,7 @@ final checkAndBackupProvider = AutoDisposeProvider<void>.internal(
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );
typedef CheckAndBackupRef = AutoDisposeProviderRef<void>; typedef CheckAndBackupRef = AutoDisposeFutureProviderRef<void>;
String _$backupFrequencyStateHash() => String _$backupFrequencyStateHash() =>
r'2e73e3fe54456978ff92f49cdc67e84f2af6de7c'; r'2e73e3fe54456978ff92f49cdc67e84f2af6de7c';
@ -39,7 +39,7 @@ final backupFrequencyStateProvider =
typedef _$BackupFrequencyState = AutoDisposeNotifier<int>; typedef _$BackupFrequencyState = AutoDisposeNotifier<int>;
String _$backupFrequencyOptionsStateHash() => String _$backupFrequencyOptionsStateHash() =>
r'98c9a7014b56b3a2ec243f82efa3c2b5aade03fc'; r'79d93411a02867c8882d2d0f2143f5da6c107075';
/// See also [BackupFrequencyOptionsState]. /// See also [BackupFrequencyOptionsState].
@ProviderFor(BackupFrequencyOptionsState) @ProviderFor(BackupFrequencyOptionsState)
@ -56,7 +56,7 @@ final backupFrequencyOptionsStateProvider = AutoDisposeNotifierProvider<
typedef _$BackupFrequencyOptionsState = AutoDisposeNotifier<List<int>>; typedef _$BackupFrequencyOptionsState = AutoDisposeNotifier<List<int>>;
String _$autoBackupLocationStateHash() => String _$autoBackupLocationStateHash() =>
r'0ec954361736e570e3bc6fa4e7895fc79070cb33'; r'87feb5475d47a77da4e87fa62e551b785fa1e7ba';
/// See also [AutoBackupLocationState]. /// See also [AutoBackupLocationState].
@ProviderFor(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/model/m_pages.dart';
import 'package:mangayomi/eval/compiler/compiler.dart'; import 'package:mangayomi/eval/compiler/compiler.dart';
import 'package:mangayomi/eval/model/m_provider.dart'; import 'package:mangayomi/eval/model/m_provider.dart';
@ -8,12 +9,11 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'search.g.dart'; part 'search.g.dart';
@riverpod @riverpod
Future<MPages?> search( Future<MPages?> search(SearchRef ref,
SearchRef ref, { {required Source source,
required Source source, required String query,
required String query, required int page,
required int page, required List<dynamic> filterList}) async {
}) async {
MPages? manga; MPages? manga;
final bytecode = final bytecode =
compilerEval(useTestSourceCode ? testSourceCode : source.sourceCode!); compilerEval(useTestSourceCode ? testSourceCode : source.sourceCode!);
@ -21,7 +21,7 @@ Future<MPages?> search(
var res = runtime.executeLib('package:mangayomi/main.dart', 'main'); var res = runtime.executeLib('package:mangayomi/main.dart', 'main');
try { try {
manga = await (res as MProvider) manga = await (res as MProvider)
.search(source.toMSource(), query, page); .search(source.toMSource(), query, page, FilterList(filterList));
} catch (e) { } catch (e) {
throw Exception(e); throw Exception(e);
} }

View file

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