Compare commits
2 Commits
7a223d614b
...
c7b77c1ad8
| Author | SHA1 | Date | |
|---|---|---|---|
| c7b77c1ad8 | |||
| 7cd022093b |
@ -1,5 +1,8 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'dart:convert';
|
||||
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
@ -527,8 +530,6 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
void _bindConnectionStatus() {
|
||||
// 添加更详细的状态监听
|
||||
ever(KRSingBoxImp.instance.kr_status, (status) {
|
||||
if (kDebugMode) {
|
||||
}
|
||||
KRLogUtil.kr_i('🔄 连接状态变化: $status', tag: 'HomeController');
|
||||
KRLogUtil.kr_i('📊 当前状态类型: ${status.runtimeType}', tag: 'HomeController');
|
||||
|
||||
@ -1075,7 +1076,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
// 后台切换成功,更新UI
|
||||
kr_cutSeletedTag.value = tag;
|
||||
kr_updateConnectionInfo();
|
||||
kr_moveToSelectedNode();
|
||||
// kr_moveToSelectedNode();
|
||||
|
||||
// 🚀 方案A增强:增加验证前等待时间,确保活动组完全更新
|
||||
KRLogUtil.kr_i('⏳ [增强] 等待活动组更新(500ms)...', tag: 'HomeController');
|
||||
@ -1156,50 +1157,110 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
}
|
||||
|
||||
/// 获取当前节点国家
|
||||
/// 🔧 修复:使用 kr_cutTag 而不是 kr_cutSeletedTag,确保UI立即响应
|
||||
/// 🔧 修复:处理 "auto" 等特殊标签,从活动组中获取实际选中的节点
|
||||
/// 🔧 修复:优先使用 kr_cutSeletedTag,避免依赖可能为空的 kr_activeGroups
|
||||
/// 策略:
|
||||
/// 1. 如果 kr_cutTag 不是 auto,直接使用(用户手动选择的节点)
|
||||
/// 2. 如果是 auto,优先使用 kr_cutSeletedTag(保存了实际选中的节点)
|
||||
/// 3. 如果 kr_cutSeletedTag 也是 auto 或空,再尝试从 kr_activeGroups 获取
|
||||
String kr_getCurrentNodeCountry() {
|
||||
KRLogUtil.kr_i('========== 开始获取国家代码 ==========', tag: 'getCurrentNodeCountry');
|
||||
KRLogUtil.kr_i('kr_cutTag: ${kr_cutTag.value}', tag: 'getCurrentNodeCountry');
|
||||
KRLogUtil.kr_i('kr_cutSeletedTag: ${kr_cutSeletedTag.value}', tag: 'getCurrentNodeCountry');
|
||||
KRLogUtil.kr_i('keyList 节点总数: ${kr_subscribeService.keyList.length}', tag: 'getCurrentNodeCountry');
|
||||
|
||||
if (kr_cutTag.isEmpty) {
|
||||
KRLogUtil.kr_w('kr_cutTag 为空,返回空字符串', tag: 'getCurrentNodeCountry');
|
||||
return '';
|
||||
String actualTag;
|
||||
|
||||
// 🔧 优先策略:
|
||||
// 1. 如果 kr_cutTag 不是 auto,直接使用(用户手动选择的节点)
|
||||
if (kr_cutTag.value != 'auto' && kr_cutTag.value != 'select' && kr_cutTag.value.isNotEmpty) {
|
||||
// 用户手动选择了具体节点
|
||||
actualTag = kr_cutTag.value;
|
||||
KRLogUtil.kr_i('✅ 使用手动选择的节点: $actualTag', tag: 'getCurrentNodeCountry');
|
||||
}
|
||||
|
||||
String actualTag = kr_cutTag.value;
|
||||
|
||||
// 🔧 修复:如果是 "auto" 或其他选择器组,从活动组中获取实际选中的节点
|
||||
if (actualTag == 'auto' || actualTag == 'select') {
|
||||
// 2. 如果是 auto,优先使用 kr_cutSeletedTag(保存了实际选中的节点)
|
||||
else if (kr_cutSeletedTag.value.isNotEmpty &&
|
||||
kr_cutSeletedTag.value != 'auto' &&
|
||||
kr_cutSeletedTag.value != 'select') {
|
||||
// auto 模式下,使用保存的实际节点
|
||||
actualTag = kr_cutSeletedTag.value;
|
||||
KRLogUtil.kr_i('✅ 使用 auto 模式下的实际节点 (kr_cutSeletedTag): $actualTag', tag: 'getCurrentNodeCountry');
|
||||
}
|
||||
// 3. 降级:尝试从活动组获取
|
||||
else {
|
||||
try {
|
||||
KRLogUtil.kr_i('检测到特殊标签: $actualTag,尝试从活动组获取实际节点', tag: 'getCurrentNodeCountry');
|
||||
KRLogUtil.kr_i('⚠️ 尝试从活动组获取实际节点', tag: 'getCurrentNodeCountry');
|
||||
KRLogUtil.kr_i('活动组数量: ${KRSingBoxImp.instance.kr_activeGroups.length}', tag: 'getCurrentNodeCountry');
|
||||
|
||||
// 从 SingBox 活动组中找到 "select" 选择器组
|
||||
final selectGroup = KRSingBoxImp.instance.kr_activeGroups.firstWhere(
|
||||
(group) => group.tag == 'select',
|
||||
orElse: () => throw Exception('未找到 select 组'),
|
||||
);
|
||||
// 🔧 修复:活动组为空时,尝试使用 allGroups
|
||||
if (KRSingBoxImp.instance.kr_activeGroups.isEmpty) {
|
||||
print('[getCurrentNodeCountry] ⚠️ 活动组为空,尝试使用 allGroups');
|
||||
KRLogUtil.kr_w('⚠️ 活动组为空,尝试使用 allGroups', tag: 'getCurrentNodeCountry');
|
||||
|
||||
KRLogUtil.kr_i('找到 select 组,当前选中: ${selectGroup.selected}', tag: 'getCurrentNodeCountry');
|
||||
final allGroups = KRSingBoxImp.instance.kr_allGroups;
|
||||
print('[getCurrentNodeCountry] allGroups 数量: ${allGroups.length}');
|
||||
if (allGroups.isEmpty) {
|
||||
print('[getCurrentNodeCountry] ❌ allGroups 也为空,返回空字符串');
|
||||
KRLogUtil.kr_w('❌ allGroups 也为空,返回空字符串', tag: 'getCurrentNodeCountry');
|
||||
return '';
|
||||
}
|
||||
|
||||
// 从 allGroups 中查找 select 组
|
||||
final selectGroup = allGroups.firstWhere(
|
||||
(group) => group.tag == 'select',
|
||||
orElse: () => throw Exception('未找到 select 组'),
|
||||
);
|
||||
print('[getCurrentNodeCountry] selectGroup.selected: ${selectGroup.selected}');
|
||||
|
||||
if (selectGroup.selected.isEmpty || selectGroup.selected == 'auto' || selectGroup.selected == 'select') {
|
||||
print('[getCurrentNodeCountry] select 组选中的是 auto,查找 urltest 组');
|
||||
// 如果 select 组选中的是 auto,从 urltest 组获取
|
||||
final urlTestGroup = allGroups.firstWhere(
|
||||
(group) => group.type == ProxyType.urltest,
|
||||
orElse: () => throw Exception('未找到 urltest 组'),
|
||||
);
|
||||
|
||||
if (urlTestGroup.selected.isNotEmpty) {
|
||||
actualTag = urlTestGroup.selected;
|
||||
print('[getCurrentNodeCountry] ✅ 从 allGroups 的 urltest 组获取节点: $actualTag');
|
||||
KRLogUtil.kr_i('✅ 从 allGroups 的 urltest 组获取节点: $actualTag', tag: 'getCurrentNodeCountry');
|
||||
} else {
|
||||
print('[getCurrentNodeCountry] ❌ urltest 组的 selected 也为空');
|
||||
KRLogUtil.kr_w('❌ urltest 组的 selected 也为空', tag: 'getCurrentNodeCountry');
|
||||
return '';
|
||||
}
|
||||
} else {
|
||||
actualTag = selectGroup.selected;
|
||||
print('[getCurrentNodeCountry] ✅ 从 allGroups 的 select 组获取节点: $actualTag');
|
||||
KRLogUtil.kr_i('✅ 从 allGroups 的 select 组获取节点: $actualTag', tag: 'getCurrentNodeCountry');
|
||||
}
|
||||
} else {
|
||||
// 活动组不为空,从活动组获取
|
||||
// 从 SingBox 活动组中找到 "select" 选择器组
|
||||
final selectGroup = KRSingBoxImp.instance.kr_activeGroups.firstWhere(
|
||||
(group) => group.tag == 'select',
|
||||
orElse: () => throw Exception('未找到 select 组'),
|
||||
);
|
||||
|
||||
if (selectGroup.selected.isEmpty) {
|
||||
KRLogUtil.kr_w('❌ select 组的 selected 为空', tag: 'getCurrentNodeCountry');
|
||||
return '';
|
||||
}
|
||||
|
||||
// 获取该组当前选中的实际节点标签
|
||||
if (selectGroup.selected.isNotEmpty) {
|
||||
actualTag = selectGroup.selected;
|
||||
KRLogUtil.kr_i('从 select 组获取实际节点: $actualTag', tag: 'getCurrentNodeCountry');
|
||||
KRLogUtil.kr_i('✅ 从活动组获取节点: $actualTag', tag: 'getCurrentNodeCountry');
|
||||
}
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_w('获取实际节点失败: $e', tag: 'getCurrentNodeCountry');
|
||||
// 失败时使用 kr_cutSeletedTag 作为备选
|
||||
if (kr_cutSeletedTag.value.isNotEmpty && kr_cutSeletedTag.value != 'auto') {
|
||||
actualTag = kr_cutSeletedTag.value;
|
||||
KRLogUtil.kr_i('使用 kr_cutSeletedTag 作为备选: $actualTag', tag: 'getCurrentNodeCountry');
|
||||
}
|
||||
KRLogUtil.kr_e('❌ 从活动组获取节点失败: $e', tag: 'getCurrentNodeCountry');
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
// 验证 actualTag 是否有效
|
||||
if (actualTag.isEmpty) {
|
||||
KRLogUtil.kr_w('❌ 节点标签为空', tag: 'getCurrentNodeCountry');
|
||||
return '';
|
||||
}
|
||||
|
||||
// 使用实际节点标签查找国家代码
|
||||
KRLogUtil.kr_i('查找节点: $actualTag', tag: 'getCurrentNodeCountry');
|
||||
final node = kr_subscribeService.keyList[actualTag];
|
||||
@ -1229,6 +1290,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
return node.country;
|
||||
}
|
||||
|
||||
|
||||
/// 获取真实连接的节点信息(auto 模式下获取实际连接的节点)
|
||||
Map<String, dynamic> kr_getRealConnectedNodeInfo() {
|
||||
// 如果不是 auto 模式,直接返回当前选中的节点信息
|
||||
@ -1281,6 +1343,8 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
String kr_getRealConnectedNodeCountry() {
|
||||
final info = kr_getRealConnectedNodeInfo();
|
||||
final delay = kr_currentNodeLatency.value;
|
||||
final country1 = kr_getCurrentNodeCountry();
|
||||
print('country----$country1');
|
||||
final country = kr_getCountryFullName(info['country']);
|
||||
if (delay == -2) {
|
||||
return '--';
|
||||
|
||||
@ -7,6 +7,8 @@ import 'package:kaer_with_panels/app/widgets/kr_local_image.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/services/global_overlay_service.dart';
|
||||
import 'package:kaer_with_panels/app/services/singbox_imp/kr_sing_box_imp.dart';
|
||||
import 'package:kaer_with_panels/singbox/model/singbox_status.dart';
|
||||
|
||||
/// ✅ 按钮组件(带多层呼吸同心圆动画)
|
||||
class HIAnimatedConnectButton extends GetView<KRHomeController> {
|
||||
@ -20,9 +22,18 @@ class HIAnimatedConnectButton extends GetView<KRHomeController> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Obx(() {
|
||||
final isConnected = controller.kr_isConnected.value;
|
||||
final delay = controller.kr_currentNodeLatency.value;
|
||||
print('当前连接情况$delay----$isConnected');
|
||||
|
||||
// 🔧 关键: 强制读取两个 observable 确保追踪
|
||||
final _ = KRSingBoxImp.instance.kr_status.value; // 强制追踪
|
||||
final isConnected = controller.kr_isConnected.value; // 使用 controller 的状态
|
||||
|
||||
// 再次读取状态用于判断
|
||||
final status = KRSingBoxImp.instance.kr_status.value;
|
||||
final isSwitching = status is SingboxStarting || status is SingboxStopping;
|
||||
|
||||
print('🔵 Switch UI 更新: status=${status.runtimeType}, isConnected=$isConnected, isSwitching=$isSwitching');
|
||||
|
||||
final isShow = isConnected; // delay == -1 || isConnected;
|
||||
|
||||
final Color buttonColor = Theme.of(context).primaryColor;
|
||||
@ -71,6 +82,10 @@ class HIAnimatedConnectButton extends GetView<KRHomeController> {
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
if(isSwitching) {
|
||||
print('🔵 Switch UI 正在更新,切换中点击了按钮: status=${status.runtimeType}, isConnected=$isConnected, isSwitching=$isSwitching');
|
||||
return;
|
||||
}
|
||||
final hasValidSubscription =
|
||||
controller.kr_subscribeService.kr_availableSubscribes.isNotEmpty;
|
||||
if (hasValidSubscription) {
|
||||
|
||||
@ -15,6 +15,7 @@ import 'package:kaer_with_panels/app/widgets/dialogs/kr_dialog.dart';
|
||||
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
|
||||
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
|
||||
|
||||
|
||||
@ -77,8 +77,6 @@ class KRSingBoxImp {
|
||||
/// 是否自动自动选择线路
|
||||
final kr_isAutoOutbound = false.obs;
|
||||
|
||||
bool _initialized = false;
|
||||
|
||||
/// 连接类型
|
||||
final kr_connectionType = KRConnectionType.rule.obs;
|
||||
|
||||
@ -148,12 +146,6 @@ class KRSingBoxImp {
|
||||
}
|
||||
|
||||
try {
|
||||
if (_initialized) {
|
||||
KRLogUtil.kr_i('SingBox 已经初始化,跳过重复初始化');
|
||||
return;
|
||||
}
|
||||
_initialized = true;
|
||||
|
||||
KRLogUtil.kr_i('开始初始化 SingBox');
|
||||
// 在应用启动时初始化
|
||||
await KRCountryUtil.kr_init();
|
||||
@ -620,8 +612,7 @@ class KRSingBoxImp {
|
||||
|
||||
/// 订阅分组数据流
|
||||
void _kr_subscribeToGroups() {
|
||||
KRLogUtil.kr_i('🛰 启动分组监听 watchActiveGroups / watchGroups', tag: 'SingBox');
|
||||
|
||||
print('[_kr_subscribeToGroups] 🚀 开始订阅分组数据流');
|
||||
// 取消之前的分组订阅
|
||||
for (var sub in _kr_subscriptions) {
|
||||
if (sub.hashCode.toString().contains('Groups')) {
|
||||
@ -634,6 +625,7 @@ class KRSingBoxImp {
|
||||
_kr_subscriptions.add(
|
||||
kr_singBox.watchActiveGroups().listen(
|
||||
(groups) {
|
||||
print('[watchActiveGroups] 📡 收到活动组更新,数量: ${groups.length}');
|
||||
KRLogUtil.kr_i('📡 收到活动组更新,数量: ${groups.length}', tag: 'SingBox');
|
||||
kr_activeGroups.value = groups;
|
||||
|
||||
@ -650,6 +642,7 @@ class KRSingBoxImp {
|
||||
KRLogUtil.kr_i('✅ 活动组处理完成', tag: 'SingBox');
|
||||
},
|
||||
onError: (error) {
|
||||
print('[watchActiveGroups] ❌ 活动分组监听错误: $error');
|
||||
KRLogUtil.kr_e('❌ 活动分组监听错误: $error', tag: 'SingBox');
|
||||
},
|
||||
cancelOnError: false,
|
||||
@ -659,14 +652,22 @@ class KRSingBoxImp {
|
||||
_kr_subscriptions.add(
|
||||
kr_singBox.watchGroups().listen(
|
||||
(groups) {
|
||||
print('[watchGroups] 📡 收到所有组更新,数量: ${groups.length}');
|
||||
kr_allGroups.value = groups;
|
||||
// 打印每个组的基本信息
|
||||
for (int i = 0; i < groups.length; i++) {
|
||||
final group = groups[i];
|
||||
print('[watchGroups] 组[$i]: tag=${group.tag}, type=${group.type}, selected=${group.selected}');
|
||||
}
|
||||
},
|
||||
onError: (error) {
|
||||
print('[watchGroups] ❌ 所有分组监听错误: $error');
|
||||
KRLogUtil.kr_e('所有分组监听错误: $error');
|
||||
},
|
||||
cancelOnError: false,
|
||||
),
|
||||
);
|
||||
print('[_kr_subscribeToGroups] ✅ 分组数据流订阅完成,当前订阅数: ${_kr_subscriptions.length}');
|
||||
}
|
||||
|
||||
/// 验证节点选择是否生效
|
||||
@ -1128,7 +1129,7 @@ class KRSingBoxImp {
|
||||
|
||||
KRLogUtil.kr_i('✅ SingBox 核心已启动,开始初始化 command client', tag: 'SingBox');
|
||||
|
||||
// 🔑 在后台延迟订阅统计流,避免阻塞 UI
|
||||
// 🔑 在后台延迟订阅统计流和分组流,避免阻塞 UI
|
||||
Future.delayed(const Duration(milliseconds: 1000), () async {
|
||||
try {
|
||||
KRLogUtil.kr_i('📊 开始订阅统计数据流...', tag: 'SingBox');
|
||||
@ -1147,6 +1148,24 @@ class KRSingBoxImp {
|
||||
});
|
||||
}
|
||||
|
||||
// 🔧 关键修复:订阅分组数据流
|
||||
try {
|
||||
KRLogUtil.kr_i('📋 开始订阅分组数据流...', tag: 'SingBox');
|
||||
_kr_subscribeToGroups();
|
||||
KRLogUtil.kr_i('✅ 分组数据流订阅成功', tag: 'SingBox');
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_w('⚠️ 分组数据流订阅失败(稍后重试): $e', tag: 'SingBox');
|
||||
// 如果第一次失败,再等待一段时间重试
|
||||
Future.delayed(const Duration(milliseconds: 2000), () {
|
||||
try {
|
||||
_kr_subscribeToGroups();
|
||||
KRLogUtil.kr_i('✅ 分组数据流重试订阅成功', tag: 'SingBox');
|
||||
} catch (e2) {
|
||||
KRLogUtil.kr_e('❌ 分组数据流重试订阅失败: $e2', tag: 'SingBox');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 🔧 关键修复:恢复用户选择的节点
|
||||
try {
|
||||
final selectedNode = await KRSecureStorage().kr_readData(key: _keySelectedNode);
|
||||
|
||||
@ -100,24 +100,38 @@ class KRSecureStorage {
|
||||
return hash.bytes;
|
||||
}
|
||||
|
||||
// 获取存储箱
|
||||
Box<dynamic> get _box => Hive.box(_boxName);
|
||||
// 🔧 修复:确保 box 始终打开
|
||||
Future<Box<dynamic>> _ensureBoxOpen() async {
|
||||
if (!Hive.isBoxOpen(_boxName)) {
|
||||
KRLogUtil.kr_w('⚠️ Box 未打开,重新打开: $_boxName', tag: 'SecureStorage');
|
||||
final key = HiveAesCipher(_generateKey());
|
||||
await Hive.openBox(_boxName, encryptionCipher: key);
|
||||
KRLogUtil.kr_i('✅ Box 已重新打开', tag: 'SecureStorage');
|
||||
}
|
||||
return Hive.box(_boxName);
|
||||
}
|
||||
|
||||
// 存储数据
|
||||
Future<void> kr_saveData({required String key, required String value}) async {
|
||||
try {
|
||||
await _box.put(key, value);
|
||||
final box = await _ensureBoxOpen();
|
||||
await box.put(key, value);
|
||||
KRLogUtil.kr_i('✅ 数据已保存: $key', tag: 'SecureStorage');
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('存储数据失败: $e', tag: 'SecureStorage');
|
||||
KRLogUtil.kr_e('❌ 存储数据失败: $e', tag: 'SecureStorage');
|
||||
rethrow; // 重新抛出异常,让调用者知道保存失败
|
||||
}
|
||||
}
|
||||
|
||||
// 读取数据
|
||||
Future<String?> kr_readData({required String key}) async {
|
||||
try {
|
||||
return _box.get(key) as String?;
|
||||
final box = await _ensureBoxOpen();
|
||||
final value = box.get(key) as String?;
|
||||
KRLogUtil.kr_i('📖 读取数据: $key = ${value != null ? "存在" : "null"}', tag: 'SecureStorage');
|
||||
return value;
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('读取数据失败: $e', tag: 'SecureStorage');
|
||||
KRLogUtil.kr_e('❌ 读取数据失败: $e', tag: 'SecureStorage');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -125,27 +139,32 @@ class KRSecureStorage {
|
||||
// 删除数据
|
||||
Future<void> kr_deleteData({required String key}) async {
|
||||
try {
|
||||
await _box.delete(key);
|
||||
final box = await _ensureBoxOpen();
|
||||
await box.delete(key);
|
||||
KRLogUtil.kr_i('🗑️ 数据已删除: $key', tag: 'SecureStorage');
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('删除数据失败: $e', tag: 'SecureStorage');
|
||||
KRLogUtil.kr_e('❌ 删除数据失败: $e', tag: 'SecureStorage');
|
||||
}
|
||||
}
|
||||
|
||||
// 清除所有数据
|
||||
Future<void> kr_clearAllData() async {
|
||||
try {
|
||||
await _box.clear();
|
||||
final box = await _ensureBoxOpen();
|
||||
await box.clear();
|
||||
KRLogUtil.kr_i('🧹 所有数据已清除', tag: 'SecureStorage');
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('清除数据失败: $e', tag: 'SecureStorage');
|
||||
KRLogUtil.kr_e('❌ 清除数据失败: $e', tag: 'SecureStorage');
|
||||
}
|
||||
}
|
||||
|
||||
// 检查键是否存在
|
||||
Future<bool> kr_hasKey({required String key}) async {
|
||||
try {
|
||||
return _box.containsKey(key);
|
||||
final box = await _ensureBoxOpen();
|
||||
return box.containsKey(key);
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('检查键失败: $e', tag: 'SecureStorage');
|
||||
KRLogUtil.kr_e('❌ 检查键失败: $e', tag: 'SecureStorage');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -153,18 +172,20 @@ class KRSecureStorage {
|
||||
// 保存布尔值
|
||||
Future<void> kr_saveBool({required String key, required bool value}) async {
|
||||
try {
|
||||
await _box.put(key, value);
|
||||
final box = await _ensureBoxOpen();
|
||||
await box.put(key, value);
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('存储布尔值失败: $e', tag: 'SecureStorage');
|
||||
KRLogUtil.kr_e('❌ 存储布尔值失败: $e', tag: 'SecureStorage');
|
||||
}
|
||||
}
|
||||
|
||||
// 获取布尔值
|
||||
Future<bool?> kr_getBool({required String key}) async {
|
||||
try {
|
||||
return _box.get(key) as bool?;
|
||||
final box = await _ensureBoxOpen();
|
||||
return box.get(key) as bool?;
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('读取布尔值失败: $e', tag: 'SecureStorage');
|
||||
KRLogUtil.kr_e('❌ 读取布尔值失败: $e', tag: 'SecureStorage');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -172,18 +193,20 @@ class KRSecureStorage {
|
||||
// 保存整数
|
||||
Future<void> kr_saveInt({required String key, required int value}) async {
|
||||
try {
|
||||
await _box.put(key, value);
|
||||
final box = await _ensureBoxOpen();
|
||||
await box.put(key, value);
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('存储整数失败: $e', tag: 'SecureStorage');
|
||||
KRLogUtil.kr_e('❌ 存储整数失败: $e', tag: 'SecureStorage');
|
||||
}
|
||||
}
|
||||
|
||||
// 获取整数
|
||||
Future<int?> kr_getInt({required String key}) async {
|
||||
try {
|
||||
return _box.get(key) as int?;
|
||||
final box = await _ensureBoxOpen();
|
||||
return box.get(key) as int?;
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('读取整数失败: $e', tag: 'SecureStorage');
|
||||
KRLogUtil.kr_e('❌ 读取整数失败: $e', tag: 'SecureStorage');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user