Files
OTSSignsOrchestrator/OTSSignsOrchestrator.Desktop/App.axaml.cs
Matt Batchelder 45c94b6536
Some checks failed
Build and Publish Docker Image / build-and-push (push) Has been cancelled
feat: Add main application views and structure
- Implemented CreateInstanceView for creating new instances.
- Added HostsView for managing SSH hosts with CRUD operations.
- Created InstancesView for displaying and managing instances.
- Developed LogsView for viewing operation logs.
- Introduced SecretsView for managing secrets associated with hosts.
- Established SettingsView for configuring application settings.
- Created MainWindow as the main application window with navigation.
- Added app manifest and configuration files for logging and settings.
2026-02-18 10:43:27 -05:00

145 lines
5.2 KiB
C#

using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Serilog;
using OTSSignsOrchestrator.Core.Configuration;
using OTSSignsOrchestrator.Core.Data;
using OTSSignsOrchestrator.Core.Services;
using OTSSignsOrchestrator.Desktop.Services;
using OTSSignsOrchestrator.Desktop.ViewModels;
using OTSSignsOrchestrator.Desktop.Views;
namespace OTSSignsOrchestrator.Desktop;
public class App : Application
{
public static IServiceProvider Services { get; private set; } = null!;
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
var services = new ServiceCollection();
ConfigureServices(services);
Services = services.BuildServiceProvider();
// Apply migrations
using (var scope = Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<XiboContext>();
db.Database.Migrate();
}
Log.Information("ApplicationLifetime type: {Type}", ApplicationLifetime?.GetType().FullName ?? "null");
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
Log.Information("Creating MainWindow...");
var vm = Services.GetRequiredService<MainWindowViewModel>();
Log.Information("MainWindowViewModel resolved");
var window = new MainWindow
{
DataContext = vm
};
desktop.MainWindow = window;
Log.Information("MainWindow assigned to lifetime");
window.Show();
window.Activate();
Log.Information("MainWindow Show() + Activate() called");
desktop.ShutdownRequested += (_, _) =>
{
var ssh = Services.GetService<SshConnectionService>();
ssh?.Dispose();
};
}
else
{
Log.Warning("ApplicationLifetime is NOT IClassicDesktopStyleApplicationLifetime — window cannot be shown");
}
base.OnFrameworkInitializationCompleted();
}
private static void ConfigureServices(IServiceCollection services)
{
// Configuration
var config = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false)
.Build();
services.AddSingleton<IConfiguration>(config);
// Options
services.Configure<GitOptions>(config.GetSection(GitOptions.SectionName));
services.Configure<DockerOptions>(config.GetSection(DockerOptions.SectionName));
services.Configure<XiboOptions>(config.GetSection(XiboOptions.SectionName));
services.Configure<DatabaseOptions>(config.GetSection(DatabaseOptions.SectionName));
services.Configure<FileLoggingOptions>(config.GetSection(FileLoggingOptions.SectionName));
// Logging
services.AddLogging(builder =>
{
builder.ClearProviders();
builder.AddSerilog(dispose: true);
});
// Data Protection
var keysDir = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"OTSSignsOrchestrator", "keys");
Directory.CreateDirectory(keysDir);
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(keysDir))
.SetApplicationName("OTSSignsOrchestrator");
// Database
var connStr = config.GetConnectionString("Default") ?? "Data Source=otssigns-desktop.db";
services.AddDbContext<XiboContext>(options => options.UseSqlite(connStr));
// HTTP
services.AddHttpClient();
services.AddHttpClient("XiboApi");
// SSH services (singletons — maintain connections)
services.AddSingleton<SshConnectionService>();
// Docker services via SSH (scoped so they get fresh per-operation context)
services.AddTransient<SshDockerCliService>();
services.AddTransient<SshDockerSecretsService>();
services.AddTransient<IDockerCliService>(sp => sp.GetRequiredService<SshDockerCliService>());
services.AddTransient<IDockerSecretsService>(sp => sp.GetRequiredService<SshDockerSecretsService>());
// Core services
services.AddTransient<SettingsService>();
services.AddTransient<GitTemplateService>();
services.AddTransient<ComposeRenderService>();
services.AddTransient<ComposeValidationService>();
services.AddTransient<XiboApiService>();
services.AddTransient<InstanceService>();
// ViewModels
services.AddTransient<MainWindowViewModel>();
services.AddTransient<HostsViewModel>();
services.AddTransient<InstancesViewModel>();
services.AddTransient<CreateInstanceViewModel>();
services.AddTransient<SecretsViewModel>();
services.AddTransient<SettingsViewModel>();
services.AddTransient<LogsViewModel>();
}
}