hi-client/lib/app/utils/kr_window_manager.dart

225 lines
6.7 KiB
Dart
Executable File

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:kaer_with_panels/app/localization/kr_language_utils.dart';
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
import 'package:kaer_with_panels/singbox/model/singbox_status.dart';
import 'package:kaer_with_panels/app/localization/app_translations.dart';
import 'package:window_manager/window_manager.dart';
import 'package:tray_manager/tray_manager.dart';
import 'dart:io' show Platform;
import '../services/singbox_imp/kr_sing_box_imp.dart';
class KRWindowManager with WindowListener, TrayListener {
static final KRWindowManager _instance = KRWindowManager._internal();
factory KRWindowManager() => _instance;
KRWindowManager._internal();
/// 初始化窗口管理器
Future<void> kr_initWindowManager() async {
KRLogUtil.kr_i('kr_initWindowManager: 开始初始化窗口管理器');
await windowManager.ensureInitialized();
KRLogUtil.kr_i('kr_initWindowManager: 窗口管理器已初始化');
const WindowOptions windowOptions = WindowOptions(
size: Size(800, 668),
minimumSize: Size(400, 334),
center: true,
backgroundColor: Colors.white,
skipTaskbar: false,
title: 'Hi快VPN',
titleBarStyle: TitleBarStyle.normal,
windowButtonVisibility: true,
);
await windowManager.waitUntilReadyToShow(windowOptions);
KRLogUtil.kr_i('kr_initWindowManager: 窗口准备就绪');
// 先添加监听器
windowManager.addListener(this);
KRLogUtil.kr_i('kr_initWindowManager: 已添加窗口监听器');
// 确保在 Windows 下正确设置窗口属性
if (Platform.isWindows) {
await windowManager.setTitleBarStyle(TitleBarStyle.normal);
await windowManager.setTitle('HiFastVPN');
await windowManager.setSize(const Size(800, 668));
await windowManager.setMinimumSize(const Size(400, 334));
await windowManager.center();
await windowManager.show();
// 阻止窗口关闭
await windowManager.setPreventClose(true);
} else {
await windowManager.setTitle('Kaer VPN');
await windowManager.setSize(const Size(800, 668));
await windowManager.setMinimumSize(const Size(400, 334));
await windowManager.center();
}
// 初始化托盘
await _initTray();
// 初始化平台通道
_initPlatformChannel();
KRLogUtil.kr_i('kr_initWindowManager: 初始化完成');
ever(KRLanguageUtils.kr_language, (_) {
final Menu menu = Menu(
items: [
MenuItem(
label: AppTranslations.kr_tray.openDashboard,
onClick: (_) => _showWindow(),
),
if (Platform.isMacOS) MenuItem.separator(),
if (Platform.isMacOS)
MenuItem(
label: AppTranslations.kr_tray.copyToTerminal,
onClick: (_) => _copyToTerminal(),
),
MenuItem.separator(),
MenuItem(
label: AppTranslations.kr_tray.exitApp,
onClick: (_) => _exitApp(),
),
],
);
trayManager.setContextMenu(menu);
});
}
/// 初始化平台通道
void _initPlatformChannel() {
if (Platform.isMacOS) {
const platform = MethodChannel('kaer_vpn/terminate');
platform.setMethodCallHandler((call) async {
if (call.method == 'onTerminate') {
KRLogUtil.kr_i('收到应用终止通知');
await _handleTerminate();
}
});
}
}
/// 初始化托盘
Future<void> _initTray() async {
KRLogUtil.kr_i('_initTray: 开始初始化托盘');
trayManager.addListener(this);
final String iconPath = Platform.isMacOS
? 'assets/images/tray_icon.png'
: 'assets/images/tray_icon.ico';
await trayManager.setIcon(iconPath);
// 初始化托盘
Future.delayed(const Duration(seconds: 1), () async {
final Menu menu = Menu(
items: [
MenuItem(
label: AppTranslations.kr_tray.openDashboard,
onClick: (_) => _showWindow(),
),
if (Platform.isMacOS) MenuItem.separator(),
if (Platform.isMacOS)
MenuItem(
label: AppTranslations.kr_tray.copyToTerminal,
onClick: (_) => _copyToTerminal(),
),
MenuItem.separator(),
MenuItem(
label: AppTranslations.kr_tray.exitApp,
onClick: (_) => _exitApp(),
),
],
);
await trayManager.setContextMenu(menu);
});
}
/// 复制到终端
Future<void> _copyToTerminal() async {
final String kr_port = KRSingBoxImp.instance.kr_port.toString();
final String proxyText =
'export https_proxy=http://127.0.0.1:$kr_port http_proxy=http://127.0.0.1:$kr_port all_proxy=socks5://127.0.0.1:$kr_port';
await Clipboard.setData(ClipboardData(text: proxyText));
}
/// 退出应用
Future<void> _exitApp() async {
KRLogUtil.kr_i('_exitApp: 退出应用');
await _handleTerminate();
await windowManager.destroy();
}
/// 显示窗口
Future<void> _showWindow() async {
KRLogUtil.kr_i('_showWindow: 开始显示窗口');
try {
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);
KRLogUtil.kr_i('_showWindow: 窗口显示成功');
} catch (e) {
KRLogUtil.kr_e('_showWindow: 显示窗口失败 - $e');
}
}
@override
void onWindowEvent(String eventName) {
KRLogUtil.kr_i('onWindowEvent: 收到窗口事件 - $eventName');
// 移除 Windows 下自动显示窗口的逻辑
}
@override
void onWindowClose() async {
if (Platform.isWindows) {
await windowManager.hide();
} else if (Platform.isMacOS) {
await windowManager.hide();
}
}
@override
void onTrayIconMouseDown() {
// 左键点击只显示菜单
trayManager.popUpContextMenu();
}
@override
void onTrayIconRightMouseDown() {
// 右键点击只显示菜单
trayManager.popUpContextMenu();
}
@override
void onWindowFocus() {
// 移除自动显示窗口的逻辑
}
@override
void onWindowBlur() {
// 当窗口失去焦点时,保持窗口可见
}
/// 设置窗口背景颜色
Future<void> kr_setBackgroundColor(Color color) async {
await windowManager.setBackgroundColor(color);
}
/// 处理应用终止
Future<void> _handleTerminate() async {
KRLogUtil.kr_i('_handleTerminate: 处理应用终止');
if (KRSingBoxImp.instance.kr_status == SingboxStatus.started()) {
await KRSingBoxImp.instance.kr_stop();
}
await trayManager.destroy();
}
}