fix(ui): guard sidebar row at min drag and widen system-icon match
DrawRow asserted on a zero-width InvisibleButton when the window was dragged below the pop-out hit threshold — the row now drops out cleanly under 2px of remaining sidebar width, and the pop-out button only splits off when there's room for both hit areas. The trailing pop-out icon is hidden too when its strip is collapsed, so the row stays as a single selectable strip on extreme drags. System icon path: ResolveTabIcon used to look only at the first key in SelectedChannels, so a System tab whose first filter happened to be a generic ChatType slipped through to Comment. The resolve now walks every key and keeps the first non-Comment match, and a final case-insensitive name match flips the icon to fa-cog when the user's filter set falls completely outside the channel-type table.
This commit is contained in:
@@ -110,10 +110,22 @@ internal sealed class Sidebar
|
|||||||
|
|
||||||
var origin = ImGui.GetCursorScreenPos();
|
var origin = ImGui.GetCursorScreenPos();
|
||||||
var avail = ImGui.GetContentRegionAvail().X;
|
var avail = ImGui.GetContentRegionAvail().X;
|
||||||
var tabHitWidth = MathF.Max(0f, avail - PopOutHitWidth);
|
|
||||||
|
|
||||||
// Tab hit area sits left of the pop-out button so the two never
|
// Drop the row entirely when the sidebar is dragged below the width
|
||||||
// steal each other's clicks.
|
// of a single hit target. ImGui's InvisibleButton asserts on a
|
||||||
|
// zero-width size, which crashes the whole window at min-drag.
|
||||||
|
if (avail < 2f)
|
||||||
|
{
|
||||||
|
ImGui.PopID();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only split off a separate pop-out hit area when there's room for
|
||||||
|
// both buttons. Below that, the whole row stays as a single
|
||||||
|
// selectable strip without the pop-out affordance.
|
||||||
|
var hasPopOut = avail > PopOutHitWidth + 4f;
|
||||||
|
var tabHitWidth = hasPopOut ? avail - PopOutHitWidth : avail;
|
||||||
|
|
||||||
ImGui.InvisibleButton("row", new Vector2(tabHitWidth, RowHeight));
|
ImGui.InvisibleButton("row", new Vector2(tabHitWidth, RowHeight));
|
||||||
var rowHovered = ImGui.IsItemHovered();
|
var rowHovered = ImGui.IsItemHovered();
|
||||||
if (ImGui.IsItemClicked())
|
if (ImGui.IsItemClicked())
|
||||||
@@ -144,13 +156,17 @@ internal sealed class Sidebar
|
|||||||
ImGui.EndPopup();
|
ImGui.EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var popHovered = false;
|
||||||
|
if (hasPopOut)
|
||||||
|
{
|
||||||
ImGui.SameLine(0f, 0f);
|
ImGui.SameLine(0f, 0f);
|
||||||
ImGui.InvisibleButton("popout", new Vector2(PopOutHitWidth, RowHeight));
|
ImGui.InvisibleButton("popout", new Vector2(PopOutHitWidth, RowHeight));
|
||||||
var popHovered = ImGui.IsItemHovered();
|
popHovered = ImGui.IsItemHovered();
|
||||||
if (ImGui.IsItemClicked())
|
if (ImGui.IsItemClicked())
|
||||||
LogPopOutStub(tab);
|
LogPopOutStub(tab);
|
||||||
|
}
|
||||||
|
|
||||||
if (rowHovered || popHovered)
|
if (hasPopOut && (rowHovered || popHovered))
|
||||||
{
|
{
|
||||||
using (_fonts.FontAwesome.Push())
|
using (_fonts.FontAwesome.Push())
|
||||||
{
|
{
|
||||||
@@ -174,12 +190,23 @@ internal sealed class Sidebar
|
|||||||
if (tab.IsTempTab)
|
if (tab.IsTempTab)
|
||||||
return FontAwesomeIcon.Envelope;
|
return FontAwesomeIcon.Envelope;
|
||||||
|
|
||||||
// Channel-type fallback. The v1.5.6 TabIconGlyphResolver did the
|
// Channel-type fallback. Walk every selected key, not just the first,
|
||||||
// same thing — picks the first selected channel and maps its
|
// so a System tab that filters multiple system-flavoured ChatTypes
|
||||||
// ChatType to a category icon so tabs without a user-set icon
|
// still picks up fa-cog when one of the later keys carries the match.
|
||||||
// still look distinct.
|
// The Comment default only wins when every key falls into the
|
||||||
if (tab.SelectedChannels.Count > 0)
|
// generic-text bucket (Say / Yell / Shout etc.).
|
||||||
return ResolveByChannelType(tab.SelectedChannels.Keys.First());
|
foreach (var chatType in tab.SelectedChannels.Keys)
|
||||||
|
{
|
||||||
|
var glyph = ResolveByChannelType(chatType);
|
||||||
|
if (glyph != FontAwesomeIcon.Comment)
|
||||||
|
return glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last-resort name match for tabs that filter exotic ChatTypes the
|
||||||
|
// mapping above doesn't cover — keeps the System tab visually
|
||||||
|
// distinct even with a custom channel set.
|
||||||
|
if (tab.Name.Contains("system", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return FontAwesomeIcon.Cog;
|
||||||
|
|
||||||
return FontAwesomeIcon.Comment;
|
return FontAwesomeIcon.Comment;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user