splittunneling_controller.dart 4.1 KB

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