Refactored startup. Removed unused usings. Improved nuget package building. Switched to yaml for configuration. Moved asset files. Set correct context type for oauth2 pages. Updated versions

This commit is contained in:
2025-07-14 21:06:54 +02:00
parent 2b62fc141d
commit acba3a9f53
45 changed files with 730 additions and 1173 deletions

View File

@@ -0,0 +1,25 @@
using Microsoft.Extensions.DependencyInjection;
using MoonCore.Blazor.FlyonUi.Auth;
using MoonCore.Permissions;
using Moonlight.Client.Services;
namespace Moonlight.Client.Startup;
public partial class Startup
{
private Task RegisterAuthentication()
{
WebAssemblyHostBuilder.Services.AddAuthorizationCore();
WebAssemblyHostBuilder.Services.AddCascadingAuthenticationState();
WebAssemblyHostBuilder.Services.AddAuthenticationStateManager<RemoteAuthStateManager>();
WebAssemblyHostBuilder.Services.AddAuthorizationPermissions(options =>
{
options.ClaimName = "permissions";
options.Prefix = "permissions:";
});
return Task.CompletedTask;
}
}

View File

@@ -0,0 +1,56 @@
using Microsoft.Extensions.DependencyInjection;
using MoonCore.Blazor.FlyonUi;
using MoonCore.Blazor.Services;
using MoonCore.Extensions;
using MoonCore.Helpers;
using Moonlight.Client.Services;
using Moonlight.Client.UI;
namespace Moonlight.Client.Startup;
public partial class Startup
{
private Task RegisterBase()
{
WebAssemblyHostBuilder.RootComponents.Add<App>("#app");
WebAssemblyHostBuilder.RootComponents.Add<HeadOutlet>("head::after");
WebAssemblyHostBuilder.Services.AddScoped(_ =>
new HttpClient
{
BaseAddress = new Uri(Configuration.ApiUrl)
}
);
WebAssemblyHostBuilder.Services.AddScoped(sp =>
{
var httpClient = sp.GetRequiredService<HttpClient>();
var httpApiClient = new HttpApiClient(httpClient);
var localStorageService = sp.GetRequiredService<LocalStorageService>();
httpApiClient.OnConfigureRequest += async request =>
{
var accessToken = await localStorageService.GetString("AccessToken");
if (string.IsNullOrEmpty(accessToken))
return;
request.Headers.Add("Authorization", $"Bearer {accessToken}");
};
return httpApiClient;
});
WebAssemblyHostBuilder.Services.AddScoped<WindowService>();
WebAssemblyHostBuilder.Services.AddFileManagerOperations();
WebAssemblyHostBuilder.Services.AddFlyonUiServices();
WebAssemblyHostBuilder.Services.AddScoped<LocalStorageService>();
WebAssemblyHostBuilder.Services.AddScoped<ThemeService>();
WebAssemblyHostBuilder.Services.AutoAddServices<Startup>();
return Task.CompletedTask;
}
}

View File

@@ -0,0 +1,24 @@
using MoonCore.Logging;
namespace Moonlight.Client.Startup;
public partial class Startup
{
private Task SetupLogging()
{
var loggerFactory = new LoggerFactory();
loggerFactory.AddAnsiConsole();
Logger = loggerFactory.CreateLogger<Startup>();
return Task.CompletedTask;
}
private Task RegisterLogging()
{
WebAssemblyHostBuilder.Logging.ClearProviders();
WebAssemblyHostBuilder.Logging.AddAnsiConsole();
return Task.CompletedTask;
}
}

View File

@@ -0,0 +1,52 @@
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using Moonlight.Shared.Misc;
namespace Moonlight.Client.Startup;
public partial class Startup
{
private Task PrintVersion()
{
// Fancy start console output... yes very fancy :>
Console.Write("Running ");
var rainbow = new Crayon.Rainbow(0.5);
foreach (var c in "Moonlight")
{
Console.Write(
rainbow
.Next()
.Bold()
.Text(c.ToString())
);
}
Console.WriteLine();
return Task.CompletedTask;
}
private async Task LoadConfiguration()
{
try
{
using var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(WebAssemblyHostBuilder.HostEnvironment.BaseAddress);
var jsonText = await httpClient.GetStringAsync("frontend.json");
Configuration = JsonSerializer.Deserialize<FrontendConfiguration>(jsonText, new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true
})!;
WebAssemblyHostBuilder.Services.AddSingleton(Configuration);
}
catch (Exception e)
{
Logger.LogCritical("Unable to load configuration. Unable to continue: {e}", e);
throw;
}
}
}

View File

@@ -0,0 +1,78 @@
using Microsoft.Extensions.DependencyInjection;
using MoonCore.Logging;
using Moonlight.Client.Plugins;
using Moonlight.Client.Services;
namespace Moonlight.Client.Startup;
public partial class Startup
{
private IPluginStartup[] PluginStartups;
private IServiceProvider PluginLoadServiceProvider;
private Task InitializePlugins()
{
// Define minimal service collection
var startupSc = new ServiceCollection();
// Create logging proxy
startupSc.AddLogging(builder =>
{
builder.ClearProviders();
builder.AddAnsiConsole();
});
PluginLoadServiceProvider = startupSc.BuildServiceProvider();
// Add application assembly service
var appAssemblyService = new ApplicationAssemblyService();
appAssemblyService.Assemblies.AddRange(
PluginStartups
.Select(x => x.GetType().Assembly)
.Distinct()
);
WebAssemblyHostBuilder.Services.AddSingleton(appAssemblyService);
return Task.CompletedTask;
}
private async Task HookPluginBuild()
{
foreach (var pluginAppStartup in PluginStartups)
{
try
{
await pluginAppStartup.BuildApplication(PluginLoadServiceProvider, WebAssemblyHostBuilder);
}
catch (Exception e)
{
Logger.LogError(
"An error occured while processing 'BuildApp' for '{name}': {e}",
pluginAppStartup.GetType().FullName,
e
);
}
}
}
private async Task HookPluginConfigure()
{
foreach (var pluginAppStartup in PluginStartups)
{
try
{
await pluginAppStartup.ConfigureApplication(PluginLoadServiceProvider, WebAssemblyHost);
}
catch (Exception e)
{
Logger.LogError(
"An error occured while processing 'ConfigureApp' for '{name}': {e}",
pluginAppStartup.GetType().FullName,
e
);
}
}
}
}

View File

@@ -0,0 +1,48 @@
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Moonlight.Client.Plugins;
using Moonlight.Shared.Misc;
namespace Moonlight.Client.Startup;
public partial class Startup
{
public ILogger<Startup> Logger { get; private set; }
// WebAssemblyHost
public WebAssemblyHostBuilder WebAssemblyHostBuilder { get; private set; }
public WebAssemblyHost WebAssemblyHost { get; private set; }
// Configuration
public FrontendConfiguration Configuration { get; private set; }
public Task Initialize(IPluginStartup[]? plugins = null)
{
PluginStartups = plugins ?? [];
return Task.CompletedTask;
}
public async Task AddMoonlight(WebAssemblyHostBuilder builder)
{
WebAssemblyHostBuilder = builder;
await PrintVersion();
await SetupLogging();
await LoadConfiguration();
await InitializePlugins();
await RegisterLogging();
await RegisterBase();
await RegisterAuthentication();
await HookPluginBuild();
}
public async Task AddMoonlight(WebAssemblyHost assemblyHost)
{
WebAssemblyHost = assemblyHost;
await HookPluginConfigure();
}
}