feat: bugfix
This commit is contained in:
@@ -109,8 +109,15 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
|
||||
// 连接计时器
|
||||
Timer? _kr_connectionTimer;
|
||||
|
||||
// 🔧 新增:EventBus 监听器 Worker(用于清理)
|
||||
Worker? _eventBusWorker;
|
||||
int _kr_connectionSeconds = 0;
|
||||
|
||||
// 🔧 保守修复:添加状态变化时间追踪,用于检测状态卡住
|
||||
DateTime? _lastStatusChangeTime;
|
||||
Timer? _statusWatchdogTimer;
|
||||
|
||||
// 当前选中的组
|
||||
final Rx<KRGroupOutboundList?> kr_currentGroup =
|
||||
Rx<KRGroupOutboundList?>(null);
|
||||
@@ -315,13 +322,8 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
});
|
||||
|
||||
// 🔧 Android 15 新增:5秒后再次强制更新高度,兜底保护
|
||||
Future.delayed(const Duration(seconds: 5), () {
|
||||
if (kr_bottomPanelHeight.value < 100) {
|
||||
KRLogUtil.kr_w('检测到底部面板高度异常(${kr_bottomPanelHeight.value}),强制修正',
|
||||
tag: 'HomeController');
|
||||
kr_updateBottomPanelHeight();
|
||||
}
|
||||
});
|
||||
// 🔧 保守修复: 启动状态监控定时器,每 30 秒检查一次状态
|
||||
_startStatusWatchdog();
|
||||
}
|
||||
|
||||
/// 🔧 新增:恢复上次选择的节点显示
|
||||
@@ -694,11 +696,14 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
}
|
||||
});
|
||||
|
||||
// 监听所有支付相关消息
|
||||
KREventBus().kr_listenMessages(
|
||||
// 🔧 修复:保存 EventBus 监听器 Worker,以便在控制器销毁时清理
|
||||
_eventBusWorker = KREventBus().kr_listenMessages(
|
||||
[KRMessageType.kr_payment, KRMessageType.kr_subscribe_update],
|
||||
_kr_handleMessage,
|
||||
);
|
||||
if (kDebugMode) {
|
||||
print('✅ [HomeController] EventBus 监听器已注册');
|
||||
}
|
||||
}
|
||||
|
||||
/// 处理消息
|
||||
@@ -735,6 +740,9 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
KRLogUtil.kr_i('🔄 连接状态变化: $status', tag: 'HomeController');
|
||||
KRLogUtil.kr_i('📊 当前状态类型: ${status.runtimeType}', tag: 'HomeController');
|
||||
|
||||
// 🔧 保守修复: 记录状态变化时间
|
||||
_lastStatusChangeTime = DateTime.now();
|
||||
|
||||
switch (status) {
|
||||
case SingboxStopped():
|
||||
KRLogUtil.kr_i('🔴 状态: 已停止', tag: 'HomeController');
|
||||
@@ -880,15 +888,28 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
tag: 'HomeController');
|
||||
if (kDebugMode) {}
|
||||
|
||||
// 🔧 关键: 如果正在切换中,直接忽略(参考 hiddify-app 的 "switching status, debounce")
|
||||
// 🔧 保守修复: 检测状态是否卡住(超过10秒)
|
||||
if (currentStatus is SingboxStarting || currentStatus is SingboxStopping) {
|
||||
KRLogUtil.kr_i('🔄 正在切换中,忽略本次操作 (当前状态: $currentStatus)',
|
||||
tag: 'HomeController');
|
||||
if (kDebugMode) {}
|
||||
return;
|
||||
final now = DateTime.now();
|
||||
if (_lastStatusChangeTime != null &&
|
||||
now.difference(_lastStatusChangeTime!) > const Duration(seconds: 10)) {
|
||||
// 状态卡住,强制重置
|
||||
KRLogUtil.kr_w('⚠️ 检测到状态卡住超过10秒 (当前: $currentStatus),执行强制重置', tag: 'HomeController');
|
||||
await _forceResetState();
|
||||
// 重置后重新尝试操作
|
||||
KRLogUtil.kr_i('🔄 状态已重置,继续执行切换操作', tag: 'HomeController');
|
||||
} else {
|
||||
KRLogUtil.kr_i('🔄 正在切换中,忽略本次操作 (当前状态: $currentStatus)', tag: 'HomeController');
|
||||
if (kDebugMode) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// 🔧 保守修复: 记录状态变化时间
|
||||
_lastStatusChangeTime = DateTime.now();
|
||||
|
||||
if (value) {
|
||||
// 开启连接
|
||||
KRLogUtil.kr_i('🔄 开始连接...', tag: 'HomeController');
|
||||
@@ -939,26 +960,40 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
}
|
||||
|
||||
/// 🔧 等待状态达到预期值
|
||||
Future<void> _waitForStatus(Type expectedType, {int maxSeconds = 3}) async {
|
||||
if (kDebugMode) {}
|
||||
/// 🔧 保守修复: 返回 bool 表示是否成功达到预期状态
|
||||
Future<bool> _waitForStatus(Type expectedType, {int maxSeconds = 3}) async {
|
||||
if (kDebugMode) {
|
||||
}
|
||||
final startTime = DateTime.now();
|
||||
|
||||
while (DateTime.now().difference(startTime).inSeconds < maxSeconds) {
|
||||
final currentStatus = KRSingBoxImp.instance.kr_status.value;
|
||||
if (kDebugMode) {}
|
||||
if (kDebugMode) {
|
||||
}
|
||||
|
||||
if (currentStatus.runtimeType == expectedType) {
|
||||
if (kDebugMode) {}
|
||||
if (kDebugMode) {
|
||||
}
|
||||
// 强制同步确保 kr_isConnected 正确
|
||||
kr_forceSyncConnectionStatus();
|
||||
return;
|
||||
// 🔧 更新状态变化时间
|
||||
_lastStatusChangeTime = DateTime.now();
|
||||
return true; // 成功
|
||||
}
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
}
|
||||
|
||||
if (kDebugMode) {}
|
||||
// 🔧 保守修复: 超时后记录详细日志
|
||||
final finalStatus = KRSingBoxImp.instance.kr_status.value;
|
||||
KRLogUtil.kr_w(
|
||||
'⏱️ 等待状态超时: 期望=${expectedType.toString()}, 实际=${finalStatus.runtimeType}, 耗时=${maxSeconds}秒',
|
||||
tag: 'HomeController',
|
||||
);
|
||||
if (kDebugMode) {
|
||||
}
|
||||
kr_forceSyncConnectionStatus();
|
||||
return false; // 超时失败
|
||||
}
|
||||
|
||||
Future<void> _kr_prepareCountrySelectionBeforeStart() async {
|
||||
@@ -1813,10 +1848,36 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// 注销应用生命周期监听
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
if (kDebugMode) {
|
||||
print('🧹 [HomeController] 开始清理资源...');
|
||||
}
|
||||
|
||||
// 清理 EventBus 监听器
|
||||
_eventBusWorker?.dispose();
|
||||
if (kDebugMode) {
|
||||
print('✅ [HomeController] EventBus 监听器已清理');
|
||||
}
|
||||
|
||||
// 清理连接计时器
|
||||
_kr_connectionTimer?.cancel();
|
||||
if (kDebugMode) {
|
||||
print('✅ [HomeController] 连接计时器已清理');
|
||||
}
|
||||
|
||||
// 🔧 保守修复: 清理状态监控定时器
|
||||
_statusWatchdogTimer?.cancel();
|
||||
_connectionTimeoutTimer?.cancel();
|
||||
if (kDebugMode) {
|
||||
print('✅ [HomeController] 状态监控定时器已清理');
|
||||
}
|
||||
|
||||
if (kDebugMode) {
|
||||
print('✅ [HomeController] 资源清理完成');
|
||||
}
|
||||
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@@ -2283,7 +2344,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
_kr_connectionTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
_kr_connectionSeconds++;
|
||||
kr_connectionTime.value = kr_formatDuration(_kr_connectionSeconds);
|
||||
KRLogUtil.kr_i(kr_connectText.value);
|
||||
KRLogUtil.kr_i(kr_connectText.value, tag: 'kr_startConnectionTimer');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2414,6 +2475,85 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
}
|
||||
}
|
||||
|
||||
/// 🔧 保守修复: 强制重置状态(用于状态卡住时)
|
||||
Future<void> _forceResetState() async {
|
||||
try {
|
||||
KRLogUtil.kr_w('🔄 开始强制重置状态...', tag: 'HomeController');
|
||||
|
||||
// 1. 尝试停止 SingBox
|
||||
try {
|
||||
await KRSingBoxImp.instance.kr_stop().timeout(
|
||||
const Duration(seconds: 5),
|
||||
onTimeout: () {
|
||||
KRLogUtil.kr_w('⚠️ 强制停止超时,继续重置', tag: 'HomeController');
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_w('⚠️ 强制停止失败: $e,继续重置', tag: 'HomeController');
|
||||
}
|
||||
|
||||
// 2. 等待状态稳定
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
// 3. 强制重置所有 UI 状态为断开
|
||||
kr_connectText.value = AppTranslations.kr_home.disconnected;
|
||||
KRSingBoxImp.instance.kr_status.value = SingboxStatus.stopped();
|
||||
kr_isConnected.value = false;
|
||||
kr_currentSpeed.value = "--";
|
||||
kr_currentNodeLatency.value = -2;
|
||||
kr_currentIp.value = "--";
|
||||
kr_currentProtocol.value = "--";
|
||||
kr_stopConnectionTimer();
|
||||
kr_resetConnectionInfo();
|
||||
|
||||
// 4. 重置状态变化时间
|
||||
_lastStatusChangeTime = null;
|
||||
|
||||
// 5. 强制更新 UI
|
||||
update();
|
||||
|
||||
KRLogUtil.kr_i('✅ 强制重置状态完成', tag: 'HomeController');
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('❌ 强制重置状态失败: $e', tag: 'HomeController');
|
||||
}
|
||||
}
|
||||
|
||||
/// 🔧 保守修复: 启动状态监控定时器,定期检测状态是否卡住
|
||||
void _startStatusWatchdog() {
|
||||
_statusWatchdogTimer?.cancel();
|
||||
_statusWatchdogTimer = Timer.periodic(const Duration(seconds: 30), (timer) {
|
||||
final currentStatus = KRSingBoxImp.instance.kr_status.value;
|
||||
|
||||
// 只检测中间状态(Starting/Stopping)
|
||||
if (currentStatus is SingboxStarting || currentStatus is SingboxStopping) {
|
||||
final now = DateTime.now();
|
||||
if (_lastStatusChangeTime != null) {
|
||||
final duration = now.difference(_lastStatusChangeTime!);
|
||||
|
||||
if (duration > const Duration(seconds: 15)) {
|
||||
// 状态卡住超过 15 秒
|
||||
KRLogUtil.kr_w(
|
||||
'⚠️ [Watchdog] 检测到状态卡住: ${currentStatus.runtimeType}, 持续时间: ${duration.inSeconds}秒',
|
||||
tag: 'HomeController',
|
||||
);
|
||||
|
||||
// 自动触发强制重置
|
||||
_forceResetState().then((_) {
|
||||
Get.snackbar(
|
||||
'系统提示',
|
||||
'VPN 状态异常已自动修复',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
duration: const Duration(seconds: 2),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
KRLogUtil.kr_i('✅ 状态监控定时器已启动', tag: 'HomeController');
|
||||
}
|
||||
|
||||
/// 连接超时处理
|
||||
Timer? _connectionTimeoutTimer;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user