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
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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user