feat: windows ico替换成圆角,macos增加tg代理
This commit is contained in:
@@ -22,6 +22,7 @@ import '../../utils/kr_country_util.dart';
|
||||
import '../../utils/kr_log_util.dart';
|
||||
import '../../utils/kr_secure_storage.dart';
|
||||
import '../../utils/kr_windows_dns_util.dart';
|
||||
import '../../utils/kr_macos_proxy_util.dart';
|
||||
import '../../common/app_run_data.dart';
|
||||
import '../../common/app_config.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@@ -297,6 +298,21 @@ class KRSingBoxImp {
|
||||
KRLogUtil.kr_i('⏳ Windows 文件系统同步等待完成', tag: 'SingBox');
|
||||
}
|
||||
|
||||
// 🍎 macOS 平台:初始化时确保代理关闭(防止上次崩溃残留)
|
||||
if (Platform.isMacOS) {
|
||||
KRLogUtil.kr_i('🍎 macOS 平台,初始化时清理系统代理残留...', tag: 'SingBox');
|
||||
try {
|
||||
// 异步执行,不阻塞初始化主流程
|
||||
KRMacosProxyUtil.disableSocks5().then((_) {
|
||||
KRLogUtil.kr_i('✅ macOS 系统代理残留清理完成', tag: 'SingBox');
|
||||
}).catchError((e) {
|
||||
KRLogUtil.kr_w('⚠️ macOS 系统代理清理异常: $e', tag: 'SingBox');
|
||||
});
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_w('⚠️ macOS 系统代理清理尝试失败: $e', tag: 'SingBox');
|
||||
}
|
||||
}
|
||||
|
||||
// 最终验证:在 setup() 之前再次确认 workingDir 和 data 目录都存在且可访问
|
||||
// libcore 的 Setup() 会调用 os.Chdir(workingPath),然后使用相对路径 "./data"
|
||||
// 如果 os.Chdir() 失败(路径不存在或权限问题),后续的相对路径访问会失败
|
||||
@@ -1555,6 +1571,19 @@ class KRSingBoxImp {
|
||||
throw err;
|
||||
}).run();
|
||||
|
||||
// 🔑 macOS 平台:启用 SOCKS5 系统代理
|
||||
if (Platform.isMacOS) {
|
||||
KRLogUtil.kr_i('🍎 macOS 平台,开启系统 SOCKS5 代理...', tag: 'SingBox');
|
||||
try {
|
||||
await KRMacosProxyUtil.enableSocks5(
|
||||
host: '127.0.0.1',
|
||||
port: kr_port,
|
||||
);
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_w('⚠️ macOS 系统代理开启失败: $e', tag: 'SingBox');
|
||||
}
|
||||
}
|
||||
|
||||
// ⚠️ 关键修复:在启动成功后立即订阅统计流
|
||||
// 原因:
|
||||
// 1. 统计流需要主动订阅才能接收数据
|
||||
@@ -1751,6 +1780,16 @@ class KRSingBoxImp {
|
||||
|
||||
// 不手动设置状态,由 libcore 通过 status stream 自动发送 Stopped 事件
|
||||
KRLogUtil.kr_i('✅ SingBox 停止请求已发送', tag: 'SingBox');
|
||||
|
||||
// 🍎 macOS 平台:关闭系统 SOCKS5 代理
|
||||
if (Platform.isMacOS) {
|
||||
KRLogUtil.kr_i('🍎 macOS 平台,关闭系统 SOCKS5 代理...', tag: 'SingBox');
|
||||
try {
|
||||
await KRMacosProxyUtil.disableSocks5();
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('❌ macOS 系统代理关闭失败: $e', tag: 'SingBox');
|
||||
}
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
KRLogUtil.kr_e('停止服务时出错: $e');
|
||||
KRLogUtil.kr_e('错误堆栈: $stackTrace');
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
import 'dart:io';
|
||||
import 'kr_log_util.dart';
|
||||
|
||||
/// macOS 系统代理管理工具类
|
||||
///
|
||||
/// 使用 `networksetup` 命令管理 macOS 的 SOCKS5 代理设置
|
||||
class KRMacosProxyUtil {
|
||||
/// 私有构造函数
|
||||
KRMacosProxyUtil._();
|
||||
|
||||
/// 获取所有网络服务列表
|
||||
static Future<List<String>> _listNetworkServices() async {
|
||||
try {
|
||||
final r = await Process.run('networksetup', ['-listallnetworkservices']);
|
||||
if (r.exitCode != 0) {
|
||||
KRLogUtil.kr_e('列出网络服务失败: ${r.stderr}', tag: 'MacosProxy');
|
||||
return [];
|
||||
}
|
||||
final lines = (r.stdout as String).split('\n').map((e) => e.trim()).toList();
|
||||
// 过滤掉第一行说明文字和空行
|
||||
return lines
|
||||
.where((l) => l.isNotEmpty && !l.toLowerCase().contains('an asterisk'))
|
||||
.skip(1)
|
||||
.toList();
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('列出网络服务异常: $e', tag: 'MacosProxy');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/// 为所有网络服务启用 SOCKS5 代理
|
||||
static Future<void> enableSocks5({
|
||||
required String host,
|
||||
required int port,
|
||||
}) async {
|
||||
if (!Platform.isMacOS) return;
|
||||
|
||||
final services = await _listNetworkServices();
|
||||
if (services.isEmpty) {
|
||||
KRLogUtil.kr_w('未找到可用的网络服务', tag: 'MacosProxy');
|
||||
return;
|
||||
}
|
||||
|
||||
for (final service in services) {
|
||||
try {
|
||||
// 1) 设置 SOCKS5 服务器地址和端口
|
||||
final r1 = await Process.run('networksetup', [
|
||||
'-setsocksfirewallproxy',
|
||||
service,
|
||||
host,
|
||||
port.toString(),
|
||||
]);
|
||||
|
||||
if (r1.exitCode != 0) {
|
||||
KRLogUtil.kr_w('服务 [$service] 设置 SOCKS5 代理失败: ${r1.stderr}', tag: 'MacosProxy');
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2) 开启 SOCKS5 代理状态
|
||||
final r2 = await Process.run('networksetup', [
|
||||
'-setsocksfirewallproxystate',
|
||||
service,
|
||||
'on',
|
||||
]);
|
||||
|
||||
if (r2.exitCode != 0) {
|
||||
KRLogUtil.kr_w('服务 [$service] 启用 SOCKS5 代理失败: ${r2.stderr}', tag: 'MacosProxy');
|
||||
continue;
|
||||
}
|
||||
|
||||
KRLogUtil.kr_i('✅ 服务 [$service] SOCKS5 代理已启用: $host:$port', tag: 'MacosProxy');
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('服务 [$service] 启用代理异常: $e', tag: 'MacosProxy');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 为所有网络服务禁用 SOCKS5 代理
|
||||
static Future<void> disableSocks5() async {
|
||||
if (!Platform.isMacOS) return;
|
||||
|
||||
final services = await _listNetworkServices();
|
||||
if (services.isEmpty) return;
|
||||
|
||||
for (final service in services) {
|
||||
try {
|
||||
final r = await Process.run('networksetup', [
|
||||
'-setsocksfirewallproxystate',
|
||||
service,
|
||||
'off',
|
||||
]);
|
||||
|
||||
if (r.exitCode == 0) {
|
||||
KRLogUtil.kr_i('✅ 服务 [$service] SOCKS5 代理已关闭', tag: 'MacosProxy');
|
||||
} else {
|
||||
KRLogUtil.kr_w('服务 [$service] 关闭 SOCKS5 代理失败: ${r.stderr}', tag: 'MacosProxy');
|
||||
}
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('服务 [$service] 关闭代理异常: $e', tag: 'MacosProxy');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取指定服务的 SOCKS5 状态 (主要用于调试)
|
||||
static Future<String> getSocks5Status(String serviceName) async {
|
||||
try {
|
||||
final r = await Process.run('networksetup', ['-getsocksfirewallproxy', serviceName]);
|
||||
return r.stdout as String;
|
||||
} catch (e) {
|
||||
return '获取状态失败: $e';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user