Files
ClaudeDo/src/ClaudeDo.App/App.axaml.cs
T
Mika Kuns 57dd676672 feat(claude-do): UI-Prozess loggt auf Platte (ui-.log) + fehlgeschlagene Hub-
## Problem
Beim DeleteTask-Bug (Fix 352aaa52) gab es null Spuren: Der UI-Prozess (ClaudeDo.App) hat gar kein File-Logging (weder Serilog noch `Microsoft.Extensions.Logging` sind in App/Ui referenziert), und im Worker loggt SignalR fehlgeschlagene Hub-Invocations nur auf Debug (`Microsoft.AspNetCore` steht in `src/ClaudeDo.Worker/Program.cs` Z. 60 auf Warning). Die Ursache ließ sich nur finden, ind

ClaudeDo-Task: d2ae3831-733f-4d40-93d7-70c93da11590
2026-09-28 13:27:21 +02:00

72 lines
2.7 KiB
C#

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<AppSettings>() 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<IslandsShellViewModel>();
// 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;
Serilog.Log.Error(e.Exception, "Unhandled exception on the UI dispatcher");
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<WorkerClient>().StartAsync();
}
base.OnFrameworkInitializationCompleted();
}
}