diff --git a/lib/eval/lib.dart b/lib/eval/lib.dart index b066d61e..e5842e93 100644 --- a/lib/eval/lib.dart +++ b/lib/eval/lib.dart @@ -5,10 +5,10 @@ import 'dart/service.dart'; import 'javascript/service.dart'; import 'mihon/service.dart'; -ExtensionService getExtensionService(Source source) { +ExtensionService getExtensionService(Source source, String androidProxyServer) { return switch (source.sourceCodeLanguage) { SourceCodeLanguage.dart => DartExtensionService(source), SourceCodeLanguage.javascript => JsExtensionService(source), - SourceCodeLanguage.mihon => MihonExtensionService(source, "http://localhost:8080"), + SourceCodeLanguage.mihon => MihonExtensionService(source, androidProxyServer), }; } diff --git a/lib/eval/mihon/service.dart b/lib/eval/mihon/service.dart index 01d42534..eb571072 100644 --- a/lib/eval/mihon/service.dart +++ b/lib/eval/mihon/service.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'package:http_interceptor/http_interceptor.dart'; +import 'package:mangayomi/eval/javascript/http.dart'; import 'package:mangayomi/eval/model/filter.dart'; import 'package:mangayomi/eval/model/m_chapter.dart'; import 'package:mangayomi/eval/model/m_manga.dart'; @@ -26,12 +27,14 @@ class MihonExtensionService implements ExtensionService { @override Map getHeaders() { - return {}; + return source.headers != null && source.headers!.isNotEmpty + ? (jsonDecode(source.headers!) as Map?)?.toMapStringString ?? {} + : {}; } @override bool get supportsLatest { - return true; + return source.supportLatest ?? false; } @override @@ -116,6 +119,7 @@ class MihonExtensionService implements ExtensionService { "method": "getSearch$name", "page": page + 1, "search": query, + // "filterList$name": _convertFilters(filters), "data": source.sourceCode, }), ); @@ -213,7 +217,7 @@ class MihonExtensionService implements ExtensionService { }), ); final data = jsonDecode(res.body) as List; - return data.map((e) => PageUrl(e['url'])).toList(); + return data.map((e) => PageUrl(e['imageUrl'])).toList(); } @override @@ -231,7 +235,7 @@ class MihonExtensionService implements ExtensionService { final tempHeaders = e['headers']['namesAndValues\$okhttp'] as List; final Map headers = {}; - for (var i = 0; i + 1 < tempHeaders.length; i++) { + for (var i = 0; i + 1 < tempHeaders.length; i += 2) { headers[tempHeaders[i]] = tempHeaders[i + 1]; } return Video( @@ -265,6 +269,7 @@ class MihonExtensionService implements ExtensionService { @override FilterList getFilterList() { + // return source.getFilterList() ?? FilterList([]); return FilterList([]); } @@ -272,4 +277,37 @@ class MihonExtensionService implements ExtensionService { List getSourcePreferences() { return []; } + + List _convertFilters(List filters) { + return filters.expand((e) sync* { + if (e is TextFilter) { + yield {"name": e.name, "state": e.state}; + } else if (e is GroupFilter) { + yield { + "name": e.name, + "state": e.state.expand((e) sync* { + if (e is CheckBoxFilter) { + yield {"name": e.name, "id": e.value, "state": e.state}; + } else if (e is TriStateFilter) { + yield { + "name": e.name, + "id": e.value, + "state": e.state, + "included": e.state == 1, + "ignored": e.state == 0, + "excluded": e.state == 2, + }; + } + }).toList(), + }; + } else if (e is SelectFilter) { + yield {"name": e.name, "state": e.state}; + } else if (e is SortFilter) { + yield { + "name": e.name, + "state": {"ascending": e.state.ascending, "index": e.state.index}, + }; + } + }).toList(); + } } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 2a24b955..14215c5a 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -443,6 +443,7 @@ "manga_extensions_repo": "Manga extensions repo", "anime_extensions_repo": "Anime extensions repo", "novel_extensions_repo": "Novel extensions repo", + "android_proxy_server": "Android Proxy Server (ApkBridge)", "undefined": "undefined", "empty_extensions_repo": "You don't have any repository urls here. Click on the plus button to add one!", "add_extensions_repo": "Add repo URL", diff --git a/lib/l10n/generated/app_localizations.dart b/lib/l10n/generated/app_localizations.dart index 15f53832..f118084b 100644 --- a/lib/l10n/generated/app_localizations.dart +++ b/lib/l10n/generated/app_localizations.dart @@ -2733,6 +2733,12 @@ abstract class AppLocalizations { /// **'Novel extensions repo'** String get novel_extensions_repo; + /// No description provided for @android_proxy_server. + /// + /// In en, this message translates to: + /// **'Android Proxy Server (ApkBridge)'** + String get android_proxy_server; + /// No description provided for @undefined. /// /// In en, this message translates to: diff --git a/lib/l10n/generated/app_localizations_ar.dart b/lib/l10n/generated/app_localizations_ar.dart index 2e2c3acd..2cd4e2cf 100644 --- a/lib/l10n/generated/app_localizations_ar.dart +++ b/lib/l10n/generated/app_localizations_ar.dart @@ -1402,6 +1402,9 @@ class AppLocalizationsAr extends AppLocalizations { @override String get novel_extensions_repo => 'مستودع إضافات الروايات'; + @override + String get android_proxy_server => 'Android Proxy Server (ApkBridge)'; + @override String get undefined => 'غير محدد'; diff --git a/lib/l10n/generated/app_localizations_as.dart b/lib/l10n/generated/app_localizations_as.dart index 1b3b235e..3457034b 100644 --- a/lib/l10n/generated/app_localizations_as.dart +++ b/lib/l10n/generated/app_localizations_as.dart @@ -1404,6 +1404,9 @@ class AppLocalizationsAs extends AppLocalizations { @override String get novel_extensions_repo => 'Novel extensions repo'; + @override + String get android_proxy_server => 'Android Proxy Server (ApkBridge)'; + @override String get undefined => 'undefined'; diff --git a/lib/l10n/generated/app_localizations_de.dart b/lib/l10n/generated/app_localizations_de.dart index 25d3ae6d..55d80a03 100644 --- a/lib/l10n/generated/app_localizations_de.dart +++ b/lib/l10n/generated/app_localizations_de.dart @@ -1413,6 +1413,9 @@ class AppLocalizationsDe extends AppLocalizations { @override String get novel_extensions_repo => 'Roman-Erweiterungs-Repository'; + @override + String get android_proxy_server => 'Android Proxy Server (ApkBridge)'; + @override String get undefined => 'Nicht definiert'; diff --git a/lib/l10n/generated/app_localizations_en.dart b/lib/l10n/generated/app_localizations_en.dart index e0dd0b27..9d7cb17b 100644 --- a/lib/l10n/generated/app_localizations_en.dart +++ b/lib/l10n/generated/app_localizations_en.dart @@ -1403,6 +1403,9 @@ class AppLocalizationsEn extends AppLocalizations { @override String get novel_extensions_repo => 'Novel extensions repo'; + @override + String get android_proxy_server => 'Android Proxy Server (ApkBridge)'; + @override String get undefined => 'undefined'; diff --git a/lib/l10n/generated/app_localizations_es.dart b/lib/l10n/generated/app_localizations_es.dart index 5a9b38fe..6f6396db 100644 --- a/lib/l10n/generated/app_localizations_es.dart +++ b/lib/l10n/generated/app_localizations_es.dart @@ -1417,6 +1417,9 @@ class AppLocalizationsEs extends AppLocalizations { @override String get novel_extensions_repo => 'Repositorio de extensiones de novelas'; + @override + String get android_proxy_server => 'Android Proxy Server (ApkBridge)'; + @override String get undefined => 'Indefinido'; diff --git a/lib/l10n/generated/app_localizations_fr.dart b/lib/l10n/generated/app_localizations_fr.dart index b9a90f9c..39603496 100644 --- a/lib/l10n/generated/app_localizations_fr.dart +++ b/lib/l10n/generated/app_localizations_fr.dart @@ -1420,6 +1420,9 @@ class AppLocalizationsFr extends AppLocalizations { @override String get novel_extensions_repo => 'Dépôt d\'extensions de romans'; + @override + String get android_proxy_server => 'Android Proxy Server (ApkBridge)'; + @override String get undefined => 'Indéfini'; diff --git a/lib/l10n/generated/app_localizations_hi.dart b/lib/l10n/generated/app_localizations_hi.dart index 9b01d5c3..63d8d9c4 100644 --- a/lib/l10n/generated/app_localizations_hi.dart +++ b/lib/l10n/generated/app_localizations_hi.dart @@ -1405,6 +1405,9 @@ class AppLocalizationsHi extends AppLocalizations { @override String get novel_extensions_repo => 'Novel extensions repo'; + @override + String get android_proxy_server => 'Android Proxy Server (ApkBridge)'; + @override String get undefined => 'undefined'; diff --git a/lib/l10n/generated/app_localizations_id.dart b/lib/l10n/generated/app_localizations_id.dart index 97b1bff0..1da43e65 100644 --- a/lib/l10n/generated/app_localizations_id.dart +++ b/lib/l10n/generated/app_localizations_id.dart @@ -1409,6 +1409,9 @@ class AppLocalizationsId extends AppLocalizations { @override String get novel_extensions_repo => 'Repositori ekstensi novel'; + @override + String get android_proxy_server => 'Android Proxy Server (ApkBridge)'; + @override String get undefined => 'Tidak terdefinisi'; diff --git a/lib/l10n/generated/app_localizations_it.dart b/lib/l10n/generated/app_localizations_it.dart index 7bda719d..21ee58fe 100644 --- a/lib/l10n/generated/app_localizations_it.dart +++ b/lib/l10n/generated/app_localizations_it.dart @@ -1417,6 +1417,9 @@ class AppLocalizationsIt extends AppLocalizations { @override String get novel_extensions_repo => 'Repository delle estensioni romanzi'; + @override + String get android_proxy_server => 'Android Proxy Server (ApkBridge)'; + @override String get undefined => 'Non definito'; diff --git a/lib/l10n/generated/app_localizations_pt.dart b/lib/l10n/generated/app_localizations_pt.dart index 9c27d999..2f01aa16 100644 --- a/lib/l10n/generated/app_localizations_pt.dart +++ b/lib/l10n/generated/app_localizations_pt.dart @@ -1414,6 +1414,9 @@ class AppLocalizationsPt extends AppLocalizations { @override String get novel_extensions_repo => 'Repositório de extensões de romances'; + @override + String get android_proxy_server => 'Android Proxy Server (ApkBridge)'; + @override String get undefined => 'Indefinido'; diff --git a/lib/l10n/generated/app_localizations_ru.dart b/lib/l10n/generated/app_localizations_ru.dart index 5d63574d..2b208f93 100644 --- a/lib/l10n/generated/app_localizations_ru.dart +++ b/lib/l10n/generated/app_localizations_ru.dart @@ -1416,6 +1416,9 @@ class AppLocalizationsRu extends AppLocalizations { @override String get novel_extensions_repo => 'Репозиторий расширений новелл'; + @override + String get android_proxy_server => 'Android Proxy Server (ApkBridge)'; + @override String get undefined => 'Не определено'; diff --git a/lib/l10n/generated/app_localizations_th.dart b/lib/l10n/generated/app_localizations_th.dart index 84c9aaff..688bf95f 100644 --- a/lib/l10n/generated/app_localizations_th.dart +++ b/lib/l10n/generated/app_localizations_th.dart @@ -1403,6 +1403,9 @@ class AppLocalizationsTh extends AppLocalizations { @override String get novel_extensions_repo => 'ที่เก็บส่วนขยายโนเวล'; + @override + String get android_proxy_server => 'Android Proxy Server (ApkBridge)'; + @override String get undefined => 'ไม่ได้กำหนด'; diff --git a/lib/l10n/generated/app_localizations_tr.dart b/lib/l10n/generated/app_localizations_tr.dart index ddc19651..4d43d306 100644 --- a/lib/l10n/generated/app_localizations_tr.dart +++ b/lib/l10n/generated/app_localizations_tr.dart @@ -1409,6 +1409,9 @@ class AppLocalizationsTr extends AppLocalizations { @override String get novel_extensions_repo => 'Roman uzantıları deposu'; + @override + String get android_proxy_server => 'Android Proxy Server (ApkBridge)'; + @override String get undefined => 'Tanımsız'; diff --git a/lib/l10n/generated/app_localizations_zh.dart b/lib/l10n/generated/app_localizations_zh.dart index 3c97660f..a4cd769f 100644 --- a/lib/l10n/generated/app_localizations_zh.dart +++ b/lib/l10n/generated/app_localizations_zh.dart @@ -1377,6 +1377,9 @@ class AppLocalizationsZh extends AppLocalizations { @override String get novel_extensions_repo => '小说扩展库'; + @override + String get android_proxy_server => 'Android Proxy Server (ApkBridge)'; + @override String get undefined => '未定义'; diff --git a/lib/models/source.dart b/lib/models/source.dart index 8811cebe..1ca0fb14 100644 --- a/lib/models/source.dart +++ b/lib/models/source.dart @@ -1,4 +1,7 @@ +import 'dart:convert'; + import 'package:isar/isar.dart'; +import 'package:mangayomi/eval/model/filter.dart'; import 'package:mangayomi/eval/model/m_source.dart'; import 'package:mangayomi/models/manga.dart'; import 'package:mangayomi/models/settings.dart'; @@ -49,6 +52,10 @@ class Source { String? headers; + bool? supportLatest; + + String? filterList; + bool? isManga; @enumerated @@ -93,6 +100,8 @@ class Source { this.versionLast = "0.0.1", this.sourceCode = '', this.headers = '', + this.supportLatest, + this.filterList, this.isManga, this.itemType = ItemType.manga, this.appMinVerReq = "", @@ -104,6 +113,10 @@ class Source { this.updatedAt = 0, }); + FilterList? getFilterList() => filterList != null + ? FilterList.fromJson(jsonDecode(filterList!) as Map) + : null; + Source.fromJson(Map json) { apiUrl = json['apiUrl']; appMinVerReq = json['appMinVerReq']; @@ -112,6 +125,8 @@ class Source { dateFormatLocale = json['dateFormatLocale']; hasCloudflare = json['hasCloudflare']; headers = json['headers']; + supportLatest = json['supportLatest']; + filterList = json['filterList']; iconUrl = json['iconUrl']; id = json['id']; isActive = json['isActive']; @@ -147,6 +162,8 @@ class Source { 'dateFormatLocale': dateFormatLocale, 'hasCloudflare': hasCloudflare, 'headers': headers, + 'supportLatest': supportLatest, + 'filterList': filterList, 'iconUrl': iconUrl, 'id': id, 'isActive': isActive, diff --git a/lib/models/source.g.dart b/lib/models/source.g.dart index c07e0242..b1f0e3fa 100644 --- a/lib/models/source.g.dart +++ b/lib/models/source.g.dart @@ -47,131 +47,141 @@ const SourceSchema = CollectionSchema( name: r'dateFormatLocale', type: IsarType.string, ), - r'hasCloudflare': PropertySchema( + r'filterList': PropertySchema( id: 6, + name: r'filterList', + type: IsarType.string, + ), + r'hasCloudflare': PropertySchema( + id: 7, name: r'hasCloudflare', type: IsarType.bool, ), r'headers': PropertySchema( - id: 7, + id: 8, name: r'headers', type: IsarType.string, ), r'iconUrl': PropertySchema( - id: 8, + id: 9, name: r'iconUrl', type: IsarType.string, ), r'isActive': PropertySchema( - id: 9, + id: 10, name: r'isActive', type: IsarType.bool, ), r'isAdded': PropertySchema( - id: 10, + id: 11, name: r'isAdded', type: IsarType.bool, ), r'isFullData': PropertySchema( - id: 11, + id: 12, name: r'isFullData', type: IsarType.bool, ), r'isLocal': PropertySchema( - id: 12, + id: 13, name: r'isLocal', type: IsarType.bool, ), r'isManga': PropertySchema( - id: 13, + id: 14, name: r'isManga', type: IsarType.bool, ), r'isNsfw': PropertySchema( - id: 14, + id: 15, name: r'isNsfw', type: IsarType.bool, ), r'isObsolete': PropertySchema( - id: 15, + id: 16, name: r'isObsolete', type: IsarType.bool, ), r'isPinned': PropertySchema( - id: 16, + id: 17, name: r'isPinned', type: IsarType.bool, ), r'isTorrent': PropertySchema( - id: 17, + id: 18, name: r'isTorrent', type: IsarType.bool, ), r'itemType': PropertySchema( - id: 18, + id: 19, name: r'itemType', type: IsarType.byte, enumMap: _SourceitemTypeEnumValueMap, ), r'lang': PropertySchema( - id: 19, + id: 20, name: r'lang', type: IsarType.string, ), r'lastUsed': PropertySchema( - id: 20, + id: 21, name: r'lastUsed', type: IsarType.bool, ), r'name': PropertySchema( - id: 21, + id: 22, name: r'name', type: IsarType.string, ), r'notes': PropertySchema( - id: 22, + id: 23, name: r'notes', type: IsarType.string, ), r'repo': PropertySchema( - id: 23, + id: 24, name: r'repo', type: IsarType.object, target: r'Repo', ), r'sourceCode': PropertySchema( - id: 24, + id: 25, name: r'sourceCode', type: IsarType.string, ), r'sourceCodeLanguage': PropertySchema( - id: 25, + id: 26, name: r'sourceCodeLanguage', type: IsarType.byte, enumMap: _SourcesourceCodeLanguageEnumValueMap, ), r'sourceCodeUrl': PropertySchema( - id: 26, + id: 27, name: r'sourceCodeUrl', type: IsarType.string, ), + r'supportLatest': PropertySchema( + id: 28, + name: r'supportLatest', + type: IsarType.bool, + ), r'typeSource': PropertySchema( - id: 27, + id: 29, name: r'typeSource', type: IsarType.string, ), r'updatedAt': PropertySchema( - id: 28, + id: 30, name: r'updatedAt', type: IsarType.long, ), r'version': PropertySchema( - id: 29, + id: 31, name: r'version', type: IsarType.string, ), r'versionLast': PropertySchema( - id: 30, + id: 32, name: r'versionLast', type: IsarType.string, ) @@ -232,6 +242,12 @@ int _sourceEstimateSize( bytesCount += 3 + value.length * 3; } } + { + final value = object.filterList; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } { final value = object.headers; if (value != null) { @@ -314,36 +330,38 @@ void _sourceSerialize( writer.writeString(offsets[3], object.baseUrl); writer.writeString(offsets[4], object.dateFormat); writer.writeString(offsets[5], object.dateFormatLocale); - writer.writeBool(offsets[6], object.hasCloudflare); - writer.writeString(offsets[7], object.headers); - writer.writeString(offsets[8], object.iconUrl); - writer.writeBool(offsets[9], object.isActive); - writer.writeBool(offsets[10], object.isAdded); - writer.writeBool(offsets[11], object.isFullData); - writer.writeBool(offsets[12], object.isLocal); - writer.writeBool(offsets[13], object.isManga); - writer.writeBool(offsets[14], object.isNsfw); - writer.writeBool(offsets[15], object.isObsolete); - writer.writeBool(offsets[16], object.isPinned); - writer.writeBool(offsets[17], object.isTorrent); - writer.writeByte(offsets[18], object.itemType.index); - writer.writeString(offsets[19], object.lang); - writer.writeBool(offsets[20], object.lastUsed); - writer.writeString(offsets[21], object.name); - writer.writeString(offsets[22], object.notes); + writer.writeString(offsets[6], object.filterList); + writer.writeBool(offsets[7], object.hasCloudflare); + writer.writeString(offsets[8], object.headers); + writer.writeString(offsets[9], object.iconUrl); + writer.writeBool(offsets[10], object.isActive); + writer.writeBool(offsets[11], object.isAdded); + writer.writeBool(offsets[12], object.isFullData); + writer.writeBool(offsets[13], object.isLocal); + writer.writeBool(offsets[14], object.isManga); + writer.writeBool(offsets[15], object.isNsfw); + writer.writeBool(offsets[16], object.isObsolete); + writer.writeBool(offsets[17], object.isPinned); + writer.writeBool(offsets[18], object.isTorrent); + writer.writeByte(offsets[19], object.itemType.index); + writer.writeString(offsets[20], object.lang); + writer.writeBool(offsets[21], object.lastUsed); + writer.writeString(offsets[22], object.name); + writer.writeString(offsets[23], object.notes); writer.writeObject( - offsets[23], + offsets[24], allOffsets, RepoSchema.serialize, object.repo, ); - writer.writeString(offsets[24], object.sourceCode); - writer.writeByte(offsets[25], object.sourceCodeLanguage.index); - writer.writeString(offsets[26], object.sourceCodeUrl); - writer.writeString(offsets[27], object.typeSource); - writer.writeLong(offsets[28], object.updatedAt); - writer.writeString(offsets[29], object.version); - writer.writeString(offsets[30], object.versionLast); + writer.writeString(offsets[25], object.sourceCode); + writer.writeByte(offsets[26], object.sourceCodeLanguage.index); + writer.writeString(offsets[27], object.sourceCodeUrl); + writer.writeBool(offsets[28], object.supportLatest); + writer.writeString(offsets[29], object.typeSource); + writer.writeLong(offsets[30], object.updatedAt); + writer.writeString(offsets[31], object.version); + writer.writeString(offsets[32], object.versionLast); } Source _sourceDeserialize( @@ -359,38 +377,40 @@ Source _sourceDeserialize( baseUrl: reader.readStringOrNull(offsets[3]), dateFormat: reader.readStringOrNull(offsets[4]), dateFormatLocale: reader.readStringOrNull(offsets[5]), - hasCloudflare: reader.readBoolOrNull(offsets[6]), - headers: reader.readStringOrNull(offsets[7]), - iconUrl: reader.readStringOrNull(offsets[8]), + filterList: reader.readStringOrNull(offsets[6]), + hasCloudflare: reader.readBoolOrNull(offsets[7]), + headers: reader.readStringOrNull(offsets[8]), + iconUrl: reader.readStringOrNull(offsets[9]), id: id, - isActive: reader.readBoolOrNull(offsets[9]), - isAdded: reader.readBoolOrNull(offsets[10]), - isFullData: reader.readBoolOrNull(offsets[11]), - isLocal: reader.readBoolOrNull(offsets[12]), - isManga: reader.readBoolOrNull(offsets[13]), - isNsfw: reader.readBoolOrNull(offsets[14]), - isObsolete: reader.readBoolOrNull(offsets[15]), - isPinned: reader.readBoolOrNull(offsets[16]), - itemType: _SourceitemTypeValueEnumMap[reader.readByteOrNull(offsets[18])] ?? + isActive: reader.readBoolOrNull(offsets[10]), + isAdded: reader.readBoolOrNull(offsets[11]), + isFullData: reader.readBoolOrNull(offsets[12]), + isLocal: reader.readBoolOrNull(offsets[13]), + isManga: reader.readBoolOrNull(offsets[14]), + isNsfw: reader.readBoolOrNull(offsets[15]), + isObsolete: reader.readBoolOrNull(offsets[16]), + isPinned: reader.readBoolOrNull(offsets[17]), + itemType: _SourceitemTypeValueEnumMap[reader.readByteOrNull(offsets[19])] ?? ItemType.manga, - lang: reader.readStringOrNull(offsets[19]), - lastUsed: reader.readBoolOrNull(offsets[20]), - name: reader.readStringOrNull(offsets[21]), - notes: reader.readStringOrNull(offsets[22]), + lang: reader.readStringOrNull(offsets[20]), + lastUsed: reader.readBoolOrNull(offsets[21]), + name: reader.readStringOrNull(offsets[22]), + notes: reader.readStringOrNull(offsets[23]), repo: reader.readObjectOrNull( - offsets[23], + offsets[24], RepoSchema.deserialize, allOffsets, ), - sourceCode: reader.readStringOrNull(offsets[24]), - sourceCodeUrl: reader.readStringOrNull(offsets[26]), - typeSource: reader.readStringOrNull(offsets[27]), - updatedAt: reader.readLongOrNull(offsets[28]), - version: reader.readStringOrNull(offsets[29]), - versionLast: reader.readStringOrNull(offsets[30]), + sourceCode: reader.readStringOrNull(offsets[25]), + sourceCodeUrl: reader.readStringOrNull(offsets[27]), + supportLatest: reader.readBoolOrNull(offsets[28]), + typeSource: reader.readStringOrNull(offsets[29]), + updatedAt: reader.readLongOrNull(offsets[30]), + version: reader.readStringOrNull(offsets[31]), + versionLast: reader.readStringOrNull(offsets[32]), ); object.sourceCodeLanguage = _SourcesourceCodeLanguageValueEnumMap[ - reader.readByteOrNull(offsets[25])] ?? + reader.readByteOrNull(offsets[26])] ?? SourceCodeLanguage.dart; return object; } @@ -415,13 +435,13 @@ P _sourceDeserializeProp

( case 5: return (reader.readStringOrNull(offset)) as P; case 6: - return (reader.readBoolOrNull(offset)) as P; - case 7: return (reader.readStringOrNull(offset)) as P; + case 7: + return (reader.readBoolOrNull(offset)) as P; case 8: return (reader.readStringOrNull(offset)) as P; case 9: - return (reader.readBoolOrNull(offset)) as P; + return (reader.readStringOrNull(offset)) as P; case 10: return (reader.readBoolOrNull(offset)) as P; case 11: @@ -437,39 +457,43 @@ P _sourceDeserializeProp

( case 16: return (reader.readBoolOrNull(offset)) as P; case 17: - return (reader.readBool(offset)) as P; + return (reader.readBoolOrNull(offset)) as P; case 18: + return (reader.readBool(offset)) as P; + case 19: return (_SourceitemTypeValueEnumMap[reader.readByteOrNull(offset)] ?? ItemType.manga) as P; - case 19: - return (reader.readStringOrNull(offset)) as P; case 20: - return (reader.readBoolOrNull(offset)) as P; - case 21: return (reader.readStringOrNull(offset)) as P; + case 21: + return (reader.readBoolOrNull(offset)) as P; case 22: return (reader.readStringOrNull(offset)) as P; case 23: + return (reader.readStringOrNull(offset)) as P; + case 24: return (reader.readObjectOrNull( offset, RepoSchema.deserialize, allOffsets, )) as P; - case 24: - return (reader.readStringOrNull(offset)) as P; case 25: + return (reader.readStringOrNull(offset)) as P; + case 26: return (_SourcesourceCodeLanguageValueEnumMap[ reader.readByteOrNull(offset)] ?? SourceCodeLanguage.dart) as P; - case 26: - return (reader.readStringOrNull(offset)) as P; case 27: return (reader.readStringOrNull(offset)) as P; case 28: - return (reader.readLongOrNull(offset)) as P; + return (reader.readBoolOrNull(offset)) as P; case 29: return (reader.readStringOrNull(offset)) as P; case 30: + return (reader.readLongOrNull(offset)) as P; + case 31: + return (reader.readStringOrNull(offset)) as P; + case 32: return (reader.readStringOrNull(offset)) as P; default: throw IsarError('Unknown property with id $propertyId'); @@ -1471,6 +1495,152 @@ extension SourceQueryFilter on QueryBuilder { }); } + QueryBuilder filterListIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'filterList', + )); + }); + } + + QueryBuilder filterListIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'filterList', + )); + }); + } + + QueryBuilder filterListEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'filterList', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder filterListGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'filterList', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder filterListLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'filterList', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder filterListBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'filterList', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder filterListStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'filterList', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder filterListEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'filterList', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder filterListContains( + String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'filterList', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder filterListMatches( + String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'filterList', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder filterListIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'filterList', + value: '', + )); + }); + } + + QueryBuilder filterListIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'filterList', + value: '', + )); + }); + } + QueryBuilder hasCloudflareIsNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNull( @@ -2954,6 +3124,32 @@ extension SourceQueryFilter on QueryBuilder { }); } + QueryBuilder supportLatestIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'supportLatest', + )); + }); + } + + QueryBuilder supportLatestIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'supportLatest', + )); + }); + } + + QueryBuilder supportLatestEqualTo( + bool? value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'supportLatest', + value: value, + )); + }); + } + QueryBuilder typeSourceIsNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNull( @@ -3546,6 +3742,18 @@ extension SourceQuerySortBy on QueryBuilder { }); } + QueryBuilder sortByFilterList() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'filterList', Sort.asc); + }); + } + + QueryBuilder sortByFilterListDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'filterList', Sort.desc); + }); + } + QueryBuilder sortByHasCloudflare() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'hasCloudflare', Sort.asc); @@ -3786,6 +3994,18 @@ extension SourceQuerySortBy on QueryBuilder { }); } + QueryBuilder sortBySupportLatest() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'supportLatest', Sort.asc); + }); + } + + QueryBuilder sortBySupportLatestDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'supportLatest', Sort.desc); + }); + } + QueryBuilder sortByTypeSource() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'typeSource', Sort.asc); @@ -3908,6 +4128,18 @@ extension SourceQuerySortThenBy on QueryBuilder { }); } + QueryBuilder thenByFilterList() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'filterList', Sort.asc); + }); + } + + QueryBuilder thenByFilterListDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'filterList', Sort.desc); + }); + } + QueryBuilder thenByHasCloudflare() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'hasCloudflare', Sort.asc); @@ -4160,6 +4392,18 @@ extension SourceQuerySortThenBy on QueryBuilder { }); } + QueryBuilder thenBySupportLatest() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'supportLatest', Sort.asc); + }); + } + + QueryBuilder thenBySupportLatestDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'supportLatest', Sort.desc); + }); + } + QueryBuilder thenByTypeSource() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'typeSource', Sort.asc); @@ -4254,6 +4498,13 @@ extension SourceQueryWhereDistinct on QueryBuilder { }); } + QueryBuilder distinctByFilterList( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'filterList', caseSensitive: caseSensitive); + }); + } + QueryBuilder distinctByHasCloudflare() { return QueryBuilder.apply(this, (query) { return query.addDistinctBy(r'hasCloudflare'); @@ -4382,6 +4633,12 @@ extension SourceQueryWhereDistinct on QueryBuilder { }); } + QueryBuilder distinctBySupportLatest() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'supportLatest'); + }); + } + QueryBuilder distinctByTypeSource( {bool caseSensitive = true}) { return QueryBuilder.apply(this, (query) { @@ -4453,6 +4710,12 @@ extension SourceQueryProperty on QueryBuilder { }); } + QueryBuilder filterListProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'filterList'); + }); + } + QueryBuilder hasCloudflareProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'hasCloudflare'); @@ -4580,6 +4843,12 @@ extension SourceQueryProperty on QueryBuilder { }); } + QueryBuilder supportLatestProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'supportLatest'); + }); + } + QueryBuilder typeSourceProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'typeSource'); diff --git a/lib/modules/browse/extension/edit_code.dart b/lib/modules/browse/extension/edit_code.dart index 1c7430ec..c3ca0f6d 100644 --- a/lib/modules/browse/extension/edit_code.dart +++ b/lib/modules/browse/extension/edit_code.dart @@ -9,6 +9,7 @@ import 'package:mangayomi/models/manga.dart'; import 'package:mangayomi/models/source.dart'; import 'package:mangayomi/modules/manga/home/widget/filter_widget.dart'; import 'package:mangayomi/modules/more/settings/appearance/providers/app_font_family.dart'; +import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart'; import 'package:mangayomi/providers/l10n_providers.dart'; import 'package:mangayomi/services/get_detail.dart'; import 'package:mangayomi/services/get_filter_list.dart'; @@ -314,6 +315,7 @@ class _CodeEditorPageState extends ConsumerState { if (source != null) { final service = getExtensionService( source!, + ref.read(androidProxyServerStateProvider), ); try { diff --git a/lib/modules/browse/global_search/global_search_screen.dart b/lib/modules/browse/global_search/global_search_screen.dart index 6b497653..444a6219 100644 --- a/lib/modules/browse/global_search/global_search_screen.dart +++ b/lib/modules/browse/global_search/global_search_screen.dart @@ -119,7 +119,7 @@ class _GlobalSearchScreenState extends ConsumerState { } } -class SourceSearchScreen extends StatefulWidget { +class SourceSearchScreen extends ConsumerStatefulWidget { final String query; final Source source; @@ -130,10 +130,10 @@ class SourceSearchScreen extends StatefulWidget { }); @override - State createState() => _SourceSearchScreenState(); + ConsumerState createState() => _SourceSearchScreenState(); } -class _SourceSearchScreenState extends State { +class _SourceSearchScreenState extends ConsumerState { @override void initState() { super.initState(); @@ -146,11 +146,13 @@ class _SourceSearchScreenState extends State { _init() async { try { _errorMessage = ""; - pages = await search( - source: widget.source, - page: 1, - query: widget.query, - filterList: [], + pages = await ref.read( + searchProvider( + source: widget.source, + page: 1, + query: widget.query, + filterList: [], + ).future, ); if (mounted) { setState(() { diff --git a/lib/modules/manga/detail/widgets/migrate_screen.dart b/lib/modules/manga/detail/widgets/migrate_screen.dart index 850a0c68..4c6fceb5 100644 --- a/lib/modules/manga/detail/widgets/migrate_screen.dart +++ b/lib/modules/manga/detail/widgets/migrate_screen.dart @@ -140,7 +140,7 @@ class _MigrationScreenScreenState extends ConsumerState { } } -class MigrationSourceSearchScreen extends StatefulWidget { +class MigrationSourceSearchScreen extends ConsumerStatefulWidget { final String query; final Manga manga; final TrackSearch? trackSearch; @@ -155,12 +155,12 @@ class MigrationSourceSearchScreen extends StatefulWidget { }); @override - State createState() => + ConsumerState createState() => _MigrationSourceSearchScreenState(); } class _MigrationSourceSearchScreenState - extends State { + extends ConsumerState { @override void initState() { super.initState(); @@ -173,11 +173,13 @@ class _MigrationSourceSearchScreenState _init() async { try { _errorMessage = ""; - pages = await search( - source: widget.source, - page: 1, - query: widget.query, - filterList: [], + pages = await ref.read( + searchProvider( + source: widget.source, + page: 1, + query: widget.query, + filterList: [], + ).future, ); if (mounted) { setState(() { diff --git a/lib/modules/more/settings/browse/browse_screen.dart b/lib/modules/more/settings/browse/browse_screen.dart index cc9104ea..c6ac35db 100644 --- a/lib/modules/more/settings/browse/browse_screen.dart +++ b/lib/modules/more/settings/browse/browse_screen.dart @@ -20,6 +20,7 @@ class BrowseSScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final androidProxyServer = ref.watch(androidProxyServerStateProvider); final onlyIncludePinnedSource = ref.watch( onlyIncludePinnedSourceStateProvider, ); @@ -51,6 +52,21 @@ class BrowseSScreen extends ConsumerWidget { ], ), ), + ListTile( + onTap: () => _showAndroidProxyServerDialog( + context, + ref, + androidProxyServer, + ), + title: Text(l10n.android_proxy_server), + subtitle: Text( + androidProxyServer, + style: TextStyle( + fontSize: 11, + color: context.secondaryColor, + ), + ), + ), ListTile( onTap: () { context.push( @@ -242,6 +258,82 @@ void _showClearAllSourcesDialog(BuildContext context, dynamic l10n) { ); } +void _showAndroidProxyServerDialog( + BuildContext context, + WidgetRef ref, + String proxyServer, +) { + final serverController = TextEditingController(text: proxyServer); + String server = proxyServer; + showDialog( + context: context, + builder: (context) => StatefulBuilder( + builder: (context, setState) { + return AlertDialog( + title: Text( + context.l10n.android_proxy_server, + style: const TextStyle(fontSize: 30), + ), + content: SizedBox( + width: context.width(0.8), + height: context.height(0.3), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: TextFormField( + controller: serverController, + autofocus: true, + onChanged: (value) => setState(() { + server = value; + }), + decoration: InputDecoration( + hintText: + "Server IP (e.g., 10.0.0.5 or https://example.com)", + filled: false, + contentPadding: const EdgeInsets.all(12), + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide(width: 0.4), + borderRadius: BorderRadius.circular(5), + ), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide(), + borderRadius: BorderRadius.circular(5), + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: const BorderSide(), + ), + ), + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: SizedBox( + width: context.width(1), + child: ElevatedButton( + onPressed: () { + ref + .read(androidProxyServerStateProvider.notifier) + .set(server); + Navigator.pop(context); + }, + child: Text(context.l10n.dialog_confirm), + ), + ), + ), + ], + ), + ), + ); + }, + ), + ); +} + void _showCleanNonLibraryDialog(BuildContext context, dynamic l10n) { showDialog( context: context, diff --git a/lib/modules/more/settings/browse/providers/browse_state_provider.dart b/lib/modules/more/settings/browse/providers/browse_state_provider.dart index f8619043..628120da 100644 --- a/lib/modules/more/settings/browse/providers/browse_state_provider.dart +++ b/lib/modules/more/settings/browse/providers/browse_state_provider.dart @@ -10,6 +10,39 @@ import 'package:mangayomi/services/http/m_client.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'browse_state_provider.g.dart'; +@riverpod +class AndroidProxyServerState extends _$AndroidProxyServerState { + @override + String build() { + String proxyServer = + isar.settings.getSync(227)!.androidProxyServer ?? + "http://127.0.0.1:8080"; + if (!proxyServer.startsWith("http")) { + proxyServer = "http://$proxyServer"; + } + if ((proxyServer.contains("localhost") || + RegExp( + r'^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$', + ).hasMatch(proxyServer.replaceAll("://", ":").split(":")[1])) && + proxyServer.split(":").length < 3) { + proxyServer = "$proxyServer:8080"; + } + return proxyServer; + } + + void set(String value) { + final settings = isar.settings.getSync(227); + state = value; + isar.writeTxnSync( + () => isar.settings.putSync( + settings! + ..androidProxyServer = value + ..updatedAt = DateTime.now().millisecondsSinceEpoch, + ), + ); + } +} + @riverpod class OnlyIncludePinnedSourceState extends _$OnlyIncludePinnedSourceState { @override diff --git a/lib/modules/more/settings/browse/providers/browse_state_provider.g.dart b/lib/modules/more/settings/browse/providers/browse_state_provider.g.dart index b892df7a..6f0c9a8c 100644 --- a/lib/modules/more/settings/browse/providers/browse_state_provider.g.dart +++ b/lib/modules/more/settings/browse/providers/browse_state_provider.g.dart @@ -157,6 +157,23 @@ class _GetRepoInfosProviderElement String get jsonUrl => (origin as GetRepoInfosProvider).jsonUrl; } +String _$androidProxyServerStateHash() => + r'c16bddb7d686a13e8f34a18dec2d983232f34c65'; + +/// See also [AndroidProxyServerState]. +@ProviderFor(AndroidProxyServerState) +final androidProxyServerStateProvider = + AutoDisposeNotifierProvider.internal( + AndroidProxyServerState.new, + name: r'androidProxyServerStateProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$androidProxyServerStateHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$AndroidProxyServerState = AutoDisposeNotifier; String _$onlyIncludePinnedSourceStateHash() => r'b9f707348d5d0f7abfa8e615c1d2b35c6dbd57f3'; diff --git a/lib/services/fetch_sources_list.dart b/lib/services/fetch_sources_list.dart index 26ba780c..de603d49 100644 --- a/lib/services/fetch_sources_list.dart +++ b/lib/services/fetch_sources_list.dart @@ -1,7 +1,9 @@ import 'dart:convert'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:http_interceptor/http_interceptor.dart'; import 'package:isar/isar.dart'; import 'package:mangayomi/eval/lib.dart'; +import 'package:mangayomi/eval/model/filter.dart'; import 'package:mangayomi/main.dart'; import 'package:mangayomi/models/manga.dart'; import 'package:mangayomi/models/settings.dart'; @@ -67,7 +69,8 @@ Future fetchSourcesList({ ? ItemType.anime : ItemType.manga ..iconUrl = "$repoUrl/icon/${e['pkg']}.png" - ..notes = "Requires Android Proxy Server!"; + ..notes = + "Requires Android Proxy Server (ApkBridge) for installing and using the extensions!"; src.id = 'mihon-${source['id']}'.hashCode; yield src; } @@ -126,12 +129,37 @@ Future _updateSource( final sourceCode = source.sourceCodeLanguage == SourceCodeLanguage.mihon ? base64.encode(req.bodyBytes) : req.body; - final headers = getExtensionService( - source..sourceCode = sourceCode, - ).getHeaders(); + final androidProxyServer = ref.read(androidProxyServerStateProvider); + Map headers = {}; + bool? supportLatest; + FilterList? filterList; + if (source.sourceCodeLanguage == SourceCodeLanguage.mihon) { + headers = await fetchHeadersDalvik( + http, + source..sourceCode = sourceCode, + androidProxyServer, + ); + supportLatest = await fetchSupportLatestDalvik( + http, + source..sourceCode = sourceCode, + androidProxyServer, + ); + filterList = await fetchFilterListDalvik( + http, + source..sourceCode = sourceCode, + androidProxyServer, + ); + } else { + headers = getExtensionService( + source..sourceCode = sourceCode, + androidProxyServer, + ).getHeaders(); + } final updatedSource = Source() ..headers = jsonEncode(headers) + ..supportLatest = supportLatest + ..filterList = filterList != null ? jsonEncode(filterList.toJson()) : null ..isAdded = true ..sourceCode = sourceCode ..sourceCodeUrl = source.sourceCodeUrl @@ -252,3 +280,133 @@ int compareVersions(String version1, String version2) { return v1Parts.length.compareTo(v2Parts.length); } + +Future> fetchHeadersDalvik( + InterceptedClient client, + Source source, + String androidProxyServer, +) async { + try { + final name = source.itemType == ItemType.anime ? "Anime" : "Manga"; + final res = await client.post( + Uri.parse("$androidProxyServer/dalvik"), + body: jsonEncode({"method": "headers$name", "data": source.sourceCode}), + ); + final data = jsonDecode(res.body) as List; + final Map headers = {}; + for (var i = 0; i + 1 < data.length; i += 2) { + headers[data[i]] = data[i + 1]; + } + return headers; + } catch (_) { + return {}; + } +} + +Future fetchSupportLatestDalvik( + InterceptedClient client, + Source source, + String androidProxyServer, +) async { + try { + final name = source.itemType == ItemType.anime ? "Anime" : "Manga"; + final res = await client.post( + Uri.parse("$androidProxyServer/dalvik"), + body: jsonEncode({ + "method": "supportLatest$name", + "data": source.sourceCode, + }), + ); + return res.body.trim() == "true"; + } catch (_) { + return false; + } +} + +Future fetchFilterListDalvik( + InterceptedClient client, + Source source, + String androidProxyServer, +) async { + try { + final name = source.itemType == ItemType.anime ? "Anime" : "Manga"; + final res = await client.post( + Uri.parse("$androidProxyServer/dalvik"), + body: jsonEncode({"method": "filters$name", "data": source.sourceCode}), + ); + final data = jsonDecode(res.body) as List; + final filters = data.expand((e) sync* { + if (e['name'] is String && + e['state'] is Map && + e['values'] is List) { + yield SortFilter( + "${e['name']}Filter", + e['name'], + SortState(e['state']['index'], e['state']['ascending'], null), + (e['values'] as List) + .map((e) => SelectFilterOption(e, e, null)) + .toList(), + null, + ); + } else if (e['name'] is String && + e['state'] is int && + (e['values'] is List || e['vals'] is List)) { + yield SelectFilter( + "${e['name']}Filter", + e['name'], + e['state'], + e['vals'] is List + ? (e['vals'] as List) + .map( + (e) => SelectFilterOption(e['first'], e['second'], null), + ) + .toList() + : e['values'] is List + ? (e['values'] as List) + .map((e) => SelectFilterOption(e, e, null)) + .toList() + : [], + "SelectFilter", + ); + } else if (e['name'] is String && e['state'] is List) { + yield GroupFilter( + "${e['name']}Filter", + e['name'], + (e['state'] as List).map((e) { + if (e['included'] is bool && + e['ignored'] is bool && + e['excluded'] is bool) { + return TriStateFilter( + null, + e['name'], + e['id'] ?? e['name'], + null, + state: e['state'], + ); + } + return CheckBoxFilter( + null, + e['name'], + e['id'] ?? e['name'], + null, + state: e['state'], + ); + }).toList(), + "GroupFilter", + ); + } else if (e['name'] is String && e['state'] is String) { + yield TextFilter( + "${e['name']}Filter", + e['name'], + null, + state: e['state'], + ); + } else if (e['name'] is String && e['state'] is int) { + yield HeaderFilter(e['name'], "${e['name']}Filter"); + } + }).toList(); + return FilterList(filters); + } catch (_) { + return null; + } +} diff --git a/lib/services/get_chapter_pages.dart b/lib/services/get_chapter_pages.dart index d073a765..290ac9f9 100644 --- a/lib/services/get_chapter_pages.dart +++ b/lib/services/get_chapter_pages.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart'; import 'package:path/path.dart' as p; import 'package:mangayomi/eval/lib.dart'; import 'package:mangayomi/eval/javascript/http.dart'; @@ -74,7 +75,10 @@ Future getChapterPages( pageUrls.add(PageUrl(isarPageUrls.urls![i], headers: headers)); } } else { - pageUrls = await getExtensionService(source).getPageList(chapter.url!); + pageUrls = await getExtensionService( + source, + ref.read(androidProxyServerStateProvider), + ).getPageList(chapter.url!); } } diff --git a/lib/services/get_chapter_pages.g.dart b/lib/services/get_chapter_pages.g.dart index 90f0e848..38b50ef3 100644 --- a/lib/services/get_chapter_pages.g.dart +++ b/lib/services/get_chapter_pages.g.dart @@ -6,7 +6,7 @@ part of 'get_chapter_pages.dart'; // RiverpodGenerator // ************************************************************************** -String _$getChapterPagesHash() => r'08f56022f03c4834c69c50d0020007fa8b26c091'; +String _$getChapterPagesHash() => r'8f6d2d661593fc5537f4dda83abea8d46d65b027'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/services/get_detail.dart b/lib/services/get_detail.dart index 9911c663..4b9c458d 100644 --- a/lib/services/get_detail.dart +++ b/lib/services/get_detail.dart @@ -1,6 +1,7 @@ import 'package:mangayomi/eval/lib.dart'; import 'package:mangayomi/eval/model/m_manga.dart'; import 'package:mangayomi/models/source.dart'; +import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; part 'get_detail.g.dart'; @@ -11,5 +12,8 @@ Future getDetail( required String url, required Source source, }) async { - return getExtensionService(source).getDetail(url); + return getExtensionService( + source, + ref.read(androidProxyServerStateProvider), + ).getDetail(url); } diff --git a/lib/services/get_detail.g.dart b/lib/services/get_detail.g.dart index 719b45dd..49f6efcd 100644 --- a/lib/services/get_detail.g.dart +++ b/lib/services/get_detail.g.dart @@ -6,7 +6,7 @@ part of 'get_detail.dart'; // RiverpodGenerator // ************************************************************************** -String _$getDetailHash() => r'84cc79aa0fd35a2d8efa95f75b85978f521c5daa'; +String _$getDetailHash() => r'6b758b79281cb00a7df2fe1903d4a67068052bca'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/services/get_filter_list.dart b/lib/services/get_filter_list.dart index 6fb387b2..b72e6182 100644 --- a/lib/services/get_filter_list.dart +++ b/lib/services/get_filter_list.dart @@ -1,6 +1,12 @@ import 'package:mangayomi/eval/lib.dart'; import 'package:mangayomi/models/source.dart'; -List getFilterList({required Source source}) { - return getExtensionService(source).getFilterList().filters; +List getFilterList({ + required Source source, + String androidProxyServer = "", +}) { + return getExtensionService( + source, + androidProxyServer, + ).getFilterList().filters; } diff --git a/lib/services/get_html_content.dart b/lib/services/get_html_content.dart index fe99da6b..856febd2 100644 --- a/lib/services/get_html_content.dart +++ b/lib/services/get_html_content.dart @@ -4,6 +4,7 @@ import 'package:epubx/epubx.dart'; import 'package:html/parser.dart'; import 'package:mangayomi/eval/lib.dart'; import 'package:mangayomi/models/chapter.dart'; +import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart'; import 'package:mangayomi/providers/storage_provider.dart'; import 'package:mangayomi/utils/utils.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; @@ -48,11 +49,16 @@ Future<(String, EpubBook?)> getHtmlContent( chapter.manga.value!.source!, ); String? html; + final proxyServer = ref.read(androidProxyServerStateProvider); if (htmlContent != null) { - html = await getExtensionService(source!).cleanHtmlContent(htmlContent); + html = await getExtensionService( + source!, + proxyServer, + ).cleanHtmlContent(htmlContent); } else { html = await getExtensionService( source!, + proxyServer, ).getHtmlContent(chapter.manga.value!.name!, chapter.url!); } return (_buildHtml(html.substring(1, html.length - 1)), null); diff --git a/lib/services/get_html_content.g.dart b/lib/services/get_html_content.g.dart index 33bebfba..91231d14 100644 --- a/lib/services/get_html_content.g.dart +++ b/lib/services/get_html_content.g.dart @@ -6,7 +6,7 @@ part of 'get_html_content.dart'; // RiverpodGenerator // ************************************************************************** -String _$getHtmlContentHash() => r'19e6959d8fceb065b19c6c6d38cd1b5132a8ba94'; +String _$getHtmlContentHash() => r'c32670ed25b093761c867f5cf1cb5dfe063edc84'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/services/get_latest_updates.dart b/lib/services/get_latest_updates.dart index ad7fb062..d743a5cc 100644 --- a/lib/services/get_latest_updates.dart +++ b/lib/services/get_latest_updates.dart @@ -1,6 +1,7 @@ import 'package:mangayomi/eval/lib.dart'; import 'package:mangayomi/eval/model/m_pages.dart'; import 'package:mangayomi/models/source.dart'; +import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; part 'get_latest_updates.g.dart'; @@ -11,5 +12,8 @@ Future getLatestUpdates( required Source source, required int page, }) async { - return getExtensionService(source).getLatestUpdates(page); + return getExtensionService( + source, + ref.read(androidProxyServerStateProvider), + ).getLatestUpdates(page); } diff --git a/lib/services/get_latest_updates.g.dart b/lib/services/get_latest_updates.g.dart index 268bdc9e..d96a255f 100644 --- a/lib/services/get_latest_updates.g.dart +++ b/lib/services/get_latest_updates.g.dart @@ -6,7 +6,7 @@ part of 'get_latest_updates.dart'; // RiverpodGenerator // ************************************************************************** -String _$getLatestUpdatesHash() => r'93e1ba376d14006110e9a6c06d191ffd12b1fdfb'; +String _$getLatestUpdatesHash() => r'fd4ece1d796e079a469e5f80f456ee821ff0bc03'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/services/get_popular.dart b/lib/services/get_popular.dart index a0fedd01..1a660da8 100644 --- a/lib/services/get_popular.dart +++ b/lib/services/get_popular.dart @@ -1,6 +1,7 @@ import 'package:mangayomi/eval/lib.dart'; import 'package:mangayomi/eval/model/m_pages.dart'; import 'package:mangayomi/models/source.dart'; +import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; part 'get_popular.g.dart'; @@ -11,5 +12,8 @@ Future getPopular( required Source source, required int page, }) async { - return getExtensionService(source).getPopular(page); + return getExtensionService( + source, + ref.read(androidProxyServerStateProvider), + ).getPopular(page); } diff --git a/lib/services/get_popular.g.dart b/lib/services/get_popular.g.dart index 278d11e3..c25b6d3f 100644 --- a/lib/services/get_popular.g.dart +++ b/lib/services/get_popular.g.dart @@ -6,7 +6,7 @@ part of 'get_popular.dart'; // RiverpodGenerator // ************************************************************************** -String _$getPopularHash() => r'02291ff9c3eba594b2344b853c34b2cea7be491b'; +String _$getPopularHash() => r'5fd933ce7e2b9c2dd113b7642ed54c1a1196f638'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/services/get_source_baseurl.dart b/lib/services/get_source_baseurl.dart index 7335454c..0390837e 100644 --- a/lib/services/get_source_baseurl.dart +++ b/lib/services/get_source_baseurl.dart @@ -1,11 +1,15 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mangayomi/eval/lib.dart'; import 'package:mangayomi/models/source.dart'; +import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'get_source_baseurl.g.dart'; @riverpod String sourceBaseUrl(Ref ref, {required Source source}) { - return getExtensionService(source).sourceBaseUrl; + return getExtensionService( + source, + ref.read(androidProxyServerStateProvider), + ).sourceBaseUrl; } diff --git a/lib/services/get_source_baseurl.g.dart b/lib/services/get_source_baseurl.g.dart index 1c3bee54..f8621dac 100644 --- a/lib/services/get_source_baseurl.g.dart +++ b/lib/services/get_source_baseurl.g.dart @@ -6,7 +6,7 @@ part of 'get_source_baseurl.dart'; // RiverpodGenerator // ************************************************************************** -String _$sourceBaseUrlHash() => r'2eaf2f441085cec9e2f035763ef2ec64aa00f838'; +String _$sourceBaseUrlHash() => r'ead3cca719e2530502d97613e3168e0031eecde7'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/services/get_source_preference.dart b/lib/services/get_source_preference.dart index 1dff1acd..a18beffc 100644 --- a/lib/services/get_source_preference.dart +++ b/lib/services/get_source_preference.dart @@ -2,6 +2,9 @@ import 'package:mangayomi/eval/lib.dart'; import 'package:mangayomi/eval/model/source_preference.dart'; import 'package:mangayomi/models/source.dart'; -List getSourcePreference({required Source source}) { - return getExtensionService(source).getSourcePreferences(); +List getSourcePreference({ + required Source source, + String androidProxyServer = "", +}) { + return getExtensionService(source, androidProxyServer).getSourcePreferences(); } diff --git a/lib/services/get_video_list.dart b/lib/services/get_video_list.dart index d1bf5984..11b7c775 100644 --- a/lib/services/get_video_list.dart +++ b/lib/services/get_video_list.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:mangayomi/eval/lib.dart'; import 'package:mangayomi/models/chapter.dart'; import 'package:mangayomi/models/video.dart'; +import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart'; import 'package:mangayomi/providers/storage_provider.dart'; import 'package:mangayomi/services/torrent_server.dart'; import 'package:mangayomi/utils/utils.dart'; @@ -58,6 +59,7 @@ Future<(List