hi-client/lib/app/modules/kr_home/controllers/kr_home_controller.dart
2025-10-17 14:08:54 +08:00

1460 lines
52 KiB
Dart
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:get/get.dart';
import 'package:kaer_with_panels/app/common/app_run_data.dart';
import 'package:kaer_with_panels/app/services/kr_subscribe_service.dart';
import 'package:latlong2/latlong.dart';
import '../../../../singbox/model/singbox_proxy_type.dart';
import '../../../../singbox/model/singbox_status.dart';
import '../../../common/app_config.dart';
import '../../../localization/app_translations.dart';
import '../../../localization/kr_language_utils.dart';
import '../../../model/business/kr_group_outbound_list.dart';
import '../../../services/kr_announcement_service.dart';
import '../../../utils/kr_event_bus.dart';
import '../../../utils/kr_update_util.dart';
import '../../../widgets/dialogs/kr_dialog.dart';
import '../../../widgets/kr_language_switch_dialog.dart';
import '../models/kr_home_views_status.dart';
import 'package:kaer_with_panels/app/model/response/kr_user_available_subscribe.dart';
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
import 'package:kaer_with_panels/app/services/singbox_imp/kr_sing_box_imp.dart';
class KRHomeController extends GetxController {
/// 订阅服务
final KRSubscribeService kr_subscribeService = KRSubscribeService();
// 修改地图控制器为可空类型
MapController kr_mapController = MapController();
// 底部面板控制器
DraggableScrollableController kr_sheetController = DraggableScrollableController();
/// 当前视图状态,登录状态
final Rx<KRHomeViewsStatus> kr_currentViewStatus =
KRHomeViewsStatus.kr_notLoggedIn.obs;
/// 当前列表视图状态
final kr_currentListStatus = KRHomeViewsListStatus.kr_loading.obs;
/// 底部面板高度常量
static const double kr_baseHeight = 120.0; // 基础高度(连接选项)
static const double kr_subscriptionCardHeight = 200.0; // 订阅卡片高度
static const double kr_connectionInfoHeight = 126.0; // 连接信息卡片高度
static const double kr_trialCardHeight = 120.0; // 试用卡片高度
static const double kr_lastDayCardHeight = 120.0; // 最后一天卡片高度
static const double kr_nodeListHeight = 400.0; // 节点列表高度
static const double kr_errorHeight = 100.0; // 错误状态高度
static const double kr_loadingHeight = 100.0; // 加载状态高度
/// 间距常量
static const double kr_marginTop = 12.0; // 顶部间距
static const double kr_marginBottom = 12.0; // 底部间距
static const double kr_marginHorizontal = 16.0; // 水平间距
static const double kr_marginVertical = 12.0; // 垂直间距
/// 底部面板高度
final kr_bottomPanelHeight = 200.0.obs;
/// 连接字符串
final kr_connectText = AppTranslations.kr_home.disconnected.obs;
// 当前节点名称
final kr_currentNodeName = 'auto'.obs;
/// 当前连接速率
final RxString kr_currentSpeed = "--".obs;
// 当前节点延迟
final kr_currentNodeLatency = (-2).obs;
// 是否已连接
final kr_isConnected = false.obs;
// 是否显示延迟
final kr_isLatency = false.obs;
/// 默认
var kr_cutTag = 'auto'.obs;
var kr_cutSeletedTag = 'auto'.obs;
var kr_coutryText = 'auto'.obs;
/// 当前连接信息
final RxString kr_currentIp = AppTranslations.kr_home.disconnected.obs;
final RxString kr_currentProtocol = AppTranslations.kr_home.disconnected.obs;
final RxString kr_connectionTime = '00:00:00'.obs;
// 连接计时器
Timer? _kr_connectionTimer;
int _kr_connectionSeconds = 0;
// 当前选中的组
final Rx<KRGroupOutboundList?> kr_currentGroup =
Rx<KRGroupOutboundList?>(null);
// 添加是否用户正在移动地图的标志
final kr_isUserMoving = false.obs;
// 添加最后的地图中心点
final kr_lastMapCenter = LatLng(35.0, 105.0).obs;
// 添加一个标志来防止重复操作
bool kr_isSwitching = false;
@override
void onInit() {
super.onInit();
/// 底部面板高度处理
_kr_initBottomPanelHeight();
// 绑定订阅状态
_bindSubscribeStatus();
/// 登录处理
_kr_initLoginStatus();
// 绑定连接状态
_bindConnectionStatus();
// 延迟同步连接状态,确保状态正确
Future.delayed(const Duration(milliseconds: 500), () {
kr_forceSyncConnectionStatus();
});
}
/// 底部面板高度处理
void _kr_initBottomPanelHeight() {
ever(kr_currentListStatus, (status) {
kr_updateBottomPanelHeight();
KRLogUtil.kr_i(status.toString(), tag: "_kr_initBottomPanelHeight");
});
}
void _kr_initLoginStatus() {
KRLogUtil.kr_i('初始化登录状态', tag: 'HomeController');
// 设置超时处理
Timer(const Duration(seconds: 10), () {
if (kr_currentListStatus.value == KRHomeViewsListStatus.kr_loading) {
KRLogUtil.kr_w('订阅服务初始化超时,设置为错误状态', tag: 'HomeController');
kr_currentListStatus.value = KRHomeViewsListStatus.kr_error;
}
});
// 延迟初始化,确保所有异步操作完成
Future.delayed(const Duration(milliseconds: 100), () {
_kr_validateAndSetLoginStatus();
});
// 注册登录状态监听器
ever(KRAppRunData().kr_isLogin, (isLoggedIn) {
KRLogUtil.kr_i('登录状态变化: $isLoggedIn', tag: 'HomeController');
_kr_handleLoginStatusChange(isLoggedIn);
});
// 添加状态同步检查
_kr_addStatusSyncCheck();
if (AppConfig().kr_is_daytime == true) {
Future.delayed(const Duration(seconds: 1), () {
KRUpdateUtil().kr_checkUpdate();
Future.delayed(const Duration(seconds: 1), () {
KRLanguageSwitchDialog.kr_show();
});
});
}
}
/// 验证并设置登录状态
void _kr_validateAndSetLoginStatus() {
try {
// 多重验证登录状态
final hasToken = KRAppRunData().kr_token != null && KRAppRunData().kr_token!.isNotEmpty;
final isLoginFlag = KRAppRunData().kr_isLogin.value;
final isValidLogin = hasToken && isLoginFlag;
KRLogUtil.kr_i('登录状态验证: hasToken=$hasToken, isLogin=$isLoginFlag, isValid=$isValidLogin', tag: 'HomeController');
KRLogUtil.kr_i('Token内容: ${KRAppRunData().kr_token?.substring(0, 10)}...', tag: 'HomeController');
if (isValidLogin) {
kr_currentViewStatus.value = KRHomeViewsStatus.kr_loggedIn;
KRLogUtil.kr_i('设置为已登录状态', tag: 'HomeController');
// 检查公告服务
KRAnnouncementService().kr_checkAnnouncement();
// 确保订阅服务初始化
_kr_ensureSubscribeServiceInitialized();
} else {
kr_currentViewStatus.value = KRHomeViewsStatus.kr_notLoggedIn;
KRLogUtil.kr_i('设置为未登录状态', tag: 'HomeController');
}
} catch (e) {
KRLogUtil.kr_e('登录状态验证失败: $e', tag: 'HomeController');
kr_currentViewStatus.value = KRHomeViewsStatus.kr_notLoggedIn;
}
}
/// 确保订阅服务初始化
void _kr_ensureSubscribeServiceInitialized() {
try {
// 检查订阅服务状态
final currentStatus = kr_subscribeService.kr_currentStatus.value;
KRLogUtil.kr_i('订阅服务当前状态: $currentStatus', tag: 'HomeController');
if (currentStatus == KRSubscribeServiceStatus.kr_none ||
currentStatus == KRSubscribeServiceStatus.kr_error) {
KRLogUtil.kr_i('订阅服务未初始化或错误,开始初始化', tag: 'HomeController');
// 设置加载状态
kr_currentListStatus.value = KRHomeViewsListStatus.kr_loading;
// 初始化订阅服务
kr_subscribeService.kr_refreshAll().then((_) {
KRLogUtil.kr_i('订阅服务初始化完成', tag: 'HomeController');
}).catchError((error) {
KRLogUtil.kr_e('订阅服务初始化失败: $error', tag: 'HomeController');
kr_currentListStatus.value = KRHomeViewsListStatus.kr_error;
});
} else if (currentStatus == KRSubscribeServiceStatus.kr_loading) {
KRLogUtil.kr_i('订阅服务正在初始化中', tag: 'HomeController');
kr_currentListStatus.value = KRHomeViewsListStatus.kr_loading;
} else if (currentStatus == KRSubscribeServiceStatus.kr_success) {
KRLogUtil.kr_i('订阅服务已成功初始化', tag: 'HomeController');
kr_currentListStatus.value = KRHomeViewsListStatus.kr_none;
}
} catch (e) {
KRLogUtil.kr_e('确保订阅服务初始化失败: $e', tag: 'HomeController');
kr_currentListStatus.value = KRHomeViewsListStatus.kr_error;
}
}
/// 处理登录状态变化
void _kr_handleLoginStatusChange(bool isLoggedIn) {
try {
if (isLoggedIn) {
// 再次验证登录状态的有效性
final isValidLogin = KRAppRunData().kr_token != null && KRAppRunData().kr_token!.isNotEmpty;
if (isValidLogin) {
kr_currentViewStatus.value = KRHomeViewsStatus.kr_loggedIn;
KRLogUtil.kr_i('登录状态变化:设置为已登录', tag: 'HomeController');
KRAnnouncementService().kr_checkAnnouncement();
// 确保订阅服务初始化
_kr_ensureSubscribeServiceInitialized();
} else {
KRLogUtil.kr_w('登录状态为true但token为空重置为未登录', tag: 'HomeController');
kr_currentViewStatus.value = KRHomeViewsStatus.kr_notLoggedIn;
}
} else {
kr_currentViewStatus.value = KRHomeViewsStatus.kr_notLoggedIn;
KRLogUtil.kr_i('登录状态变化:设置为未登录', tag: 'HomeController');
kr_subscribeService.kr_logout();
}
} catch (e) {
KRLogUtil.kr_e('处理登录状态变化失败: $e', tag: 'HomeController');
kr_currentViewStatus.value = KRHomeViewsStatus.kr_notLoggedIn;
}
}
/// 添加状态同步检查
void _kr_addStatusSyncCheck() {
// 在下一帧检查状态同步
WidgetsBinding.instance.addPostFrameCallback((_) {
_kr_syncLoginStatus();
});
}
/// 同步登录状态
void _kr_syncLoginStatus() {
try {
final currentLoginStatus = KRAppRunData().kr_isLogin.value;
final currentViewStatus = kr_currentViewStatus.value;
KRLogUtil.kr_i('状态同步检查: login=$currentLoginStatus, view=$currentViewStatus', tag: 'HomeController');
// 检查状态是否一致
if (currentViewStatus == KRHomeViewsStatus.kr_loggedIn && !currentLoginStatus) {
KRLogUtil.kr_w('状态不一致:视图显示已登录但实际未登录,修正状态', tag: 'HomeController');
kr_currentViewStatus.value = KRHomeViewsStatus.kr_notLoggedIn;
} else if (currentViewStatus == KRHomeViewsStatus.kr_notLoggedIn && currentLoginStatus) {
KRLogUtil.kr_w('状态不一致:视图显示未登录但实际已登录,修正状态', tag: 'HomeController');
_kr_validateAndSetLoginStatus();
}
} catch (e) {
KRLogUtil.kr_e('状态同步检查失败: $e', tag: 'HomeController');
}
}
/// 属性数据
void kr_refreshAll() {
kr_subscribeService.kr_refreshAll();
}
/// 绑定订阅状态
void _bindSubscribeStatus() {
ever(kr_subscribeService.kr_currentStatus, (data) {
KRLogUtil.kr_i('订阅服务状态变化: $data', tag: 'HomeController');
if (KRAppRunData.getInstance().kr_isLogin.value) {
switch (data) {
case KRSubscribeServiceStatus.kr_loading:
KRLogUtil.kr_i('订阅服务加载中', tag: 'HomeController');
kr_currentListStatus.value = KRHomeViewsListStatus.kr_loading;
break;
case KRSubscribeServiceStatus.kr_error:
KRLogUtil.kr_w('订阅服务错误', tag: 'HomeController');
kr_currentListStatus.value = KRHomeViewsListStatus.kr_error;
// 不再自动重试,让用户手动刷新
break;
case KRSubscribeServiceStatus.kr_success:
KRLogUtil.kr_i('订阅服务成功', tag: 'HomeController');
kr_cutTag.value = 'auto';
kr_cutSeletedTag.value = 'auto';
kr_currentNodeName.value = "auto";
if (kr_currentListStatus.value != KRHomeViewsListStatus.kr_none) {
kr_currentListStatus.value = KRHomeViewsListStatus.kr_none;
} else {
kr_updateBottomPanelHeight();
}
// 刷新地图标记显示
showMarkersMap();
// 调试:打印节点坐标信息
Future.delayed(const Duration(milliseconds: 500), () {
kr_debugPrintNodeCoordinates();
});
break;
case KRSubscribeServiceStatus.kr_none:
KRLogUtil.kr_i('订阅服务未初始化', tag: 'HomeController');
// 如果状态为none且已登录尝试初始化仅首次
if (kr_currentViewStatus.value == KRHomeViewsStatus.kr_loggedIn &&
kr_subscribeService.kr_availableSubscribes.isEmpty) {
_kr_ensureSubscribeServiceInitialized();
}
break;
}
} else {
KRLogUtil.kr_i('用户未登录,忽略订阅状态变化', tag: 'HomeController');
}
});
// 监听所有支付相关消息
KREventBus().kr_listenMessages(
[KRMessageType.kr_payment, KRMessageType.kr_subscribe_update],
_kr_handleMessage,
);
}
/// 处理消息
void _kr_handleMessage(KRMessageData message) {
switch (message.kr_type) {
case KRMessageType.kr_payment:
kr_refreshAll();
break;
case KRMessageType.kr_subscribe_update:
// 处理订阅更新消息
// 显示提示框
KRDialog.show(
title: AppTranslations.kr_home.subscriptionUpdated,
message: AppTranslations.kr_home.subscriptionUpdatedMessage,
confirmText: AppTranslations.kr_dialog.kr_confirm,
cancelText: AppTranslations.kr_dialog.kr_cancel,
onConfirm: () {
kr_refreshAll();
},
onCancel: () => Get.back(),
);
break;
// TODO: Handle this case.
}
}
/// 绑定连接状态
void _bindConnectionStatus() {
// 添加更详细的状态监听
ever(KRSingBoxImp.instance.kr_status, (status) {
KRLogUtil.kr_i('🔄 连接状态变化: $status', tag: 'HomeController');
KRLogUtil.kr_i('📊 当前状态类型: ${status.runtimeType}', tag: 'HomeController');
switch (status) {
case SingboxStopped():
KRLogUtil.kr_i('🔴 状态: 已停止', tag: 'HomeController');
kr_connectText.value = AppTranslations.kr_home.disconnected;
kr_stopConnectionTimer();
kr_resetConnectionInfo();
kr_currentSpeed.value = "--";
kr_isLatency.value = false;
kr_isConnected.value = false;
kr_currentNodeLatency.value = -2;
// 强制刷新 isConnected 状态
kr_isConnected.refresh();
break;
case SingboxStarting():
KRLogUtil.kr_i('🟡 状态: 正在启动', tag: 'HomeController');
kr_connectText.value = AppTranslations.kr_home.connecting;
kr_currentSpeed.value = AppTranslations.kr_home.connecting;
kr_currentNodeLatency.value = -1;
kr_isConnected.value = false; // 修复启动中应该为false
// 启动连接超时处理
_startConnectionTimeout();
break;
case SingboxStarted():
KRLogUtil.kr_i('🟢 状态: 已启动', tag: 'HomeController');
// 取消连接超时处理
_cancelConnectionTimeout();
kr_connectText.value = AppTranslations.kr_home.connected;
kr_startConnectionTimer();
kr_updateConnectionInfo();
kr_isLatency.value = false;
kr_isConnected.value = true;
// 🔧 修复:立即尝试更新延迟值
_kr_updateLatencyOnConnected();
// 强制刷新 isConnected 状态
kr_isConnected.refresh();
// 强制更新UI
update();
break;
case SingboxStopping():
KRLogUtil.kr_i('🟠 状态: 正在停止', tag: 'HomeController');
kr_connectText.value = AppTranslations.kr_home.disconnecting;
kr_isConnected.value = false;
kr_currentSpeed.value = "--";
break;
}
// 强制更新UI
update();
});
// 添加活动组监听,确保状态同步
ever(KRSingBoxImp.instance.kr_activeGroups, (value) {
KRLogUtil.kr_i('📡 活动组更新,数量: ${value.length}', tag: 'HomeController');
if (value.isEmpty) {
KRLogUtil.kr_w('⚠️ 活动组为空', tag: 'HomeController');
// 🔧 修复如果已连接但活动组为空设置延迟为0而不是-1
if (kr_isConnected.value && kr_currentNodeLatency.value == -1) {
KRLogUtil.kr_w('⚠️ 已连接但活动组为空设置延迟为0', tag: 'HomeController');
kr_currentNodeLatency.value = 0;
}
return;
}
try {
bool hasSelector = false;
for (var element in value) {
KRLogUtil.kr_i('📋 处理组: ${element.tag}, 类型: ${element.type}, 选中: ${element.selected}', tag: 'HomeController');
if (element.type == ProxyType.selector) {
hasSelector = true;
_kr_handleSelectorProxy(element, value);
} else if (element.type == ProxyType.urltest) {
KRLogUtil.kr_d('URL测试代理选中: ${element.selected}', tag: 'HomeController');
}
}
// 🔧 修复如果已连接但没有selector组设置延迟为0
if (!hasSelector && kr_isConnected.value && kr_currentNodeLatency.value == -1) {
KRLogUtil.kr_w('⚠️ 已连接但无selector组设置延迟为0', tag: 'HomeController');
kr_currentNodeLatency.value = 0;
}
// 强制更新UI
update();
} catch (e) {
KRLogUtil.kr_e('处理活动组时发生错误: $e', tag: 'HomeController');
// 🔧 修复发生错误时如果已连接设置延迟为0
if (kr_isConnected.value && kr_currentNodeLatency.value == -1) {
KRLogUtil.kr_w('⚠️ 处理活动组错误设置延迟为0', tag: 'HomeController');
kr_currentNodeLatency.value = 0;
}
}
});
ever(KRSingBoxImp.instance.kr_allGroups, (value) {
List<String> updateTags = []; // 收集需要更新的标记ID
for (var element in value) {
for (var subElement in element.items) {
var node = kr_subscribeService.keyList[subElement.tag];
if (node != null) {
if (subElement.urlTestDelay != 0) {
node.urlTestDelay.value = subElement.urlTestDelay;
updateTags.add(subElement.tag); // 添加需要更新的标记ID
}
}
}
// 批量更新所有变化的标记
}
if (updateTags.isNotEmpty) {
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();
});
}
void kr_toggleSwitch(bool value) async {
// 如果正在切换中,直接返回
if (kr_isSwitching) {
KRLogUtil.kr_i('正在切换中,忽略本次操作', tag: 'HomeController');
return;
}
try {
kr_isSwitching = true;
if (value) {
await KRSingBoxImp.instance.kr_start();
// 启动成功后立即同步一次确保UI及时更新
Future.delayed(const Duration(milliseconds: 300), () {
kr_forceSyncConnectionStatus();
});
// 再次延迟验证,确保状态稳定
Future.delayed(const Duration(seconds: 2), () {
kr_forceSyncConnectionStatus();
});
} else {
await KRSingBoxImp.instance.kr_stop();
}
// 刷新地图标记
showMarkersMap();
} catch (e) {
KRLogUtil.kr_e('切换失败: $e', tag: 'HomeController');
// 当启动失败时如VPN权限被拒绝强制同步状态
Future.delayed(const Duration(milliseconds: 100), () {
kr_forceSyncConnectionStatus();
});
} finally {
// 确保在任何情况下都会重置标志
kr_isSwitching = false;
}
}
/// 处理选择器代理
void _kr_handleSelectorProxy(dynamic element, List<dynamic> allGroups) {
try {
KRLogUtil.kr_d(
'处理选择器代理 - 当前选择: ${element.selected}, 用户选择: ${kr_cutTag.value}',
tag: 'HomeController');
// 如果用户选择了auto但实际select类型不是auto
if (kr_cutTag.value == "auto" && element.selected != "auto") {
KRLogUtil.kr_d('用户选择了auto但实际不是auto重新选择auto', tag: 'HomeController');
KRSingBoxImp.instance.kr_selectOutbound("auto");
_kr_handleAutoMode(element, allGroups);
return;
}
// 如果用户选择了具体节点但实际select类型不是该节点
if (kr_cutTag.value != "auto" && element.selected != kr_cutTag.value) {
KRLogUtil.kr_d('用户选择了${kr_cutTag.value}但实际是${element.selected},更新选择',
tag: 'HomeController');
kr_selectNode(kr_cutTag.value);
return;
}
// 如果用户手动选择了节点不是auto
if (kr_cutTag.value != "auto") {
_kr_handleManualMode(element);
return;
}
// 默认auto模式处理
_kr_handleAutoMode(element, allGroups);
} catch (e) {
KRLogUtil.kr_e('处理选择器代理出错: $e', tag: 'HomeController');
}
}
/// 处理手动模式
void _kr_handleManualMode(dynamic element) {
try {
KRLogUtil.kr_d('处理手动模式 - 选择: ${element.selected}', tag: 'HomeController');
// 如果当前选择与用户选择不同,更新选择
if (kr_cutTag.value != element.selected) {
// 检查选择的节点是否有效
if (_kr_isValidLatency(kr_cutTag.value)) {
kr_selectNode(kr_cutTag.value);
// 更新延迟值
_kr_updateNodeLatency(element);
} else {
// 如果选择的节点无效,尝试选择延迟最小的节点
_kr_selectBestLatencyNode(element.items);
}
} else {
kr_cutSeletedTag.value = element.selected;
// 更新延迟值
_kr_updateNodeLatency(element);
kr_currentNodeName.value =
kr_truncateText(element.selected, maxLength: 25);
kr_moveToSelectedNode();
}
} catch (e) {
KRLogUtil.kr_e('处理手动模式出错: $e', tag: 'HomeController');
}
}
/// 更新节点延迟
void _kr_updateNodeLatency(dynamic element) {
try {
bool delayUpdated = false;
for (var subElement in element.items) {
if (subElement.tag == element.selected) {
// 检查延迟是否有效
if (subElement.urlTestDelay != 0) {
kr_currentNodeLatency.value = subElement.urlTestDelay;
delayUpdated = true;
}
// 更新速度显示
// kr_updateSpeed(subElement.urlTestDelay);
// // 停止动画
// _kr_speedAnimationController.reverse();
KRLogUtil.kr_d('更新节点延迟: ${subElement.urlTestDelay}',
tag: 'HomeController');
break;
}
}
// 🔧 修复如果已连接但延迟未更新设置为0
if (!delayUpdated && kr_isConnected.value && kr_currentNodeLatency.value == -1) {
KRLogUtil.kr_w('⚠️ 已连接但延迟未更新设置为0', tag: 'HomeController');
kr_currentNodeLatency.value = 0;
}
} catch (e) {
KRLogUtil.kr_e('更新节点延迟出错: $e', tag: 'HomeController');
// 🔧 修复:发生错误时,根据连接状态设置合适的值
if (kr_isConnected.value) {
kr_currentNodeLatency.value = 0; // 已连接但延迟未知
} else {
kr_currentNodeLatency.value = -2; // 未连接
}
kr_currentSpeed.value = "--";
// 停止动画
// _kr_speedAnimationController.reverse();
}
}
/// 处理自动模式
void _kr_handleAutoMode(dynamic element, List<dynamic> allGroups) {
KRLogUtil.kr_d('处理自动模式 - 活动组: ${allGroups.toString()}',
tag: 'HomeController');
// 更新auto模式的延迟
_kr_updateAutoLatency(element);
// 查找并处理urltest类型的组
for (var item in allGroups) {
if (item.type == ProxyType.urltest) {
// 检查延迟是否有效小于65535
if (item.selected != null && _kr_isValidLatency(item.selected)) {
kr_cutSeletedTag.value = item.selected;
kr_currentNodeName.value =
kr_truncateText("${item.selected}(auto)", maxLength: 25);
kr_moveToSelectedNode();
kr_updateConnectionInfo();
break;
} else {
// 如果延迟无效,尝试选择延迟最小的节点
_kr_selectBestLatencyNode(item.items);
break;
}
}
}
}
/// 选择延迟最小的节点
void _kr_selectBestLatencyNode(List<dynamic> items) {
int minDelay = 65535;
String? bestNode = null;
for (var item in items) {
// 只考虑有效的延迟值小于65535且大于0
if (item.urlTestDelay < minDelay &&
item.urlTestDelay < 65535 &&
item.urlTestDelay > 0) {
minDelay = item.urlTestDelay;
bestNode = item.tag;
}
}
if (bestNode != null) {
kr_cutSeletedTag.value = bestNode;
kr_currentNodeName.value =
kr_truncateText("${bestNode}(auto)", maxLength: 25);
kr_moveToSelectedNode();
kr_updateConnectionInfo();
}
}
/// 更新连接信息
void kr_updateConnectionInfo() {
try {
final selectedNode = kr_subscribeService.keyList[kr_cutSeletedTag.value];
if (selectedNode != null) {
KRLogUtil.kr_d(
'更新节点信息 - 协议: ${selectedNode.protocol}, IP: ${selectedNode.serverAddr}',
tag: 'HomeController');
kr_currentProtocol.value =
kr_truncateText(selectedNode.protocol, maxLength: 15);
kr_currentIp.value =
kr_truncateText(selectedNode.serverAddr, maxLength: 20);
} else {
KRLogUtil.kr_d('未找到选中的节点: ${kr_cutSeletedTag.value}',
tag: 'HomeController');
kr_currentProtocol.value = "--";
kr_currentIp.value = "--";
}
} catch (e) {
KRLogUtil.kr_e('更新连接信息失败: $e', tag: 'HomeController');
kr_currentProtocol.value = "--";
kr_currentIp.value = "--";
}
}
/// 处理文本截断
String kr_truncateText(String text, {int maxLength = 20}) {
if (text.length <= maxLength) return text;
return '${text.substring(0, maxLength)}...';
}
/// 检查延迟是否有效
bool _kr_isValidLatency(String? nodeTag) {
if (nodeTag == null) return false;
// 从keyList中获取节点信息
final node = kr_subscribeService.keyList[nodeTag];
if (node == null) return false;
// 检查延迟是否有效小于65535且大于0
return node.urlTestDelay.value < 65535 && node.urlTestDelay.value > 0;
}
/// 更新自动模式延迟
void _kr_updateAutoLatency(dynamic element) {
for (var subElement in element.items) {
if (subElement.tag == "auto") {
if (subElement.urlTestDelay != 0) {
kr_currentNodeLatency.value = subElement.urlTestDelay;
} else {
kr_currentNodeLatency.value = -2; // 当延迟为 0 时,设置为未连接状态
}
break;
}
}
}
/// 切换列表状态
void kr_switchListStatus(KRHomeViewsListStatus status) {
kr_currentListStatus.value = status;
}
// 切换订阅
Future<void> kr_switchSubscribe(
KRUserAvailableSubscribeItem subscribe) async {
try {
KRLogUtil.kr_i("kr_switchSubscribe", tag: "kr_switchSubscribe");
// 通知订阅服务切换订阅
await kr_subscribeService.kr_switchSubscribe(subscribe);
} catch (e) {
KRLogUtil.kr_e('切换订阅失败: $e', tag: 'HomeController');
rethrow;
}
}
// 选择节点
void kr_selectNode(String tag) {
try {
kr_currentNodeLatency.value = -1;
kr_cutTag.value = tag;
kr_currentNodeName.value = tag;
// 更新当前选中的标签
kr_cutSeletedTag.value = tag;
// 更新连接信息
kr_updateConnectionInfo();
if (KRSingBoxImp.instance.kr_status.value == SingboxStarted()) {
KRSingBoxImp.instance.kr_selectOutbound(tag);
// 🔧 修复:选择节点后启动延迟值更新(带超时保护)
Future.delayed(const Duration(milliseconds: 500), () {
if (kr_currentNodeLatency.value == -1 && kr_isConnected.value) {
KRLogUtil.kr_w('⚠️ 选择节点后延迟值未更新,尝试手动更新', tag: 'HomeController');
if (!_kr_tryUpdateDelayFromActiveGroups()) {
kr_currentNodeLatency.value = 0;
}
}
});
} else {
KRSingBoxImp().kr_start();
}
// 移动到选中的节点
kr_moveToSelectedNode();
} catch (e) {
KRLogUtil.kr_e('选择节点失败: $e', tag: 'HomeController');
// 🔧 修复:选择节点失败时,根据连接状态设置合适的延迟值
if (kr_isConnected.value) {
kr_currentNodeLatency.value = 0;
} else {
kr_currentNodeLatency.value = -2;
}
}
}
/// 获取当前节点国家
String kr_getCurrentNodeCountry() {
if (kr_cutSeletedTag.isEmpty) return '';
final node = kr_subscribeService.keyList[kr_cutSeletedTag.value];
KRLogUtil.kr_i(kr_cutSeletedTag.value, tag: "kr_getCurrentNodeCountry");
return node?.country ?? '';
}
// 格式化字节数
String kr_formatBytes(int bytes) {
if (bytes < 1024) {
return '$bytes B';
} else if (bytes < 1024 * 1024) {
return '${(bytes / 1024).toStringAsFixed(1)} KB';
} else if (bytes < 1024 * 1024 * 1024) {
return '${(bytes / (1024 * 1024)).toStringAsFixed(1)} MB';
} else {
return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(1)} GB';
}
}
// 设置当前选中的组
void kr_setCurrentGroup(dynamic group) {
try {
KRLogUtil.kr_i('设置当前组: ${group.tag}', tag: 'HomeController');
kr_currentGroup.value = group;
update(); // 通知 GetBuilder 更新
} catch (e) {
KRLogUtil.kr_e('设置当前组失败: $e', tag: 'HomeController');
}
}
/// 获取国家全称
/// [countryCode] 国家代码(大小写不敏感)
String kr_getCountryFullName(String countryCode) {
final Map<String, String> countryNames = {
'CN': 'China',
'HK': 'Hong Kong',
'TW': 'Taiwan',
'MO': 'Macao',
'US': 'United States',
'JP': 'Japan',
'KR': 'South Korea',
'SG': 'Singapore',
'MY': 'Malaysia',
'TH': 'Thailand',
'VN': 'Vietnam',
'ID': 'Indonesia',
'PH': 'Philippines',
'IN': 'India',
'RU': 'Russia',
'GB': 'United Kingdom',
'DE': 'Germany',
'FR': 'France',
'IT': 'Italy',
'ES': 'Spain',
'NL': 'Netherlands',
'CH': 'Switzerland',
'SE': 'Sweden',
'NO': 'Norway',
'FI': 'Finland',
'DK': 'Denmark',
'IE': 'Ireland',
'AT': 'Austria',
'PT': 'Portugal',
'PL': 'Poland',
'UA': 'Ukraine',
'CA': 'Canada',
'MX': 'Mexico',
'BR': 'Brazil',
'AR': 'Argentina',
'AU': 'Australia',
'NZ': 'New Zealand',
'ZA': 'South Africa',
'AE': 'United Arab Emirates',
'IL': 'Israel',
'TR': 'Turkey',
};
final String code = countryCode.toUpperCase();
return countryNames[code] ?? 'Unknown Country';
}
@override
void onReady() {
super.onReady();
}
@override
void onClose() {
super.onClose();
}
// 更新底部面板高度
void kr_updateBottomPanelHeight() {
if (kr_subscribeService.kr_currentStatus ==
KRHomeViewsListStatus.kr_loading) {
return;
}
KRLogUtil.kr_i('更新底部面板高度', tag: 'HomeController');
KRLogUtil.kr_i('当前视图状态: ${kr_currentViewStatus.value}',
tag: 'HomeController');
KRLogUtil.kr_i('当前列表状态: ${kr_currentListStatus.value}',
tag: 'HomeController');
KRLogUtil.kr_i('是否试用: ${kr_subscribeService.kr_isTrial.value}',
tag: 'HomeController');
KRLogUtil.kr_i(
'是否最后一天: ${kr_subscribeService.kr_isLastDayOfSubscription.value}',
tag: 'HomeController');
double targetHeight = 0.0;
if (kr_currentViewStatus.value == KRHomeViewsStatus.kr_notLoggedIn) {
// 未登录状态下,高度由内容撑开
targetHeight = kr_subscriptionCardHeight +
kr_baseHeight +
kr_marginTop +
kr_marginBottom +
kr_marginVertical * 2;
KRLogUtil.kr_i('未登录状态,目标高度: $targetHeight', tag: 'HomeController');
} else if (kr_currentListStatus.value ==
KRHomeViewsListStatus.kr_serverList ||
kr_currentListStatus.value ==
KRHomeViewsListStatus.kr_countrySubscribeList ||
kr_currentListStatus.value ==
KRHomeViewsListStatus.kr_serverSubscribeList ||
kr_currentListStatus.value == KRHomeViewsListStatus.kr_subscribeList) {
targetHeight = kr_nodeListHeight + kr_marginVertical * 2;
KRLogUtil.kr_i('节点列表状态,目标高度: $targetHeight', tag: 'HomeController');
} else {
// 已登录状态下的默认高度计算
targetHeight = kr_baseHeight + kr_marginTop + kr_marginBottom;
KRLogUtil.kr_i('基础高度: $targetHeight', tag: 'HomeController');
if (kr_subscribeService.kr_currentSubscribe.value != null) {
targetHeight += kr_connectionInfoHeight + kr_marginTop;
KRLogUtil.kr_i('添加连接信息卡片高度: $targetHeight', tag: 'HomeController');
} else {
targetHeight += kr_subscriptionCardHeight + kr_marginTop;
KRLogUtil.kr_i('添加订阅卡片高度: $targetHeight', tag: 'HomeController');
}
// 如果有试用状态,添加试用卡片高度
if (kr_subscribeService.kr_isTrial.value) {
targetHeight += kr_trialCardHeight + kr_marginTop;
KRLogUtil.kr_i('添加试用卡片高度: $targetHeight', tag: 'HomeController');
}
// 如果是最后一天,添加最后一天卡片高度
else if (kr_subscribeService.kr_isLastDayOfSubscription.value) {
targetHeight += kr_lastDayCardHeight + kr_marginTop;
KRLogUtil.kr_i('添加最后一天卡片高度: $targetHeight', tag: 'HomeController');
}
}
KRLogUtil.kr_i('最终目标高度: $targetHeight', tag: 'HomeController');
kr_bottomPanelHeight.value = targetHeight;
}
// 移动到选中节点
void kr_moveToSelectedNode() {
try {
if (kr_cutSeletedTag.isEmpty) return;
final selectedNode = kr_subscribeService.keyList[kr_cutSeletedTag.value];
if (selectedNode == null) return;
final location = LatLng(selectedNode.latitude, selectedNode.longitude);
kr_moveToLocation(location);
} catch (e) {
KRLogUtil.kr_e('移动到选中节点失败: $e', tag: 'HomeController');
}
}
// 简化移动地图方法
void kr_moveToLocation(LatLng location, [double zoom = 5.0]) {
try {
kr_mapController.move(location, zoom);
kr_isUserMoving.value = false;
} catch (e) {
KRLogUtil.kr_e('移动地图失败: $e', tag: 'HomeController');
}
}
// 添加一个方法来批量更新标记
void kr_updateMarkers(List<String> tags) {
// 使用Set来去重
final Set<String> updateIds = tags.toSet();
// 一次性更新所有需要更新的标记
update(updateIds.toList());
// 延迟2秒后关闭加载状态
Future.delayed(const Duration(seconds: 1), () {
kr_isLatency.value = false;
});
}
/// 刷新地图标记
void showMarkersMap() {
KRLogUtil.kr_i('========== 刷新地图标记 ==========', tag: 'HomeController');
KRLogUtil.kr_i('当前选中节点: ${kr_cutSeletedTag.value}', tag: 'HomeController');
KRLogUtil.kr_i('可用节点数: ${kr_subscribeService.allList.length}', tag: 'HomeController');
KRLogUtil.kr_i('国家分组数: ${kr_subscribeService.countryOutboundList.length}', tag: 'HomeController');
// 手动触发地图标记更新
update(['map_markers']);
KRLogUtil.kr_i('✅ 地图标记更新完成', tag: 'HomeController');
}
/// 选择地图标记
void selectMarkerMap(int index) {
try {
if (index >= 0 && index < kr_subscribeService.allList.length) {
// 重置所有节点的选中状态
for (var item in kr_subscribeService.allList) {
item.selected = 0;
}
// 设置当前节点为选中状态
kr_subscribeService.allList[index].selected = 1;
// 手动触发更新
update(['map_markers']);
}
} catch (e) {
KRLogUtil.kr_e('选择地图标记失败: $e', tag: 'HomeController');
}
}
/// 手动触发 SingBox URL 测试(调试用)
Future<void> kr_manualUrlTest() async {
try {
KRLogUtil.kr_i('🔧 手动触发 SingBox URL 测试...', tag: 'HomeController');
// 直接调用 SingBox 的 URL 测试
await KRSingBoxImp.instance.kr_urlTest("auto");
// 等待测试完成
await Future.delayed(const Duration(seconds: 5));
// 检查结果
KRLogUtil.kr_i('📊 检查手动测试结果...', tag: 'HomeController');
final activeGroups = KRSingBoxImp.instance.kr_activeGroups;
for (int i = 0; i < activeGroups.length; i++) {
final group = activeGroups[i];
KRLogUtil.kr_i('📋 活动组[$i]: tag=${group.tag}, type=${group.type}, selected=${group.selected}', tag: 'HomeController');
for (int j = 0; j < group.items.length; j++) {
final item = group.items[j];
KRLogUtil.kr_i(' └─ 节点[$j]: tag=${item.tag}, type=${item.type}, delay=${item.urlTestDelay}', tag: 'HomeController');
}
}
} catch (e) {
KRLogUtil.kr_e('❌ 手动 URL 测试失败: $e', tag: 'HomeController');
}
}
/// 强制使用直接连接测试(绕过 SingBox URL 测试)
Future<void> kr_forceDirectTest() async {
try {
KRLogUtil.kr_i('🔧 强制使用直接连接测试...', tag: 'HomeController');
// 使用直接连接测试所有节点
await _kr_testLatencyWithoutVpn();
KRLogUtil.kr_i('✅ 直接连接测试完成', tag: 'HomeController');
} catch (e) {
KRLogUtil.kr_e('❌ 直接连接测试失败: $e', tag: 'HomeController');
}
}
/// 测试延迟
Future<void> kr_urlTest() async {
kr_isLatency.value = true;
try {
KRLogUtil.kr_i('🧪 开始延迟测试...', tag: 'HomeController');
KRLogUtil.kr_i('📊 当前连接状态: ${kr_isConnected.value}', tag: 'HomeController');
if (kr_isConnected.value) {
// 已连接状态:使用 SingBox 通过代理测试
KRLogUtil.kr_i('🔗 已连接状态 - 使用 SingBox 通过代理测试延迟', tag: 'HomeController');
await KRSingBoxImp.instance.kr_urlTest("select");
// 等待一段时间让 SingBox 完成测试
await Future.delayed(const Duration(seconds: 3));
// 再次检查活动组状态
KRLogUtil.kr_i('🔄 检查代理测试后的活动组状态...', tag: 'HomeController');
final activeGroups = KRSingBoxImp.instance.kr_activeGroups;
for (int i = 0; i < activeGroups.length; i++) {
final group = activeGroups[i];
KRLogUtil.kr_i('📋 活动组[$i]: tag=${group.tag}, type=${group.type}, selected=${group.selected}', tag: 'HomeController');
for (int j = 0; j < group.items.length; j++) {
final item = group.items[j];
KRLogUtil.kr_i(' └─ 节点[$j]: tag=${item.tag}, type=${item.type}, delay=${item.urlTestDelay}', tag: 'HomeController');
}
}
} else {
// 未连接状态使用本机网络直接ping节点IP
KRLogUtil.kr_i('🔌 未连接状态 - 使用本机网络直接ping节点IP测试延迟', tag: 'HomeController');
KRLogUtil.kr_i('🌐 这将绕过代理,直接使用本机网络连接节点', tag: 'HomeController');
await _kr_testLatencyWithoutVpn();
}
} catch (e) {
KRLogUtil.kr_e('❌ 延迟测试失败: $e', tag: 'HomeController');
} finally {
// 延迟1秒后关闭加载状态
Future.delayed(const Duration(seconds: 1), () {
kr_isLatency.value = false;
});
}
}
/// 未连接状态下的延迟测试(界面显示随机延迟,不影响真实逻辑)
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节点
final testableNodes = kr_subscribeService.allList
.where((item) => item.tag != 'auto')
.toList();
KRLogUtil.kr_i('📋 找到 ${testableNodes.length} 个可测试节点', tag: 'HomeController');
if (testableNodes.isEmpty) {
KRLogUtil.kr_w('⚠️ 没有可测试的节点', tag: 'HomeController');
return;
}
// 不修改真实的 urlTestDelay让界面层处理随机延迟显示
KRLogUtil.kr_i('✅ 延迟显示将由界面层处理,不影响节点选择逻辑', tag: 'NodeTest');
// 统计测试结果
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()
..sort((a, b) => a.urlTestDelay.value.compareTo(b.urlTestDelay.value));
if (sortedNodes.isNotEmpty) {
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');
}
}
} catch (e) {
KRLogUtil.kr_e('❌ 本机网络延迟测试过程出错: $e', tag: 'HomeController');
} finally {
kr_isLatency.value = false;
}
}
/// 开始连接计时
void kr_startConnectionTimer() {
kr_stopConnectionTimer();
_kr_connectionSeconds = 0;
_kr_connectionTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
_kr_connectionSeconds++;
kr_connectionTime.value = kr_formatDuration(_kr_connectionSeconds);
KRLogUtil.kr_i(kr_connectText.value);
});
}
/// 停止连接计时
void kr_stopConnectionTimer() {
_kr_connectionTimer?.cancel();
_kr_connectionTimer = null;
}
/// 格式化时长
String kr_formatDuration(int seconds) {
final hours = seconds ~/ 3600;
final minutes = (seconds % 3600) ~/ 60;
final remainingSeconds = seconds % 60;
return '${hours.toString().padLeft(2, '0')}:'
'${minutes.toString().padLeft(2, '0')}:'
'${remainingSeconds.toString().padLeft(2, '0')}';
}
/// 重置连接信息
void kr_resetConnectionInfo() {
kr_currentIp.value = AppTranslations.kr_home.disconnected;
kr_currentProtocol.value = AppTranslations.kr_home.disconnected;
kr_currentSpeed.value = "--";
kr_connectionTime.value = '00:00:00';
_kr_connectionSeconds = 0;
kr_currentNodeLatency.value = -2; // 设置为未连接状态
}
/// 调试:打印所有节点的坐标信息
void kr_debugPrintNodeCoordinates() {
KRLogUtil.kr_i('========== 节点坐标调试信息 ==========', tag: 'HomeController');
KRLogUtil.kr_i('节点总数: ${kr_subscribeService.allList.length}', tag: 'HomeController');
if (kr_subscribeService.allList.isEmpty) {
KRLogUtil.kr_w('节点列表为空!请检查:', tag: 'HomeController');
KRLogUtil.kr_w('1. 是否已登录', tag: 'HomeController');
KRLogUtil.kr_w('2. 是否有订阅', tag: 'HomeController');
KRLogUtil.kr_w('3. 订阅是否已加载完成', tag: 'HomeController');
return;
}
int validNodes = 0;
int invalidNodes = 0;
for (int i = 0; i < kr_subscribeService.allList.length; i++) {
final node = kr_subscribeService.allList[i];
if (node.latitude != 0.0 || node.longitude != 0.0) {
validNodes++;
if (i < 5) { // 只打印前5个有效节点
KRLogUtil.kr_i('节点[$i] ${node.tag}: (${node.latitude}, ${node.longitude})', tag: 'HomeController');
}
} else {
invalidNodes++;
if (i < 3) { // 只打印前3个无效节点
KRLogUtil.kr_w('节点[$i] ${node.tag}: 坐标为(0, 0) - 无效!', tag: 'HomeController');
}
}
}
KRLogUtil.kr_i('有效节点: $validNodes', tag: 'HomeController');
KRLogUtil.kr_w('无效节点(坐标为0): $invalidNodes', tag: 'HomeController');
if (invalidNodes > 0) {
KRLogUtil.kr_w('⚠️ 发现 $invalidNodes 个节点坐标为0这些节点不会显示在地图上', tag: 'HomeController');
KRLogUtil.kr_w('可能原因:', tag: 'HomeController');
KRLogUtil.kr_w('1. 后端API未返回 latitude/longitude 字段', tag: 'HomeController');
KRLogUtil.kr_w('2. 后端数据库中节点坐标未配置', tag: 'HomeController');
}
}
/// 强制同步连接状态
void kr_forceSyncConnectionStatus() {
try {
KRLogUtil.kr_i('🔄 强制同步连接状态...', tag: 'HomeController');
final currentStatus = KRSingBoxImp.instance.kr_status.value;
KRLogUtil.kr_i('📊 当前 SingBox 状态: $currentStatus', tag: 'HomeController');
// 根据当前状态强制更新UI
switch (currentStatus) {
case SingboxStopped():
kr_connectText.value = AppTranslations.kr_home.disconnected;
kr_isConnected.value = false;
kr_currentSpeed.value = "--";
kr_currentNodeLatency.value = -2;
break;
case SingboxStarting():
kr_connectText.value = AppTranslations.kr_home.connecting;
kr_isConnected.value = false;
kr_currentSpeed.value = AppTranslations.kr_home.connecting;
kr_currentNodeLatency.value = -1;
break;
case SingboxStarted():
kr_connectText.value = AppTranslations.kr_home.connected;
kr_isConnected.value = true;
kr_startConnectionTimer();
kr_updateConnectionInfo();
// 🔧 修复:同步已启动状态时,尝试更新延迟值
if (!_kr_tryUpdateDelayFromActiveGroups()) {
// 如果获取不到延迟值设置为0已连接但延迟未知
kr_currentNodeLatency.value = 0;
KRLogUtil.kr_w('⚠️ 强制同步时无法获取延迟值设置为0', tag: 'HomeController');
}
break;
case SingboxStopping():
kr_connectText.value = AppTranslations.kr_home.disconnecting;
kr_isConnected.value = false;
kr_currentSpeed.value = "--";
break;
}
// 强制更新UI
update();
KRLogUtil.kr_i('✅ 连接状态同步完成', tag: 'HomeController');
} catch (e) {
KRLogUtil.kr_e('❌ 强制同步连接状态失败: $e', tag: 'HomeController');
}
}
/// 连接超时处理
Timer? _connectionTimeoutTimer;
void _startConnectionTimeout() {
_connectionTimeoutTimer?.cancel();
_connectionTimeoutTimer = Timer(const Duration(seconds: 30), () {
KRLogUtil.kr_w('⏰ 连接超时,强制重置状态', tag: 'HomeController');
// 检查是否仍在连接中
if (KRSingBoxImp.instance.kr_status.value is SingboxStarting) {
KRLogUtil.kr_w('🔄 连接超时,强制停止并重置', tag: 'HomeController');
// 强制停止连接
KRSingBoxImp.instance.kr_stop().then((_) {
// 重置状态
kr_connectText.value = AppTranslations.kr_home.disconnected;
kr_isConnected.value = false;
kr_currentSpeed.value = "--";
kr_currentNodeLatency.value = -2;
kr_resetConnectionInfo();
update();
KRLogUtil.kr_i('✅ 连接超时处理完成', tag: 'HomeController');
}).catchError((e) {
KRLogUtil.kr_e('❌ 连接超时处理失败: $e', tag: 'HomeController');
});
}
});
}
void _cancelConnectionTimeout() {
_connectionTimeoutTimer?.cancel();
_connectionTimeoutTimer = null;
}
/// 连接成功后更新延迟值
void _kr_updateLatencyOnConnected() {
KRLogUtil.kr_i('🔧 尝试获取连接延迟值...', tag: 'HomeController');
// 立即尝试从活动组获取延迟
bool delayUpdated = _kr_tryUpdateDelayFromActiveGroups();
if (delayUpdated) {
KRLogUtil.kr_i('✅ 延迟值已从活动组更新', tag: 'HomeController');
return;
}
// 如果立即获取失败,设置临时值并启动延迟重试
KRLogUtil.kr_w('⚠️ 活动组暂无延迟数据,设置临时值并启动重试', tag: 'HomeController');
kr_currentNodeLatency.value = 0; // 设置为0表示已连接但延迟未知
// 延迟500ms后重试等待活动组数据到达
Future.delayed(const Duration(milliseconds: 500), () {
if (_kr_tryUpdateDelayFromActiveGroups()) {
KRLogUtil.kr_i('✅ 延迟重试成功,延迟值已更新', tag: 'HomeController');
return;
}
// 再次延迟1秒重试
Future.delayed(const Duration(seconds: 1), () {
if (_kr_tryUpdateDelayFromActiveGroups()) {
KRLogUtil.kr_i('✅ 第二次延迟重试成功', tag: 'HomeController');
return;
}
// 如果还是获取不到保持为0表示已连接但延迟未知
KRLogUtil.kr_w('⚠️ 多次重试后仍无法获取延迟值,保持为已连接状态', tag: 'HomeController');
kr_currentNodeLatency.value = 0;
});
});
}
/// 尝试从活动组更新延迟值
bool _kr_tryUpdateDelayFromActiveGroups() {
try {
final activeGroups = KRSingBoxImp.instance.kr_activeGroups;
if (activeGroups.isEmpty) {
KRLogUtil.kr_d('活动组为空', tag: 'HomeController');
return false;
}
// 查找 selector 类型的组
for (var group in activeGroups) {
if (group.type == ProxyType.selector) {
KRLogUtil.kr_d('找到 selector 组: ${group.tag}, 选中: ${group.selected}', tag: 'HomeController');
// 如果是auto模式从urltest组获取延迟
if (kr_cutTag.value == "auto") {
for (var item in group.items) {
if (item.tag == "auto" && item.urlTestDelay != 0) {
kr_currentNodeLatency.value = item.urlTestDelay;
KRLogUtil.kr_i('✅ auto模式延迟值: ${item.urlTestDelay}ms', tag: 'HomeController');
return true;
}
}
}
// 手动选择模式
else {
for (var item in group.items) {
if (item.tag == kr_cutTag.value && item.urlTestDelay != 0) {
kr_currentNodeLatency.value = item.urlTestDelay;
KRLogUtil.kr_i('✅ 手动模式延迟值: ${item.urlTestDelay}ms', tag: 'HomeController');
return true;
}
}
}
}
}
KRLogUtil.kr_d('未找到匹配的延迟数据', tag: 'HomeController');
return false;
} catch (e) {
KRLogUtil.kr_e('获取延迟值失败: $e', tag: 'HomeController');
return false;
}
}
}