import 'dart:async'; import 'dart:io'; import 'package:dart_json_mapper/dart_json_mapper.dart'; import 'package:get/get.dart'; import 'package:naiyouwl/app/common/constants.dart'; import 'package:naiyouwl/app/controller/GlobalController.dart'; import 'package:naiyouwl/app/controller/controllers.dart'; import 'package:naiyouwl/app/utils/shell.dart'; import 'package:naiyouwl/app/utils/utils.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../../common/LogHelper.dart'; import '../../../common/SharedPreferencesUtil.dart'; import '../../../component/connection_status.dart'; import '../../../data/model/LocalUser.dart'; import '../../../data/model/NodeMode.dart'; import '../../../data/model/SysConfig.dart'; import '../../../data/model/UserMode.dart'; import '../../../network/api_service.dart'; import '../../../routes/app_pages.dart'; enum ImageType { CUSTOMER, PROMOTION, TUTORIAL, RENEWAL, } class HomeController extends GetxController { //TODO: Implement HomeController var isLoading = false.obs; var sysConfig = SysConfig().obs; var localUsers = LocalUser().obs; var userMode = User().obs; var UsersysConfig = SysConfig().obs; var serviceStuatus = false.obs; var coreStuatus = false.obs; var connectStatus = Rx(ConnectionStatus.disconnected); var nodeModes = []; bool get isRunning => connectStatus.value == ConnectionStatus.stopped && controllers.global.allowStatusUpdate; late final GlobalController globalController = controllers.global; StreamSubscription? _statusSubscription; final Map imageMap = { ImageType.CUSTOMER: "assets/images/main/customer.png", ImageType.PROMOTION: "assets/images/main/promotion.png", ImageType.TUTORIAL: "assets/images/main/tutorial.png", ImageType.RENEWAL: "assets/images/main/renewal.png", }; void onImageTap(ImageType type) async { if(type == ImageType.CUSTOMER){ await launchUrl(Uri.parse(UsersysConfig.value.userTicket ?? "")); } else if (type == ImageType.PROMOTION){ await launchUrl(Uri.parse(UsersysConfig.value.affUrl ?? "")); } else if (type == ImageType.TUTORIAL){ await launchUrl(Uri.parse(UsersysConfig.value.userDownload ?? "")); } else if (type == ImageType.RENEWAL){ await launchUrl(Uri.parse(UsersysConfig.value.userBuy ?? "")); } LogHelper().d("${imageMap[type]} tapped as ${type.toString().split('.').last}"); } void updateStatus(ConnectionStatus newStatus) { connectStatus.value = newStatus; } void _handleStateChange([dynamic _]) async { final coreStatus = controllers.service.coreStatus.value; final isVisible = controllers.window.isVisible.value; final serviceStatus = controllers.service.serviceStatus.value; if(serviceStatus != RunningState.running){ updateStatus(ConnectionStatus.disconnected); return; } if (coreStatus == RunningState.running && isVisible && controllers.global.allowStatusUpdate) { // if(connectStatus.value == ConnectionStatus.connecting){ // controllers.global.updateMsg("连接完成..."); // } } } Future handleButtonClick() async { if(userMode.value.enable != 1){ controllers.global.handleApiError("用户是禁用的,无法连接"); return; } if(connectStatus.value == ConnectionStatus.connecting ){ return; } // 如果当前状态是已连接或正在连接,则停止服务 if (connectStatus.value == ConnectionStatus.stopped) { controllers.global.allowStatusUpdate = false; await controllers.config.setBreakConnections(true); // // 停止服务 await controllers.service.stopClash(); await controllers.global.systemProxySwitch(false); updateStatus(ConnectionStatus.disconnected); return; } else { controllers.config.config.value.selected = 'proxy.yaml'; controllers.global.updateMsg("开始连接..."); await controllers.config.setBreakConnections(true); controllers.global.allowStatusUpdate = true; var routeModes = controllers.global.routeModesSelect.value; if(routeModes == "tun"){ controllers.global.updateMsg("正在启动网卡模式..."); controllers.config.clashCoreTunEnable.value = true; controllers.global.startTunMode(); if(controllers.service.serviceMode.value == false){ if(Platform.isWindows) { if(!await isRunningAsAdmin()){ controllers.global.updateMsg("网卡模式需要管理模式运行..."); return; } } else { if(controllers.service.serviceMode.value == false){ controllers.global.updateMsg("需要开启服务,才能使用..."); return; } } //await controllers.service.serviceModeSwitch(true); serviceStuatus.value = true; } final coreStatus = controllers.service.coreStatus.value; if (coreStatus == RunningState.running){ await controllers.service.reloadClashCore(); } else{ await controllers.service.startClashCore(); } } else { controllers.global.updateMsg("正在启动系统模式..."); controllers.config.clashCoreTunEnable.value = false; controllers.global.startSysMode(); final coreStatus = controllers.service.coreStatus.value; if (coreStatus == RunningState.running){ controllers.global.updateMsg("正在重启内核..."); await controllers.service.reloadClashCore(); } else{ controllers.global.updateMsg("正在启动内核..."); await controllers.service.startClashCore(); } } updateStatus(ConnectionStatus.connecting); Future.delayed(const Duration(seconds: 3), () async { updateStatus(ConnectionStatus.stopped); await controllers.global.updateDate(); await controllers.global.updateNode(); // await controllers.tray.updateTray(); if(routeModes == "tun"){ } else{ await controllers.global.systemProxySwitch(true); controllers.global.updateMsg("设置系统代理完成..."); } }); } } void SetSysProxy() async{ } Future stopVpn() async { controllers.global.updateMsg("正在停止..."); await controllers.global.systemProxySwitch(false); await controllers.config.setBreakConnections(true); await controllers.tray.updateTray(); // // 停止服务 await controllers.service.stopClashCore(); controllers.global.updateMsg("正在停止.等待3秒防止端口无法释放"); Future.delayed(const Duration(seconds: 3), () async { controllers.global.allowStatusUpdate = false; updateStatus(ConnectionStatus.disconnected); controllers.global.updateMsg("停止完成,点击立即加速"); }); } Future fetchAuthUser() async { try { // if (!controllers.service.isRunning){ // controllers.global.updateMsg("内核没有启动..."); // return; // } if(controllers.global.routeModesSelect.value == "tun") { if(Platform.isWindows) { if(!await isRunningAsAdmin()){ controllers.global.updateMsg("网卡模式需要管理模式运行..."); return; } } else { if(controllers.service.serviceMode.value == false){ controllers.global.updateMsg("需要开启服务,才能使用,记得卸载服务才能卸载软件..."); return; } } } if (controllers.global.allowStatusUpdate && connectStatus.value == ConnectionStatus.stopped || connectStatus.value == ConnectionStatus.connecting) { controllers.global.updateMsg("当前连接状态未停止,不要多次启动..."); return; } controllers.global.updateMsg("正在身份验证..."); final ret = await ApiService().fetchAuthUser(KAuthUser); if(controllers.global.selectedNode.value == null){ controllers.global.selectedNode.value = ret; controllers.global.selectNode(ret); controllers.global.updateMsg("获取自动节点完成..."); } await handleButtonClick(); } catch (e) { controllers.global.handleApiError(e); } finally { } } Future fetchSysConfig() async { try { String? data = await SharedPreferencesUtil().getString("sysconfig"); if(data != null){ sysConfig.value =JsonMapper.deserialize(data)!; } } catch (e) { controllers.global.handleApiError(e); } finally { } } Future fetchUserinfo() async { try { isLoading.value = true; userMode.value = await ApiService().userinfo("/api/client/v4/userinfo"); await globalController.fetchNodes(); await fetchlUserUrl(localUsers.value.email ?? "",localUsers.value.password ?? ""); //await controllers.global.makeProxy(); //await controllers.global.initService(); // //生成配置 // await controllers.global.makeProxy(); // // 开始重启服务 // await controllers.service.reloadClashCore(); } catch (e) { controllers.global.handleApiError(e); } finally { isLoading.value = false; } } Future fetchNode() async { try { isLoading.value = true; await globalController.fetchNodes(); } catch (e) { controllers.global.handleApiError(e); } finally { isLoading.value = false; } } Future outlogin() async { if(connectStatus.value == ConnectionStatus.connecting || connectStatus.value == ConnectionStatus.stopped){ controllers.global.handleApiError("当前连接状态无法退出(先停止加速)"); return ; } await SharedPreferencesUtil().delete("token"); try { //isLoading.value = true; await ApiService().fetchLogout(KLogout); } catch (e) { //errorMsg.value = e.toString(); } finally { //isLoading.value = false; } Get.offNamed(Routes.LOGIN); } //await SharedPreferencesUtil().setObject("localUser", userModes.toJson()); Future fetchlUserUrl(String username,String password) async { try { isLoading.value = true; UsersysConfig.value = await ApiService().fetchUserSysConfig(kSysConfig,{"email":username,"password":password}); } catch (e) { controllers.global.handleApiError(e); } finally { isLoading.value = false; } } Future fetchLocalUser() async { try { String? userdata = await SharedPreferencesUtil().getString("localUser"); if(userdata != null){ localUsers.value = JsonMapper.deserialize(userdata)!; } await fetchSysConfig(); } catch (e) { controllers.global.handleApiError(e); } finally { } } Future installService() async{ if(serviceStuatus.value == false){ controllers.global.updateMsg("正在安装服务"); await controllers.service.serviceModeSwitch(true); serviceStuatus.value = true; } } Future UninstallService() async{ if(serviceStuatus.value){ controllers.global.updateMsg("正在卸载服务"); await controllers.service.serviceModeSwitch(false); serviceStuatus.value = false; } } Future coreRestart() async{ await controllers.service.reloadClashCore(); } final count = 0.obs; @override void onInit() { super.onInit(); _statusSubscription = controllers.service.coreStatus.stream.listen(_handleStateChange); fetchSysConfig(); fetchLocalUser(); fetchUserinfo(); //controllers.global.initService(); } @override void onReady() { super.onReady(); } @override void onClose() { _statusSubscription?.cancel(); super.onClose(); } bool GetEnable() => userMode.value.enable == 1; String GetUserName() => localUsers.value.email.toString(); String GetExpiredAt() => "到期时间:${userMode.value.expiredAt}"; String GetTraffic() => "用户流量:${userMode.value.unusedTraffic}"; String GetNode() => controllers.global.selectedNode.value?.name ?? "未选择节点"; String getHttp() => "http 127.0.0.1:${controllers.config.mixedPort.value}"; String getSocket() => "sock 127.0.0.1:${controllers.config.mixedPort.value}"; void RouteNode() => Get.toNamed(Routes.NODE); }