using Avalonia; using ClaudeDo.Data; using ClaudeDo.Data.Git; using ClaudeDo.Releases; using ClaudeDo.Ui; using ClaudeDo.Ui.Services; using ClaudeDo.Ui.ViewModels; using ClaudeDo.Ui.ViewModels.Islands; using ClaudeDo.Ui.ViewModels.Modals; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using System; using System.Net.Http; using System.Reflection; using System.Runtime.InteropServices; namespace ClaudeDo.App; sealed class Program { [DllImport("shell32.dll", CharSet = CharSet.Unicode)] private static extern int SetCurrentProcessExplicitAppUserModelID(string appId); [STAThread] public static void Main(string[] args) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) SetCurrentProcessExplicitAppUserModelID("ClaudeDo.App"); var services = BuildServices(); App.Services = services; using (var scope = services.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); ClaudeDoDbContext.MigrateAndConfigure(db); } try { BuildAvaloniaApp() .StartWithClassicDesktopLifetime(args); } finally { // Dispose the container so WorkerClient.DisposeAsync runs — // cancels the retry loop and closes the SignalR connection cleanly // instead of abandoning it. try { services.DisposeAsync().AsTask().GetAwaiter().GetResult(); } catch { /* best effort on shutdown */ } } } public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure() .UsePlatformDetect() #if DEBUG .WithDeveloperTools() #endif .WithInterFont() .LogToTrace(); private static ServiceProvider BuildServices() { var settings = AppSettings.Load(); var dbPath = Paths.Expand(settings.DbPath); var sc = new ServiceCollection(); // Infrastructure sc.AddSingleton(settings); sc.AddDbContextFactory(opt => opt.UseSqlite($"Data Source={dbPath}")); sc.AddScoped(sp => sp.GetRequiredService>().CreateDbContext()); // Services sc.AddSingleton(); sc.AddSingleton(sp => new WorkerClient(sp.GetRequiredService().SignalRUrl)); // Release check + installer update sc.AddSingleton(_ => new HttpClient { Timeout = TimeSpan.FromSeconds(10) }); sc.AddSingleton(sp => new ReleaseClient(sp.GetRequiredService())); sc.AddSingleton(); sc.AddSingleton(sp => { var releases = sp.GetRequiredService(); var version = Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? "0.0.0.0"; return new UpdateCheckService(releases, version); }); // ViewModels sc.AddTransient(); sc.AddTransient(); sc.AddTransient(); sc.AddTransient(); // Islands shell VMs sc.AddSingleton(sp => new ListsIslandViewModel( sp.GetRequiredService>(), sp, sp.GetRequiredService())); sc.AddSingleton(sp => new TasksIslandViewModel( sp.GetRequiredService>(), sp.GetRequiredService())); sc.AddSingleton(sp => new DetailsIslandViewModel( sp.GetRequiredService>(), sp.GetRequiredService(), sp)); sc.AddSingleton(); return sc.BuildServiceProvider(); } }