feat: 增加账号未初始化提示登录重新初始化

This commit is contained in:
speakeloudest 2025-12-03 03:08:26 -08:00
parent c87d5d4d38
commit 33b9cd34f1
2 changed files with 83 additions and 41 deletions

View File

@ -208,7 +208,10 @@ class VPNManager: ObservableObject {
} }
func disconnect() { func disconnect() {
guard state == .connected else { return } if state != .disconnected && state != .invalid {
manager.connection.stopVPNTunnel() manager.connection.stopVPNTunnel()
} else {
alert = VPNManagerAlert(alert: nil, message: nil)
}
} }
} }

View File

@ -24,6 +24,7 @@ import '../../../utils/kr_update_util.dart';
import '../../../widgets/dialogs/kr_dialog.dart'; import '../../../widgets/dialogs/kr_dialog.dart';
import 'package:kaer_with_panels/app/widgets/dialogs/hi_dialog.dart'; import 'package:kaer_with_panels/app/widgets/dialogs/hi_dialog.dart';
import 'package:kaer_with_panels/app/widgets/kr_app_text_style.dart'; import 'package:kaer_with_panels/app/widgets/kr_app_text_style.dart';
import 'package:kaer_with_panels/app/routes/app_pages.dart';
import '../models/kr_home_views_status.dart'; import '../models/kr_home_views_status.dart';
@ -224,14 +225,17 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
await _kr_prepareCountrySelectionBeforeStart(); await _kr_prepareCountrySelectionBeforeStart();
final selectedAfter = final selectedAfter =
await KRSecureStorage().kr_readData(key: 'SELECTED_NODE_TAG'); await KRSecureStorage().kr_readData(key: 'SELECTED_NODE_TAG');
KRLogUtil.kr_i('准备后 SELECTED_NODE_TAG_autoConnect: ${selectedAfter ?? ''}', KRLogUtil.kr_i(
'准备后 SELECTED_NODE_TAG_autoConnect: ${selectedAfter ?? ''}',
tag: 'HomeController'); tag: 'HomeController');
KRLogUtil.kr_i('准备后 kr_currentNodeName_autoConnect: ${kr_currentNodeName.value}', KRLogUtil.kr_i(
'准备后 kr_currentNodeName_autoConnect: ${kr_currentNodeName.value}',
tag: 'HomeController'); tag: 'HomeController');
KRLogUtil.kr_i('准备后 kr_cutTag_autoConnect: ${kr_cutTag.value}', KRLogUtil.kr_i('准备后 kr_cutTag_autoConnect: ${kr_cutTag.value}',
tag: 'HomeController'); tag: 'HomeController');
KRLogUtil.kr_i('准备后 kr_cutSeletedTag_autoConnect: ${kr_cutSeletedTag.value}', KRLogUtil.kr_i(
'准备后 kr_cutSeletedTag_autoConnect: ${kr_cutSeletedTag.value}',
tag: 'HomeController'); tag: 'HomeController');
await kr_performNodeSwitch(selectedAfter!); await kr_performNodeSwitch(selectedAfter!);
await KRSingBoxImp.instance.kr_start(); await KRSingBoxImp.instance.kr_start();
@ -267,6 +271,25 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
void onInit() async { void onInit() async {
super.onInit(); super.onInit();
WidgetsBinding.instance.addPostFrameCallback((_) {
Future.delayed(const Duration(milliseconds: 300), () async {
final rawAccount = KRAppRunData.getInstance().kr_account.value;
final account = rawAccount?.trim();
if (account == null ||
account.isEmpty ||
account.toLowerCase() == 'null') {
await HIDialog.show(
message: '未检测到账号信息,请重试初始化',
confirmText: '重试',
preventBackDismiss: true,
onConfirm: () {
Get.offAllNamed(Routes.KR_SPLASH);
},
);
}
});
});
// 🔧 onInit // 🔧 onInit
try { try {
final dir = await getApplicationDocumentsDirectory(); final dir = await getApplicationDocumentsDirectory();
@ -892,16 +915,18 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
if (currentStatus is SingboxStarting || currentStatus is SingboxStopping) { if (currentStatus is SingboxStarting || currentStatus is SingboxStopping) {
final now = DateTime.now(); final now = DateTime.now();
if (_lastStatusChangeTime != null && if (_lastStatusChangeTime != null &&
now.difference(_lastStatusChangeTime!) > const Duration(seconds: 10)) { now.difference(_lastStatusChangeTime!) >
const Duration(seconds: 10)) {
// //
KRLogUtil.kr_w('⚠️ 检测到状态卡住超过10秒 (当前: $currentStatus),执行强制重置', tag: 'HomeController'); KRLogUtil.kr_w('⚠️ 检测到状态卡住超过10秒 (当前: $currentStatus),执行强制重置',
tag: 'HomeController');
await _forceResetState(); await _forceResetState();
// //
KRLogUtil.kr_i('🔄 状态已重置,继续执行切换操作', tag: 'HomeController'); KRLogUtil.kr_i('🔄 状态已重置,继续执行切换操作', tag: 'HomeController');
} else { } else {
KRLogUtil.kr_i('🔄 正在切换中,忽略本次操作 (当前状态: $currentStatus)', tag: 'HomeController'); KRLogUtil.kr_i('🔄 正在切换中,忽略本次操作 (当前状态: $currentStatus)',
if (kDebugMode) { tag: 'HomeController');
} if (kDebugMode) {}
return; return;
} }
} }
@ -962,18 +987,15 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
/// 🔧 /// 🔧
/// 🔧 : bool /// 🔧 : bool
Future<bool> _waitForStatus(Type expectedType, {int maxSeconds = 3}) async { Future<bool> _waitForStatus(Type expectedType, {int maxSeconds = 3}) async {
if (kDebugMode) { if (kDebugMode) {}
}
final startTime = DateTime.now(); final startTime = DateTime.now();
while (DateTime.now().difference(startTime).inSeconds < maxSeconds) { while (DateTime.now().difference(startTime).inSeconds < maxSeconds) {
final currentStatus = KRSingBoxImp.instance.kr_status.value; final currentStatus = KRSingBoxImp.instance.kr_status.value;
if (kDebugMode) { if (kDebugMode) {}
}
if (currentStatus.runtimeType == expectedType) { if (currentStatus.runtimeType == expectedType) {
if (kDebugMode) { if (kDebugMode) {}
}
// kr_isConnected // kr_isConnected
kr_forceSyncConnectionStatus(); kr_forceSyncConnectionStatus();
// 🔧 // 🔧
@ -990,8 +1012,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
'⏱️ 等待状态超时: 期望=${expectedType.toString()}, 实际=${finalStatus.runtimeType}, 耗时=${maxSeconds}', '⏱️ 等待状态超时: 期望=${expectedType.toString()}, 实际=${finalStatus.runtimeType}, 耗时=${maxSeconds}',
tag: 'HomeController', tag: 'HomeController',
); );
if (kDebugMode) { if (kDebugMode) {}
}
kr_forceSyncConnectionStatus(); kr_forceSyncConnectionStatus();
return false; // return false; //
} }
@ -1183,7 +1204,9 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
/// ///
void _kr_handleManualMode(dynamic element) { void _kr_handleManualMode(dynamic element) {
try { try {
KRLogUtil.kr_d('处理手动模式 - 内核选择: ${element.selected}, 用户选择: ${kr_cutTag.value}', tag: 'HomeController'); KRLogUtil.kr_d(
'处理手动模式 - 内核选择: ${element.selected}, 用户选择: ${kr_cutTag.value}',
tag: 'HomeController');
// 🔧 selected // 🔧 selected
// //
@ -1195,12 +1218,15 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
// UI // UI
if (element.selected == kr_cutTag.value) { if (element.selected == kr_cutTag.value) {
kr_cutSeletedTag.value = element.selected; kr_cutSeletedTag.value = element.selected;
kr_currentNodeName.value = kr_truncateText(element.selected, maxLength: 25); kr_currentNodeName.value =
kr_truncateText(element.selected, maxLength: 25);
// kr_moveToSelectedNode(); // kr_moveToSelectedNode();
KRLogUtil.kr_d('✅ 内核确认节点切换成功: ${element.selected}', tag: 'HomeController'); KRLogUtil.kr_d('✅ 内核确认节点切换成功: ${element.selected}',
tag: 'HomeController');
} else { } else {
// //
KRLogUtil.kr_d('⏳ 等待内核切换到用户选择的节点: ${kr_cutTag.value}', tag: 'HomeController'); KRLogUtil.kr_d('⏳ 等待内核切换到用户选择的节点: ${kr_cutTag.value}',
tag: 'HomeController');
} }
} catch (e) { } catch (e) {
KRLogUtil.kr_e('处理手动模式出错: $e', tag: 'HomeController'); KRLogUtil.kr_e('处理手动模式出错: $e', tag: 'HomeController');
@ -1399,9 +1425,12 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
// 🔒 2 // 🔒 2
final now = DateTime.now(); final now = DateTime.now();
if (_lastSwitchTime != null && now.difference(_lastSwitchTime!) < _switchThrottleDuration) { if (_lastSwitchTime != null &&
final remainingTime = _switchThrottleDuration.inMilliseconds - now.difference(_lastSwitchTime!).inMilliseconds; now.difference(_lastSwitchTime!) < _switchThrottleDuration) {
KRLogUtil.kr_w('⚠️ 切换过于频繁,请等待 ${remainingTime}ms', tag: 'HomeController'); final remainingTime = _switchThrottleDuration.inMilliseconds -
now.difference(_lastSwitchTime!).inMilliseconds;
KRLogUtil.kr_w('⚠️ 切换过于频繁,请等待 ${remainingTime}ms',
tag: 'HomeController');
KRCommonUtil.kr_showToast('切换过于频繁,请稍后再试'); KRCommonUtil.kr_showToast('切换过于频繁,请稍后再试');
return false; return false;
} }
@ -1428,7 +1457,9 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
// 🔧 便VPN启动时应用 // 🔧 便VPN启动时应用
KRLogUtil.kr_i('💾 保存节点选择以便稍后应用: $tag', tag: 'HomeController'); KRLogUtil.kr_i('💾 保存节点选择以便稍后应用: $tag', tag: 'HomeController');
KRSecureStorage().kr_saveData(key: 'SELECTED_NODE_TAG', value: tag).then((_) { KRSecureStorage()
.kr_saveData(key: 'SELECTED_NODE_TAG', value: tag)
.then((_) {
KRLogUtil.kr_i('✅ 节点选择已保存: $tag', tag: 'HomeController'); KRLogUtil.kr_i('✅ 节点选择已保存: $tag', tag: 'HomeController');
}).catchError((e) { }).catchError((e) {
KRLogUtil.kr_e('❌ 保存节点选择失败: $e', tag: 'HomeController'); KRLogUtil.kr_e('❌ 保存节点选择失败: $e', tag: 'HomeController');
@ -1447,11 +1478,13 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
// 🔧 // 🔧
KRLogUtil.kr_i('💾 保存新节点选择: $tag', tag: 'HomeController'); KRLogUtil.kr_i('💾 保存新节点选择: $tag', tag: 'HomeController');
await KRSecureStorage().kr_saveData(key: 'SELECTED_NODE_TAG', value: tag); await KRSecureStorage()
.kr_saveData(key: 'SELECTED_NODE_TAG', value: tag);
// 🚀 使 selectOutbound hiddify-app // 🚀 使 selectOutbound hiddify-app
// VPNVPN开关不闪烁 // VPNVPN开关不闪烁
KRLogUtil.kr_i('🔄 [热切换] 调用 selectOutbound 切换节点...', tag: 'HomeController'); KRLogUtil.kr_i('🔄 [热切换] 调用 selectOutbound 切换节点...',
tag: 'HomeController');
// 🔧 selector tag // 🔧 selector tag
// selectOutbound(groupTag, outboundTag) - tagtag // selectOutbound(groupTag, outboundTag) - tagtag
@ -1462,12 +1495,14 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
for (var group in activeGroups) { for (var group in activeGroups) {
if (group.type == ProxyType.selector) { if (group.type == ProxyType.selector) {
selectorGroupTag = group.tag; selectorGroupTag = group.tag;
KRLogUtil.kr_i('🔍 找到 selector 组: $selectorGroupTag', tag: 'HomeController'); KRLogUtil.kr_i('🔍 找到 selector 组: $selectorGroupTag',
tag: 'HomeController');
break; break;
} }
} }
KRLogUtil.kr_i('📡 调用 selectOutbound("$selectorGroupTag", "$tag")', tag: 'HomeController'); KRLogUtil.kr_i('📡 调用 selectOutbound("$selectorGroupTag", "$tag")',
tag: 'HomeController');
// sing-box selectOutbound API // sing-box selectOutbound API
final result = await KRSingBoxImp.instance.kr_singBox final result = await KRSingBoxImp.instance.kr_singBox
@ -1476,12 +1511,13 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
// //
result.fold( result.fold(
(error) { (error) {
// //
KRLogUtil.kr_e('❌ selectOutbound 调用失败: $error', tag: 'HomeController'); KRLogUtil.kr_e('❌ selectOutbound 调用失败: $error',
tag: 'HomeController');
throw Exception('节点切换失败: $error'); throw Exception('节点切换失败: $error');
}, },
(_) { (_) {
// //
KRLogUtil.kr_i('✅ selectOutbound 调用成功', tag: 'HomeController'); KRLogUtil.kr_i('✅ selectOutbound 调用成功', tag: 'HomeController');
}, },
@ -1501,15 +1537,18 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
try { try {
final updatedGroups = KRSingBoxImp.instance.kr_activeGroups; final updatedGroups = KRSingBoxImp.instance.kr_activeGroups;
final selectGroup = updatedGroups.firstWhere( final selectGroup = updatedGroups.firstWhere(
(group) => group.type == ProxyType.selector, (group) => group.type == ProxyType.selector,
orElse: () => throw Exception('未找到 selector 组'), orElse: () => throw Exception('未找到 selector 组'),
); );
KRLogUtil.kr_i('📊 [验证] ${selectGroup.tag}组当前选中: ${selectGroup.selected}', tag: 'HomeController'); KRLogUtil.kr_i(
'📊 [验证] ${selectGroup.tag}组当前选中: ${selectGroup.selected}',
tag: 'HomeController');
KRLogUtil.kr_i('📊 [验证] 目标节点: $tag', tag: 'HomeController'); KRLogUtil.kr_i('📊 [验证] 目标节点: $tag', tag: 'HomeController');
if (selectGroup.selected != tag) { if (selectGroup.selected != tag) {
KRLogUtil.kr_w('⚠️ [验证] 节点选择验证失败,实际选中: ${selectGroup.selected}', tag: 'HomeController'); KRLogUtil.kr_w('⚠️ [验证] 节点选择验证失败,实际选中: ${selectGroup.selected}',
tag: 'HomeController');
// //
} else { } else {
KRLogUtil.kr_i('✅ [验证] 节点选择验证成功!', tag: 'HomeController'); KRLogUtil.kr_i('✅ [验证] 节点选择验证成功!', tag: 'HomeController');
@ -1523,7 +1562,6 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
KRLogUtil.kr_i('✅ 节点热切换成功VPN保持连接: $tag', tag: 'HomeController'); KRLogUtil.kr_i('✅ 节点热切换成功VPN保持连接: $tag', tag: 'HomeController');
return true; return true;
} catch (switchError) { } catch (switchError) {
// //
KRLogUtil.kr_e('❌ 后台节点切换失败: $switchError', tag: 'HomeController'); KRLogUtil.kr_e('❌ 后台节点切换失败: $switchError', tag: 'HomeController');
@ -1535,7 +1573,8 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
// //
try { try {
await KRSecureStorage().kr_saveData(key: 'SELECTED_NODE_TAG', value: originalTag); await KRSecureStorage()
.kr_saveData(key: 'SELECTED_NODE_TAG', value: originalTag);
} catch (e) { } catch (e) {
KRLogUtil.kr_e('❌ 恢复节点选择失败: $e', tag: 'HomeController'); KRLogUtil.kr_e('❌ 恢复节点选择失败: $e', tag: 'HomeController');
} }
@ -1848,7 +1887,6 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
super.onReady(); super.onReady();
} }
@override @override
void onClose() { void onClose() {
if (kDebugMode) { if (kDebugMode) {
@ -2525,7 +2563,8 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
final currentStatus = KRSingBoxImp.instance.kr_status.value; final currentStatus = KRSingBoxImp.instance.kr_status.value;
// Starting/Stopping // Starting/Stopping
if (currentStatus is SingboxStarting || currentStatus is SingboxStopping) { if (currentStatus is SingboxStarting ||
currentStatus is SingboxStopping) {
final now = DateTime.now(); final now = DateTime.now();
if (_lastStatusChangeTime != null) { if (_lastStatusChangeTime != null) {
final duration = now.difference(_lastStatusChangeTime!); final duration = now.difference(_lastStatusChangeTime!);