Fix startup of launcher

Fixes #391
This commit is contained in:
Pat Hartl 2026-01-16 22:43:10 -06:00
parent 54a120f870
commit 6307f0351e
7 changed files with 124 additions and 107 deletions

View file

@ -12,71 +12,86 @@ using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Photino.Blazor;
using Photino.Blazor.CustomWindow.Extensions;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices;
using LANCommander.UI.Extensions;
var builder = PhotinoBlazorAppBuilder.CreateDefault(args);
// Map the Microsoft.Extensions.Logging.LogLevel to Serilog.LogEventLevel.
builder.Services.AddLogging(loggingBuilder => loggingBuilder.AddStandardLogging());
builder.Services.AddOpenTelemetryDefaults("Launcher", false);
namespace LANCommander.Launcher;
// Configure services
builder.AddSettings();
builder.Services.AddCustomWindow();
builder.Services.AddAntDesign();
builder.Services.AddSingleton<LocalizationService>();
builder.Services.AddLANCommanderClient<Settings>();
builder.Services.AddLANCommanderLauncher();
// Configure root component
builder.RootComponents.Add<App_Main>("app");
var app = builder.Build();
var logger = app.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("Starting launcher | Version: {Version}", UpdateService.GetCurrentVersion());
// Configure main window
app.RegisterMainWindow()
.RegisterMediaHandler()
.RegisterNotificationHandler()
.RegisterImportHandler()
.RestoreWindowPosition();
// Initialize application
using var scope = app.Services.CreateScope();
var connectionClient = scope.ServiceProvider.GetRequiredService<IConnectionClient>();
var settingsProvider = scope.ServiceProvider.GetRequiredService<SettingsProvider<Settings>>();
var databaseContext = scope.ServiceProvider.GetRequiredService<DatabaseContext>();
await connectionClient.ConnectAsync();
if (!await connectionClient.PingAsync())
await connectionClient.EnableOfflineModeAsync();
if (settingsProvider.CurrentValue.Games.InstallDirectories.Length == 0)
class Program
{
settingsProvider.Update(static s => s.Games.InstallDirectories = GetOSPlatform() switch
[STAThread]
static void Main(string[] args)
{
var platform when platform == OSPlatform.Windows => [Path.Combine(Path.GetPathRoot(AppContext.BaseDirectory) ?? "C:", "Games")],
var platform when platform == OSPlatform.Linux => [Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Games")],
var platform when platform == OSPlatform.OSX => [Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Games")],
_ => throw new NotSupportedException("Unsupported OS platform")
});
}
var builder = PhotinoBlazorAppBuilder.CreateDefault(args);
// Map the Microsoft.Extensions.Logging.LogLevel to Serilog.LogEventLevel.
builder.Services.AddLogging(loggingBuilder => loggingBuilder.AddStandardLogging());
builder.Services.AddOpenTelemetryDefaults("Launcher", false);
// Configure services
builder.AddSettings();
builder.Services.AddCustomWindow();
builder.Services.AddAntDesign();
builder.Services.AddSingleton<LocalizationService>();
builder.Services.AddLANCommanderUI();
builder.Services.AddLANCommanderClient<Settings.Settings>();
builder.Services.AddLANCommanderLauncher();
// Configure root component
builder.RootComponents.Add<App_Main>("app");
await databaseContext.Database.MigrateAsync();
var app = builder.Build();
app.Run();
var logger = app.Services.GetRequiredService<ILogger<Program>>();
static OSPlatform GetOSPlatform()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return OSPlatform.Windows;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return OSPlatform.Linux;
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
return OSPlatform.OSX;
throw new NotSupportedException("Unsupported OS platform");
logger.LogInformation("Starting launcher | Version: {Version}", UpdateService.GetCurrentVersion());
// Configure main window
app.RegisterMainWindow()
.RegisterMediaHandler()
.RegisterNotificationHandler()
.RegisterImportHandler()
.RestoreWindowPosition();
// Initialize application
using var scope = app.Services.CreateScope();
var connectionClient = scope.ServiceProvider.GetRequiredService<IConnectionClient>();
var settingsProvider = scope.ServiceProvider.GetRequiredService<SettingsProvider<Settings.Settings>>();
var databaseContext = scope.ServiceProvider.GetRequiredService<DatabaseContext>();
Task.Run(async () =>
{
connectionClient.ConnectAsync().Wait();
if (!await connectionClient.PingAsync())
await connectionClient.EnableOfflineModeAsync();
}).Wait();
if (settingsProvider.CurrentValue.Games.InstallDirectories.Length == 0)
{
settingsProvider.Update(static s => s.Games.InstallDirectories = GetOSPlatform() switch
{
var platform when platform == OSPlatform.Windows => [Path.Combine(Path.GetPathRoot(AppContext.BaseDirectory) ?? "C:", "Games")],
var platform when platform == OSPlatform.Linux => [Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Games")],
var platform when platform == OSPlatform.OSX => [Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Games")],
_ => throw new NotSupportedException("Unsupported OS platform")
});
}
if (databaseContext.Database.GetPendingMigrations().Any())
databaseContext.Database.Migrate();
app.Run();
static OSPlatform GetOSPlatform()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return OSPlatform.Windows;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return OSPlatform.Linux;
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
return OSPlatform.OSX;
throw new NotSupportedException("Unsupported OS platform");
}
}
}

View file

@ -4,7 +4,7 @@
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainWindow)" />
</Found>
<NotFound>
<RedirectToRoute Route="/Library" />
<RedirectToRoute Route="/Authenticate" />
</NotFound>
</Router>
</div>

View file

@ -1,3 +1,4 @@
@page "/Authenticate"
@layout AuthWindow
<AuthenticationForm />

View file

@ -0,0 +1,33 @@
@using Photino.Blazor.CustomWindow.Components
@namespace LANCommander.Launcher.UI
@inherits LayoutComponentBase
@inject AuthenticationClient AuthenticationClient
@inject NavigationManager NavigationManager
@inject LocalizationService LocalizationService
<CustomWindow HeaderHeight="37">
<WindowContent>
<ErrorHandler Title="@LocalizationService.GetString("LauncherCrashed")">
<Body>
<Layout>
@Body
</Layout>
<UpdateChecker/>
<AntContainer/>
</Body>
<Extra>
<Button Type="ButtonType.Primary" OnClick="@(() => NavigationManager.NavigateTo("/Authenticate", true))">@LocalizationService.GetString("Reload")</Button>
</Extra>
</ErrorHandler>
</WindowContent>
</CustomWindow>
@code {
protected override async Task OnInitializedAsync()
{
if (await AuthenticationClient.ValidateTokenAsync())
NavigationManager.NavigateTo("/Library");
}
}

View file

@ -0,0 +1,12 @@
.auth-window {
.pb-custom-window-content {
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
display: flex;
flex-direction: column;
height: 100% !important;
width: 100% !important;
}
}

View file

@ -102,11 +102,7 @@
ImportHandler ImportHandler;
ImportHandler.ImportProgressEventArgs ImportStatus = new();
private ImportProgress _importProgress => ImportService.Progress;
string RandomQuip = "";
string[] _crashQuips;
protected override async Task OnInitializedAsync()
{
ConnectionClient.OnOfflineModeEnabled += OnOfflineModeChanged;
@ -119,40 +115,6 @@
await ImportManagerService.RequestImport();
await InvokeAsync(StateHasChanged);
}
_crashQuips = new[]
{
LocalizationService.GetString("CrashQuip_YouDied"),
LocalizationService.GetString("CrashQuip_Snake"),
LocalizationService.GetString("CrashQuip_Wasted"),
LocalizationService.GetString("CrashQuip_MajorFracture"),
LocalizationService.GetString("CrashQuip_PastIsGapingHole"),
LocalizationService.GetString("CrashQuip_TownCenterDestroyed"),
LocalizationService.GetString("CrashQuip_ForcesUnderAttack"),
LocalizationService.GetString("CrashQuip_LostLead"),
LocalizationService.GetString("CrashQuip_TerroristsWin"),
LocalizationService.GetString("CrashQuip_WarNeverChanges"),
LocalizationService.GetString("CrashQuip_DiedOfDysentery"),
LocalizationService.GetString("CrashQuip_FailedToRestoreBooks"),
LocalizationService.GetString("CrashQuip_PlayerSplattered"),
LocalizationService.GetString("CrashQuip_BlameISP"),
LocalizationService.GetString("CrashQuip_BabaNoMore"),
LocalizationService.GetString("CrashQuip_GuestsLost"),
LocalizationService.GetString("CrashQuip_DarknessOvercome"),
LocalizationService.GetString("CrashQuip_GordonFreemanTerminated"),
LocalizationService.GetString("CrashQuip_MissionFailedSpotted"),
LocalizationService.GetString("CrashQuip_CriticalDamageEject"),
LocalizationService.GetString("CrashQuip_MinionsUnhappy"),
LocalizationService.GetString("CrashQuip_EmpireTriumphed"),
LocalizationService.GetString("CrashQuip_QuestEndedFailure"),
LocalizationService.GetString("CrashQuip_EatenByGrue"),
LocalizationService.GetString("CrashQuip_NoMessWithLoWang"),
LocalizationService.GetString("CrashQuip_SamKilled"),
LocalizationService.GetString("CrashQuip_AlienBastardsPay")
};
var randIndex = new Random().Next(0, _crashQuips.Length - 1);
RandomQuip = _crashQuips[randIndex];
}
private async void OnConnect(object? sender, EventArgs e)
@ -177,13 +139,6 @@
await InvokeAsync(StateHasChanged);
}
async Task CopyError(Exception ex)
{
await JS.InvokeVoidAsync("navigator.clipboard.writeText", ex.Message + "\n" + ex.StackTrace);
MessageService.Info(LocalizationService.GetString("ErrorCopiedToClipboard"));
}
async Task Connect()
{
Connecting = true;

View file

@ -1,4 +1,5 @@
@forward 'Windows/Window';
@forward 'Windows/AuthWindow.razor';
@forward 'Windows/MainWindow.razor';
@forward 'Windows/ChatWindow.razor';