tray_controller.dart 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import 'dart:io';
  2. import 'package:flutter/foundation.dart';
  3. import 'package:flutter/services.dart';
  4. import 'package:shortid/shortid.dart';
  5. import 'package:path/path.dart' as path;
  6. import '../../constants/assets.dart';
  7. import 'menu_base/menu_base.dart';
  8. import 'tray_listener.dart';
  9. const kEventOnTrayIconLButtonDown = 'onTrayIconLButtonDown';
  10. const kEventOnTrayIconLButtonUp = 'onTrayIconLButtonUp';
  11. const kEventOnTrayIconRButtonDown = 'onTrayIconRButtonDown';
  12. const kEventOnTrayIconRButtonUp = 'onTrayIconRButtonUp';
  13. const kEventOnTrayMenuItemClick = 'onTrayMenuItemClick';
  14. class TrayController {
  15. final _channel = const MethodChannel("app.nomo/tray");
  16. final ObserverList<TrayListener> _listeners = ObserverList<TrayListener>();
  17. Menu? _trayMenu;
  18. TrayController() {
  19. _channel.setMethodCallHandler(_methodCallHandler);
  20. }
  21. Future<void> _methodCallHandler(MethodCall call) async {
  22. for (final TrayListener listener in _listeners) {
  23. switch (call.method) {
  24. case kEventOnTrayIconLButtonDown:
  25. listener.onTrayIconLButtonDown();
  26. break;
  27. case kEventOnTrayIconLButtonUp:
  28. listener.onTrayIconLButtonUp();
  29. break;
  30. case kEventOnTrayIconRButtonDown:
  31. listener.onTrayIconRButtonDown();
  32. break;
  33. case kEventOnTrayIconRButtonUp:
  34. listener.onTrayIconRButtonUp();
  35. break;
  36. case kEventOnTrayMenuItemClick:
  37. int id = call.arguments['id'];
  38. MenuItem? menuItem = _trayMenu?.getMenuItemById(id);
  39. if (menuItem != null) {
  40. bool? oldChecked = menuItem.checked;
  41. if (menuItem.onClick != null) {
  42. menuItem.onClick!(menuItem);
  43. }
  44. listener.onTrayMenuItemClick(menuItem);
  45. bool? newChecked = menuItem.checked;
  46. if (oldChecked != newChecked) {
  47. await _setContextMenu(_trayMenu!);
  48. }
  49. }
  50. break;
  51. }
  52. }
  53. }
  54. Future<void> _setContextMenu(Menu menu) {
  55. _trayMenu = menu;
  56. final Map<String, dynamic> arguments = {'menu': menu.toJson()};
  57. return _channel.invokeMethod('setContextMenu', arguments);
  58. }
  59. Future<void> _setSystemTrayWindows(String iconPath, String? tooltip) {
  60. final Map<String, dynamic> arguments = {
  61. 'id': shortid.generate(),
  62. 'icon': path.joinAll([
  63. path.dirname(Platform.resolvedExecutable),
  64. 'data/flutter_assets',
  65. iconPath,
  66. ]),
  67. 'tooltip': tooltip ?? '',
  68. };
  69. return _channel.invokeMethod('setSystemTray', arguments);
  70. }
  71. /// 设置托盘图标
  72. Future<void> setSystemTray(
  73. bool isConnected,
  74. bool isDark, {
  75. String? title,
  76. String? tooltip,
  77. }) {
  78. String iconPath;
  79. if (isConnected) {
  80. iconPath = isDark
  81. ? Assets.trayIconDarkConnectedWin
  82. : Assets.trayIconLightConnectedWin;
  83. } else {
  84. iconPath = isDark
  85. ? Assets.trayIconDarkUnConnectedWin
  86. : Assets.trayIconLightUnConnectedWin;
  87. }
  88. if (Platform.isWindows) {
  89. return _setSystemTrayWindows(iconPath, tooltip);
  90. } else {
  91. throw UnimplementedError();
  92. }
  93. }
  94. /// 设置托盘菜单
  95. Future<void> setContextMenu(Menu trayMenu) {
  96. return _setContextMenu(trayMenu);
  97. }
  98. /// 弹出系统托盘菜单
  99. Future<void> popUpContextMenu() {
  100. return _channel.invokeMethod('popupContextMenu');
  101. }
  102. /// 销毁系统托盘
  103. Future<void> resetSystemTray() {
  104. return _channel.invokeMethod('resetSystemTray');
  105. }
  106. bool get hasListeners {
  107. return _listeners.isNotEmpty;
  108. }
  109. void addListener(TrayListener listener) {
  110. _listeners.add(listener);
  111. }
  112. void removeListener(TrayListener listener) {
  113. _listeners.remove(listener);
  114. }
  115. }