From 0a76e64d2f67c6d601fa1bf36a08d32f621c35e3 Mon Sep 17 00:00:00 2001 From: ChiaraBm Date: Sun, 1 Dec 2024 18:34:08 +0100 Subject: [PATCH] Added AssetService. Added command line handling for assets. Added asset streaming on the client --- .../Http/Controllers/AssetsController.cs | 27 ++++++++ Moonlight.ApiServer/Services/AssetService.cs | 10 +++ Moonlight.ApiServer/Startup.cs | 69 +++++++++++++++++++ Moonlight.Client/Startup.cs | 22 +++++- .../Responses/Assets/FrontendAssetResponse.cs | 7 ++ 5 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 Moonlight.ApiServer/Http/Controllers/AssetsController.cs create mode 100644 Moonlight.ApiServer/Services/AssetService.cs create mode 100644 Moonlight.Shared/Http/Responses/Assets/FrontendAssetResponse.cs diff --git a/Moonlight.ApiServer/Http/Controllers/AssetsController.cs b/Moonlight.ApiServer/Http/Controllers/AssetsController.cs new file mode 100644 index 00000000..4257e4e5 --- /dev/null +++ b/Moonlight.ApiServer/Http/Controllers/AssetsController.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Mvc; +using Moonlight.ApiServer.Services; +using Moonlight.Shared.Http.Responses.Assets; + +namespace Moonlight.ApiServer.Http.Controllers; + +[ApiController] +[Route("api/assets")] +public class AssetsController : Controller +{ + private readonly AssetService AssetService; + + public AssetsController(AssetService assetService) + { + AssetService = assetService; + } + + [HttpGet] + public async Task Get() + { + return new FrontendAssetResponse() + { + CssFiles = AssetService.CssFiles.ToArray(), + JavascriptFiles = AssetService.JavascriptFiles.ToArray(), + }; + } +} \ No newline at end of file diff --git a/Moonlight.ApiServer/Services/AssetService.cs b/Moonlight.ApiServer/Services/AssetService.cs new file mode 100644 index 00000000..92064a04 --- /dev/null +++ b/Moonlight.ApiServer/Services/AssetService.cs @@ -0,0 +1,10 @@ +using MoonCore.Attributes; + +namespace Moonlight.ApiServer.Services; + +[Singleton] +public class AssetService +{ + public readonly List CssFiles = new(); + public readonly List JavascriptFiles = new(); +} \ No newline at end of file diff --git a/Moonlight.ApiServer/Startup.cs b/Moonlight.ApiServer/Startup.cs index dabf8bc3..7066f130 100644 --- a/Moonlight.ApiServer/Startup.cs +++ b/Moonlight.ApiServer/Startup.cs @@ -78,9 +78,11 @@ public class Startup await RegisterOAuth2(); await RegisterCaching(); await HookPluginBuild(); + await HandleConfigureArguments(); await BuildWebApplication(); + await HandleServiceArguments(); await PrepareDatabase(); await UseBase(); @@ -124,6 +126,73 @@ public class Startup return Task.CompletedTask; } + #region Command line arguments + + private Task HandleConfigureArguments() + { + return Task.CompletedTask; + } + + private Task HandleServiceArguments() + { + // Handle manual asset loading arguments + if (Args.Any(x => x.StartsWith("--frontend-asset"))) + { + if (!Configuration.Client.Enable) + { + Logger.LogWarning("The hosting of the moonlight frontend is disabled. Ignoring all --frontend-asset options"); + return Task.CompletedTask; // TODO: Change this when adding more service argument handling functions + } + + if (!WebApplicationBuilder.Environment.IsDevelopment()) + Logger.LogWarning("Using the --frontend-asset option is not meant to be used in production. Plugin assets will be loaded automaticly"); + + var assetService = WebApplication.Services.GetRequiredService(); + + for (int i = 0; i < Args.Length; i++) + { + var currentArg = Args[i]; + + // Ignore all args without relation to our frontend assets + if(!currentArg.Equals("--frontend-asset", StringComparison.InvariantCultureIgnoreCase)) + continue; + + if (i + 1 >= Args.Length) + { + Logger.LogWarning("You need to specify an asset path after the --frontend-asset option"); + continue; + } + + var nextArg = Args[i + 1]; + + if (nextArg.StartsWith("--")) + { + Logger.LogWarning("You need to specify an asset path after the --frontend-asset option"); + continue; + } + + var extension = Path.GetExtension(nextArg); + + switch (extension) + { + case ".css": + assetService.CssFiles.Add(nextArg); + break; + case ".js": + assetService.JavascriptFiles.Add(nextArg); + break; + default: + Logger.LogWarning("Unknown asset extension {extension}. Ignoring it", extension); + break; + } + } + } + + return Task.CompletedTask; + } + + #endregion + #region Base private Task RegisterBase() diff --git a/Moonlight.Client/Startup.cs b/Moonlight.Client/Startup.cs index 11d86dee..4e05acb2 100644 --- a/Moonlight.Client/Startup.cs +++ b/Moonlight.Client/Startup.cs @@ -15,6 +15,7 @@ using Moonlight.Client.Interfaces; using Moonlight.Client.Services; using Moonlight.Client.UI; using Moonlight.Client.UI.Forms; +using Moonlight.Shared.Http.Responses.Assets; using Moonlight.Shared.Http.Responses.PluginsStream; namespace Moonlight.Client; @@ -50,7 +51,7 @@ public class Startup await SetupLogging(); await CreateWebAssemblyHostBuilder(); - + await LoadPlugins(); await RegisterLogging(); @@ -62,6 +63,7 @@ public class Startup await BuildWebAssemblyHost(); await LoadPluginAssets(); + await LoadAssets(); await WebAssemblyHost.RunAsync(); } @@ -124,6 +126,24 @@ public class Startup return Task.CompletedTask; } + #region Asset Loading + + private async Task LoadAssets() + { + var apiClient = WebAssemblyHost.Services.GetRequiredService(); + var assetManifest = await apiClient.GetJson("api/assets"); + + var jsRuntime = WebAssemblyHost.Services.GetRequiredService(); + + foreach (var cssFile in assetManifest.CssFiles) + await jsRuntime.InvokeVoidAsync("moonlight.assets.loadCss", cssFile); + + foreach (var javascriptFile in assetManifest.JavascriptFiles) + await jsRuntime.InvokeVoidAsync("moonlight.assets.loadJavascript", javascriptFile); + } + + #endregion + #region Interfaces private Task RegisterInterfaces() diff --git a/Moonlight.Shared/Http/Responses/Assets/FrontendAssetResponse.cs b/Moonlight.Shared/Http/Responses/Assets/FrontendAssetResponse.cs new file mode 100644 index 00000000..3892add2 --- /dev/null +++ b/Moonlight.Shared/Http/Responses/Assets/FrontendAssetResponse.cs @@ -0,0 +1,7 @@ +namespace Moonlight.Shared.Http.Responses.Assets; + +public class FrontendAssetResponse +{ + public string[] CssFiles { get; set; } + public string[] JavascriptFiles { get; set; } +} \ No newline at end of file