|
@@ -1,19 +1,13 @@
|
|
|
-import 'dart:ffi';
|
|
|
import 'dart:io';
|
|
|
-import 'package:flutter/services.dart';
|
|
|
import 'package:flutter/widgets.dart';
|
|
|
import 'package:get/get.dart';
|
|
|
import 'package:naiyouwl/app/bean/proxie.dart';
|
|
|
import 'package:naiyouwl/app/common/LogHelper.dart';
|
|
|
import 'package:naiyouwl/app/common/SharedPreferencesUtil.dart';
|
|
|
-import 'package:naiyouwl/app/common/constants.dart';
|
|
|
import 'package:naiyouwl/app/controller/controllers.dart';
|
|
|
import 'package:naiyouwl/app/data/model/NodeMode.dart';
|
|
|
import 'package:naiyouwl/app/network/api_service.dart';
|
|
|
-import 'package:naiyouwl/app/network/dio_client.dart';
|
|
|
-import 'package:naiyouwl/app/utils/shell.dart';
|
|
|
import 'package:naiyouwl/app/utils/system_proxy.dart';
|
|
|
-import 'package:naiyouwl/app/utils/utils.dart';
|
|
|
import 'package:proxy_manager/proxy_manager.dart';
|
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
import 'package:tray_manager/tray_manager.dart';
|
|
@@ -21,11 +15,16 @@ import 'package:window_manager/window_manager.dart';
|
|
|
import 'package:path/path.dart' as path;
|
|
|
import 'package:wl_base_help/wl_base_help.dart';
|
|
|
import '../clash/service/clash_service.dart';
|
|
|
+import '../common/constants.dart';
|
|
|
import '../const/const.dart';
|
|
|
+import '../data/model/UserMode.dart';
|
|
|
+import '../network/dio_client.dart';
|
|
|
+import '../utils/shell.dart';
|
|
|
+import '../utils/utils.dart';
|
|
|
|
|
|
class GlobalController extends GetxController {
|
|
|
final proxyManager = ProxyManager();
|
|
|
- bool systemProxy = false;
|
|
|
+ var systemProxy = false.obs;
|
|
|
late BuildContext context;
|
|
|
final List<String> modes = ['rule', 'global'];
|
|
|
final List<String> routeModes = ['sys', 'tun'];
|
|
@@ -44,16 +43,9 @@ class GlobalController extends GetxController {
|
|
|
final _wlBaseHelpPlugin = WlBaseHelp();
|
|
|
var sysInfo = ''.obs;
|
|
|
var sysVersion = kVersion.obs;
|
|
|
+ var connectStatus = false.obs;
|
|
|
|
|
|
final selectedNode = Rx<NodeMode?>(null);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
|
|
|
final List<String> groupInternalTypes = ['DIRECT', 'REJECT', 'GLOBAL'];
|
|
|
final List<String> groupTypes = [
|
|
@@ -62,150 +54,90 @@ class GlobalController extends GetxController {
|
|
|
ProxieProxieType.fallback,
|
|
|
ProxieProxieType.loadbalance,
|
|
|
];
|
|
|
+
|
|
|
Future<void> init(BuildContext context) async {
|
|
|
this.context = context;
|
|
|
watchExit();
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+ await controllers.config.initConfig();
|
|
|
+ await controllers.cc_service.initConfig();
|
|
|
+ sysInfo.value = await platformState();
|
|
|
await SharedPreferencesUtil().delete("last_successful_url");
|
|
|
-
|
|
|
await controllers.tray.initTray();
|
|
|
controllers.window.initWindow();
|
|
|
+ await controllers.cc_service.isCanOperationService();
|
|
|
}
|
|
|
|
|
|
-
|
|
|
void updateMsg(String msg) {
|
|
|
msgStatus.value = msg;
|
|
|
}
|
|
|
|
|
|
Future<void> updateMode(String route) async {
|
|
|
- if(allowStatusUpdate){
|
|
|
-
|
|
|
- return;
|
|
|
- }
|
|
|
+ if(allowStatusUpdate) return;
|
|
|
modesSelect.value = route;
|
|
|
- final coreStatus = controllers.service.coreStatus.value;
|
|
|
- if( coreStatus == RunningState.running){
|
|
|
- controllers.core.fetchConfigUpdate({'mode': modesSelect.value});
|
|
|
- }
|
|
|
+ await controllers.core.fetchConfigUpdate({
|
|
|
+ "mode": modesSelect.value
|
|
|
+ });
|
|
|
+ await controllers.global.swift(selectedNode.value?.name ?? "");
|
|
|
}
|
|
|
|
|
|
void updateUserInfo(User user) {
|
|
|
-
|
|
|
- if (user != null) {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- update();
|
|
|
- }
|
|
|
+ update();
|
|
|
}
|
|
|
- Future<void> updateRoute(String route) async {
|
|
|
- if(allowStatusUpdate){
|
|
|
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+ Future<void> updateRoute(String route) async {
|
|
|
+ if(allowStatusUpdate) return;
|
|
|
routeModesSelect.value = route;
|
|
|
LogHelper().d("当前ROUTE模式${routeModesSelect.value}");
|
|
|
}
|
|
|
+
|
|
|
Future<void> fetchNodes() async {
|
|
|
nodeModes.value = await ApiService().getNode("/api/client/v4/nodes?vless=1");
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
Future<void> updateNode() async {
|
|
|
NodeMode? targetNode;
|
|
|
if (selectedNode.value == null) {
|
|
|
targetNode = await findNodeWithMinUsers(nodeModes);
|
|
|
+ selectedNode.value = targetNode;
|
|
|
} else {
|
|
|
targetNode = selectedNode.value;
|
|
|
}
|
|
|
if (targetNode != null){
|
|
|
selectNode(targetNode);
|
|
|
await swift(targetNode.name ?? "");
|
|
|
-
|
|
|
}
|
|
|
}
|
|
|
|
|
|
Future<void> showConsole() async {
|
|
|
await _wlBaseHelpPlugin.showConsole();
|
|
|
}
|
|
|
+
|
|
|
Future<void> hideConsole() async {
|
|
|
await _wlBaseHelpPlugin.hideConsole();
|
|
|
}
|
|
|
- Future<void> startSysMode() async {
|
|
|
-
|
|
|
- await makeProxy();
|
|
|
-
|
|
|
-
|
|
|
- }
|
|
|
- Future<void> startTunMode() async {
|
|
|
- await makeProxy();
|
|
|
- }
|
|
|
|
|
|
Future<void> swift(String name) async {
|
|
|
-
|
|
|
try{
|
|
|
var g = "proxy";
|
|
|
- if(modesSelect.value == "global")
|
|
|
- {
|
|
|
+ if(modesSelect.value == "global") {
|
|
|
g = "GLOBAL";
|
|
|
}
|
|
|
|
|
|
await controllers.core.fetchSetProxieGroup(g, name);
|
|
|
final conn = await controllers.core.fetchConnection();
|
|
|
- if(conn == null) { return; }
|
|
|
+ if(conn == null) return;
|
|
|
for (final it in conn.connections) {
|
|
|
if (it.chains.contains(name)) controllers.core.fetchCloseConnections(it.id);
|
|
|
}
|
|
|
- }catch (e) {
|
|
|
+ } catch (e) {
|
|
|
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- Future<void> makeTestProxy() async {
|
|
|
- final clashService = ClashService();
|
|
|
-
|
|
|
- if (!await Paths.config.exists()) await Paths.config.create(recursive: true);
|
|
|
- await clashService.saveConfigToFile(path.join(Paths.config.path, 'proxyfino.yaml'), nodeModes);
|
|
|
}
|
|
|
+
|
|
|
Future<void> makeProxy() async {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- await controllers.config.makeClashConfig(nodeModes);
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
+ await controllers.service.saveConfigToFile(path.join(Paths.config.path, Files.makeProxyConfig.path), nodeModes);
|
|
|
}
|
|
|
Future<NodeMode> findNodeWithMinUsers(List<NodeMode> nodes) async {
|
|
|
return nodes
|
|
@@ -214,13 +146,6 @@ class GlobalController extends GetxController {
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
- Future<SystemProxyConfig> getSysProxy() async{
|
|
|
- return await SystemProxy.instance.get();
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
Future<void> TunProxySwitch(bool open) async {
|
|
|
tunProxySwitchIng.value = true;
|
|
|
routeModesSelect.value = open ? "tun": "sys";
|
|
@@ -228,119 +153,24 @@ class GlobalController extends GetxController {
|
|
|
tunProxySwitchIng.value = false;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
Future<void> systemProxySwitch(bool open) async {
|
|
|
systemProxySwitchIng.value = true;
|
|
|
-
|
|
|
- await controllers.config.setSystemProxy(open);
|
|
|
- if(open)
|
|
|
- {
|
|
|
- await openProxy();
|
|
|
-
|
|
|
- } else {
|
|
|
- await closeProxy();
|
|
|
-
|
|
|
- }
|
|
|
systemProxySwitchIng.value = false;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
void watchExit() {
|
|
|
-
|
|
|
-
|
|
|
if (Platform.isMacOS) {
|
|
|
-
|
|
|
-
|
|
|
ProcessSignal.sigterm.watch().listen((_) {
|
|
|
stdout.writeln('exit: sigterm');
|
|
|
handleExit();
|
|
|
});
|
|
|
}
|
|
|
-
|
|
|
ProcessSignal.sigint.watch().listen((_) {
|
|
|
stdout.writeln('exit: sigint');
|
|
|
handleExit();
|
|
|
});
|
|
|
}
|
|
|
+
|
|
|
void selectNode(NodeMode node) {
|
|
|
nodeId.value = node.id ?? 0;
|
|
|
controllers.global.selectedNode.value = node;
|
|
@@ -349,46 +179,19 @@ class GlobalController extends GetxController {
|
|
|
|
|
|
Future<void> _storeSelectedNode(NodeMode node) async {
|
|
|
final prefs = await SharedPreferences.getInstance();
|
|
|
-
|
|
|
-
|
|
|
prefs.setInt('selectedNodeId', node.id ?? -1);
|
|
|
await loadSelectedNode();
|
|
|
}
|
|
|
|
|
|
-
|
|
|
Future<void> loadSelectedNode() async {
|
|
|
final prefs = await SharedPreferences.getInstance();
|
|
|
final selectedNodeId = prefs.getInt('selectedNodeId');
|
|
|
if (selectedNodeId != null) {
|
|
|
-
|
|
|
selectedNode.value = nodeModes.firstWhere((node) => node.id == selectedNodeId);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- void initRegularlyUpdate() {
|
|
|
- Future.delayed(const Duration(minutes: 5)).then((_) async {
|
|
|
- for (final it in controllers.config.config.value.subs) {
|
|
|
- try {
|
|
|
- if (it.url == null || it.url!.isEmpty) continue;
|
|
|
- if (((DateTime.now().millisecondsSinceEpoch ~/ 1000) - (it.updateTime ?? 0)) < controllers.config.config.value.updateInterval) continue;
|
|
|
- final chenged = await controllers.config.updateSub(it);
|
|
|
- if (!chenged) continue;
|
|
|
- if (it.name != controllers.config.config.value.selected) continue;
|
|
|
-
|
|
|
- await controllers.service.reloadClashCore();
|
|
|
- await Future.delayed(const Duration(seconds: 20));
|
|
|
- } catch (_) {}
|
|
|
- }
|
|
|
- initRegularlyUpdate();
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
Future<void> openProxy() async {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
int? port = controllers.config.mixedPort.value;
|
|
|
if (port == 0) {
|
|
|
port = null;
|
|
@@ -403,69 +206,27 @@ class GlobalController extends GetxController {
|
|
|
}
|
|
|
port = port ?? mixedPort ?? 0;
|
|
|
if (port != 0) {
|
|
|
- if(Platform.isWindows){
|
|
|
- String loa = '127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*';
|
|
|
- int? exitCode;
|
|
|
-
|
|
|
-
|
|
|
- try {
|
|
|
- var result = await Process.run(
|
|
|
- Files.assetsSysProxyWin.path,
|
|
|
- ['global','127.0.0.1:$port',loa],
|
|
|
- runInShell: true,
|
|
|
- );
|
|
|
- LogHelper().d(result.stderr);
|
|
|
- LogHelper().d(result.stdout);
|
|
|
- } on ProcessException catch (e) {
|
|
|
-
|
|
|
- await proxyManager.setAsSystemProxy(
|
|
|
- ProxyTypes.http,
|
|
|
- "127.0.0.1",
|
|
|
- port,
|
|
|
- );
|
|
|
-
|
|
|
- await proxyManager.setAsSystemProxy(
|
|
|
- ProxyTypes.https,
|
|
|
- "127.0.0.1",
|
|
|
- port,
|
|
|
- );
|
|
|
- await proxyManager.setAsSystemProxy(
|
|
|
- ProxyTypes.socks,
|
|
|
- "127.0.0.1",
|
|
|
- port,
|
|
|
- );
|
|
|
- }
|
|
|
- } else {
|
|
|
- await proxyManager.setAsSystemProxy(
|
|
|
- ProxyTypes.http,
|
|
|
- "127.0.0.1",
|
|
|
- port,
|
|
|
- );
|
|
|
- await proxyManager.setAsSystemProxy(
|
|
|
- ProxyTypes.https,
|
|
|
- "127.0.0.1",
|
|
|
- port,
|
|
|
- );
|
|
|
+ await proxyManager.setAsSystemProxy(
|
|
|
+ ProxyTypes.http,
|
|
|
+ "127.0.0.1",
|
|
|
+ port,
|
|
|
+ );
|
|
|
+ await proxyManager.setAsSystemProxy(
|
|
|
+ ProxyTypes.https,
|
|
|
+ "127.0.0.1",
|
|
|
+ port,
|
|
|
+ );
|
|
|
+
|
|
|
+ await proxyManager.setAsSystemProxy(
|
|
|
+ ProxyTypes.socks,
|
|
|
+ "127.0.0.1",
|
|
|
+ port,
|
|
|
+ );
|
|
|
|
|
|
- await proxyManager.setAsSystemProxy(
|
|
|
- ProxyTypes.socks,
|
|
|
- "127.0.0.1",
|
|
|
- port,
|
|
|
- );
|
|
|
- systemProxy = true;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
socksPort = socksPort ?? mixedPort ?? 0;
|
|
|
if (socksPort != 0) {
|
|
|
-
|
|
|
if (!Platform.isWindows) {
|
|
|
await proxyManager.setAsSystemProxy(
|
|
|
ProxyTypes.socks,
|
|
@@ -473,57 +234,48 @@ class GlobalController extends GetxController {
|
|
|
socksPort,
|
|
|
);
|
|
|
}
|
|
|
- systemProxy = true;
|
|
|
+
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
-
|
|
|
+ systemProxy.value = true;
|
|
|
+ }
|
|
|
|
|
|
Future<void> closeProxy() async {
|
|
|
-
|
|
|
- if (Platform.isWindows) {
|
|
|
- try {
|
|
|
- var result = await Process.run(
|
|
|
- Files.assetsSysProxyWin.path,
|
|
|
- ['set','1','','',''],
|
|
|
- runInShell: true,
|
|
|
- );
|
|
|
- LogHelper().d(result.stderr);
|
|
|
- LogHelper().d(result.stdout);
|
|
|
- } on ProcessException catch (e) {
|
|
|
-
|
|
|
- throw Exception('Failed to start sysproxy: ${e.message}');
|
|
|
- }
|
|
|
- proxyManager.cleanSystemProxy();
|
|
|
- }
|
|
|
-
|
|
|
- systemProxy = false;
|
|
|
+ await proxyManager.cleanSystemProxy();
|
|
|
+ systemProxy.value = false;
|
|
|
}
|
|
|
+
|
|
|
Future<void> stopAllCore() async {
|
|
|
await systemProxySwitch(false);
|
|
|
if(Platform.isWindows){
|
|
|
await controllers.service.stopClashCore();
|
|
|
} else if(Platform.isMacOS) {
|
|
|
- await controllers.cc_service.fetchStop();
|
|
|
+ if (controllers.cc_service.serviceIsRuning) {
|
|
|
+ await controllers.cc_service.fetchStop();
|
|
|
+ } else {
|
|
|
+ await controllers.service.stopClashCore();
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
- if(!controllers.service.serviceMode.value){{
|
|
|
+ if(!controllers.service.serviceMode.value){
|
|
|
if(Platform.isWindows){
|
|
|
- await onKillProcess(path.basename(Files.assetsCCore.path));
|
|
|
+ await onKillProcess(path.basename(Files.assetsClashService.path));
|
|
|
}
|
|
|
await killProcess(path.basename(Files.assetsCCore.path));
|
|
|
- }}
|
|
|
+ await killProcess(path.basename(Files.assetsClashService.path));
|
|
|
+ }
|
|
|
|
|
|
if(!controllers.service.serviceMode.value){
|
|
|
await killProcess(path.basename(Files.assetsClashService.path));
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
+
|
|
|
Future<void> handleExit() async {
|
|
|
await stopAllCore();
|
|
|
await trayManager.destroy();
|
|
|
await windowManager.destroy();
|
|
|
-
|
|
|
}
|
|
|
+
|
|
|
void handleApiError(dynamic error) {
|
|
|
if (error is AppException) {
|
|
|
LogHelper().d('API error with status code: ${error.statusCode}');
|
|
@@ -533,14 +285,12 @@ class GlobalController extends GetxController {
|
|
|
LogHelper().d('Other error: $error');
|
|
|
errorMsg.value = error.toString();
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
@override
|
|
|
void dispose() {
|
|
|
controllers.tray.dispose();
|
|
|
controllers.window.dispose();
|
|
|
-
|
|
|
super.dispose();
|
|
|
}
|
|
|
}
|