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(); /// 当前视图状态,登录状态 final Rx 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 kr_currentGroup = Rx(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; // 启动重试机制 _kr_retrySubscribeService(); } }); // 延迟初始化,确保所有异步操作完成 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; // 启动重试机制 _kr_retrySubscribeService(); }); } 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_retrySubscribeService() { KRLogUtil.kr_i('启动订阅服务重试机制', tag: 'HomeController'); Timer(const Duration(seconds: 3), () { if (kr_currentListStatus.value == KRHomeViewsListStatus.kr_error) { KRLogUtil.kr_i('重试订阅服务初始化', tag: 'HomeController'); kr_subscribeService.kr_refreshAll().then((_) { KRLogUtil.kr_i('订阅服务重试成功', tag: 'HomeController'); }).catchError((error) { KRLogUtil.kr_e('订阅服务重试失败: $error', tag: 'HomeController'); // 如果重试失败,再次重试(最多重试3次) Timer(const Duration(seconds: 5), () { if (kr_currentListStatus.value == KRHomeViewsListStatus.kr_error) { KRLogUtil.kr_i('第二次重试订阅服务初始化', tag: 'HomeController'); kr_subscribeService.kr_refreshAll().catchError((error) { KRLogUtil.kr_e('第二次重试失败: $error', tag: 'HomeController'); }); } }); }); } }); } /// 处理登录状态变化 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; // 添加重试机制 _kr_retrySubscribeService(); 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(); } break; case KRSubscribeServiceStatus.kr_none: KRLogUtil.kr_i('订阅服务未初始化', tag: 'HomeController'); // 如果状态为none且已登录,尝试初始化 if (kr_currentViewStatus.value == KRHomeViewsStatus.kr_loggedIn) { _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; 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; // 强制更新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'); return; } try { for (var element in value) { KRLogUtil.kr_i('📋 处理组: ${element.tag}, 类型: ${element.type}, 选中: ${element.selected}', tag: 'HomeController'); if (element.type == ProxyType.selector) { _kr_handleSelectorProxy(element, value); } else if (element.type == ProxyType.urltest) { KRLogUtil.kr_d('URL测试代理选中: ${element.selected}', tag: 'HomeController'); } } // 强制更新UI update(); } catch (e) { KRLogUtil.kr_e('处理活动组时发生错误: $e', tag: 'HomeController'); } }); ever(KRSingBoxImp.instance.kr_allGroups, (value) { List 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(); // 添加延迟验证,确保状态正确更新 Future.delayed(const Duration(seconds: 2), () { kr_forceSyncConnectionStatus(); }); } else { await KRSingBoxImp.instance.kr_stop(); } } 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 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 { for (var subElement in element.items) { if (subElement.tag == element.selected) { // 检查延迟是否有效 if (subElement.urlTestDelay != 0) { kr_currentNodeLatency.value = subElement.urlTestDelay; } // 更新速度显示 // kr_updateSpeed(subElement.urlTestDelay); // // 停止动画 // _kr_speedAnimationController.reverse(); KRLogUtil.kr_d('更新节点延迟: ${subElement.urlTestDelay}', tag: 'HomeController'); break; } } } catch (e) { KRLogUtil.kr_e('更新节点延迟出错: $e', tag: 'HomeController'); kr_currentNodeLatency.value = -2; kr_currentSpeed.value = "--"; // 停止动画 // _kr_speedAnimationController.reverse(); } } /// 处理自动模式 void _kr_handleAutoMode(dynamic element, List 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 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 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); } else { KRSingBoxImp().kr_start(); } // 移动到选中的节点 kr_moveToSelectedNode(); } catch (e) { KRLogUtil.kr_e('选择节点失败: $e', tag: 'HomeController'); } } /// 获取当前节点国家 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 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 tags) { // 使用Set来去重 final Set updateIds = tags.toSet(); // 一次性更新所有需要更新的标记 update(updateIds.toList()); // 延迟2秒后关闭加载状态 Future.delayed(const Duration(seconds: 1), () { kr_isLatency.value = false; }); } /// 手动触发 SingBox URL 测试(调试用) Future 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 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 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 _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_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(); 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; } }