import 'dart:io'; import 'dart:ui'; import 'package:flutter/foundation.dart'; import 'package:system_tray/system_tray.dart'; import 'package:window_manager/window_manager.dart'; /// 系统托盘服务 class TrayService { static final TrayService _instance = TrayService._internal(); factory TrayService() => _instance; TrayService._internal(); final SystemTray _systemTray = SystemTray(); bool _isInitialized = false; // 回调函数 VoidCallback? onShow; VoidCallback? onHide; VoidCallback? onExit; VoidCallback? onRefresh; /// 是否支持系统托盘(仅桌面平台) bool get isSupported => !kIsWeb && (Platform.isWindows || Platform.isLinux || Platform.isMacOS); /// 初始化系统托盘 Future init({ VoidCallback? onShow, VoidCallback? onHide, VoidCallback? onExit, VoidCallback? onRefresh, }) async { if (!isSupported || _isInitialized) return; this.onShow = onShow; this.onHide = onHide; this.onExit = onExit; this.onRefresh = onRefresh; try { // 初始化托盘图标 String iconPath = Platform.isWindows ? 'assets/app_icon.ico' : 'assets/app_icon.png'; await _systemTray.initSystemTray( title: '家庭网络监控', iconPath: iconPath, toolTip: '家庭网络监控 - 运行中', ); // 创建右键菜单 final menu = Menu(); await menu.buildFrom([ MenuItemLabel( label: '显示窗口', onClicked: (menuItem) => _handleShow(), ), MenuItemLabel( label: '隐藏窗口', onClicked: (menuItem) => _handleHide(), ), MenuSeparator(), MenuItemLabel( label: '刷新状态', onClicked: (menuItem) => _handleRefresh(), ), MenuSeparator(), MenuItemLabel( label: '退出程序', onClicked: (menuItem) => _handleExit(), ), ]); await _systemTray.setContextMenu(menu); // 注册托盘事件 _systemTray.registerSystemTrayEventHandler((eventName) { if (eventName == kSystemTrayEventClick) { // 单击托盘图标显示窗口 _handleShow(); } else if (eventName == kSystemTrayEventRightClick) { // 右键显示菜单 _systemTray.popUpContextMenu(); } }); _isInitialized = true; } catch (e) { debugPrint('系统托盘初始化失败: $e'); } } /// 更新托盘提示文字 Future updateToolTip(String message) async { if (!_isInitialized) return; await _systemTray.setToolTip('家庭网络监控 - $message'); } /// 更新托盘标题 Future updateTitle(String title) async { if (!_isInitialized) return; await _systemTray.setTitle(title); } void _handleShow() { onShow?.call(); } void _handleHide() { onHide?.call(); } void _handleExit() { onExit?.call(); } void _handleRefresh() { onRefresh?.call(); } /// 销毁托盘 Future destroy() async { if (!_isInitialized) return; await _systemTray.destroy(); _isInitialized = false; } } /// 窗口管理服务 class WindowService with WindowListener { static final WindowService _instance = WindowService._internal(); factory WindowService() => _instance; WindowService._internal(); bool _isInitialized = false; VoidCallback? onCloseRequested; /// 是否支持窗口管理 bool get isSupported => !kIsWeb && (Platform.isWindows || Platform.isLinux || Platform.isMacOS); /// 初始化窗口管理 Future init({VoidCallback? onCloseRequested}) async { if (!isSupported || _isInitialized) return; this.onCloseRequested = onCloseRequested; await windowManager.ensureInitialized(); // 配置窗口选项 const windowOptions = WindowOptions( size: Size(420, 700), minimumSize: Size(350, 500), center: true, backgroundColor: Color(0x00000000), skipTaskbar: false, titleBarStyle: TitleBarStyle.normal, title: '家庭网络监控', ); await windowManager.waitUntilReadyToShow(windowOptions, () async { await windowManager.show(); await windowManager.focus(); }); // 添加窗口监听器 windowManager.addListener(this); // 阻止默认关闭行为 await windowManager.setPreventClose(true); _isInitialized = true; } /// 显示窗口 Future showWindow() async { if (!isSupported) return; await windowManager.show(); await windowManager.focus(); } /// 隐藏窗口(最小化到托盘) Future hideWindow() async { if (!isSupported) return; await windowManager.hide(); } /// 最小化窗口 Future minimizeWindow() async { if (!isSupported) return; await windowManager.minimize(); } /// 关闭窗口 Future closeWindow() async { if (!isSupported) return; await windowManager.destroy(); } /// 设置窗口始终置顶 Future setAlwaysOnTop(bool isAlwaysOnTop) async { if (!isSupported) return; await windowManager.setAlwaysOnTop(isAlwaysOnTop); } /// 窗口关闭事件 @override void onWindowClose() { onCloseRequested?.call(); } /// 销毁 void dispose() { if (_isInitialized) { windowManager.removeListener(this); } } }