using System; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; using Avalonia.Threading; using ClaudeDo.Ui; using ClaudeDo.Ui.Localization; using ClaudeDo.Ui.Services; using ClaudeDo.Ui.ViewModels; using ClaudeDo.Ui.Views; using Microsoft.Extensions.DependencyInjection; namespace ClaudeDo.App; public partial class App : Application { private readonly IServiceProvider? _services; // Parameterless ctor is required by the XAML previewer / designer. public App() { } public App(IServiceProvider services) => _services = services; public override void Initialize() { AvaloniaXamlLoader.Load(this); if (_services?.GetService() is { } settings) AccentPresetService.Apply(AccentPresets.Find(settings.AccentPreset)); } public override void OnFrameworkInitializationCompleted() { if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { var services = _services ?? throw new InvalidOperationException("App was constructed without a service provider."); FocusClearing.Install(); // The main window is authoritative — closing it shuts the app down even if the // modeless Mission Control window is still open. desktop.ShutdownMode = ShutdownMode.OnMainWindowClose; var shell = services.GetRequiredService(); // Last-resort backstop: an exception escaping a dispatcher job kills the process, and // ClaudeDo hosts third-party UI (the ConPTY terminal control) whose async void key and // render handlers have done exactly that — one bad keystroke took the whole app down, // losing every open session. Swallowing is the lesser evil here: the failing job is // already dead either way, and the user still gets told via the footer error strip. Dispatcher.UIThread.UnhandledException += (_, e) => { e.Handled = true; shell.FlashFooterError(Loc.T("vm.shell.unexpectedError", e.Exception.Message)); }; desktop.MainWindow = new MainWindow { DataContext = shell, }; // Kick off the SignalR retry loop — reconnects indefinitely if the worker // is not up yet, or goes down and comes back. _ = services.GetRequiredService().StartAsync(); } base.OnFrameworkInitializationCompleted(); } }