Files
ClaudeDo/src/ClaudeDo.App/Program.cs

118 lines
4.0 KiB
C#

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>();
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<App>()
.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<ClaudeDoDbContext>(opt =>
opt.UseSqlite($"Data Source={dbPath}"));
sc.AddScoped<ClaudeDoDbContext>(sp =>
sp.GetRequiredService<IDbContextFactory<ClaudeDoDbContext>>().CreateDbContext());
// Services
sc.AddSingleton<GitService>();
sc.AddSingleton(sp => new WorkerClient(sp.GetRequiredService<AppSettings>().SignalRUrl));
// Release check + installer update
sc.AddSingleton<HttpClient>(_ => new HttpClient { Timeout = TimeSpan.FromSeconds(10) });
sc.AddSingleton<IReleaseClient>(sp => new ReleaseClient(sp.GetRequiredService<HttpClient>()));
sc.AddSingleton<InstallerLocator>();
sc.AddSingleton(sp =>
{
var releases = sp.GetRequiredService<IReleaseClient>();
var version = Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? "0.0.0.0";
return new UpdateCheckService(releases, version);
});
// ViewModels
sc.AddTransient<WorktreeModalViewModel>();
sc.AddTransient<SettingsModalViewModel>();
sc.AddTransient<MergeModalViewModel>();
sc.AddTransient<ListSettingsModalViewModel>();
// Islands shell VMs
sc.AddSingleton<ListsIslandViewModel>(sp =>
new ListsIslandViewModel(
sp.GetRequiredService<IDbContextFactory<ClaudeDoDbContext>>(),
sp,
sp.GetRequiredService<WorkerClient>()));
sc.AddSingleton<TasksIslandViewModel>(sp =>
new TasksIslandViewModel(
sp.GetRequiredService<IDbContextFactory<ClaudeDoDbContext>>(),
sp.GetRequiredService<WorkerClient>()));
sc.AddSingleton<DetailsIslandViewModel>(sp =>
new DetailsIslandViewModel(
sp.GetRequiredService<IDbContextFactory<ClaudeDoDbContext>>(),
sp.GetRequiredService<WorkerClient>(),
sp));
sc.AddSingleton<IslandsShellViewModel>();
return sc.BuildServiceProvider();
}
}