123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- import 'dart:io';
- import 'package:get/get.dart';
- import 'package:shared_preferences/shared_preferences.dart';
- import '../../../common/LogHelper.dart';
- import '../../../data/model/NodeMode.dart';
- import '../../../global_controller/GlobalController.dart';
- import '../../../network/api_service.dart';
- enum NodeDisplayStrategy {
- All,
- LeastUsers,
- SelectedFirst,
- }
- class NodeController extends GetxController {
- //TODO: Implement NodeController
- final count = 0.obs;
- var isLoading = false.obs;
- var nodesToShow = <NodeMode>[].obs;
- var nodeModes = <NodeMode>[];
- var selectedIndex = (-1).obs;
- var errorMsg = ''.obs;
- final selectedNode = Rx<NodeMode?>(null);
- var pingResults = <int, String>{}.obs;
- //final selectedNodeId = (-1).obs;
- final isLoadingMap = <int, bool>{}.obs;
- var displayStrategy = Rx<NodeDisplayStrategy>(NodeDisplayStrategy.All);
- late final GlobalController globalController ;
- // Future<void> fetchNodes() async {
- // try {
- // isLoading.value = true;
- // nodeModes.clear();
- // nodeModes = await ApiService().getNode("/api/client/v4/nodes?vless=1");
- // nodesToShow.value = nodeModes;
- // LogHelper().d(nodeModes.toList());
- // loadSelectedNode();
- // } catch (e) {
- // errorMsg.value = e.toString();
- // } finally {
- // isLoading.value = false;
- // }
- // }
- Future<void> tcpPing(NodeMode node) async {
- int? nodeId = node.id;
- if (nodeId != null) {
- isLoadingMap[nodeId] = true; // 开始ping时设置为true
- isLoadingMap.refresh(); // 通知观察者
- final stopwatch = Stopwatch()..start();
- Socket? socket;
- try {
- socket = await Socket.connect(node.host!, node.port!, timeout: const Duration(seconds: 3));
- final elapsed = stopwatch.elapsedMilliseconds;
- pingResults[nodeId] = '${elapsed}ms'; // 使用普通的映射赋值
- pingResults.refresh(); // 通知观察者
- socket.destroy();
- } catch (e) {
- pingResults[nodeId] = 'Error'; // 使用普通的映射赋值
- pingResults.refresh(); // 通知观察者
- }
- isLoadingMap[nodeId] = false; // ping结束后设置为false
- isLoadingMap.refresh(); // 通知观察者
- }
- }
- void pingAllNodes() async {
- for (var node in nodeModes) {
- tcpPing(node); // 这里用了 await 使其串行 ping,若希望并行可移除 await
- }
- }
- Future<void> pingSingleNode(NodeMode node) async {
- await tcpPing(node);
- }
- void selectNode(NodeMode node) {
- selectedNode.value = node;
- _storeSelectedNode(node);
- //selectedIndex.value = nodeModes.indexWhere((item) => item.id == node.id);
- }
- Future<void> _storeSelectedNode(NodeMode node) async {
- final prefs = await SharedPreferences.getInstance();
- // 为简化起见,我们只存储node的ID,但您可以根据需要存储更多信息
- prefs.setInt('selectedNodeId', node.id!);
- }
- Future<void> loadSelectedNode() async {
- final prefs = await SharedPreferences.getInstance();
- final selectedNodeId = prefs.getInt('selectedNodeId');
- if (selectedNodeId != null) {
- //selectedIndex.value = nodeModes.indexWhere((item) => item.id == selectedNodeId);
- selectedNode.value = nodeModes.firstWhere((node) => node.id == selectedNodeId);
- }
- }
- //自动选择人数最小的线路
- NodeMode selectBestNode(List<NodeMode> nodes) {
- return nodes.where((node) => node.countryCode == 'HK') //筛选地区是HK的节点
- .reduce((value, element) =>
- value.onlineUsers! < element.onlineUsers! ? value : element); //选择人数最小的
- }
- void selectMinOnlineUsersNodeInRegion(String region) {
- List<NodeMode> nodesInRegion = nodeModes.where((node) => node.countryCode == region).toList();
- if (nodesInRegion.isNotEmpty) {
- NodeMode? minNode = nodesInRegion.reduce((curr, next) => curr.onlineUsers! <= next.onlineUsers! ? curr : next);
- if (minNode != null) {
- selectNode(minNode);
- }
- }
- }
- void filterNodesWithLeastUsersInHK() {
- displayStrategy.value = NodeDisplayStrategy.LeastUsers;
- updateNodesToDisplay();
- }
- void filterNodesByRegion(String region) {
- nodesToShow.value = nodeModes.where((node) => node.countryCode == region).toList();
- updateNodesToDisplay();
- }
- void showAllNodes() {
- displayStrategy.value = NodeDisplayStrategy.All;
- updateNodesToDisplay();
- // nodesToShow.value = List.from(nodeModes);
- }
- void showSelectedFirst() {
- displayStrategy.value = NodeDisplayStrategy.SelectedFirst;
- updateNodesToDisplay();
- // 如果需要,可以添加其他逻辑。
- }
- void updateNodesToDisplay() {
- List<NodeMode> nodes = List.from(nodeModes);
- switch (displayStrategy.value) {
- case NodeDisplayStrategy.LeastUsers:
- List<NodeMode> filteredNodes = nodeModes.where((node) => node.countryCode == "hk" && node.onlineUsers != null).toList();
- if (filteredNodes.isNotEmpty) {
- int? minUsers = filteredNodes.map((node) => node.onlineUsers!).reduce((curr, next) => curr < next ? curr : next);
- nodes = nodes.where((node) => node.onlineUsers == minUsers && node.countryCode == "hk").toList();
- selectNode(nodes.first);
- } else {
- // Handle the case where no nodes match the criteria. Maybe display a message or use a fallback.
- nodes = []; // Empty list or some fallback
- }
- break;
- case NodeDisplayStrategy.SelectedFirst:
- break;
- case NodeDisplayStrategy.All:
- // // 将选中的节点移动到前面
- // if (selectedNode.value != null) {
- // nodes.removeWhere((node) => node.id == selectedNode.value?.id);
- // nodes.insert(0, selectedNode.value!);
- // }
- break;
- default:
- // 不需要额外的处理,因为nodes已经包含所有节点。
- break;
- }
- nodesToShow.value = nodes; // 使用 assignAll() 方法触发更新
- }
- @override
- void onInit() {
- super.onInit();
- //fetchNodes();
- globalController = Get.put(GlobalController());
- nodeModes = globalController.nodeModes;
- nodesToShow.value = nodeModes;
- }
- @override
- void onReady() {
- super.onReady();
- }
- @override
- void onClose() {
- super.onClose();
- }
- void increment() => count.value++;
- }
|