feat: 减少日志,增强状态,减少监听
This commit is contained in:
parent
33b9cd34f1
commit
5bd77511cc
@ -561,15 +561,7 @@ class HINodeListView extends GetView<HINodeListController> {
|
|||||||
SizedBox(width: 12.w),
|
SizedBox(width: 12.w),
|
||||||
Obx(() {
|
Obx(() {
|
||||||
final selectedCountryField =
|
final selectedCountryField =
|
||||||
controller.homeController.kr_coutryText.value;
|
controller.homeController.kr_selectedCountryTag.value;
|
||||||
if (selectedCountryField == 'auto') {
|
|
||||||
return KrLocalImage(
|
|
||||||
imageName: 'radio-icon',
|
|
||||||
imageType: ImageType.svg,
|
|
||||||
width: 16.w,
|
|
||||||
height: 16.h,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
final selected = selectedCountryField == country.country;
|
final selected = selectedCountryField == country.country;
|
||||||
return selected
|
return selected
|
||||||
? KrLocalImage(
|
? KrLocalImage(
|
||||||
|
|||||||
@ -270,26 +270,6 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
@override
|
@override
|
||||||
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();
|
||||||
@ -340,8 +320,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
|
|
||||||
// 延迟同步连接状态,确保状态正确
|
// 延迟同步连接状态,确保状态正确
|
||||||
Future.delayed(const Duration(milliseconds: 500), () {
|
Future.delayed(const Duration(milliseconds: 500), () {
|
||||||
kr_forceSyncConnectionStatus();
|
kr_forceSyncConnectionStatus(true);
|
||||||
_checkQuickConnectAutoStart();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 🔧 Android 15 新增:5秒后再次强制更新高度,兜底保护
|
// 🔧 Android 15 新增:5秒后再次强制更新高度,兜底保护
|
||||||
@ -703,6 +682,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
} else {
|
} else {
|
||||||
// kr_updateBottomPanelHeight();
|
// kr_updateBottomPanelHeight();
|
||||||
}
|
}
|
||||||
|
_kr_testLatencyWithoutVpn();
|
||||||
break;
|
break;
|
||||||
case KRSubscribeServiceStatus.kr_none:
|
case KRSubscribeServiceStatus.kr_none:
|
||||||
KRLogUtil.kr_i('订阅服务未初始化', tag: 'HomeController');
|
KRLogUtil.kr_i('订阅服务未初始化', tag: 'HomeController');
|
||||||
@ -911,12 +891,11 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
tag: 'HomeController');
|
tag: 'HomeController');
|
||||||
if (kDebugMode) {}
|
if (kDebugMode) {}
|
||||||
|
|
||||||
// 🔧 保守修复: 检测状态是否卡住(超过10秒)
|
// 🔧 保守修复: 检测状态是否卡住(超过5秒)
|
||||||
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!) >
|
now.difference(_lastStatusChangeTime!) > const Duration(seconds: 5)) {
|
||||||
const Duration(seconds: 10)) {
|
|
||||||
// 状态卡住,强制重置
|
// 状态卡住,强制重置
|
||||||
KRLogUtil.kr_w('⚠️ 检测到状态卡住超过10秒 (当前: $currentStatus),执行强制重置',
|
KRLogUtil.kr_w('⚠️ 检测到状态卡住超过10秒 (当前: $currentStatus),执行强制重置',
|
||||||
tag: 'HomeController');
|
tag: 'HomeController');
|
||||||
@ -942,21 +921,22 @@ 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: ${selectedAfter ?? ''}',
|
// KRLogUtil.kr_i('准备后 SELECTED_NODE_TAG: ${selectedAfter ?? ''}',
|
||||||
tag: 'HomeController');
|
// tag: 'HomeController');
|
||||||
KRLogUtil.kr_i('准备后 kr_currentNodeName: ${kr_currentNodeName.value}',
|
// KRLogUtil.kr_i('准备后 kr_currentNodeName: ${kr_currentNodeName.value}',
|
||||||
tag: 'HomeController');
|
// tag: 'HomeController');
|
||||||
KRLogUtil.kr_i('准备后 kr_cutTag: ${kr_cutTag.value}',
|
// KRLogUtil.kr_i('准备后 kr_cutTag: ${kr_cutTag.value}',
|
||||||
tag: 'HomeController');
|
// tag: 'HomeController');
|
||||||
KRLogUtil.kr_i('准备后 kr_cutSeletedTag: ${kr_cutSeletedTag.value}',
|
// KRLogUtil.kr_i('准备后 kr_cutSeletedTag: ${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();
|
||||||
KRLogUtil.kr_i('✅ 连接命令已发送', tag: 'HomeController');
|
KRLogUtil.kr_i('✅ 连接命令已发送', tag: 'HomeController');
|
||||||
if (kDebugMode) {}
|
if (kDebugMode) {}
|
||||||
|
|
||||||
// 🔧 修复: 等待状态更新,最多3秒
|
// 🔧 修复: 等待状态更新,最多3秒
|
||||||
await _waitForStatus(SingboxStarted, maxSeconds: 3);
|
await _waitForStatus(SingboxStatus.started().runtimeType,
|
||||||
|
maxSeconds: 3);
|
||||||
} else {
|
} else {
|
||||||
// 关闭连接
|
// 关闭连接
|
||||||
KRLogUtil.kr_i('🛑 开始断开连接...', tag: 'HomeController');
|
KRLogUtil.kr_i('🛑 开始断开连接...', tag: 'HomeController');
|
||||||
@ -971,8 +951,16 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
KRLogUtil.kr_i('✅ 断开命令已发送', tag: 'HomeController');
|
KRLogUtil.kr_i('✅ 断开命令已发送', tag: 'HomeController');
|
||||||
if (kDebugMode) {}
|
if (kDebugMode) {}
|
||||||
|
|
||||||
// 🔧 修复: 等待状态更新,最多2秒
|
// 🔧 保守修复: 等待状态更新,增加超时处理
|
||||||
await _waitForStatus(SingboxStopped, maxSeconds: 2);
|
final success = await _waitForStatus(
|
||||||
|
SingboxStatus.stopped().runtimeType,
|
||||||
|
maxSeconds: 3,
|
||||||
|
);
|
||||||
|
if (!success) {
|
||||||
|
// 停止超时,强制同步状态
|
||||||
|
KRLogUtil.kr_w('⚠️ VPN 停止超时(3秒),强制同步状态', tag: 'HomeController');
|
||||||
|
kr_forceSyncConnectionStatus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
KRLogUtil.kr_e('❌ 切换失败: $e', tag: 'HomeController');
|
KRLogUtil.kr_e('❌ 切换失败: $e', tag: 'HomeController');
|
||||||
@ -1019,39 +1007,31 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
|
|
||||||
Future<void> _kr_prepareCountrySelectionBeforeStart() async {
|
Future<void> _kr_prepareCountrySelectionBeforeStart() async {
|
||||||
try {
|
try {
|
||||||
KRLogUtil.kr_i('开始准备国家选择', tag: 'CountrySelect');
|
// KRLogUtil.kr_i('开始准备国家选择', tag: 'CountrySelect');
|
||||||
final storedCountry = kr_selectedCountryTag.value;
|
final storedCountry = kr_selectedCountryTag.value;
|
||||||
KRLogUtil.kr_i('使用响应式 SELECTED_COUNTRY_TAG: $storedCountry',
|
// KRLogUtil.kr_i('使用响应式 SELECTED_COUNTRY_TAG: $storedCountry',
|
||||||
tag: 'CountrySelect');
|
// tag: 'CountrySelect');
|
||||||
if (storedCountry == 'auto') {
|
if (storedCountry == 'auto') {
|
||||||
KRLogUtil.kr_w('当前为 auto,按全局最优节点进行选择', tag: 'CountrySelect');
|
KRLogUtil.kr_w('当前为 auto,按全局最优节点进行选择', tag: 'CountrySelect');
|
||||||
final best = _kr_selectBestNodeTagGlobal();
|
final best = _kr_selectBestNodeTagGlobal();
|
||||||
if (best != null && best.isNotEmpty) {
|
if (best != null && best.isNotEmpty) {
|
||||||
KRLogUtil.kr_i('选中全局最优节点: $best', tag: 'CountrySelect');
|
// KRLogUtil.kr_i('选中全局最优节点: $best', tag: 'CountrySelect');
|
||||||
await KRSecureStorage()
|
await KRSecureStorage()
|
||||||
.kr_saveData(key: 'SELECTED_NODE_TAG', value: best);
|
.kr_saveData(key: 'SELECTED_NODE_TAG', value: best);
|
||||||
final verify =
|
|
||||||
await KRSecureStorage().kr_readData(key: 'SELECTED_NODE_TAG');
|
|
||||||
KRLogUtil.kr_i('写入后校验 SELECTED_NODE_TAG: $verify',
|
|
||||||
tag: 'CountrySelect');
|
|
||||||
kr_currentNodeName.value = best;
|
kr_currentNodeName.value = best;
|
||||||
kr_cutTag.value = best;
|
kr_cutTag.value = best;
|
||||||
kr_cutSeletedTag.value = best;
|
kr_cutSeletedTag.value = best;
|
||||||
kr_updateConnectionInfo();
|
kr_updateConnectionInfo();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
KRLogUtil.kr_w('未找到可用的全局最优节点', tag: 'CountrySelect');
|
// KRLogUtil.kr_w('未找到可用的全局最优节点', tag: 'CountrySelect');
|
||||||
KRLogUtil.kr_i('触发直接延迟测试以获取有效延迟', tag: 'CountrySelect');
|
// KRLogUtil.kr_i('触发直接延迟测试以获取有效延迟', tag: 'CountrySelect');
|
||||||
await _kr_testLatencyWithoutVpn();
|
await _kr_testLatencyWithoutVpn();
|
||||||
final bestAfterTest = _kr_selectBestNodeTagGlobal();
|
final bestAfterTest = _kr_selectBestNodeTagGlobal();
|
||||||
if (bestAfterTest != null && bestAfterTest.isNotEmpty) {
|
if (bestAfterTest != null && bestAfterTest.isNotEmpty) {
|
||||||
KRLogUtil.kr_i('延迟测试后选中全局最优节点: $bestAfterTest', tag: 'CountrySelect');
|
// KRLogUtil.kr_i('延迟测试后选中全局最优节点: $bestAfterTest', tag: 'CountrySelect');
|
||||||
await KRSecureStorage()
|
await KRSecureStorage()
|
||||||
.kr_saveData(key: 'SELECTED_NODE_TAG', value: bestAfterTest);
|
.kr_saveData(key: 'SELECTED_NODE_TAG', value: bestAfterTest);
|
||||||
final verifyA =
|
|
||||||
await KRSecureStorage().kr_readData(key: 'SELECTED_NODE_TAG');
|
|
||||||
KRLogUtil.kr_i('写入后校验 SELECTED_NODE_TAG: $verifyA',
|
|
||||||
tag: 'CountrySelect');
|
|
||||||
kr_currentNodeName.value = bestAfterTest;
|
kr_currentNodeName.value = bestAfterTest;
|
||||||
kr_cutTag.value = bestAfterTest;
|
kr_cutTag.value = bestAfterTest;
|
||||||
kr_cutSeletedTag.value = bestAfterTest;
|
kr_cutSeletedTag.value = bestAfterTest;
|
||||||
@ -1423,6 +1403,10 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (kr_cutTag.value == tag) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// 🔒 节流控制:2秒内的重复切换请求直接忽略
|
// 🔒 节流控制:2秒内的重复切换请求直接忽略
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
if (_lastSwitchTime != null &&
|
if (_lastSwitchTime != null &&
|
||||||
@ -1612,14 +1596,14 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
/// 2. 如果是 auto,优先使用 kr_cutSeletedTag(保存了实际选中的节点)
|
/// 2. 如果是 auto,优先使用 kr_cutSeletedTag(保存了实际选中的节点)
|
||||||
/// 3. 如果 kr_cutSeletedTag 也是 auto 或空,再尝试从 kr_activeGroups 获取
|
/// 3. 如果 kr_cutSeletedTag 也是 auto 或空,再尝试从 kr_activeGroups 获取
|
||||||
String kr_getCurrentNodeCountry() {
|
String kr_getCurrentNodeCountry() {
|
||||||
KRLogUtil.kr_i('========== 开始获取国家代码 ==========',
|
// KRLogUtil.kr_i('========== 开始获取国家代码 ==========',
|
||||||
tag: 'getCurrentNodeCountry');
|
// tag: 'getCurrentNodeCountry');
|
||||||
KRLogUtil.kr_i('kr_cutTag: ${kr_cutTag.value}',
|
// KRLogUtil.kr_i('kr_cutTag: ${kr_cutTag.value}',
|
||||||
tag: 'getCurrentNodeCountry');
|
// tag: 'getCurrentNodeCountry');
|
||||||
KRLogUtil.kr_i('kr_cutSeletedTag: ${kr_cutSeletedTag.value}',
|
// KRLogUtil.kr_i('kr_cutSeletedTag: ${kr_cutSeletedTag.value}',
|
||||||
tag: 'getCurrentNodeCountry');
|
// tag: 'getCurrentNodeCountry');
|
||||||
KRLogUtil.kr_i('keyList 节点总数: ${kr_subscribeService.keyList.length}',
|
// KRLogUtil.kr_i('keyList 节点总数: ${kr_subscribeService.keyList.length}',
|
||||||
tag: 'getCurrentNodeCountry');
|
// tag: 'getCurrentNodeCountry');
|
||||||
|
|
||||||
String actualTag;
|
String actualTag;
|
||||||
|
|
||||||
@ -1633,7 +1617,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
kr_cutTag.value.isNotEmpty) {
|
kr_cutTag.value.isNotEmpty) {
|
||||||
// 用户手动选择了具体节点
|
// 用户手动选择了具体节点
|
||||||
actualTag = kr_cutTag.value;
|
actualTag = kr_cutTag.value;
|
||||||
KRLogUtil.kr_i('✅ 使用手动选择的节点: $actualTag', tag: 'getCurrentNodeCountry');
|
// KRLogUtil.kr_i('✅ 使用手动选择的节点: $actualTag', tag: 'getCurrentNodeCountry');
|
||||||
}
|
}
|
||||||
// 2. 如果是 auto,优先使用 kr_cutSeletedTag(保存了实际选中的节点)
|
// 2. 如果是 auto,优先使用 kr_cutSeletedTag(保存了实际选中的节点)
|
||||||
else if (kr_cutSeletedTag.value.isNotEmpty &&
|
else if (kr_cutSeletedTag.value.isNotEmpty &&
|
||||||
@ -1641,15 +1625,15 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
kr_cutSeletedTag.value != 'select') {
|
kr_cutSeletedTag.value != 'select') {
|
||||||
// auto 模式下,使用保存的实际节点
|
// auto 模式下,使用保存的实际节点
|
||||||
actualTag = kr_cutSeletedTag.value;
|
actualTag = kr_cutSeletedTag.value;
|
||||||
KRLogUtil.kr_i('✅ 使用 auto 模式下的实际节点 (kr_cutSeletedTag): $actualTag',
|
// KRLogUtil.kr_i('✅ 使用 auto 模式下的实际节点 (kr_cutSeletedTag): $actualTag',
|
||||||
tag: 'getCurrentNodeCountry');
|
// tag: 'getCurrentNodeCountry');
|
||||||
}
|
}
|
||||||
// 3. 降级:尝试从活动组获取
|
// 3. 降级:尝试从活动组获取
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
KRLogUtil.kr_i('⚠️ 尝试从活动组获取实际节点', tag: 'getCurrentNodeCountry');
|
// KRLogUtil.kr_i('⚠️ 尝试从活动组获取实际节点', tag: 'getCurrentNodeCountry');
|
||||||
KRLogUtil.kr_i('活动组数量: ${KRSingBoxImp.instance.kr_activeGroups.length}',
|
// KRLogUtil.kr_i('活动组数量: ${KRSingBoxImp.instance.kr_activeGroups.length}',
|
||||||
tag: 'getCurrentNodeCountry');
|
// tag: 'getCurrentNodeCountry');
|
||||||
|
|
||||||
// 🔧 修复:活动组为空时,尝试使用 allGroups
|
// 🔧 修复:活动组为空时,尝试使用 allGroups
|
||||||
if (KRSingBoxImp.instance.kr_activeGroups.isEmpty) {
|
if (KRSingBoxImp.instance.kr_activeGroups.isEmpty) {
|
||||||
@ -1756,16 +1740,16 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
KRLogUtil.kr_i('✅ 找到节点: $actualTag', tag: 'getCurrentNodeCountry');
|
// KRLogUtil.kr_i('✅ 找到节点: $actualTag', tag: 'getCurrentNodeCountry');
|
||||||
KRLogUtil.kr_i(' - city: ${node.city}', tag: 'getCurrentNodeCountry');
|
// KRLogUtil.kr_i(' - city: ${node.city}', tag: 'getCurrentNodeCountry');
|
||||||
KRLogUtil.kr_i(' - country: "${node.country}"',
|
// KRLogUtil.kr_i(' - country: "${node.country}"',
|
||||||
tag: 'getCurrentNodeCountry');
|
// tag: 'getCurrentNodeCountry');
|
||||||
KRLogUtil.kr_i(' - country.isEmpty: ${node.country.isEmpty}',
|
// KRLogUtil.kr_i(' - country.isEmpty: ${node.country.isEmpty}',
|
||||||
tag: 'getCurrentNodeCountry');
|
// tag: 'getCurrentNodeCountry');
|
||||||
KRLogUtil.kr_i(' - country.length: ${node.country.length}',
|
// KRLogUtil.kr_i(' - country.length: ${node.country.length}',
|
||||||
tag: 'getCurrentNodeCountry');
|
// tag: 'getCurrentNodeCountry');
|
||||||
KRLogUtil.kr_i('========== 国家代码获取结束 ==========',
|
// KRLogUtil.kr_i('========== 国家代码获取结束 ==========',
|
||||||
tag: 'getCurrentNodeCountry');
|
// tag: 'getCurrentNodeCountry');
|
||||||
|
|
||||||
return node.country;
|
return node.country;
|
||||||
}
|
}
|
||||||
@ -1885,6 +1869,24 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
@override
|
@override
|
||||||
void onReady() {
|
void onReady() {
|
||||||
super.onReady();
|
super.onReady();
|
||||||
|
|
||||||
|
Future.delayed(const Duration(milliseconds: 200), () 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);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -2378,12 +2380,12 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
/// 开始连接计时
|
/// 开始连接计时
|
||||||
void kr_startConnectionTimer() {
|
void kr_startConnectionTimer() {
|
||||||
kr_stopConnectionTimer();
|
kr_stopConnectionTimer();
|
||||||
_kr_connectionSeconds = 0;
|
// _kr_connectionSeconds = 0;
|
||||||
_kr_connectionTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
// _kr_connectionTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||||
_kr_connectionSeconds++;
|
// _kr_connectionSeconds++;
|
||||||
kr_connectionTime.value = kr_formatDuration(_kr_connectionSeconds);
|
// kr_connectionTime.value = kr_formatDuration(_kr_connectionSeconds);
|
||||||
KRLogUtil.kr_i(kr_connectText.value, tag: 'kr_startConnectionTimer');
|
// KRLogUtil.kr_i(kr_connectText.value, tag: 'kr_startConnectionTimer');
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 停止连接计时
|
/// 停止连接计时
|
||||||
@ -2464,7 +2466,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 强制同步连接状态
|
/// 强制同步连接状态
|
||||||
void kr_forceSyncConnectionStatus() {
|
void kr_forceSyncConnectionStatus([bool? isQuickConnect]) {
|
||||||
try {
|
try {
|
||||||
KRLogUtil.kr_i('🔄 强制同步连接状态...', tag: 'HomeController');
|
KRLogUtil.kr_i('🔄 强制同步连接状态...', tag: 'HomeController');
|
||||||
|
|
||||||
@ -2507,6 +2509,9 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
|
|
||||||
// 强制更新UI
|
// 强制更新UI
|
||||||
update();
|
update();
|
||||||
|
if (isQuickConnect == true) {
|
||||||
|
_checkQuickConnectAutoStart();
|
||||||
|
}
|
||||||
KRLogUtil.kr_i('✅ 连接状态同步完成', tag: 'HomeController');
|
KRLogUtil.kr_i('✅ 连接状态同步完成', tag: 'HomeController');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
KRLogUtil.kr_e('❌ 强制同步连接状态失败: $e', tag: 'HomeController');
|
KRLogUtil.kr_e('❌ 强制同步连接状态失败: $e', tag: 'HomeController');
|
||||||
@ -2569,22 +2574,15 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
if (_lastStatusChangeTime != null) {
|
if (_lastStatusChangeTime != null) {
|
||||||
final duration = now.difference(_lastStatusChangeTime!);
|
final duration = now.difference(_lastStatusChangeTime!);
|
||||||
|
|
||||||
if (duration > const Duration(seconds: 15)) {
|
if (duration > const Duration(seconds: 5)) {
|
||||||
// 状态卡住超过 15 秒
|
// 状态卡住超过 5 秒
|
||||||
KRLogUtil.kr_w(
|
KRLogUtil.kr_w(
|
||||||
'⚠️ [Watchdog] 检测到状态卡住: ${currentStatus.runtimeType}, 持续时间: ${duration.inSeconds}秒',
|
'⚠️ [Watchdog] 检测到状态卡住: ${currentStatus.runtimeType}, 持续时间: ${duration.inSeconds}秒',
|
||||||
tag: 'HomeController',
|
tag: 'HomeController',
|
||||||
);
|
);
|
||||||
|
|
||||||
// 自动触发强制重置
|
// 自动触发强制重置
|
||||||
_forceResetState().then((_) {
|
_forceResetState().then((_) {});
|
||||||
Get.snackbar(
|
|
||||||
'系统提示',
|
|
||||||
'VPN 状态异常已自动修复',
|
|
||||||
snackPosition: SnackPosition.TOP,
|
|
||||||
duration: const Duration(seconds: 2),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -502,11 +502,11 @@ class _KRSimpleHttpInterceptor extends Interceptor {
|
|||||||
}
|
}
|
||||||
// 尝试格式化 JSON
|
// 尝试格式化 JSON
|
||||||
try {
|
try {
|
||||||
final jsonData = jsonDecode(decrypted);
|
// final jsonData = jsonDecode(decrypted);
|
||||||
final prettyJson = JsonEncoder.withIndent(' ').convert(jsonData);
|
// final prettyJson = JsonEncoder.withIndent(' ').convert(jsonData);
|
||||||
if (kDebugMode) {
|
// if (kDebugMode) {
|
||||||
print(prettyJson);
|
// print(prettyJson);
|
||||||
}
|
// }
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
print(decrypted);
|
print(decrypted);
|
||||||
|
|||||||
@ -108,6 +108,8 @@ class KRSingBoxImp {
|
|||||||
/// Stream 订阅管理器
|
/// Stream 订阅管理器
|
||||||
final List<StreamSubscription<dynamic>> _kr_subscriptions = [];
|
final List<StreamSubscription<dynamic>> _kr_subscriptions = [];
|
||||||
|
|
||||||
|
StreamSubscription<SingboxStatus>? _kr_statusSubscription;
|
||||||
|
|
||||||
/// 初始化标志,防止重复初始化
|
/// 初始化标志,防止重复初始化
|
||||||
bool _kr_isInitialized = false;
|
bool _kr_isInitialized = false;
|
||||||
|
|
||||||
@ -736,35 +738,25 @@ class KRSingBoxImp {
|
|||||||
}
|
}
|
||||||
KRLogUtil.kr_i('🔵 _kr_subscribeToStatus 被调用', tag: 'SingBox');
|
KRLogUtil.kr_i('🔵 _kr_subscribeToStatus 被调用', tag: 'SingBox');
|
||||||
|
|
||||||
// 取消之前的状态订阅
|
_kr_statusSubscription?.cancel();
|
||||||
for (var sub in _kr_subscriptions) {
|
_kr_statusSubscription = kr_singBox.watchStatus().listen(
|
||||||
if (sub.hashCode.toString().contains('Status')) {
|
(status) {
|
||||||
sub.cancel();
|
if (status == kr_status.value) {
|
||||||
if (kDebugMode) {
|
return;
|
||||||
print('🔵 已取消旧的状态订阅');
|
|
||||||
}
|
}
|
||||||
}
|
if (kDebugMode) {
|
||||||
}
|
print('🔵 收到 Native 状态更新: ${status.runtimeType}');
|
||||||
_kr_subscriptions
|
}
|
||||||
.removeWhere((sub) => sub.hashCode.toString().contains('Status'));
|
KRLogUtil.kr_i('📡 收到状态更新: $status', tag: 'SingBox');
|
||||||
|
kr_status.value = status;
|
||||||
_kr_subscriptions.add(
|
},
|
||||||
kr_singBox.watchStatus().listen(
|
onError: (error) {
|
||||||
(status) {
|
if (kDebugMode) {
|
||||||
if (kDebugMode) {
|
print('🔵 状态流错误: $error');
|
||||||
print('🔵 收到 Native 状态更新: ${status.runtimeType}');
|
}
|
||||||
}
|
KRLogUtil.kr_e('📡 状态流错误: $error', tag: 'SingBox');
|
||||||
KRLogUtil.kr_i('📡 收到状态更新: $status', tag: 'SingBox');
|
},
|
||||||
kr_status.value = status;
|
cancelOnError: false,
|
||||||
},
|
|
||||||
onError: (error) {
|
|
||||||
if (kDebugMode) {
|
|
||||||
print('🔵 状态流错误: $error');
|
|
||||||
}
|
|
||||||
KRLogUtil.kr_e('📡 状态流错误: $error', tag: 'SingBox');
|
|
||||||
},
|
|
||||||
cancelOnError: false,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
@ -1201,32 +1193,32 @@ class KRSingBoxImp {
|
|||||||
KRLogUtil.kr_i('📊 出站节点数量: ${outbounds.length}', tag: 'SingBox');
|
KRLogUtil.kr_i('📊 出站节点数量: ${outbounds.length}', tag: 'SingBox');
|
||||||
|
|
||||||
// 打印每个节点的详细配置
|
// 打印每个节点的详细配置
|
||||||
for (int i = 0; i < outbounds.length; i++) {
|
// for (int i = 0; i < outbounds.length; i++) {
|
||||||
final outbound = outbounds[i];
|
// final outbound = outbounds[i];
|
||||||
KRLogUtil.kr_i('📋 节点[$i] 配置:', tag: 'SingBox');
|
// KRLogUtil.kr_i('📋 节点[$i] 配置:', tag: 'SingBox');
|
||||||
KRLogUtil.kr_i(' - type: ${outbound['type']}', tag: 'SingBox');
|
// KRLogUtil.kr_i(' - type: ${outbound['type']}', tag: 'SingBox');
|
||||||
KRLogUtil.kr_i(' - tag: ${outbound['tag']}', tag: 'SingBox');
|
// KRLogUtil.kr_i(' - tag: ${outbound['tag']}', tag: 'SingBox');
|
||||||
KRLogUtil.kr_i(' - server: ${outbound['server']}', tag: 'SingBox');
|
// KRLogUtil.kr_i(' - server: ${outbound['server']}', tag: 'SingBox');
|
||||||
KRLogUtil.kr_i(' - server_port: ${outbound['server_port']}',
|
// KRLogUtil.kr_i(' - server_port: ${outbound['server_port']}',
|
||||||
tag: 'SingBox');
|
// tag: 'SingBox');
|
||||||
if (outbound['method'] != null) {
|
// if (outbound['method'] != null) {
|
||||||
KRLogUtil.kr_i(' - method: ${outbound['method']}', tag: 'SingBox');
|
// KRLogUtil.kr_i(' - method: ${outbound['method']}', tag: 'SingBox');
|
||||||
}
|
// }
|
||||||
if (outbound['interval'] != null) {
|
// if (outbound['interval'] != null) {
|
||||||
KRLogUtil.kr_i(' - interval: ${outbound['interval']}', tag: 'SingBox');
|
// KRLogUtil.kr_i(' - interval: ${outbound['interval']}', tag: 'SingBox');
|
||||||
}
|
// }
|
||||||
if (outbound['password'] != null) {
|
// if (outbound['password'] != null) {
|
||||||
KRLogUtil.kr_i(
|
// KRLogUtil.kr_i(
|
||||||
' - password: ${outbound['password']?.toString().substring(0, 8)}...',
|
// ' - password: ${outbound['password']?.toString().substring(0, 8)}...',
|
||||||
tag: 'SingBox');
|
// tag: 'SingBox');
|
||||||
}
|
// }
|
||||||
if (outbound['uuid'] != null) {
|
// if (outbound['uuid'] != null) {
|
||||||
KRLogUtil.kr_i(
|
// KRLogUtil.kr_i(
|
||||||
' - uuid: ${outbound['uuid']?.toString().substring(0, 8)}...',
|
// ' - uuid: ${outbound['uuid']?.toString().substring(0, 8)}...',
|
||||||
tag: 'SingBox');
|
// tag: 'SingBox');
|
||||||
}
|
// }
|
||||||
KRLogUtil.kr_i(' - 完整配置: ${jsonEncode(outbound)}', tag: 'SingBox');
|
// KRLogUtil.kr_i(' - 完整配置: ${jsonEncode(outbound)}', tag: 'SingBox');
|
||||||
}
|
// }
|
||||||
|
|
||||||
// ⚠️ 临时过滤 Hysteria2 节点以避免 libcore 崩溃
|
// ⚠️ 临时过滤 Hysteria2 节点以避免 libcore 崩溃
|
||||||
kr_outbounds = outbounds.where((outbound) {
|
kr_outbounds = outbounds.where((outbound) {
|
||||||
@ -1525,9 +1517,9 @@ class KRSingBoxImp {
|
|||||||
if (await configFile.exists()) {
|
if (await configFile.exists()) {
|
||||||
final configContent = await configFile.readAsString();
|
final configContent = await configFile.readAsString();
|
||||||
KRLogUtil.kr_i('📄 配置文件内容长度: ${configContent.length}', tag: 'SingBox');
|
KRLogUtil.kr_i('📄 配置文件内容长度: ${configContent.length}', tag: 'SingBox');
|
||||||
KRLogUtil.kr_i(
|
// KRLogUtil.kr_i(
|
||||||
'📄 配置文件前500字符: ${configContent.substring(0, configContent.length > 500 ? 500 : configContent.length)}',
|
// '📄 配置文件前500字符: ${configContent.substring(0, configContent.length > 500 ? 500 : configContent.length)}',
|
||||||
tag: 'SingBox');
|
// tag: 'SingBox');
|
||||||
} else {
|
} else {
|
||||||
KRLogUtil.kr_w('⚠️ 配置文件不存在: $_cutPath', tag: 'SingBox');
|
KRLogUtil.kr_w('⚠️ 配置文件不存在: $_cutPath', tag: 'SingBox');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,6 @@ class _HIEdgeSwipeDetectorState extends State<HIEdgeSwipeDetector> {
|
|||||||
bool _fromRight = false;
|
bool _fromRight = false;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
KRLogUtil.kr_d('HIEdgeSwipeDetector build');
|
|
||||||
return Stack(
|
return Stack(
|
||||||
fit: StackFit.expand,
|
fit: StackFit.expand,
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@ -39,23 +39,23 @@ class KRCountryFlag extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// 🔍 调试日志
|
// 🔍 调试日志
|
||||||
if (kDebugMode) {
|
// if (kDebugMode) {
|
||||||
print('🏳️ KRCountryFlag.build 被调用');
|
// print('🏳️ KRCountryFlag.build 被调用');
|
||||||
}
|
// }
|
||||||
if (kDebugMode) {
|
// if (kDebugMode) {
|
||||||
print(' - 原始 countryCode: "$countryCode"');
|
// print(' - 原始 countryCode: "$countryCode"');
|
||||||
}
|
// }
|
||||||
if (kDebugMode) {
|
// if (kDebugMode) {
|
||||||
print(' - countryCode.isEmpty: ${countryCode.isEmpty}');
|
// print(' - countryCode.isEmpty: ${countryCode.isEmpty}');
|
||||||
}
|
// }
|
||||||
if (kDebugMode) {
|
// if (kDebugMode) {
|
||||||
print(' - countryCode.length: ${countryCode.length}');
|
// print(' - countryCode.length: ${countryCode.length}');
|
||||||
}
|
// }
|
||||||
|
|
||||||
final processedCode = _getCountryCode(countryCode);
|
final processedCode = _getCountryCode(countryCode);
|
||||||
if (kDebugMode) {
|
// if (kDebugMode) {
|
||||||
print(' - 处理后 code: "$processedCode"');
|
// print(' - 处理后 code: "$processedCode"');
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 如果国家代码为空,显示占位符
|
// 如果国家代码为空,显示占位符
|
||||||
if (countryCode.isEmpty) {
|
if (countryCode.isEmpty) {
|
||||||
|
|||||||
@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 0.0.4+100
|
version: 0.0.4+101
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.5.0 <4.0.0'
|
sdk: '>=3.5.0 <4.0.0'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user