From bfbc3d40b35d644448cce1fe469fda8b3a94ee3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Sun, 19 Apr 2026 10:47:42 +0200 Subject: [PATCH] Make system tray icon optional --- .../Interfaces/IPreferencesService.cs | 5 ++ Wino.Mail.WinUI/App.xaml.cs | 77 +++++++++++++++---- .../Services/PreferencesService.cs | 6 ++ .../Views/Settings/AppPreferencesPage.xaml | 7 ++ 4 files changed, 80 insertions(+), 15 deletions(-) diff --git a/Wino.Core.Domain/Interfaces/IPreferencesService.cs b/Wino.Core.Domain/Interfaces/IPreferencesService.cs index cde1ca06..7134e44d 100644 --- a/Wino.Core.Domain/Interfaces/IPreferencesService.cs +++ b/Wino.Core.Domain/Interfaces/IPreferencesService.cs @@ -62,6 +62,11 @@ public interface IPreferencesService : INotifyPropertyChanged /// bool IsStoreUpdateNotificationsEnabled { get; set; } + /// + /// Setting: Whether the system tray icon should be created while the shell is available. + /// + bool IsSystemTrayIconEnabled { get; set; } + /// /// Setting: Whether the Wino account profile button in the shell title bar should be hidden. /// diff --git a/Wino.Mail.WinUI/App.xaml.cs b/Wino.Mail.WinUI/App.xaml.cs index 60e17e66..a230b9ae 100644 --- a/Wino.Mail.WinUI/App.xaml.cs +++ b/Wino.Mail.WinUI/App.xaml.cs @@ -137,6 +137,11 @@ public partial class App : WinoApplication, ?? windowManager.GetWindow(WinoWindowKind.Shell) ?? windowManager.GetWindow(WinoWindowKind.Welcome); + if (window is IWinoShellWindow) + { + DisposeTrayIcon(); + } + InitializeNavigationDispatcher(); } @@ -159,6 +164,37 @@ public partial class App : WinoApplication, _trayIcon.Create(); } + private void DisposeTrayIcon() + { + _trayIcon?.Dispose(); + _trayIcon = null; + } + + private void EnsurePreferenceChangedSubscription() + { + if (_preferencesService == null) + return; + + _preferencesService.PreferenceChanged -= PreferencesServiceChanged; + _preferencesService.PreferenceChanged += PreferencesServiceChanged; + } + + private bool ShouldCreateTrayIcon() + => _hasConfiguredAccounts && + HasShellWindow() && + (_preferencesService?.IsSystemTrayIconEnabled ?? true); + + private void UpdateTrayIconState(bool allowCreation) + { + if (!allowCreation || !ShouldCreateTrayIcon()) + { + DisposeTrayIcon(); + return; + } + + EnsureTrayIconCreated(); + } + private IReadOnlyList BuildTrayMenu() { List items = @@ -268,6 +304,7 @@ public partial class App : WinoApplication, if (windowManager.GetWindow(WinoWindowKind.Shell) is not ShellWindow shellWindow) return; + DisposeTrayIcon(); windowManager.HideWindow(shellWindow); if (ReferenceEquals(MainWindow, shellWindow)) { @@ -289,6 +326,8 @@ public partial class App : WinoApplication, { await NewThemeService.ApplyThemeToActiveWindowAsync(); } + + UpdateTrayIconState(window is IWinoShellWindow); } private Task ExitApplicationAsync() @@ -303,8 +342,7 @@ public partial class App : WinoApplication, return; _isExiting = true; - _trayIcon?.Dispose(); - _trayIcon = null; + DisposeTrayIcon(); Services.GetRequiredService().CloseAllWindows(); Application.Current.Exit(); @@ -476,12 +514,10 @@ public partial class App : WinoApplication, return; EnsureWindowManagerConfigured(); - EnsureTrayIconCreated(); + EnsurePreferenceChangedSubscription(); if (_hasConfiguredAccounts) { - _preferencesService!.PreferenceChanged -= PreferencesServiceChanged; - _preferencesService.PreferenceChanged += PreferencesServiceChanged; RestartAutoSynchronizationLoop(); } @@ -942,11 +978,16 @@ public partial class App : WinoApplication, if (isStartupTaskLaunch) { + UpdateTrayIconState(allowCreation: true); LogActivation("Launched by startup task. Window created but hidden (system tray only)."); return; } - MainWindow?.Activate(); + if (MainWindow is WindowEx window) + { + await ActivateWindowAsync(window, applyThemeToWindow: false); + } + LogActivation("Window created and activated."); } @@ -1186,8 +1227,10 @@ public partial class App : WinoApplication, // Initialize theme service after window is created. await NewThemeService.InitializeAsync(); - if (MainWindow != null) - Services.GetRequiredService().ActivateWindow(MainWindow); + if (MainWindow is WindowEx window) + { + await ActivateWindowAsync(window, applyThemeToWindow: false); + } LogActivation("Window created and activated."); } @@ -1398,6 +1441,7 @@ public partial class App : WinoApplication, public void Receive(AccountCreatedMessage message) { _hasConfiguredAccounts = true; + EnsurePreferenceChangedSubscription(); var windowManager = Services.GetRequiredService(); @@ -1436,11 +1480,7 @@ public partial class App : WinoApplication, MainWindow?.DispatcherQueue?.TryEnqueue(async () => { - if (_preferencesService != null) - { - _preferencesService.PreferenceChanged -= PreferencesServiceChanged; - _preferencesService.PreferenceChanged += PreferencesServiceChanged; - } + EnsurePreferenceChangedSubscription(); CreateWindow( null, @@ -1484,6 +1524,7 @@ public partial class App : WinoApplication, // All accounts removed — go back to welcome wizard from step 1 Services.GetRequiredService().Reset(); StopAutoSynchronizationLoop(); + UpdateTrayIconState(allowCreation: false); CloseShellWindowIfPresent(); CreateWelcomeWindow(); if (MainWindow != null) @@ -1577,10 +1618,16 @@ public partial class App : WinoApplication, private void PreferencesServiceChanged(object? sender, string propertyName) { - if (propertyName != nameof(IPreferencesService.EmailSyncIntervalMinutes)) + if (propertyName == nameof(IPreferencesService.EmailSyncIntervalMinutes)) + { + RestartAutoSynchronizationLoop(); return; + } - RestartAutoSynchronizationLoop(); + if (propertyName == nameof(IPreferencesService.IsSystemTrayIconEnabled)) + { + UpdateTrayIconState(allowCreation: true); + } } private void RestartAutoSynchronizationLoop() diff --git a/Wino.Mail.WinUI/Services/PreferencesService.cs b/Wino.Mail.WinUI/Services/PreferencesService.cs index d7d3feb3..0abced6c 100644 --- a/Wino.Mail.WinUI/Services/PreferencesService.cs +++ b/Wino.Mail.WinUI/Services/PreferencesService.cs @@ -387,6 +387,12 @@ public class PreferencesService(IConfigurationService configurationService) : Ob set => SetPropertyAndSave(nameof(IsStoreUpdateNotificationsEnabled), value); } + public bool IsSystemTrayIconEnabled + { + get => _configurationService.Get(nameof(IsSystemTrayIconEnabled), true); + set => SetPropertyAndSave(nameof(IsSystemTrayIconEnabled), value); + } + public bool IsWinoAccountButtonHidden { get => _configurationService.Get(nameof(IsWinoAccountButtonHidden), false); diff --git a/Wino.Mail.WinUI/Views/Settings/AppPreferencesPage.xaml b/Wino.Mail.WinUI/Views/Settings/AppPreferencesPage.xaml index 798e1c5c..aae7fdd3 100644 --- a/Wino.Mail.WinUI/Views/Settings/AppPreferencesPage.xaml +++ b/Wino.Mail.WinUI/Views/Settings/AppPreferencesPage.xaml @@ -63,6 +63,13 @@ + + + + + + +