feat: debug
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (push) Has been cancelled
Build Windows / build (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled

This commit is contained in:
2025-11-01 23:14:39 -07:00
parent 1e7175edf5
commit 765b45c0fc
4 changed files with 185 additions and 282 deletions
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
@@ -115,7 +116,6 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
// 国家内节点重选相关属性
final RxString currentSelectedCountry = ''.obs;
final RxBool isCountryReselectionEnabled = true.obs;
final int countryReselectionLatencyThreshold = 3000; // 延迟阈值(毫秒)
// 添加一个方法来切换状态
@@ -601,8 +601,6 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
// 强制更新UI
update();
// 检查是否需要进行国家内节点重选
_checkCountryReselection(value);
} catch (e) {
KRLogUtil.kr_e('处理活动组时发生错误: $e', tag: 'HomeController');
// 🔧 修复:发生错误时,如果已连接,设置延迟为0
@@ -632,34 +630,6 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
kr_updateMarkers(updateTags);
}
});
// 语言变化监听
/**
ever(KRLanguageUtils.kr_language, (_) {
KRLogUtil.kr_i('🌐 语言变化,更新连接文本', tag: 'HomeController');
kr_connectText.value = "";
switch (KRSingBoxImp.instance.kr_status.value) {
case SingboxStopped():
kr_connectText.value = AppTranslations.kr_home.disconnected;
kr_currentIp.value = "--";
kr_currentProtocol.value = "--";
break;
case SingboxStarting():
kr_connectText.value = AppTranslations.kr_home.connecting;
break;
case SingboxStarted():
kr_connectText.value = AppTranslations.kr_home.connected;
break;
case SingboxStopping():
kr_connectText.value = AppTranslations.kr_home.disconnecting;
break;
}
// 强制更新UI
update();
});
***/
}
/// 🔧 重构: 参考 hiddify-app 的 toggleConnection 实现
@@ -946,79 +916,6 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
return node.urlTestDelay.value < 65535 && node.urlTestDelay.value > 0;
}
/// 检查是否需要进行国家内节点重选
void _checkCountryReselection(List<dynamic> activeGroups) {
// 如果未启用国家内重选功能,直接返回
if (!isCountryReselectionEnabled.value) {
return;
}
// 如果未连接,直接返回
if (!kr_isConnected.value) {
return;
}
// 如果没有选择国家,直接返回
if (currentSelectedCountry.isEmpty) {
return;
}
try {
// 获取当前节点信息
final currentNodeInfo = kr_getRealConnectedNodeInfo();
final currentDelay = currentNodeInfo['delay'] as int;
// 检查当前节点延迟是否超过阈值
if (currentDelay > 0 && currentDelay < countryReselectionLatencyThreshold) {
// 延迟正常,无需重选
return;
}
// 如果延迟超过阈值或无效,尝试在当前国家内重选
if (currentDelay >= countryReselectionLatencyThreshold || currentDelay <= 0) {
KRLogUtil.kr_w('🔄 当前节点延迟过高(${currentDelay}ms),尝试国家内重选', tag: 'HomeController');
_performCountryReselection(currentSelectedCountry.value);
}
} catch (e) {
KRLogUtil.kr_e('检查国家内重选时出错: $e', tag: 'HomeController');
}
}
/// 执行国家内节点重选
void _performCountryReselection(String country) {
try {
// 获取指定国家的所有节点
final countryNodes = kr_subscribeService.allList
.where((node) => node.country == country && node.tag != 'auto')
.toList();
if (countryNodes.isEmpty) {
KRLogUtil.kr_w('⚠️ 国家 $country 内没有可用节点', tag: 'HomeController');
return;
}
// 找到延迟最小的有效节点
String? bestNode;
int minDelay = 65535;
for (var node in countryNodes) {
final delay = node.urlTestDelay.value;
if (delay > 0 && delay < 65535 && delay < minDelay) {
minDelay = delay;
bestNode = node.tag;
}
}
if (bestNode != null && bestNode != kr_cutSeletedTag.value) {
KRLogUtil.kr_i('🎯 国家内重选: $bestNode (${minDelay}ms)', tag: 'HomeController');
kr_selectNode(bestNode);
} else {
KRLogUtil.kr_w('⚠️ 国家 $country 内没有更好的节点可选', tag: 'HomeController');
}
} catch (e) {
KRLogUtil.kr_e('执行国家内重选时出错: $e', tag: 'HomeController');
}
}
/// 设置当前选择的国家(由hi_node_list_controller调用)
void setCurrentSelectedCountry(String country) {
@@ -1026,66 +923,6 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
KRLogUtil.kr_i('🌍 设置当前选择国家: $country', tag: 'HomeController');
}
/// 启用/禁用国家内重选功能
void setCountryReselectionEnabled(bool enabled) {
isCountryReselectionEnabled.value = enabled;
KRLogUtil.kr_i('🔄 国家内重选功能已${enabled ? "启用" : "禁用"}', tag: 'HomeController');
}
/// 获取当前国家内的节点统计信息
Map<String, dynamic> getCurrentCountryNodeStats() {
if (currentSelectedCountry.isEmpty) {
return {'error': '没有选择国家'};
}
final countryNodes = kr_subscribeService.allList
.where((node) => node.country == currentSelectedCountry.value && node.tag != 'auto')
.toList();
if (countryNodes.isEmpty) {
return {'error': '国家内没有节点'};
}
List<int> validDelays = [];
int totalNodes = countryNodes.length;
int validNodes = 0;
int minDelay = 65535;
int maxDelay = 0;
String? fastestNode;
String? slowestNode;
for (var node in countryNodes) {
final delay = node.urlTestDelay.value;
if (delay > 0 && delay < 65535) {
validDelays.add(delay);
validNodes++;
if (delay < minDelay) {
minDelay = delay;
fastestNode = node.tag;
}
if (delay > maxDelay) {
maxDelay = delay;
slowestNode = node.tag;
}
}
}
double avgDelay = validDelays.isEmpty ? 0 : validDelays.reduce((a, b) => a + b) / validDelays.length;
return {
'country': currentSelectedCountry.value,
'totalNodes': totalNodes,
'validNodes': validNodes,
'minDelay': minDelay == 65535 ? 0 : minDelay,
'maxDelay': maxDelay,
'avgDelay': avgDelay.round(),
'fastestNode': fastestNode,
'slowestNode': slowestNode,
'validDelays': validDelays,
};
}
/// 更新自动模式延迟
void _kr_updateAutoLatency(dynamic element) {
@@ -1138,8 +975,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
if (!kr_isConnected.value) {
KRLogUtil.kr_i('📴 VPN未连接,只更新UI变量: $tag', tag: 'HomeController');
kr_cutSeletedTag.value = tag;
kr_updateConnectionInfo();
kr_moveToSelectedNode();
// kr_moveToSelectedNode();
// 🔧 修复:保存节点选择以便VPN启动时应用
KRLogUtil.kr_i('💾 保存节点选择以便稍后应用: $tag', tag: 'HomeController');
@@ -1215,6 +1051,11 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
}
}
Future<void> onCountrySelected(String countryTag) async {
await KRSingBoxImp.instance.kr_selectCountry(countryTag);
KRCommonUtil.kr_showToast('已切换到 $countryTag 节点组');
}
/// 🔧 修复:简化的 kr_selectNode 方法
/// 现在只是委托给新的 kr_performNodeSwitch 方法
/// 为了保持向后兼容,保留此方法但改为调用新方法
@@ -1309,7 +1150,9 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
}
// auto 模式下,获取 urltest 组的实际连接节点
print('当前活动组----${KRSingBoxImp.instance.kr_activeGroups.length}');
for (var group in KRSingBoxImp.instance.kr_activeGroups) {
print('当前活动组----$group}');
if (group.type == ProxyType.urltest) {
final selectedNode = group.selected;
final node = kr_subscribeService.keyList[selectedNode];
@@ -1320,6 +1163,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
};
}
}
print('hhhhhh${kr_subscribeService.keyList}', );
// 如果没有找到 urltest 组,返回默认值
return {
@@ -1344,7 +1188,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
/// 获取真实连接的节点国家
String kr_getRealConnectedNodeCountry() {
final info = kr_getRealConnectedNodeInfo();
final delay = info['delay'];
final delay = kr_currentNodeLatency.value;
final country = kr_getCountryFullName(info['country']);
if (delay == -2) {
return '--';
@@ -1722,45 +1566,75 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
}
}
/// 未连接状态下的延迟测试(界面显示随机延迟,不影响真实逻辑)
Future<void> _kr_testSingleNode(dynamic item) async {
final stopwatch = Stopwatch()..start();
try {
// 解析地址和端口
String address = item.serverAddr;
int port = 443; // 默认端口
// 如果 serverAddr 带端口
if (item.serverAddr.contains(':')) {
final parts = item.serverAddr.split(':');
address = parts[0];
port = int.tryParse(parts[1]) ?? 443;
} else if (item.config['server_port'] != null) {
port = item.config['server_port'];
}
// TCP 测试连接
final socket = await Socket.connect(
address,
port,
timeout: const Duration(seconds: 8),
);
final delay = stopwatch.elapsedMilliseconds;
socket.destroy();
// 设置延迟阈值:超过5秒认为不可用
if (delay > 5000) {
item.urlTestDelay.value = 65535;
} else {
item.urlTestDelay.value = delay;
}
print('✅ 节点 ${item.tag} 测试完成,延迟: ${item.urlTestDelay.value}ms');
} catch (e) {
// 连接失败
item.urlTestDelay.value = 65535;
print('⚠️ 节点 ${item.tag} 测试失败: $e');
}
}
/// 未连接状态下的延迟测试(使用本机网络真实测速)
Future<void> _kr_testLatencyWithoutVpn() async {
kr_isLatency.value = true;
try {
KRLogUtil.kr_i(
'🔌 开始未连接状态延迟测试(界面显示随机延迟)', tag: 'HomeController');
KRLogUtil.kr_i(
'📊 当前连接状态: ${kr_isConnected.value}', tag: 'HomeController');
KRLogUtil.kr_i('🎲 界面将显示30ms-100ms的随机延迟,不影响其他逻辑',
tag: 'HomeController');
// 获取所有非auto节点
try {
KRLogUtil.kr_i('🔌 开始未连接状态延迟测试(真实测速)', tag: 'HomeController');
KRLogUtil.kr_i('📊 当前连接状态: ${kr_isConnected.value}', tag: 'HomeController');
// 获取所有非 auto 节点
final testableNodes = kr_subscribeService.allList
.where((item) => item.tag != 'auto')
.toList();
KRLogUtil.kr_i(
'📋 找到 ${testableNodes.length} 个可测试节点', tag: 'HomeController');
KRLogUtil.kr_i('📋 找到 ${testableNodes.length} 个可测试节点', tag: 'HomeController');
if (testableNodes.isEmpty) {
KRLogUtil.kr_w('⚠️ 没有可测试的节点', tag: 'HomeController');
return;
}
// 不修改真实的 urlTestDelay,让界面层处理随机延迟显示
KRLogUtil.kr_i(
'✅ 延迟显示将由界面层处理,不影响节点选择逻辑', tag: 'NodeTest');
// 依次测试每个节点延迟
for (var node in testableNodes) {
await _kr_testSingleNode(node); // 真实测速
KRLogUtil.kr_i('节点 ${node.tag} 延迟: ${node.urlTestDelay.value}ms', tag: 'HomeController');
}
// 统计测试结果
final successCount = testableNodes
.where((item) => item.urlTestDelay.value < 65535)
.length;
final failCount = testableNodes.length - successCount;
KRLogUtil.kr_i('✅ 本机网络延迟测试完成', tag: 'HomeController');
KRLogUtil.kr_i('📊 测试结果: 成功 $successCount 个,失败 $failCount',
tag: 'HomeController');
// 显示前几个节点的延迟结果
// 测试完成后,按延迟排序,方便界面展示
final sortedNodes = testableNodes
.where((item) => item.urlTestDelay.value < 65535)
.toList()
@@ -1770,11 +1644,11 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
KRLogUtil.kr_i('🏆 延迟最低的前3个节点:', tag: 'HomeController');
for (int i = 0; i < 3 && i < sortedNodes.length; i++) {
final node = sortedNodes[i];
KRLogUtil.kr_i(
' ${i + 1}. ${node.tag}: ${node.urlTestDelay.value}ms',
tag: 'HomeController');
KRLogUtil.kr_i(' ${i + 1}. ${node.tag}: ${node.urlTestDelay.value}ms', tag: 'HomeController');
}
}
KRLogUtil.kr_i('✅ 本机网络延迟测试完成', tag: 'HomeController');
} catch (e) {
KRLogUtil.kr_e('❌ 本机网络延迟测试过程出错: $e', tag: 'HomeController');
} finally {
@@ -1782,7 +1656,6 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
}
}
/// 开始连接计时
void kr_startConnectionTimer() {
kr_stopConnectionTimer();
@@ -1989,14 +1862,4 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
return false;
}
}
/// 公共方法:检查国家内重选(供其他控制器调用)
void checkCountryReselection(List<dynamic> activeGroups) {
_checkCountryReselection(activeGroups);
}
/// 公共方法:执行国家内重选(供其他控制器调用)
void performCountryReselection(String country) {
_performCountryReselection(country);
}
}