- 后台托盘(mac/Windows):window_manager 拦截关窗改隐藏,服务持续运行; 托盘单击恢复窗口、右键菜单(显示主界面/退出),退出入口仅放托盘菜单 - 品牌:App 更名"资安信插件助手"(mac PRODUCT_NAME/xib、win main.cpp+Runner.rc(code_page 65001)、 MaterialApp/侧栏/托盘 tooltip/日志);图标全家桶换资安信盾牌 logo (tool/gen_app_icons.dart 生成 mac AppIcon 7 尺寸/win ICO 7 尺寸/托盘白底圆盘版/assets logo) - 修复启动布局断言:SliverList 内 Row(stretch) 需 IntrinsicHeight 包裹, 否则子项收到 h=Infinity 约束(用户实测报错,test/ui_smoke_test.dart 守护复现) - Agent.stop 幂等(托盘退出与窗口销毁竞态安全) - 测试修复:smoke 测试改 tester.runAsync 包真实 socket I/O(fake async zone 里会永久挂起)、 显式 pump 替代 pumpAndSettle;13 个测试全过,analyze 零问题,release 构建实测通过
84 lines
2.3 KiB
Dart
84 lines
2.3 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:tray_manager/tray_manager.dart';
|
|
import 'package:window_manager/window_manager.dart';
|
|
|
|
import '../agent.dart';
|
|
|
|
/// 后台托盘:点窗口关闭按钮 = 隐藏窗口进后台(服务继续运行),
|
|
/// 托盘常驻(mac 菜单栏 template 图标 / Windows 系统托盘彩色图标),
|
|
/// 单击/双击托盘恢复窗口,右键弹菜单,退出入口只放在托盘菜单里。
|
|
class AppTray with TrayListener, WindowListener {
|
|
AppTray({required this.agent});
|
|
|
|
final Agent agent;
|
|
|
|
static const _menuShow = 'menu_show';
|
|
static const _menuExit = 'menu_exit';
|
|
|
|
bool _started = false;
|
|
|
|
Future<void> start() async {
|
|
if (_started) return;
|
|
_started = true;
|
|
windowManager.addListener(this);
|
|
await windowManager.setPreventClose(true);
|
|
|
|
await trayManager.setIcon(
|
|
Platform.isMacOS ? 'assets/tray_icon_mac.png' : 'assets/tray_icon_win.png',
|
|
);
|
|
await trayManager.setToolTip('资安信插件助手 · 饭卡打印(后台运行中)');
|
|
await trayManager.setContextMenu(_menu);
|
|
trayManager.addListener(this);
|
|
agent.log.write('托盘已就绪:关闭窗口将最小化到托盘,服务持续运行');
|
|
}
|
|
|
|
// ---------------- 窗口事件 ----------------
|
|
|
|
@override
|
|
void onWindowClose() async {
|
|
// 关窗不退出:隐藏窗口,服务与托盘保持运行
|
|
await windowManager.hide();
|
|
}
|
|
|
|
// ---------------- 托盘事件 ----------------
|
|
|
|
@override
|
|
void onTrayIconMouseDown() => _showWindow();
|
|
|
|
@override
|
|
void onTrayIconRightMouseDown() {
|
|
trayManager.popUpContextMenu();
|
|
}
|
|
|
|
@override
|
|
void onTrayMenuItemClick(MenuItem menuItem) async {
|
|
switch (menuItem.key) {
|
|
case _menuShow:
|
|
await _showWindow();
|
|
case _menuExit:
|
|
await _exitApp();
|
|
}
|
|
}
|
|
|
|
Menu get _menu => Menu(
|
|
items: [
|
|
MenuItem(key: _menuShow, label: '显示主界面'),
|
|
MenuItem.separator(),
|
|
MenuItem(key: _menuExit, label: '退出'),
|
|
],
|
|
);
|
|
|
|
Future<void> _showWindow() async {
|
|
await windowManager.show();
|
|
await windowManager.focus();
|
|
}
|
|
|
|
Future<void> _exitApp() async {
|
|
agent.log.write('用户从托盘退出,停止服务');
|
|
await agent.stop();
|
|
await trayManager.destroy();
|
|
await windowManager.destroy();
|
|
}
|
|
}
|