feat: win代码同步

This commit is contained in:
2026-01-13 19:26:03 -08:00
parent 9a907f6531
commit 6ef08c9e7b
12 changed files with 586 additions and 205 deletions
+84 -4
View File
@@ -62,6 +62,7 @@ class KRWindowManager with WindowListener, TrayListener {
await windowManager.setMaximumSize(const Size(420, 900));
await windowManager.setResizable(true);
await windowManager.center();
await windowManager.show(); // macOS 也需要显式显示窗口
}
// 初始化托盘
@@ -154,8 +155,66 @@ class KRWindowManager with WindowListener, TrayListener {
}
/// 退出应用
/// ✅ 改进:先恢复窗口(如果最小化),再显示对话框
Future<void> _exitApp() async {
KRLogUtil.kr_i('_exitApp: 退出应用');
// ✅ 关键修复:先恢复窗口(从最小化状态)
// 这样可以确保对话框可见
try {
await windowManager.show();
await windowManager.focus();
await windowManager.setAlwaysOnTop(true);
KRLogUtil.kr_i('✅ 窗口已恢复,准备显示对话框', tag: 'WindowManager');
} catch (e) {
KRLogUtil.kr_w('⚠️ 恢复窗口失败(可能已显示): $e', tag: 'WindowManager');
}
// 🔧 修复:检查 VPN 是否在运行,如果运行则弹窗提醒用户
if (KRSingBoxImp.instance.kr_status.value is! SingboxStopped) {
KRLogUtil.kr_w('⚠️ VPN 正在运行,询问用户是否关闭', tag: 'WindowManager');
// 显示确认对话框
final shouldExit = await Get.dialog<bool>(
AlertDialog(
title: Text('关闭 VPN'),
content: Text("VPN 代理正在运行。\n\n是否现在关闭 VPN 并退出应用?\n\n(应用将等待 VPN 优雅关闭,预计 3-5 秒)"),
actions: [
TextButton(
onPressed: () => Get.back(result: false),
child: Text('取消'),
),
TextButton(
onPressed: () => Get.back(result: true),
child: Text('关闭并退出', style: const TextStyle(color: Colors.red)),
),
],
),
barrierDismissible: false,
) ?? false;
// ✅ 关键修复:对话框关闭后,恢复窗口的 AlwaysOnTop 状态
try {
await windowManager.setAlwaysOnTop(false);
} catch (e) {
KRLogUtil.kr_w('⚠️ 恢复 AlwaysOnTop 失败: $e', tag: 'WindowManager');
}
if (!shouldExit) {
KRLogUtil.kr_i('_exitApp: 用户取消退出');
return;
}
KRLogUtil.kr_i('_exitApp: 用户确认关闭 VPN 并退出');
} else {
// ✅ VPN 未运行,也要恢复 AlwaysOnTop 状态
try {
await windowManager.setAlwaysOnTop(false);
} catch (e) {
KRLogUtil.kr_w('⚠️ 恢复 AlwaysOnTop 失败: $e', tag: 'WindowManager');
}
}
await _handleTerminate();
await windowManager.destroy();
}
@@ -164,9 +223,9 @@ class KRWindowManager with WindowListener, TrayListener {
Future<void> _showWindow() async {
KRLogUtil.kr_i('_showWindow: 开始显示窗口');
try {
await windowManager.setSkipTaskbar(false);
await windowManager.show();
await windowManager.focus();
await windowManager.setSkipTaskbar(false);
await windowManager.setAlwaysOnTop(true);
await Future.delayed(const Duration(milliseconds: 100));
await windowManager.setAlwaysOnTop(false);
@@ -185,6 +244,7 @@ class KRWindowManager with WindowListener, TrayListener {
@override
void onWindowClose() async {
if (Platform.isWindows) {
await windowManager.setSkipTaskbar(true);
await windowManager.hide();
} else if (Platform.isMacOS) {
await windowManager.hide();
@@ -221,9 +281,29 @@ class KRWindowManager with WindowListener, TrayListener {
/// 处理应用终止
Future<void> _handleTerminate() async {
KRLogUtil.kr_i('_handleTerminate: 处理应用终止');
if (KRSingBoxImp.instance.kr_status == SingboxStatus.started()) {
await KRSingBoxImp.instance.kr_stop();
// 🔧 修复 BUG:正确检查 VPN 状态而不是直接比较 Rx 对象
// 之前的代码:if (KRSingBoxImp.instance.kr_status == SingboxStatus.started())
// 问题:kr_status 是 Rx<SingboxStatus> 对象,不能直接与 SingboxStatus.started() 比较
// 结果:该条件总是 false,导致 kr_stop() 从不被调用,VPN 不会关闭
if (KRSingBoxImp.instance.kr_status.value is SingboxStarted) {
KRLogUtil.kr_i('🛑 VPN 正在运行,开始关闭...', tag: 'WindowManager');
try {
await KRSingBoxImp.instance.kr_stop();
KRLogUtil.kr_i('✅ VPN 已关闭', tag: 'WindowManager');
} catch (e) {
KRLogUtil.kr_e('❌ VPN 关闭出错: $e', tag: 'WindowManager');
}
} else {
KRLogUtil.kr_i('✅ VPN 未运行,无需关闭', tag: 'WindowManager');
}
// 销毁托盘
try {
await trayManager.destroy();
KRLogUtil.kr_i('✅ 托盘已销毁', tag: 'WindowManager');
} catch (e) {
KRLogUtil.kr_w('⚠️ 销毁托盘出错: $e', tag: 'WindowManager');
}
await trayManager.destroy();
}
}