From 09b002be8bd1d4f532c79d8a997cbbbe0a57b08e Mon Sep 17 00:00:00 2001 From: kodjomoustapha <107993382+kodjodevf@users.noreply.github.com> Date: Thu, 23 Nov 2023 19:56:55 +0100 Subject: [PATCH] feat: search filter feature --- lib/eval/bridge/filter.dart | 1034 +++++++++++++++++ lib/eval/bridge/m_provider.dart | 56 +- lib/eval/model/filter.dart | 92 ++ lib/eval/model/m_provider.dart | 6 +- lib/eval/plugin.dart | 36 + .../global_search/global_search_screen.dart | 7 +- lib/modules/manga/home/manga_home_screen.dart | 110 +- .../manga/home/widget/filter_widget.dart | 163 +++ .../providers/auto_backup.g.dart | 10 +- lib/services/get_filter_list.dart | 27 + lib/services/search.dart | 14 +- lib/services/search.g.dart | 20 +- 12 files changed, 1536 insertions(+), 39 deletions(-) create mode 100644 lib/eval/bridge/filter.dart create mode 100644 lib/eval/model/filter.dart create mode 100644 lib/modules/manga/home/widget/filter_widget.dart create mode 100644 lib/services/get_filter_list.dart diff --git a/lib/eval/bridge/filter.dart b/lib/eval/bridge/filter.dart new file mode 100644 index 00000000..4fa18b9a --- /dev/null +++ b/lib/eval/bridge/filter.dart @@ -0,0 +1,1034 @@ +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/model/filter.dart'; + +class $FilterList implements FilterList, $Instance { + $FilterList.wrap(this.$value) : _superclass = $Object($value); + + static const $type = BridgeTypeRef( + BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'FilterList')); + + static const $declaration = BridgeClassDef(BridgeClassType($type), + constructors: { + '': BridgeConstructorDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [ + BridgeParameter( + 'filters', + BridgeTypeAnnotation(BridgeTypeRef( + CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])), + false), + ])) + }, + fields: { + 'filters': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef( + CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])), + ), + }, + wrap: true); + + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $FilterList.wrap(args[0]!.$value); + } + + @override + final FilterList $value; + + @override + FilterList get $reified => $value; + + final $Instance _superclass; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'filters': + return $List.wrap($value.filters); + + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + @override + int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + switch (identifier) { + case 'filters': + $value.filters = (value.$reified as List) + .map((e) => e is $Value ? e.$reified : e) + .toList(); + default: + _superclass.$setProperty(runtime, identifier, value); + } + } + + @override + List get filters => $value.filters; + + @override + set filters(List filters) {} +} + +class $SelectFilter implements SelectFilter, $Instance { + $SelectFilter.wrap(this.$value) : _superclass = $Object($value); + + static const $type = BridgeTypeRef( + BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'SelectFilter')); + + static const $declaration = BridgeClassDef(BridgeClassType($type), + constructors: { + '': BridgeConstructorDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [ + BridgeParameter('type', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + BridgeParameter('name', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + BridgeParameter('state', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)), false), + BridgeParameter( + 'values', + BridgeTypeAnnotation(BridgeTypeRef( + CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])), + false), + ])) + }, + fields: { + 'type': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'name': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'state': BridgeFieldDef(BridgeTypeAnnotation( + BridgeTypeRef(CoreTypes.int), + )), + 'values': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef( + CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])), + ), + }, + wrap: true); + + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $SelectFilter.wrap(SelectFilter( + args[0]!.$value, + args[1]!.$value, + args[2]!.$value, + (args[3]!.$value as List) + .map((e) => SelectFilterOption(e.$reified.name, e.$reified.value)) + .toList(), + )); + } + + @override + final SelectFilter $value; + + @override + SelectFilter get $reified => $value; + + final $Instance _superclass; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'name': + return $String($value.name); + case 'type': + return $String($value.type ?? ''); + case 'state': + return $int($value.state); + case 'values': + return $List.wrap($value.values); + + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + @override + int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + switch (identifier) { + case 'type': + $value.type = value.$reified; + case 'name': + $value.name = value.$reified; + case 'state': + $value.state = value.$reified; + case 'values': + $value.values = value.$reified; + default: + _superclass.$setProperty(runtime, identifier, value); + } + } + + @override + String? get type => $value.type ?? ''; + + @override + String get name => $value.name; + + @override + int get state => $value.state; + + @override + List get values => $value.values; + + @override + set name(String name) {} + + @override + set type(String? type) {} + + @override + set state(int state) {} + + @override + set values(List values) {} +} + +class $SelectFilterOption implements SelectFilterOption, $Instance { + $SelectFilterOption.wrap(this.$value) : _superclass = $Object($value); + + static const $type = BridgeTypeRef(BridgeTypeSpec( + 'package:mangayomi/bridge_lib.dart', 'SelectFilterOption')); + + static const $declaration = BridgeClassDef(BridgeClassType($type), + constructors: { + '': BridgeConstructorDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [ + BridgeParameter('name', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + BridgeParameter('value', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + ])) + }, + fields: { + 'name': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'value': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + }, + wrap: true); + + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $SelectFilterOption + .wrap(SelectFilterOption(args[0]!.$value, args[1]!.$value)); + } + + @override + final SelectFilterOption $value; + + @override + SelectFilterOption get $reified => $value; + + final $Instance _superclass; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'name': + return $String($value.name); + case 'value': + return $String($value.value); + + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + @override + int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + switch (identifier) { + case 'value': + $value.value = value.$reified; + case 'name': + $value.name = value.$reified; + + default: + _superclass.$setProperty(runtime, identifier, value); + } + } + + @override + String get value => $value.value; + + @override + String get name => $value.name; + + @override + set name(String name) {} + + @override + set value(String value) {} +} + +class $SeparatorFilter implements SeparatorFilter, $Instance { + $SeparatorFilter.wrap(this.$value) : _superclass = $Object($value); + + static const $type = BridgeTypeRef( + BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'SeparatorFilter')); + + static const $declaration = BridgeClassDef(BridgeClassType($type), + constructors: { + '': BridgeConstructorDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [ + BridgeParameter('type', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), true), + ])) + }, + fields: { + 'type': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + }, + wrap: true); + + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $SeparatorFilter.wrap(SeparatorFilter(type: args[0]?.$value ?? '')); + } + + @override + final SeparatorFilter $value; + + @override + SeparatorFilter get $reified => $value; + + final $Instance _superclass; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'type': + return $String($value.type ?? ''); + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + @override + int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + switch (identifier) { + case 'type': + $value.type = value.$reified; + + default: + _superclass.$setProperty(runtime, identifier, value); + } + } + + @override + String? get type => $value.type ?? ''; + + @override + set type(String? type) {} +} + +class $HeaderFilter implements HeaderFilter, $Instance { + $HeaderFilter.wrap(this.$value) : _superclass = $Object($value); + + static const $type = BridgeTypeRef( + BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'HeaderFilter')); + + static const $declaration = BridgeClassDef(BridgeClassType($type), + constructors: { + '': BridgeConstructorDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [ + BridgeParameter('name', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + BridgeParameter('type', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), true), + ])) + }, + fields: { + 'name': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'type': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + }, + wrap: true); + + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $HeaderFilter + .wrap(HeaderFilter(args[0]!.$value, type: args[1]?.$value ?? '')); + } + + @override + final HeaderFilter $value; + + @override + HeaderFilter get $reified => $value; + + final $Instance _superclass; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'type': + return $String($value.type ?? ''); + case 'name': + return $String($value.name); + + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + @override + int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + switch (identifier) { + case 'name': + $value.name = value.$reified; + case 'type': + $value.type = value.$reified; + + default: + _superclass.$setProperty(runtime, identifier, value); + } + } + + @override + String get name => $value.name; + + @override + set name(String name) {} + + @override + set type(String? type) {} + + @override + String? get type => $value.type ?? ''; +} + +class $TextFilter implements TextFilter, $Instance { + $TextFilter.wrap(this.$value) : _superclass = $Object($value); + + static const $type = BridgeTypeRef( + BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'TextFilter')); + + static const $declaration = BridgeClassDef(BridgeClassType($type), + constructors: { + '': BridgeConstructorDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [ + BridgeParameter('type', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + BridgeParameter('name', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + ])) + }, + fields: { + 'type': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'name': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + }, + wrap: true); + + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $TextFilter.wrap(TextFilter(args[0]!.$value, args[1]!.$value)); + } + + @override + final TextFilter $value; + + @override + TextFilter get $reified => $value; + + final $Instance _superclass; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'type': + return $String($value.type ?? ''); + case 'name': + return $String($value.name); + case 'state': + return $String($value.state); + + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + @override + int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + switch (identifier) { + case 'type': + $value.type = value.$reified; + case 'name': + $value.name = value.$reified; + case 'state': + $value.state = value.$reified; + + default: + _superclass.$setProperty(runtime, identifier, value); + } + } + + @override + String? get type => $value.type ?? ''; + @override + String get name => $value.name; + + @override + String get state => $value.state; + + @override + set type(String? type) {} + + @override + set name(String name) {} + + @override + set state(String state) {} +} + +class $SortFilter implements SortFilter, $Instance { + $SortFilter.wrap(this.$value) : _superclass = $Object($value); + + static const $type = BridgeTypeRef( + BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'SortFilter')); + + static const $declaration = BridgeClassDef(BridgeClassType($type), + constructors: { + '': BridgeConstructorDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [ + BridgeParameter('type', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + BridgeParameter('name', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + BridgeParameter( + 'state', BridgeTypeAnnotation($SortState.$type), false), + BridgeParameter( + 'values', + BridgeTypeAnnotation(BridgeTypeRef( + CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])), + false), + ])) + }, + fields: { + 'type': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'name': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'state': BridgeFieldDef(BridgeTypeAnnotation($SortState.$type)), + 'values': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef( + CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])), + ), + }, + wrap: true); + + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $SortFilter.wrap(SortFilter( + args[0]!.$value, + args[1]!.$value, + args[2]!.$value, + (args[3]!.$value as List) + .map((e) => SelectFilterOption(e.$reified.name, e.$reified.value)) + .toList(), + )); + } + + @override + final SortFilter $value; + + @override + SortFilter get $reified => $value; + + final $Instance _superclass; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'type': + return $String($value.type ?? ''); + case 'name': + return $String($value.name); + case 'state': + return $SortState.wrap($value.state); + case 'values': + return $List.wrap($value.values); + + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + @override + int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + switch (identifier) { + case 'type': + $value.type = value.$reified; + case 'name': + $value.name = value.$reified; + case 'state': + $value.state = value.$reified; + case 'values': + $value.values = value.$reified; + default: + _superclass.$setProperty(runtime, identifier, value); + } + } + + @override + String? get type => $value.type ?? ''; + + @override + String get name => $value.name; + + @override + SortState get state => $value.state; + + @override + List get values => $value.values; + + @override + set type(String? type) {} + + @override + set name(String name) {} + + @override + set state(SortState state) {} + + @override + set values(List values) {} +} + +class $SortState implements SortState, $Instance { + $SortState.wrap(this.$value) : _superclass = $Object($value); + + static const $type = BridgeTypeRef( + BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'SortState')); + + static const $declaration = BridgeClassDef(BridgeClassType($type), + constructors: { + '': BridgeConstructorDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [ + BridgeParameter('index', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)), false), + BridgeParameter('ascending', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), false), + ])) + }, + fields: { + 'index': BridgeFieldDef(BridgeTypeAnnotation( + BridgeTypeRef(CoreTypes.int), + )), + 'ascending': BridgeFieldDef(BridgeTypeAnnotation( + BridgeTypeRef(CoreTypes.bool), + )), + }, + wrap: true); + + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $SortState.wrap(SortState(args[0]!.$value, args[1]!.$value)); + } + + @override + final SortState $value; + + @override + SortState get $reified => $value; + + final $Instance _superclass; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'index': + return $int($value.index); + case 'ascending': + return $bool($value.ascending); + + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + @override + int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + switch (identifier) { + case 'index': + $value.index = value.$reified; + case 'ascending': + $value.ascending = value.$reified; + + default: + _superclass.$setProperty(runtime, identifier, value); + } + } + + @override + int get index => $value.index; + + @override + bool get ascending => $value.ascending; + + @override + set ascending(bool ascending) {} + + @override + set index(int index) {} +} + +class $TriStateFilter implements TriStateFilter, $Instance { + $TriStateFilter.wrap(this.$value) : _superclass = $Object($value); + + static const $type = BridgeTypeRef( + BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'TriStateFilter')); + + static const $declaration = BridgeClassDef(BridgeClassType($type), + constructors: { + '': BridgeConstructorDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [ + BridgeParameter('type', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + BridgeParameter('name', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + BridgeParameter('value', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + ], namedParams: [ + BridgeParameter( + 'state', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)), true) + ])) + }, + fields: { + 'type': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'name': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'value': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'state': BridgeFieldDef(BridgeTypeAnnotation( + BridgeTypeRef(CoreTypes.int), + )), + }, + wrap: true); + + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $TriStateFilter.wrap(TriStateFilter( + args[0]!.$value, args[1]!.$value, args[2]!.$value, + state: args[3]?.$value ?? 0)); + } + + @override + final TriStateFilter $value; + + @override + TriStateFilter get $reified => $value; + + final $Instance _superclass; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'type': + return $String($value.type ?? ''); + case 'name': + return $String($value.name); + case 'state': + return $int($value.state); + case 'value': + return $String($value.value); + + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + @override + int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + switch (identifier) { + case 'type': + $value.type = value.$reified; + case 'name': + $value.name = value.$reified; + case 'state': + $value.state = value.$reified; + case 'value': + $value.value = value.$reified; + + default: + _superclass.$setProperty(runtime, identifier, value); + } + } + + @override + String? get type => $value.type ?? ''; + + @override + String get name => $value.name; + + @override + set name(String name) {} + + @override + int get state => $value.state; + + @override + String get value => $value.value; + + @override + set state(int state) {} + + @override + set type(String? type) {} + + @override + set value(String value) {} +} + +class $GroupFilter implements GroupFilter, $Instance { + $GroupFilter.wrap(this.$value) : _superclass = $Object($value); + + static const $type = BridgeTypeRef( + BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'GroupFilter')); + + static const $declaration = BridgeClassDef(BridgeClassType($type), + constructors: { + '': BridgeConstructorDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [ + BridgeParameter('type', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + BridgeParameter('name', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + BridgeParameter( + 'state', + BridgeTypeAnnotation(BridgeTypeRef( + CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])), + false), + ])) + }, + fields: { + 'type': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'name': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'state': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef( + CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])), + ), + }, + wrap: true); + + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $GroupFilter.wrap(GroupFilter( + args[0]!.$value, + args[1]!.$value, + (args[2]!.$value as List).map((e) { + if (e is $Value) { + if (e.$reified is Map) { + final val = e.$reified as Map; + Map map = {}; + map = val.map((key, value) => MapEntry(key.toString(), value)); + if (map['type'] == 'TriState') { + final filter = map['filter'] as Map; + return TriStateFilter.fromJson(filter + .map((key, value) => MapEntry(key.toString(), value))); + } else if (map['type'] == 'CheckBox') { + final filter = map['filter'] as Map; + return CheckBoxFilter.fromJson(filter + .map((key, value) => MapEntry(key.toString(), value))); + } + } + } + return e; + }).toList())); + } + + @override + final GroupFilter $value; + + @override + GroupFilter get $reified => $value; + + final $Instance _superclass; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'type': + return $String($value.type ?? ''); + case 'name': + return $String($value.name); + case 'state': + return $List.wrap($value.state.map((e) => e).toList()); + + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + @override + int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + switch (identifier) { + case 'type': + $value.type = value.$reified; + case 'name': + $value.name = value.$reified; + case 'state': + $value.state = value.$reified; + + default: + _superclass.$setProperty(runtime, identifier, value); + } + } + + @override + String? get type => $value.type ?? ''; + + @override + String get name => $value.name; + + @override + List get state => $value.state; + + @override + set type(String? type) {} + + @override + set name(String name) {} + + @override + set state(List state) {} +} + +class $CheckBoxFilter implements CheckBoxFilter, $Instance { + $CheckBoxFilter.wrap(this.$value) : _superclass = $Object($value); + + static const $type = BridgeTypeRef( + BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'CheckBoxFilter')); + + static const $declaration = BridgeClassDef(BridgeClassType($type), + constructors: { + '': BridgeConstructorDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [ + BridgeParameter('type', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + BridgeParameter('name', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + BridgeParameter('value', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + ], namedParams: [ + BridgeParameter('state', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), true), + ])) + }, + fields: { + 'type': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'name': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'value': BridgeFieldDef( + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))), + 'state': BridgeFieldDef(BridgeTypeAnnotation( + BridgeTypeRef(CoreTypes.bool), + )), + }, + wrap: true); + + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $CheckBoxFilter.wrap(CheckBoxFilter( + args[0]!.$value, args[1]!.$value, args[2]!.$value, + state: args[3]?.$value ?? false)); + } + + @override + final CheckBoxFilter $value; + + @override + CheckBoxFilter get $reified => $value; + + final $Instance _superclass; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'type': + return $String($value.type ?? ''); + case 'name': + return $String($value.name); + case 'state': + return $bool($value.state); + case 'value': + return $String($value.value); + + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + @override + int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + switch (identifier) { + case 'type': + $value.type = value.$reified; + case 'name': + $value.name = value.$reified; + case 'state': + $value.state = value.$reified; + case 'value': + $value.value = value.$reified; + + default: + _superclass.$setProperty(runtime, identifier, value); + } + } + + @override + String? get type => $value.type ?? ''; + + @override + String get name => $value.name; + + @override + set name(String name) {} + + @override + bool get state => $value.state; + + @override + String get value => $value.value; + + @override + set type(String? type) {} + + @override + set state(bool state) {} + + @override + set value(String value) {} +} diff --git a/lib/eval/bridge/m_provider.dart b/lib/eval/bridge/m_provider.dart index 9b7db4f6..9db3f769 100644 --- a/lib/eval/bridge/m_provider.dart +++ b/lib/eval/bridge/m_provider.dart @@ -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 { 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 { await $_invoke('getPopular', [$MSource.wrap(source), $int(page)]); @override - Future search(MSource source, String query, int page) async => - await $_invoke( - 'search', [$MSource.wrap(source), $String(query), $int(page)]); + Future 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> getPageList(MSource source, String url) async { @@ -977,6 +987,15 @@ class $MProvider extends MProvider with $Bridge { return res; } + @override + List getFilterList() { + final res = $_invoke('getFilterList', []); + if (res is $List) { + return res.$reified; + } + return res; + } + @override Future> getVideoList(MSource source, String url) async { final res = @@ -1000,4 +1019,35 @@ class $MProvider extends MProvider with $Bridge { : 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(); + } } diff --git a/lib/eval/model/filter.dart b/lib/eval/model/filter.dart new file mode 100644 index 00000000..75dd73b7 --- /dev/null +++ b/lib/eval/model/filter.dart @@ -0,0 +1,92 @@ +class FilterList { + List filters; + FilterList(this.filters); +} + +class SelectFilter { + String? type; + String name; + int state; + List 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 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 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 state; + + GroupFilter(this.type, this.name, this.state); +} + +class CheckBoxFilter { + String? type; + String name; + String value; + bool state; + factory CheckBoxFilter.fromJson(Map json) { + return CheckBoxFilter(json['type'], json['name'], json['value']); + } + CheckBoxFilter(this.type, this.name, this.value, {this.state = false}); +} diff --git a/lib/eval/model/m_provider.dart b/lib/eval/model/m_provider.dart index 6d595732..35e567f5 100644 --- a/lib/eval/model/m_provider.dart +++ b/lib/eval/model/m_provider.dart @@ -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 getPopular(MSource source, int page); - Future search(MSource source, String query, int page); + Future search( + MSource source, String query, int page, FilterList filterList); Future getDetail(MSource source, String url); @@ -18,5 +20,5 @@ abstract class MProvider { Future> getVideoList(MSource source, String url); - // FilterList getFilterList(); + List getFilterList(); } diff --git a/lib/eval/plugin.dart b/lib/eval/plugin.dart index fefd0041..c6ab3099 100644 --- a/lib/eval/plugin.dart +++ b/lib/eval/plugin.dart @@ -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); } } diff --git a/lib/modules/browse/global_search/global_search_screen.dart b/lib/modules/browse/global_search/global_search_screen.dart index bf9a2614..7a7ca398 100644 --- a/lib/modules/browse/global_search/global_search_screen.dart +++ b/lib/modules/browse/global_search/global_search_screen.dart @@ -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, diff --git a/lib/modules/manga/home/manga_home_screen.dart b/lib/modules/manga/home/manga_home_screen.dart index 50b40863..27cc7817 100644 --- a/lib/modules/manga/home/manga_home_screen.dart +++ b/lib/modules/manga/home/manga_home_screen.dart @@ -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 { int _fullDataLength = 50; int _page = 1; late int _selectedIndex = widget.isSearch ? 2 : 0; + List filters = []; List _types(BuildContext context) { final l10n = l10nLocalizations(context)!; return [ @@ -72,12 +76,15 @@ class _MangaHomeScreenState extends ConsumerState { 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 { late bool _isSearch = widget.isSearch; AsyncValue? _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 { if (_textEditingController.text.isEmpty) { _isSearch = false; _query = ""; + _isFiltering = false; _selectedIndex = 0; _page = 1; _textEditingController.clear(); @@ -189,11 +201,75 @@ class _MangaHomeScreenState extends ConsumerState { 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 { }, 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 { 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) { diff --git a/lib/modules/manga/home/widget/filter_widget.dart b/lib/modules/manga/home/widget/filter_widget.dart new file mode 100644 index 00000000..c01421f5 --- /dev/null +++ b/lib/modules/manga/home/widget/filter_widget.dart @@ -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 filterList; + final Function(List) 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(); + }, + ); + } +} diff --git a/lib/modules/more/backup_and_restore/providers/auto_backup.g.dart b/lib/modules/more/backup_and_restore/providers/auto_backup.g.dart index 22c44e27..65e0b880 100644 --- a/lib/modules/more/backup_and_restore/providers/auto_backup.g.dart +++ b/lib/modules/more/backup_and_restore/providers/auto_backup.g.dart @@ -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.internal( +final checkAndBackupProvider = AutoDisposeFutureProvider.internal( checkAndBackup, name: r'checkAndBackupProvider', debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') @@ -20,7 +20,7 @@ final checkAndBackupProvider = AutoDisposeProvider.internal( allTransitiveDependencies: null, ); -typedef CheckAndBackupRef = AutoDisposeProviderRef; +typedef CheckAndBackupRef = AutoDisposeFutureProviderRef; String _$backupFrequencyStateHash() => r'2e73e3fe54456978ff92f49cdc67e84f2af6de7c'; @@ -39,7 +39,7 @@ final backupFrequencyStateProvider = typedef _$BackupFrequencyState = AutoDisposeNotifier; String _$backupFrequencyOptionsStateHash() => - r'98c9a7014b56b3a2ec243f82efa3c2b5aade03fc'; + r'79d93411a02867c8882d2d0f2143f5da6c107075'; /// See also [BackupFrequencyOptionsState]. @ProviderFor(BackupFrequencyOptionsState) @@ -56,7 +56,7 @@ final backupFrequencyOptionsStateProvider = AutoDisposeNotifierProvider< typedef _$BackupFrequencyOptionsState = AutoDisposeNotifier>; String _$autoBackupLocationStateHash() => - r'0ec954361736e570e3bc6fa4e7895fc79070cb33'; + r'87feb5475d47a77da4e87fa62e551b785fa1e7ba'; /// See also [AutoBackupLocationState]. @ProviderFor(AutoBackupLocationState) diff --git a/lib/services/get_filter_list.dart b/lib/services/get_filter_list.dart new file mode 100644 index 00000000..42a63fdf --- /dev/null +++ b/lib/services/get_filter_list.dart @@ -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 getFilterList({required Source source}) { + List 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; +} diff --git a/lib/services/search.dart b/lib/services/search.dart index c0fda6e9..2ccf339a 100644 --- a/lib/services/search.dart +++ b/lib/services/search.dart @@ -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 search( - SearchRef ref, { - required Source source, - required String query, - required int page, -}) async { +Future search(SearchRef ref, + {required Source source, + required String query, + required int page, + required List filterList}) async { MPages? manga; final bytecode = compilerEval(useTestSourceCode ? testSourceCode : source.sourceCode!); @@ -21,7 +21,7 @@ Future 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); } diff --git a/lib/services/search.g.dart b/lib/services/search.g.dart index 0876111d..80557c57 100644 --- a/lib/services/search.g.dart +++ b/lib/services/search.g.dart @@ -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> { required Source source, required String query, required int page, + required List filterList, }) { return SearchProvider( source: source, query: query, page: page, + filterList: filterList, ); } @@ -59,6 +61,7 @@ class SearchFamily extends Family> { source: provider.source, query: provider.query, page: provider.page, + filterList: provider.filterList, ); } @@ -84,12 +87,14 @@ class SearchProvider extends AutoDisposeFutureProvider { required Source source, required String query, required int page, + required List 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 { source: source, query: query, page: page, + filterList: filterList, ); SearchProvider._internal( @@ -114,11 +120,13 @@ class SearchProvider extends AutoDisposeFutureProvider { 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 filterList; @override Override overrideWith( @@ -136,6 +144,7 @@ class SearchProvider extends AutoDisposeFutureProvider { source: source, query: query, page: page, + filterList: filterList, ), ); } @@ -150,7 +159,8 @@ class SearchProvider extends AutoDisposeFutureProvider { 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 { 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 { /// The parameter `page` of this provider. int get page; + + /// The parameter `filterList` of this provider. + List get filterList; } class _SearchProviderElement extends AutoDisposeFutureProviderElement @@ -185,6 +199,8 @@ class _SearchProviderElement extends AutoDisposeFutureProviderElement String get query => (origin as SearchProvider).query; @override int get page => (origin as SearchProvider).page; + @override + List 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