splittunneling_controller.dart 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import 'dart:convert';
  2. import 'package:get/get.dart';
  3. import '../../../../utils/event_bus.dart';
  4. import '../../../../utils/log/logger.dart';
  5. import 'package:nomo/app/data/sp/ix_sp.dart';
  6. import '../../../routes/app_pages.dart';
  7. import '../selectapp/controllers/splittunneling_selectapp_controller.dart';
  8. class SplittunnelingController extends GetxController with EventBusMixin {
  9. static const String TAG = 'SplittunnelingController';
  10. // 当前选中的分流隧道模式
  11. final selectedMode = SplitTunnelingMode.none.obs;
  12. // 缓存键
  13. static const String _selectedModeKey = 'splittunneling_selected_mode';
  14. @override
  15. void onInit() {
  16. super.onInit();
  17. _loadSelectedMode();
  18. // 监听 PageVisibleEvent
  19. listenEvent<SplitTunnelingPageEvent>((event) {
  20. final selectApps = getSelectedApps(event.mode);
  21. if (selectApps.isNotEmpty) {
  22. selectedMode.value = event.mode;
  23. _saveSelectedMode();
  24. refreshSelectedApps();
  25. } else {
  26. if (selectedMode.value == event.mode) {
  27. selectedMode.value = SplitTunnelingMode.none;
  28. _saveSelectedMode();
  29. refreshSelectedApps();
  30. }
  31. }
  32. });
  33. }
  34. /// 刷新选中应用显示
  35. void refreshSelectedApps() {
  36. // 触发UI更新
  37. selectedMode.refresh();
  38. }
  39. /// 加载选中的模式
  40. void _loadSelectedMode() {
  41. final modeString = IXSP.getString(_selectedModeKey);
  42. if (modeString != null) {
  43. try {
  44. selectedMode.value = SplitTunnelingMode.values.firstWhere(
  45. (mode) => mode.toString() == modeString,
  46. orElse: () => SplitTunnelingMode.none,
  47. );
  48. } catch (e) {
  49. log(TAG, '加载选中模式失败: $e');
  50. }
  51. }
  52. }
  53. /// 保存选中的模式
  54. void _saveSelectedMode() {
  55. IXSP.setString(_selectedModeKey, selectedMode.value.toString());
  56. }
  57. /// 选择分流隧道模式
  58. void selectMode(SplitTunnelingMode mode) {
  59. if (mode == SplitTunnelingMode.none) {
  60. selectedMode.value = SplitTunnelingMode.none;
  61. _saveSelectedMode();
  62. refreshSelectedApps();
  63. } else {
  64. final selectedApps = getSelectedApps(mode);
  65. if (selectedApps.isNotEmpty) {
  66. if (selectedMode.value == mode) {
  67. selectedMode.value = SplitTunnelingMode.none;
  68. } else {
  69. selectedMode.value = mode;
  70. }
  71. _saveSelectedMode();
  72. refreshSelectedApps();
  73. } else {
  74. Get.toNamed(Routes.SPLITTUNNELING_SELECTAPP, arguments: mode);
  75. }
  76. }
  77. }
  78. void toSelectAppPage(SplitTunnelingMode mode) {
  79. Get.toNamed(Routes.SPLITTUNNELING_SELECTAPP, arguments: mode);
  80. }
  81. /// 获取当前模式选中的应用(最多3个)
  82. List<Map<String, dynamic>> getSelectedApps(SplitTunnelingMode mode) {
  83. if (mode == SplitTunnelingMode.none) {
  84. return [];
  85. }
  86. try {
  87. final key = mode == SplitTunnelingMode.exclude
  88. ? 'splittunneling_exclude_selected_apps'
  89. : 'splittunneling_include_selected_apps';
  90. final selectedAppsJson = IXSP.getString(key);
  91. if (selectedAppsJson != null) {
  92. final selectedPackageNames =
  93. jsonDecode(selectedAppsJson) as List<dynamic>;
  94. // 获取缓存的应用数据
  95. final cachedAppsJson = IXSP.getString('splittunneling_cached_apps');
  96. if (cachedAppsJson != null) {
  97. final cachedApps = jsonDecode(cachedAppsJson) as List;
  98. // 按照保存的顺序重建列表
  99. final selectedApps = <Map<String, dynamic>>[];
  100. for (final packageName in selectedPackageNames) {
  101. if (selectedApps.length >= 3) break; // 最多取3个
  102. final app = cachedApps.firstWhere(
  103. (app) => app['packageName'] == packageName,
  104. orElse: () => null,
  105. );
  106. if (app != null) {
  107. selectedApps.add({
  108. 'name': app['name'],
  109. 'packageName': app['packageName'],
  110. 'icon': app['icon'],
  111. });
  112. }
  113. }
  114. return selectedApps;
  115. }
  116. }
  117. } catch (e) {
  118. log(TAG, '获取选中应用失败: $e');
  119. }
  120. return [];
  121. }
  122. }