From 186e02c3eefa7b1a4bbcea043dacf31f15f44519 Mon Sep 17 00:00:00 2001 From: Jon Kazama Date: Wed, 27 May 2026 22:59:01 +0200 Subject: [PATCH] fix(plugin): register UiBuilder.OpenConfigUi / OpenMainUi stubs Dalamud's plugin validator flagged two issues on v0.1.0: - "The plugin does not register a config UI callback." - "The plugin does not register a main UI callback." v0.1.0 ships the RecipeData layer only - the actual SettingsWindow and MainWindow arrive with module 08 (UI). To pass validation and to give users a useful response when they click "Open Settings" or "Open Main" in the plugin installer, both callbacks now fire toast notifications via INotificationManager that point at the roadmap. The handlers wire up in the constructor right after the host build and unwire in DisposeAsync. INotificationManager joins the Block A Dalamud services in PluginHostDependencies + PluginHostFactory so the DI container also exposes it for later modules. --- Anvil/Plugin.cs | 56 +++++++++++++++++++++++++++++---- Anvil/PluginHostDependencies.cs | 3 +- Anvil/PluginHostFactory.cs | 1 + 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/Anvil/Plugin.cs b/Anvil/Plugin.cs index 8a29e43..24d4871 100644 --- a/Anvil/Plugin.cs +++ b/Anvil/Plugin.cs @@ -1,15 +1,19 @@ // Anvil plugin entry. Implements IAsyncDalamudPlugin so Dalamud awaits // LoadAsync before considering the plugin loaded. The constructor wires // the generic-host DI container synchronously - Dalamud's IoC fills the -// five Dalamud services as ctor args (Lightless pattern), the bundle is -// handed to PluginHostFactory, and PluginLifecycle takes it from there. +// services as ctor args (Lightless pattern), the bundle is handed to +// PluginHostFactory, and PluginLifecycle takes it from there. // -// v0.1.0 is intentionally thin. Module 02+ extends PluginHostFactory's -// services collection; this file does not need to change. +// v0.1.0 ships the RecipeData layer only. The OpenConfigUi / OpenMainUi +// callbacks fire toast notifications so Dalamud's plugin validator stops +// complaining about missing UI callbacks while module 08 (the actual +// windows) is still under construction. The callbacks will be replaced +// once the SettingsWindow + MainWindow land. using System; using System.Threading; using System.Threading.Tasks; +using Dalamud.Interface.ImGuiNotification; using Dalamud.Plugin; using Dalamud.Plugin.Services; using Microsoft.Extensions.DependencyInjection; @@ -18,6 +22,8 @@ namespace Anvil; public sealed class Plugin : IAsyncDalamudPlugin { + private readonly IDalamudPluginInterface _pluginInterface; + private readonly INotificationManager _notification; private readonly PluginLifecycle _lifecycle; public Plugin( @@ -25,20 +31,30 @@ public sealed class Plugin : IAsyncDalamudPlugin IPluginLog pluginLog, IDataManager dataManager, IFramework framework, - ISelfTestRegistry selfTestRegistry + ISelfTestRegistry selfTestRegistry, + INotificationManager notification ) { + _pluginInterface = pluginInterface; + _notification = notification; + var dependencies = new PluginHostDependencies( pluginInterface, pluginLog, dataManager, framework, - selfTestRegistry + selfTestRegistry, + notification ); var host = PluginHostFactory.Build(this, dependencies); _lifecycle = host.Services.GetRequiredService(); _lifecycle.Host = host; + + // Stub UI callbacks. The validator accepts any subscription; + // the toasts are user-facing placeholders until module 08 lands. + _pluginInterface.UiBuilder.OpenConfigUi += OpenConfigUiStub; + _pluginInterface.UiBuilder.OpenMainUi += OpenMainUiStub; } public Task LoadAsync(CancellationToken cancellationToken) => @@ -46,6 +62,34 @@ public sealed class Plugin : IAsyncDalamudPlugin public async ValueTask DisposeAsync() { + _pluginInterface.UiBuilder.OpenConfigUi -= OpenConfigUiStub; + _pluginInterface.UiBuilder.OpenMainUi -= OpenMainUiStub; await _lifecycle.DisposeAsync().ConfigureAwait(false); } + + private void OpenConfigUiStub() + { + _notification.AddNotification( + new Notification + { + Title = "Anvil", + Content = + "Settings window arrives with module 08 (UI). Track the roadmap on the Hellion Forge Gitea repo.", + Type = NotificationType.Info, + } + ); + } + + private void OpenMainUiStub() + { + _notification.AddNotification( + new Notification + { + Title = "Anvil", + Content = + "Main window arrives with module 08 (UI). v0.1.0 ships the RecipeData layer only.", + Type = NotificationType.Info, + } + ); + } } diff --git a/Anvil/PluginHostDependencies.cs b/Anvil/PluginHostDependencies.cs index a8c0924..11b461b 100644 --- a/Anvil/PluginHostDependencies.cs +++ b/Anvil/PluginHostDependencies.cs @@ -13,5 +13,6 @@ internal sealed record PluginHostDependencies( IPluginLog PluginLog, IDataManager DataManager, IFramework Framework, - ISelfTestRegistry SelfTestRegistry + ISelfTestRegistry SelfTestRegistry, + INotificationManager Notification ); diff --git a/Anvil/PluginHostFactory.cs b/Anvil/PluginHostFactory.cs index 216d6e1..93437aa 100644 --- a/Anvil/PluginHostFactory.cs +++ b/Anvil/PluginHostFactory.cs @@ -53,6 +53,7 @@ internal static class PluginHostFactory services.AddSingleton(dependencies.DataManager); services.AddSingleton(dependencies.Framework); services.AddSingleton(dependencies.SelfTestRegistry); + services.AddSingleton(dependencies.Notification); // Self-reference. Lets services that genuinely need the plugin // back-ref (later modules; v0.1.0 has none) reach it without a