From e0b29cf08fd909a4465ef8b86239fa13372cebb3 Mon Sep 17 00:00:00 2001 From: wanghongenpin Date: Thu, 7 May 2026 23:57:49 +0800 Subject: [PATCH] feat: add minimize to tray functionality (#711) --- lib/ui/configuration.dart | 18 +++++------------- lib/ui/desktop/preference.dart | 2 +- lib/ui/launch/launch.dart | 16 +++++++++------- lib/utils/desktop_support.dart | 1 + 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/lib/ui/configuration.dart b/lib/ui/configuration.dart index 702f16d..06e7c7c 100644 --- a/lib/ui/configuration.dart +++ b/lib/ui/configuration.dart @@ -104,10 +104,7 @@ class AppConfiguration { double panelRatio = 0.3; /// 关闭窗口时最小化到系统托盘 - bool minimizeToTray = false; - - /// 首次关闭时是否已经提示过最小化到托盘 - bool? minimizeToTrayPromptShown; + bool? minimizeToTray; AppConfiguration._(); @@ -206,12 +203,9 @@ class AppConfiguration { _theme.color = config['themeColor'] ?? "Blue"; upgradeNoticeV27 = config['upgradeNoticeV27'] ?? true; - _language = config['language'] == null - ? null - : Locale.fromSubtags( - languageCode: config['language'], - scriptCode: config['languageScript'] - ); + _language = config['language'] == null + ? null + : Locale.fromSubtags(languageCode: config['language'], scriptCode: config['languageScript']); pipEnabled.value = config['pipEnabled'] ?? true; pipIcon.value = config['pipIcon'] ?? false; headerExpanded = config['headerExpanded'] ?? true; @@ -228,8 +222,7 @@ class AppConfiguration { if (config['panelRatio'] != null) { panelRatio = config['panelRatio']; } - minimizeToTray = config['minimizeToTray'] ?? false; - minimizeToTrayPromptShown = config['minimizeToTrayPromptShown']; + minimizeToTray = config['minimizeToTray']; } catch (e) { logger.e(e); } @@ -275,7 +268,6 @@ class AppConfiguration { "windowPosition": windowPosition == null ? null : {"dx": windowPosition?.dx, "dy": windowPosition?.dy}, if (Platforms.isDesktop()) 'panelRatio': panelRatio, if (Platforms.isDesktop()) 'minimizeToTray': minimizeToTray, - if (Platforms.isDesktop() && minimizeToTrayPromptShown != null) 'minimizeToTrayPromptShown': minimizeToTrayPromptShown, }; } } diff --git a/lib/ui/desktop/preference.dart b/lib/ui/desktop/preference.dart index 25ffd57..766f3fb 100644 --- a/lib/ui/desktop/preference.dart +++ b/lib/ui/desktop/preference.dart @@ -127,7 +127,7 @@ class _PreferenceState extends State { subtitle: Text(localizations.minimizeToTraySubtitle, style: subtitleStyle), trailing: SwitchWidget( scale: 0.75, - value: appConfiguration.minimizeToTray, + value: appConfiguration.minimizeToTray ?? false, onChanged: (value) { appConfiguration.minimizeToTray = value; appConfiguration.flushConfig(); diff --git a/lib/ui/launch/launch.dart b/lib/ui/launch/launch.dart index 8d16c85..70f8fd0 100644 --- a/lib/ui/launch/launch.dart +++ b/lib/ui/launch/launch.dart @@ -106,14 +106,14 @@ class _SocketLaunchState extends State with WindowListener, Widget Future _handleWindowClose() async { final appConfiguration = AppConfiguration.current; - if (Platforms.isDesktop() && appConfiguration?.minimizeToTray == true) { - if (appConfiguration?.minimizeToTrayPromptShown == null) { + if (Platforms.isDesktop() && appConfiguration?.minimizeToTray == null || appConfiguration?.minimizeToTray == true) { + if (appConfiguration?.minimizeToTray == null) { final minimize = await _showTrayClosePrompt(); if (!mounted) { return; } - appConfiguration?.minimizeToTrayPromptShown = true; + appConfiguration?.minimizeToTray = minimize; await appConfiguration?.flushConfig(); if (!minimize) { @@ -129,6 +129,7 @@ class _SocketLaunchState extends State with WindowListener, Widget logger.e('show to tray failed, fallback to exit', error: e); } } + await appExit(); } @@ -139,9 +140,7 @@ class _SocketLaunchState extends State with WindowListener, Widget builder: (ctx) { return AlertDialog( title: Text(localizations.minimizeToTrayTitle), - content: SizedBox( - width: 320, - child: Text(maxLines: 3, localizations.trayClosePromptContent)), + content: SizedBox(width: 320, child: Text(maxLines: 3, localizations.trayClosePromptContent)), actions: [ TextButton( onPressed: () => Navigator.of(ctx).pop(false), @@ -181,7 +180,10 @@ class _SocketLaunchState extends State with WindowListener, Widget @override Future didRequestAppExit() async { - await appExit(); + bool isPreventClose = await windowManager.isPreventClose(); + if (!isPreventClose || Platform.isMacOS) { + await appExit(); + } return super.didRequestAppExit(); } diff --git a/lib/utils/desktop_support.dart b/lib/utils/desktop_support.dart index b9c5ec2..1cdf8f4 100644 --- a/lib/utils/desktop_support.dart +++ b/lib/utils/desktop_support.dart @@ -48,6 +48,7 @@ class DesktopSupport { await windowManager.focus(); }); + windowManager.addListener(WindowChangeListener(appConfiguration)); registerMethodHandler(); } catch (e) { logger.e("Error during desktop initialization: $e");