From becc03acfdb947955aec488bc1ca61becd985ca4 Mon Sep 17 00:00:00 2001 From: speakeloudest Date: Fri, 21 Nov 2025 02:52:23 -0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=94=B9=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E6=B5=8B=E9=80=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controllers/hi_node_list_controller.dart | 39 +++++++++++- .../hi_node_list/views/hi_node_list_view.dart | 28 +++------ .../controllers/kr_home_controller.dart | 32 ++-------- .../services/singbox_imp/kr_sing_box_imp.dart | 61 ++++++++++++++++--- 4 files changed, 104 insertions(+), 56 deletions(-) diff --git a/lib/app/modules/hi_node_list/controllers/hi_node_list_controller.dart b/lib/app/modules/hi_node_list/controllers/hi_node_list_controller.dart index a5e41d9..1927d43 100644 --- a/lib/app/modules/hi_node_list/controllers/hi_node_list_controller.dart +++ b/lib/app/modules/hi_node_list/controllers/hi_node_list_controller.dart @@ -1,11 +1,12 @@ import 'package:get/get.dart'; +import 'package:flutter/material.dart'; import 'package:kaer_with_panels/app/utils/kr_log_util.dart'; import 'package:kaer_with_panels/app/services/kr_subscribe_service.dart'; import 'package:kaer_with_panels/app/services/singbox_imp/kr_sing_box_imp.dart'; import '../../../localization/app_translations.dart'; import 'package:kaer_with_panels/app/modules/kr_home/controllers/kr_home_controller.dart'; -class HINodeListController extends GetxController { +class HINodeListController extends GetxController with WidgetsBindingObserver { /// 订阅服务 final KRSubscribeService kr_subscribeService = KRSubscribeService(); @@ -94,4 +95,40 @@ class HINodeListController extends GetxController { KRLogUtil.kr_i('调试模式已重置', tag: 'HINodeListController'); } + @override + void onInit() { + super.onInit(); + WidgetsBinding.instance.addObserver(this); + ever(homeController.kr_cutTag, (tag) { + if (homeController.kr_isLatency.value) return; + KRLogUtil.kr_i('🔄 节点切换成功 - 自动触发延迟测试', tag: 'HINodeListView'); + homeController.kr_urlTest(); + }); + } + + @override + void onReady() { + super.onReady(); + if (homeController.kr_isLatency.value) return; + KRLogUtil.kr_i('🔄 节点列表显示 - 自动触发延迟测试', tag: 'HINodeListView'); + homeController.kr_urlTest(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + // 当应用从后台切换回前台时 + if (state == AppLifecycleState.resumed) { + if (homeController.kr_isLatency.value) return; + KRLogUtil.kr_i('🔄 节点列表显示 - 自动触发延迟测试', tag: 'HINodeListView'); + homeController.kr_urlTest(); + } + } + + @override + void onClose() { + WidgetsBinding.instance.removeObserver(this); + super.onClose(); + } + } diff --git a/lib/app/modules/hi_node_list/views/hi_node_list_view.dart b/lib/app/modules/hi_node_list/views/hi_node_list_view.dart index 1018e8e..ae8d008 100755 --- a/lib/app/modules/hi_node_list/views/hi_node_list_view.dart +++ b/lib/app/modules/hi_node_list/views/hi_node_list_view.dart @@ -84,16 +84,9 @@ class HINodeListView extends GetView { ); } - /// 构建国家/地区分组列表 + /// 构建国家/地区分组列表(废弃不使用) Widget _kr_buildRegionList(BuildContext context) { return Obx(() { - // 自动触发延迟测试(仅在未连接状态下) - WidgetsBinding.instance.addPostFrameCallback((_) { - if (!controller.homeController.kr_isConnected.value && !controller.homeController.kr_isLatency.value) { - KRLogUtil.kr_i('🔄 节点列表显示 - 自动触发延迟测试', tag: 'HINodeListView'); - controller.homeController.kr_urlTest(); - } - }); return _kr_buildListContainer( context, child: ListView( @@ -217,14 +210,6 @@ class HINodeListView extends GetView { /// 构建默认的订阅节点列表 Widget _buildSubscribeList(BuildContext context) { return Obx(() { - - // 自动触发延迟测试(仅在未连接状态下) - WidgetsBinding.instance.addPostFrameCallback((_) { - if (!controller.homeController.kr_isConnected.value && !controller.homeController.kr_isLatency.value) { - KRLogUtil.kr_i('🔄 节点列表显示 - 自动触发延迟测试', tag: 'HINodeListView'); - controller.homeController.kr_urlTest(); - } - }); return _kr_buildListContainer( context, child: ListView( @@ -293,7 +278,14 @@ class HINodeListView extends GetView { ), ), // 2. 第二个 Text: "根据网络IP自动匹配最快线路" - Obx(() { + Text( + '根据网络IP自动匹配最快线路', // 默认文本 + style: KrAppTextStyle( + fontSize: 10, + color: Colors.white, + ), + ), + /* Obx(() { // 当选择全局 auto 时,显示当前选中的节点信息 if (controller.homeController.kr_cutTag.value == 'auto') { final autoNodeInfo = controller.homeController.kr_getGlobalAutoSelectedNode(); @@ -314,7 +306,7 @@ class HINodeListView extends GetView { color: Colors.white, ), ); - }), + }),*/ ], ), ), diff --git a/lib/app/modules/kr_home/controllers/kr_home_controller.dart b/lib/app/modules/kr_home/controllers/kr_home_controller.dart index 4e3bb17..b977ca2 100755 --- a/lib/app/modules/kr_home/controllers/kr_home_controller.dart +++ b/lib/app/modules/kr_home/controllers/kr_home_controller.dart @@ -1438,7 +1438,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver { print('当前活动组----$group}'); // 处理全局 auto 模式 - if (kr_cutTag.value == 'auto' && group.type == ProxyType.urltest && group.tag == 'auto') { + if (kr_cutTag.value.endsWith('auto') && group.type == ProxyType.urltest && group.tag == 'auto') { final selectedNode = group.selected; final node = kr_subscribeService.keyList[selectedNode]; return { @@ -1447,21 +1447,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver { 'country': node?.country ?? '', }; } - - // 处理 country-auto 模式 - if (kr_cutTag.value.endsWith('-auto') && group.type == ProxyType.urltest) { - if (group.tag == kr_cutTag.value) { - final selectedNode = group.selected; - final node = kr_subscribeService.keyList[selectedNode]; - return { - 'nodeName': selectedNode, - 'delay': node?.urlTestDelay.value ?? -2, - 'country': node?.country ?? '', - }; - } - } } - print('hhhhhh${kr_subscribeService.keyList}', ); // 处理 country-auto 模式的备用方案(当 SingBox 组数据不可用时) if (kr_cutTag.value.endsWith('-auto')) { @@ -2280,7 +2266,8 @@ class KRHomeController extends GetxController with WidgetsBindingObserver { for (var node in allNodes) { final delay = node.urlTestDelay.value; - if (delay > 0 && delay < 3000 && delay < fastestDelay) { + KRLogUtil.kr_w('🔍 检查节点 ${node.tag} 的延迟: $delay', tag: 'HomeController'); + if (delay > 0 && delay < fastestDelay) { fastestDelay = delay; fastestNode = node; } @@ -2446,7 +2433,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver { KRLogUtil.kr_d('找到 selector 组: ${group.tag}, 选中: ${group.selected}', tag: 'HomeController'); // 如果是auto模式,从urltest组获取延迟 - if (kr_cutTag.value == "auto") { + if (kr_cutTag.value.endsWith('auto')) { for (var item in group.items) { if (item.tag == "auto" && item.urlTestDelay != 0) { kr_currentNodeLatency.value = item.urlTestDelay; @@ -2455,17 +2442,6 @@ class KRHomeController extends GetxController with WidgetsBindingObserver { } } } - // 如果是国家-auto模式,从对应的国家urltest组获取延迟 - else if (kr_cutTag.value.endsWith('-auto')) { - final countryCode = kr_cutTag.value.replaceAll('-auto', ''); - for (var item in group.items) { - if (item.tag == kr_cutTag.value && item.urlTestDelay != 0) { - kr_currentNodeLatency.value = item.urlTestDelay; - KRLogUtil.kr_i('✅ ${countryCode}-auto模式延迟值: ${item.urlTestDelay}ms', tag: 'HomeController'); - return true; - } - } - } // 手动选择模式 else { for (var item in group.items) { diff --git a/lib/app/services/singbox_imp/kr_sing_box_imp.dart b/lib/app/services/singbox_imp/kr_sing_box_imp.dart index 204ff9c..b0ff3e3 100755 --- a/lib/app/services/singbox_imp/kr_sing_box_imp.dart +++ b/lib/app/services/singbox_imp/kr_sing_box_imp.dart @@ -642,15 +642,7 @@ class KRSingBoxImp { "enable-fake-dns": false, "enable-dns-routing": true, "independent-dns-cache": true, - "rules": [ - // ✅ 自定义域名直连规则 - 添加到 HiddifyOptions.Rules 中 - // 这样 Native 层的 config.BuildConfig() 会将其包含到最终配置 - // 注意:libcore 要求 domains 字段使用前缀格式,如 "domain:ip.sb" 表示 domain_suffix - { - "domains": "domain:api.hifast.biz", // domain: 前缀表示 domain_suffix 匹配 - "outbound": "bypass" // bypass = direct - } - ], + "rules": _kr_buildHiddifyRules(), "mux": { "enable": false, "padding": false, @@ -709,6 +701,57 @@ class KRSingBoxImp { return op; } + List> _kr_buildHiddifyRules() { + final rules = >[]; + rules.add({ + "domains": "domain:api.hifast.biz", + "outbound": "bypass" + }); + + final nodeDomains = _kr_collectNodeDomains(); + for (final d in nodeDomains) { + rules.add({ + "domains": "domain:$d", + "outbound": "bypass" + }); + } + + KRLogUtil.kr_i('✅ 节点域名白名单数量: ${nodeDomains.length}', tag: 'SingBox'); + KRLogUtil.kr_i('✅ 节点域名白名单集合: ${jsonEncode(nodeDomains.toList())}', tag: 'SingBox'); + return rules; + } + + Set _kr_collectNodeDomains() { + final set = {}; + + void addFromOutbound(Map o) { + final server = o['server']?.toString(); + if (server != null && server.isNotEmpty && InternetAddress.tryParse(server) == null) { + set.add(server.toLowerCase()); + } + + final tls = o['tls']; + if (tls is Map) { + final sni = tls['server_name']?.toString(); + if (sni != null && sni.isNotEmpty && InternetAddress.tryParse(sni) == null) { + set.add(sni.toLowerCase()); + } + } + } + + for (final g in kr_outbounds) { + addFromOutbound(g); + } + + for (final g in Kr_allOutbounds) { + for (final it in g.outboundList) { + addFromOutbound(it.config); + } + } + + return set; + } + /// 动态构建 DNS 配置 /// /// - 真机:使用远程 DoH + 本地系统 DNS,final 指向远程