using System.Windows; using System.Windows.Controls; using EngineeringSync.TrayApp.Services; using EngineeringSync.TrayApp.ViewModels; using EngineeringSync.TrayApp.Views; using H.NotifyIcon; namespace EngineeringSync.TrayApp; public partial class App : Application { private TaskbarIcon? _trayIcon; private SignalRService? _signalR; private ApiClient? _apiClient; private PendingChangesWindow? _pendingChangesWindow; private PendingChangesViewModel? _pendingChangesViewModel; protected override async void OnStartup(StartupEventArgs e) { try { base.OnStartup(e); _apiClient = new ApiClient(new System.Net.Http.HttpClient()); _signalR = new SignalRService(); // TaskbarIcon aus XAML-Resource laden (wird dadurch korrekt im Shell registriert) _trayIcon = (TaskbarIcon)FindResource("TrayIcon"); _trayIcon.ContextMenu = BuildContextMenu(); // ForceCreate() aufrufen, um sicherzustellen dass das Icon im System Tray erscheint _trayIcon.ForceCreate(enablesEfficiencyMode: false); _signalR.ChangeNotificationReceived += OnChangeNotificationReceived; _signalR.ChangeNotificationReceived += OnPendingChangesWindowNotification; try { await _signalR.ConnectAsync(); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"[TrayApp] SignalR Connect Fehler: {ex}"); } } catch (Exception ex) { // Debug-Fehlerbehandlung für Icon-Initialisierung MessageBox.Show( $"Fehler bei der Initialisierung des Tray Icons:\n\n{ex.Message}\n\n{ex.StackTrace}", "EngineeringSync Startup Error", MessageBoxButton.OK, MessageBoxImage.Error); throw; } } private ContextMenu BuildContextMenu() { var menu = new ContextMenu(); var showChanges = new MenuItem { Header = "Änderungen anzeigen" }; showChanges.Click += (_, _) => OpenChangesWindow(); menu.Items.Add(showChanges); var showProjects = new MenuItem { Header = "Projekte verwalten" }; showProjects.Click += (_, _) => OpenProjectsWindow(); menu.Items.Add(showProjects); menu.Items.Add(new Separator()); var exit = new MenuItem { Header = "Beenden" }; exit.Click += (_, _) => ExitApp(); menu.Items.Add(exit); return menu; } private void OpenChangesWindow() { // Fenster beim ersten Mal erstellen if (_pendingChangesWindow is null) { _pendingChangesViewModel = new PendingChangesViewModel(_apiClient!); _pendingChangesWindow = new PendingChangesWindow(_pendingChangesViewModel); } // Fenster anzeigen/aktivieren _pendingChangesWindow.Show(); _pendingChangesWindow.Activate(); _ = _pendingChangesViewModel!.LoadProjectsCommand.ExecuteAsync(null); } private void OpenProjectsWindow() { var existing = Windows.OfType().FirstOrDefault(); if (existing is not null) { existing.Activate(); return; } var vm = new ProjectManagementViewModel(_apiClient!); var window = new ProjectManagementWindow(vm); window.Show(); _ = vm.LoadCommand.ExecuteAsync(null); } private void OnChangeNotificationReceived(Guid projectId, string projectName, int count) { Dispatcher.Invoke(() => { _trayIcon?.ShowNotification( title: "Neue Engineering-Daten", message: $"Projekt \"{projectName}\": {count} ausstehende Änderung(en)."); }); } private void OnPendingChangesWindowNotification(Guid projectId, string projectName, int count) { // Handler für PendingChangesWindow: nur aktualisieren wenn Fenster sichtbar ist if (_pendingChangesWindow?.IsVisible == true && _pendingChangesViewModel is not null) { Dispatcher.Invoke(() => _ = _pendingChangesViewModel.LoadChangesCommand.ExecuteAsync(null)); } } private async void ExitApp() { if (_signalR is not null) { await _signalR.DisposeAsync(); _signalR = null; } _trayIcon?.Dispose(); Shutdown(); } protected override async void OnExit(ExitEventArgs e) { if (_signalR is not null) { await _signalR.DisposeAsync(); _signalR = null; } _trayIcon?.Dispose(); base.OnExit(e); } }