feat(message-list): wire ChunkRenderer ctor + AttachPayloadHandler setter
H integrates the chunk-render pipeline into MessageList: - Extends ctor to 4 params (themes, resolver, fonts, chunkRenderer); TokenResolver preserved as load-bearing dep - Adds private PayloadHandler? _handler field + internal AttachPayloadHandler(PayloadHandler) setter - Switches DrawCompactRow/DrawCardRow render-path to _chunkRenderer.DrawChunks(message.Content, wrap, handler, 0f) instead of plain TextUnformatted Setter-injection for PayloadHandler is the §6.2 cycle-resolution (PayloadHandler → MainWindow → MessageList → PayloadHandler ctor-cycle broken by post-construction wiring). G's HostedService.StartAsync will call AttachPayloadHandler after both singletons resolve. Also extends MessageList DI-reg in PluginHostFactory.cs with the ChunkRenderer arg (4th GetRequiredService).
This commit is contained in:
@@ -132,7 +132,8 @@ internal static class PluginHostFactory
|
||||
services.AddSingleton(sp => new Ui.Components.MessageList(
|
||||
sp.GetRequiredService<ThemeRegistry>(),
|
||||
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>(),
|
||||
sp.GetRequiredService<FontManager>()
|
||||
sp.GetRequiredService<FontManager>(),
|
||||
sp.GetRequiredService<Ui.Components.ChunkRenderer>()
|
||||
));
|
||||
services.AddSingleton(_ => new Ui.Components.SymbolPicker());
|
||||
services.AddSingleton(sp => new Ui.Components.InputBar(
|
||||
|
||||
@@ -12,8 +12,7 @@ namespace HellionChat.Ui.Components;
|
||||
// rows have a constant line height; card mode falls back to a linear
|
||||
// render with a per-message height cache and an IsItemVisible skip path
|
||||
// so off-screen rows place a Dummy of the cached height rather than
|
||||
// running the full render again. Text-only rendering for now — full
|
||||
// chunk/payload rendering re-attaches in a later cycle.
|
||||
// running the full render again.
|
||||
internal sealed class MessageList
|
||||
{
|
||||
private const float CompactRowHeight = 18f;
|
||||
@@ -21,12 +20,28 @@ internal sealed class MessageList
|
||||
private readonly ThemeRegistry _themes;
|
||||
private readonly TokenResolver _resolver;
|
||||
private readonly FontManager _fonts;
|
||||
private readonly ChunkRenderer _chunkRenderer;
|
||||
|
||||
public MessageList(ThemeRegistry themes, TokenResolver resolver, FontManager fonts)
|
||||
private PayloadHandler? _handler;
|
||||
|
||||
// §6.2: setter-injection breaks the PayloadHandler → MainWindow → MessageList → PayloadHandler 3-cycle.
|
||||
// Wired by PayloadHandlerInitHostedService.StartAsync after both singletons exist.
|
||||
internal void AttachPayloadHandler(PayloadHandler handler)
|
||||
{
|
||||
_handler = handler;
|
||||
}
|
||||
|
||||
public MessageList(
|
||||
ThemeRegistry themes,
|
||||
TokenResolver resolver,
|
||||
FontManager fonts,
|
||||
ChunkRenderer chunkRenderer
|
||||
)
|
||||
{
|
||||
_themes = themes;
|
||||
_resolver = resolver;
|
||||
_fonts = fonts;
|
||||
_chunkRenderer = chunkRenderer;
|
||||
}
|
||||
|
||||
public void Draw(Tab tab)
|
||||
@@ -40,10 +55,6 @@ internal sealed class MessageList
|
||||
// No own ImRaii.Child here — MainWindow already wraps the message
|
||||
// area in one. Nesting would give the window two stacked scrolls
|
||||
// and a runaway content-height computation.
|
||||
var theme = _themes.Active;
|
||||
var textAbgr = ColourUtil.RgbaToAbgr(theme.Colors.TextPrimary);
|
||||
var mutedAbgr = ColourUtil.RgbaToAbgr(theme.Colors.TextMuted);
|
||||
|
||||
using var messages = tab.Messages.GetReadOnly(3);
|
||||
var compact = Plugin.Config.UseCompactDensity;
|
||||
|
||||
@@ -53,15 +64,15 @@ internal sealed class MessageList
|
||||
var pinnedToBottom = ImGui.GetScrollY() >= ImGui.GetScrollMaxY() - 1f;
|
||||
|
||||
if (compact)
|
||||
DrawCompact(messages, textAbgr, mutedAbgr);
|
||||
DrawCompact(messages);
|
||||
else
|
||||
DrawCard(tab, messages, textAbgr, mutedAbgr);
|
||||
DrawCard(tab, messages);
|
||||
|
||||
if (pinnedToBottom)
|
||||
ImGui.SetScrollHereY(1f);
|
||||
}
|
||||
|
||||
private void DrawCompact(IReadOnlyList<Message> messages, uint textAbgr, uint mutedAbgr)
|
||||
private void DrawCompact(IReadOnlyList<Message> messages)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
@@ -72,7 +83,7 @@ internal sealed class MessageList
|
||||
while (clipper.Step())
|
||||
{
|
||||
for (var i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
|
||||
DrawCompactRow(messages[i], textAbgr, mutedAbgr);
|
||||
DrawCompactRow(messages[i]);
|
||||
}
|
||||
clipper.End();
|
||||
}
|
||||
@@ -83,18 +94,18 @@ internal sealed class MessageList
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCompactRow(Message message, uint textAbgr, uint mutedAbgr)
|
||||
private void DrawCompactRow(Message message)
|
||||
{
|
||||
var timestamp = FormatTimestamp(message.Date);
|
||||
var sender = message.SenderSource.TextValue;
|
||||
var content = message.ContentSource.TextValue;
|
||||
var line = string.IsNullOrEmpty(sender)
|
||||
? $"{timestamp} {content}"
|
||||
: $"{timestamp} {sender}: {content}";
|
||||
ImGui.TextUnformatted(line);
|
||||
ImGui.TextUnformatted(
|
||||
string.IsNullOrEmpty(sender) ? timestamp : $"{timestamp} {sender}: "
|
||||
);
|
||||
ImGui.SameLine();
|
||||
_chunkRenderer.DrawChunks(message.Content, wrap: true, handler: _handler, lineWidth: 0f);
|
||||
}
|
||||
|
||||
private void DrawCard(Tab tab, IReadOnlyList<Message> messages, uint textAbgr, uint mutedAbgr)
|
||||
private void DrawCard(Tab tab, IReadOnlyList<Message> messages)
|
||||
{
|
||||
var tabId = tab.Identifier;
|
||||
for (var i = 0; i < messages.Count; i++)
|
||||
@@ -127,11 +138,8 @@ internal sealed class MessageList
|
||||
{
|
||||
var timestamp = FormatTimestamp(message.Date);
|
||||
var sender = message.SenderSource.TextValue;
|
||||
var content = message.ContentSource.TextValue;
|
||||
ImGui.TextUnformatted(string.IsNullOrEmpty(sender) ? timestamp : $"{timestamp} {sender}");
|
||||
ImGui.PushTextWrapPos(0f);
|
||||
ImGui.TextUnformatted(content);
|
||||
ImGui.PopTextWrapPos();
|
||||
_chunkRenderer.DrawChunks(message.Content, wrap: true, handler: _handler, lineWidth: 0f);
|
||||
}
|
||||
|
||||
private static string FormatTimestamp(DateTimeOffset date)
|
||||
|
||||
Reference in New Issue
Block a user