From c06709aeb7f26fc6e6950f5e3f654c928c4b4f1b Mon Sep 17 00:00:00 2001 From: nyne Date: Mon, 30 Dec 2024 22:55:01 +0800 Subject: [PATCH] DNS overrides --- assets/translation.json | 8 +- lib/foundation/appdata.dart | 2 + lib/foundation/js_engine.dart | 8 +- lib/network/app_dio.dart | 17 +++ lib/pages/settings/network.dart | 142 +++++++++++++++++++++++++- lib/pages/settings/settings_page.dart | 1 + pubspec.lock | 8 +- 7 files changed, 177 insertions(+), 9 deletions(-) diff --git a/assets/translation.json b/assets/translation.json index 61cb8bc..ebb586a 100644 --- a/assets/translation.json +++ b/assets/translation.json @@ -258,7 +258,9 @@ "View Detail": "查看详情", "Select a directory which contains multiple cbz/zip files." : "选择一个包含多个cbz/zip文件的目录", "Multiple cbz files" : "多个cbz文件", - "No valid comics found" : "未找到有效的漫画" + "No valid comics found" : "未找到有效的漫画", + "Enable DNS Overrides": "启用DNS覆写", + "DNS Overrides": "DNS覆写" }, "zh_TW": { "Home": "首頁", @@ -519,6 +521,8 @@ "View Detail": "查看詳情", "Select a directory which contains multiple cbz/zip files." : "選擇一個包含多個cbz/zip文件的目錄", "Multiple cbz files" : "多個cbz文件", - "No valid comics found" : "未找到有效的漫畫" + "No valid comics found" : "未找到有效的漫畫", + "Enable DNS Overrides": "啟用DNS覆寫", + "DNS Overrides": "DNS覆寫" } } \ No newline at end of file diff --git a/lib/foundation/appdata.dart b/lib/foundation/appdata.dart index dc49623..c88bff0 100644 --- a/lib/foundation/appdata.dart +++ b/lib/foundation/appdata.dart @@ -123,6 +123,8 @@ class _Settings with ChangeNotifier { 'ignoreCertificateErrors': false, 'authorizationRequired': false, 'onClickFavorite': 'viewDetail', // viewDetail, read + 'enableDnsOverrides': false, + 'dnsOverrides': {}, }; operator [](String key) { diff --git a/lib/foundation/js_engine.dart b/lib/foundation/js_engine.dart index 206ffa2..f7e935a 100644 --- a/lib/foundation/js_engine.dart +++ b/lib/foundation/js_engine.dart @@ -58,6 +58,11 @@ class JsEngine with _JSEngineApi { JsEngine().init(); } + void resetDio() { + _dio = AppDio(BaseOptions( + responseType: ResponseType.plain, validateStatus: (status) => true)); + } + Future init() async { if (!_closed) { return; @@ -198,7 +203,8 @@ class JsEngine with _JSEngineApi { ..findProxy = (uri) => proxy == null ? "DIRECT" : "PROXY $proxy"; }, ); - dio.interceptors.add(CookieManagerSql(SingleInstanceCookieJar.instance!)); + dio.interceptors + .add(CookieManagerSql(SingleInstanceCookieJar.instance!)); dio.interceptors.add(LogInterceptor()); } response = await dio!.request(req["url"], diff --git a/lib/network/app_dio.dart b/lib/network/app_dio.dart index 540960c..59ab961 100644 --- a/lib/network/app_dio.dart +++ b/lib/network/app_dio.dart @@ -222,6 +222,22 @@ class AppDio with DioMixin { class RHttpAdapter implements HttpClientAdapter { rhttp.ClientSettings settings; + static Map> _getOverrides() { + if (!appdata.settings['enableDnsOverrides'] == true) { + return {}; + } + var config = appdata.settings["dnsOverrides"]; + var result = >{}; + if (config is Map) { + for (var entry in config.entries) { + if (entry.key is String && entry.value is String) { + result[entry.key] = [entry.value]; + } + } + } + return result; + } + RHttpAdapter([this.settings = const rhttp.ClientSettings()]) { settings = settings.copyWith( redirectSettings: const rhttp.RedirectSettings.limited(5), @@ -234,6 +250,7 @@ class RHttpAdapter implements HttpClientAdapter { tlsSettings: rhttp.TlsSettings( verifyCertificates: !AppDio.ignoreCertificateErrors, ), + dnsSettings: rhttp.DnsSettings.static(overrides: _getOverrides()), ); } diff --git a/lib/pages/settings/network.dart b/lib/pages/settings/network.dart index 9396b7e..f6ec75b 100644 --- a/lib/pages/settings/network.dart +++ b/lib/pages/settings/network.dart @@ -17,6 +17,10 @@ class _NetworkSettingsState extends State { title: "Proxy".tl, builder: () => const _ProxySettingView(), ).toSliver(), + _PopupWindowSetting( + title: "DNS Overrides".tl, + builder: () => const _DNSOverrides(), + ).toSliver(), _SliderSetting( title: "Download Threads".tl, settingsIndex: 'downloadThreads', @@ -100,7 +104,8 @@ class _ProxySettingViewState extends State<_ProxySettingView> { void initState() { var proxy = appdata.settings['proxy']; parseProxyString(proxy); - ignoreCertificateErrors = appdata.settings['ignoreCertificateErrors'] ?? false; + ignoreCertificateErrors = + appdata.settings['ignoreCertificateErrors'] ?? false; super.initState(); } @@ -153,7 +158,8 @@ class _ProxySettingViewState extends State<_ProxySettingView> { setState(() { ignoreCertificateErrors = v; }); - appdata.settings['ignoreCertificateErrors'] = ignoreCertificateErrors; + appdata.settings['ignoreCertificateErrors'] = + ignoreCertificateErrors; appdata.saveData(); }, ), @@ -250,3 +256,135 @@ class _ProxySettingViewState extends State<_ProxySettingView> { ).paddingHorizontal(16).paddingTop(16); } } + +class _DNSOverrides extends StatefulWidget { + const _DNSOverrides(); + + @override + State<_DNSOverrides> createState() => __DNSOverridesState(); +} + +class __DNSOverridesState extends State<_DNSOverrides> { + var overrides = <(String, String)>[]; + + @override + void initState() { + for (var entry in (appdata.settings['dnsOverrides'] as Map).entries) { + if (entry.key is String && entry.value is String) { + overrides.add((entry.key, entry.value)); + } + } + super.initState(); + } + + @override + void dispose() { + var map = {}; + for (var entry in overrides) { + map[entry.$1] = entry.$2; + } + appdata.settings['dnsOverrides'] = map; + appdata.saveData(); + JsEngine().resetDio(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return PopUpWidgetScaffold( + title: "DNS Overrides".tl, + body: SingleChildScrollView( + child: Column( + children: [ + _SwitchSetting( + title: "Enable DNS Overrides".tl, + settingKey: "enableDnsOverrides", + ), + const SizedBox(height: 8), + Container( + height: 1, + margin: EdgeInsets.symmetric(horizontal: 8), + color: context.colorScheme.outlineVariant, + ), + for (var i = 0; i < overrides.length; i++) buildOverride(i), + const SizedBox(height: 8), + TextButton.icon( + onPressed: () { + setState(() { + overrides.add(('', '')); + }); + }, + icon: const Icon(Icons.add), + label: Text("Add".tl), + ), + ], + ), + ), + ); + } + + Widget buildOverride(int index) { + var entry = overrides[index]; + return Container( + height: 48, + margin: EdgeInsets.symmetric(horizontal: 8), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: context.colorScheme.outlineVariant, + ), + left: BorderSide( + color: context.colorScheme.outlineVariant, + ), + right: BorderSide( + color: context.colorScheme.outlineVariant, + ), + ), + ), + child: Row( + children: [ + Expanded( + child: TextField( + decoration: InputDecoration( + border: InputBorder.none, + hintText: "Domain".tl, + ), + controller: TextEditingController(text: entry.$1), + onChanged: (v) { + overrides[index] = (v, entry.$2); + }, + ).paddingHorizontal(8), + ), + Container( + width: 1, + color: context.colorScheme.outlineVariant, + ), + Expanded( + child: TextField( + decoration: InputDecoration( + border: InputBorder.none, + hintText: "IP".tl, + ), + controller: TextEditingController(text: entry.$2), + onChanged: (v) { + overrides[index] = (entry.$1, v); + }, + ).paddingHorizontal(8), + ), + Container( + width: 1, + color: context.colorScheme.outlineVariant, + ), + IconButton( + icon: const Icon(Icons.delete_outline), + onPressed: () { + setState(() { + overrides.removeAt(index); + }); + }, + ), + ], + ), + ); + } +} diff --git a/lib/pages/settings/settings_page.dart b/lib/pages/settings/settings_page.dart index bad2e09..3827206 100644 --- a/lib/pages/settings/settings_page.dart +++ b/lib/pages/settings/settings_page.dart @@ -12,6 +12,7 @@ import 'package:venera/foundation/appdata.dart'; import 'package:venera/foundation/cache_manager.dart'; import 'package:venera/foundation/comic_source/comic_source.dart'; import 'package:venera/foundation/favorites.dart'; +import 'package:venera/foundation/js_engine.dart'; import 'package:venera/foundation/local.dart'; import 'package:venera/foundation/log.dart'; import 'package:venera/network/app_dio.dart'; diff --git a/pubspec.lock b/pubspec.lock index 0fe101a..b5b6a9c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -408,8 +408,8 @@ packages: dependency: "direct main" description: path: "." - ref: "1657f62fe7545ac43a339e0a5ee2b82bacd81e9f" - resolved-ref: "1657f62fe7545ac43a339e0a5ee2b82bacd81e9f" + ref: "9c99ac258a11f8e91761a5466a190efba3ca64af" + resolved-ref: "9c99ac258a11f8e91761a5466a190efba3ca64af" url: "https://github.com/wgh136/flutter_qjs" source: git version: "0.3.7" @@ -1125,10 +1125,10 @@ packages: dependency: "direct main" description: name: zip_flutter - sha256: "955b53d58709fcd9feefbed3d41b5522bc5273e677603e9fc67017a81e568d24" + sha256: be21152c35fcb6d0ef4ce89fc3aed681f7adc0db5490ca3eb5893f23fd20e646 url: "https://pub.dev" source: hosted - version: "0.0.5" + version: "0.0.6" sdks: dart: ">=3.6.0 <4.0.0" flutter: ">=3.27.1"