129 lines
4.9 KiB
C#
129 lines
4.9 KiB
C#
using Duempelkas.Infrastructure;
|
||
using Duempelkas.Infrastructure.Persistence;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using Photino.Blazor;
|
||
using System.Runtime.InteropServices;
|
||
|
||
namespace Duempelkas.Desktop;
|
||
|
||
class Program
|
||
{
|
||
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
|
||
private static extern int SetCurrentProcessExplicitAppUserModelID(string appID);
|
||
|
||
[STAThread]
|
||
static void Main(string[] args)
|
||
{
|
||
if (OperatingSystem.IsWindows())
|
||
{
|
||
// Ensure Windows taskbar does not group this process under generic dotnet host identity.
|
||
SetCurrentProcessExplicitAppUserModelID("Duempelkas.Desktop");
|
||
}
|
||
|
||
var appBuilder = PhotinoBlazorAppBuilder.CreateDefault(args);
|
||
|
||
// Use a per-user writable DB location so debugging via dotnet host works reliably.
|
||
var appDataDir = Path.Combine(
|
||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||
"Duempelkas");
|
||
var isolated = false;
|
||
#if DEBUG
|
||
var directoryIndex = Array.IndexOf(args, "--data-directory");
|
||
if (directoryIndex >= 0)
|
||
{
|
||
if (directoryIndex + 1 >= args.Length) throw new ArgumentException("Datenordner fehlt.");
|
||
appDataDir = Path.GetFullPath(args[directoryIndex + 1]);
|
||
isolated = true;
|
||
}
|
||
#endif
|
||
Directory.CreateDirectory(appDataDir);
|
||
|
||
var dbPath = Path.Combine(appDataDir, "duempelkas.db");
|
||
|
||
// One-time compatibility: keep existing data if older versions stored DB next to the app executable.
|
||
var legacyExeDirectory = Path.GetDirectoryName(Environment.ProcessPath ?? AppContext.BaseDirectory) ?? AppContext.BaseDirectory;
|
||
var legacyDbPath = Path.Combine(legacyExeDirectory, "duempelkas.db");
|
||
if (!isolated && !File.Exists(dbPath) && File.Exists(legacyDbPath))
|
||
{
|
||
try
|
||
{
|
||
using var source = new Microsoft.Data.Sqlite.SqliteConnection($"Data Source={legacyDbPath};Mode=ReadOnly");
|
||
using var target = new Microsoft.Data.Sqlite.SqliteConnection($"Data Source={dbPath}");
|
||
source.Open();
|
||
target.Open();
|
||
source.BackupDatabase(target);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw new InvalidOperationException("Die vorhandene Datenbank konnte nicht übernommen werden. Der Start wurde abgebrochen; die ursprüngliche Datei bleibt erhalten.", ex);
|
||
}
|
||
}
|
||
|
||
appBuilder.Services.AddInfrastructure(new Microsoft.Data.Sqlite.SqliteConnectionStringBuilder { DataSource = dbPath }.ToString(), appDataDir);
|
||
|
||
appBuilder.RootComponents.Add<Duempelkas.App.Components.App>("app");
|
||
|
||
var app = appBuilder.Build();
|
||
|
||
app.MainWindow.StartUrl = PhotinoWebViewManager.AppBaseUri;
|
||
|
||
// Force the native window icon for title bar + taskbar representation.
|
||
var iconPath = Path.Combine(AppContext.BaseDirectory, "Assets", "app-icon.ico");
|
||
if (File.Exists(iconPath))
|
||
{
|
||
app.MainWindow.SetIconFile(iconPath);
|
||
}
|
||
|
||
using (var scope = app.Services.CreateScope())
|
||
{
|
||
var db = scope.ServiceProvider.GetRequiredService<FinanceDbContext>();
|
||
db.Database.Migrate();
|
||
}
|
||
|
||
// Load saved window size or use defaults
|
||
var settingsPath = Path.Combine(appDataDir, "window.json");
|
||
|
||
int savedWidth = 1280, savedHeight = 800;
|
||
if (File.Exists(settingsPath))
|
||
{
|
||
try
|
||
{
|
||
var json = File.ReadAllText(settingsPath);
|
||
var doc = System.Text.Json.JsonDocument.Parse(json);
|
||
savedWidth = doc.RootElement.GetProperty("width").GetInt32();
|
||
savedHeight = doc.RootElement.GetProperty("height").GetInt32();
|
||
}
|
||
catch { /* use defaults on parse error */ }
|
||
}
|
||
|
||
app.MainWindow
|
||
.SetTitle(isolated ? "Dümpelkas – Testdaten" : "Dümpelkas – Kassenbuch")
|
||
.SetSize(savedWidth, savedHeight)
|
||
.SetUseOsDefaultSize(false);
|
||
|
||
app.MainWindow.MinWidth = 768;
|
||
app.MainWindow.MinHeight = 480;
|
||
|
||
// Persist window size on resize
|
||
app.MainWindow.RegisterSizeChangedHandler((_, size) =>
|
||
{
|
||
try
|
||
{
|
||
var dir = Path.GetDirectoryName(settingsPath)!;
|
||
Directory.CreateDirectory(dir);
|
||
File.WriteAllText(settingsPath,
|
||
System.Text.Json.JsonSerializer.Serialize(new { width = size.Width, height = size.Height }));
|
||
}
|
||
catch { /* ignore save errors */ }
|
||
});
|
||
|
||
AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
|
||
{
|
||
app.MainWindow.ShowMessage("Schwerwiegender Fehler", error.ExceptionObject.ToString());
|
||
};
|
||
|
||
app.Run();
|
||
}
|
||
}
|