feat(input): expose state API, wire settings cog, add test hooks

This commit is contained in:
2026-05-26 13:31:00 +02:00
parent 11eb7b9e90
commit e01de0403a
3 changed files with 31 additions and 6 deletions
+2
View File
@@ -111,6 +111,7 @@ public sealed class Plugin : IAsyncDalamudPlugin
internal IpcManager Ipc { get; private set; } = null!;
internal ExtraChat ExtraChat { get; private set; } = null!;
internal TypingIpc TypingIpc { get; private set; } = null!;
internal Ui.Components.InputBar InputBar { get; private set; } = null!;
internal FontManager FontManager { get; private set; } = null!;
internal Themes.ThemeRegistry ThemeRegistry { get; private set; } = null!;
internal Integrations.HonorificService HonorificService { get; private set; } = null!;
@@ -292,6 +293,7 @@ public sealed class Plugin : IAsyncDalamudPlugin
MessageManager = _host.Services.GetRequiredService<MessageManager>();
AutoTellTabsService = _host.Services.GetRequiredService<AutoTellTabsService>();
InputBar = _host.Services.GetRequiredService<Ui.Components.InputBar>();
MainWindow = _host.Services.GetRequiredService<Ui.Windows.MainWindow>();
SettingsWindow = _host.Services.GetRequiredService<SettingsWindow>();
DbViewer = _host.Services.GetRequiredService<DbViewer>();
+2 -1
View File
@@ -139,7 +139,8 @@ internal static class PluginHostFactory
sp.GetRequiredService<FontManager>(),
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>(),
sp.GetRequiredService<ILogger<Ui.Components.InputBar>>()
sp.GetRequiredService<ILogger<Ui.Components.InputBar>>(),
() => sp.GetRequiredService<Plugin>().SettingsWindow.Toggle()
));
services.AddSingleton(sp => new Ui.Components.StatusBar(
sp.GetRequiredService<ThemeRegistry>(),
+27 -5
View File
@@ -30,15 +30,19 @@ internal sealed class InputBar
private readonly ThemeRegistry _themes;
private readonly TokenResolver _resolver;
private readonly ILogger<InputBar> _logger;
private readonly Action _onOpenSettings;
private string _pendingMessage = string.Empty;
private bool _isFocused;
private bool? _isFocusedOverride; // Test-only; null = honour per-frame Draw() value.
public InputBar(
SymbolPicker symbolPicker,
FontManager fonts,
ThemeRegistry themes,
TokenResolver resolver,
ILogger<InputBar> logger
ILogger<InputBar> logger,
Action onOpenSettings
)
{
_symbolPicker = symbolPicker;
@@ -46,9 +50,22 @@ internal sealed class InputBar
_themes = themes;
_resolver = resolver;
_logger = logger;
_onOpenSettings = onOpenSettings;
}
public string PendingMessage => _pendingMessage;
public int PendingLength => _pendingMessage.Length;
// IsFocused respects the test override first so a SelfTest can pin focus
// state without racing against per-frame ImGui.IsItemFocused() in Draw().
// Note: when MainWindow is closed, DrawInputField never runs, so
// _isFocused keeps the last value written by the previous draw pass.
// The consumer that actually pushes this state across the IPC boundary
// (TypingIpc.BuildState, see F3 Step 2) gates on Plugin.MainWindow.IsOpen
// itself, so the stale backing-field never leaks to subscribers. Mirroring
// the gate here would require an extra Plugin-backref in InputBar that the
// rest of the component doesn't need.
public bool IsFocused => _isFocusedOverride ?? _isFocused;
public void ClearBuffer() => _pendingMessage = string.Empty;
@@ -163,6 +180,7 @@ internal sealed class InputBar
{
TrySend(activeTab);
}
_isFocused = ImGui.IsItemFocused();
}
private void TrySend(Tab? activeTab)
@@ -212,10 +230,7 @@ internal sealed class InputBar
ImGui.SameLine();
if (ImGui.Button(FontAwesomeIcon.Cog.ToIconString()))
{
// Settings toggle wires up when the plugin window registers
// its open handler; no-op until then so the button is
// visible without dragging a half-finished settings call
// into the component.
_onOpenSettings();
}
if (ImGui.IsItemHovered())
{
@@ -235,4 +250,11 @@ internal sealed class InputBar
}
}
}
// Test-only hook; do not call from production code.
internal void TestSetPendingMessageForSelfTest(string value) => _pendingMessage = value;
// Test-only hook; do not call from production code. Pass null to release the
// override and let Draw()'s ImGui.IsItemFocused() result take over again.
internal void TestSetFocusedForSelfTest(bool? value) => _isFocusedOverride = value;
}