Added hook option for plugins to inject into the main layout before the router

This commit is contained in:
2026-02-20 12:28:22 +01:00
parent 9b9272cd6e
commit 5ad7a6db7b
5 changed files with 90 additions and 20 deletions

View File

@@ -0,0 +1,26 @@
using System.Diagnostics.CodeAnalysis;
using Moonlight.Frontend.Interfaces;
namespace Moonlight.Frontend.Configuration;
public class LayoutMiddlewareOptions
{
public IReadOnlyList<Type> Components => InnerComponents;
private readonly List<Type> InnerComponents = new();
public void Add<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>() where T : LayoutMiddlewareBase
{
InnerComponents.Add(typeof(T));
}
public void Insert<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(int index) where T : LayoutMiddlewareBase
{
InnerComponents.Insert(index, typeof(T));
}
public void Remove<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>() where T : LayoutMiddlewareBase
{
InnerComponents.Remove(typeof(T));
}
}

View File

@@ -0,0 +1,8 @@
using Microsoft.AspNetCore.Components;
namespace Moonlight.Frontend.Interfaces;
public abstract class LayoutMiddlewareBase : ComponentBase
{
[Parameter] public RenderFragment ChildContent { get; set; }
}

View File

@@ -9,6 +9,10 @@
@using ShadcnBlazor.Emptys @using ShadcnBlazor.Emptys
@using Moonlight.Frontend.UI.Shared.Components.Auth @using Moonlight.Frontend.UI.Shared.Components.Auth
@using Moonlight.Frontend.UI.Shared.Partials @using Moonlight.Frontend.UI.Shared.Partials
@using ShadcnBlazor.Extras.AlertDialogs
@using ShadcnBlazor.Extras.Dialogs
@using ShadcnBlazor.Extras.Toasts
@using ShadcnBlazor.Portals
@inject NavigationManager Navigation @inject NavigationManager Navigation
@inject IOptions<NavigationAssemblyOptions> NavigationOptions @inject IOptions<NavigationAssemblyOptions> NavigationOptions
@@ -17,6 +21,7 @@
<ChildContent> <ChildContent>
<AuthorizeView> <AuthorizeView>
<ChildContent> <ChildContent>
<LayoutMiddleware>
<Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="Assemblies" NotFoundPage="typeof(NotFound)"> <Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="Assemblies" NotFoundPage="typeof(NotFound)">
<Found Context="routeData"> <Found Context="routeData">
<AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)"> <AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)">
@@ -26,6 +31,13 @@
</AuthorizeRouteView> </AuthorizeRouteView>
</Found> </Found>
</Router> </Router>
</LayoutMiddleware>
<ToastLauncher/>
<DialogLauncher/>
<AlertDialogLauncher/>
<PortalOutlet />
</ChildContent> </ChildContent>
<Authorizing> <Authorizing>
<Authenticating/> <Authenticating/>

View File

@@ -0,0 +1,34 @@
@using Microsoft.Extensions.Options
@using Moonlight.Frontend.Configuration
@using Moonlight.Frontend.Interfaces
@inject IOptions<LayoutMiddlewareOptions> Options
@Chain
@code
{
[Parameter] public RenderFragment ChildContent { get; set; }
private RenderFragment Chain;
protected override void OnInitialized()
{
Chain = ChildContent;
foreach (var component in Options.Value.Components)
{
// Capture current values
var currentChain = Chain;
var currentComponent = component;
Chain = builder =>
{
builder.OpenComponent(0, currentComponent);
builder.SetKey(component);
builder.AddComponentParameter(1, nameof(LayoutMiddlewareBase.ChildContent), currentChain);
builder.CloseComponent();
};
}
}
}

View File

@@ -1,8 +1,4 @@
@using ShadcnBlazor.Extras.AlertDialogs @using ShadcnBlazor.Extras.Alerts
@using ShadcnBlazor.Extras.Alerts
@using ShadcnBlazor.Extras.Dialogs
@using ShadcnBlazor.Extras.Toasts
@using ShadcnBlazor.Portals
@using ShadcnBlazor.Sidebars @using ShadcnBlazor.Sidebars
@inherits LayoutComponentBase @inherits LayoutComponentBase
@@ -18,11 +14,5 @@
@Body @Body
</div> </div>
<ToastLauncher/>
<DialogLauncher/>
<AlertDialogLauncher/>
<PortalOutlet />
</SidebarInset> </SidebarInset>
</SidebarProvider> </SidebarProvider>