Files
home/home_monitor/lib/services/tray_service.dart
panw df266614e1 feat(desktop): 增加桌面端系统托盘和窗口管理功能
- 主函数中添加窗口管理初始化,支持Windows、Linux和MacOS平台
- HomeScreen中集成托盘服务和窗口服务,实现托盘菜单交互
- 实现窗口关闭时弹出对话框,支持最小化到托盘或退出程序
- 添加托盘服务TrayService,封装系统托盘图标和菜单的初始化、事件处理
- 添加窗口服务WindowService,实现窗口的显示、隐藏、关闭及事件监听
- 在界面添加最小化到托盘的按钮,仅桌面端显示
- pubspec.yaml添加assets目录,包含托盘图标资源文件
2025-12-08 09:13:59 +08:00

219 lines
5.3 KiB
Dart

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<void> 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<void> updateToolTip(String message) async {
if (!_isInitialized) return;
await _systemTray.setToolTip('家庭网络监控 - $message');
}
/// 更新托盘标题
Future<void> 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<void> 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<void> 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<void> showWindow() async {
if (!isSupported) return;
await windowManager.show();
await windowManager.focus();
}
/// 隐藏窗口(最小化到托盘)
Future<void> hideWindow() async {
if (!isSupported) return;
await windowManager.hide();
}
/// 最小化窗口
Future<void> minimizeWindow() async {
if (!isSupported) return;
await windowManager.minimize();
}
/// 关闭窗口
Future<void> closeWindow() async {
if (!isSupported) return;
await windowManager.destroy();
}
/// 设置窗口始终置顶
Future<void> setAlwaysOnTop(bool isAlwaysOnTop) async {
if (!isSupported) return;
await windowManager.setAlwaysOnTop(isAlwaysOnTop);
}
/// 窗口关闭事件
@override
void onWindowClose() {
onCloseRequested?.call();
}
/// 销毁
void dispose() {
if (_isInitialized) {
windowManager.removeListener(this);
}
}
}