feat(sidebar): per-tell hashed icon variety + unread-dot indicator
This commit is contained in:
@@ -61,4 +61,47 @@ internal static class AutoTellTabTint
|
|||||||
var hash = (uint)(key.GetHashCode() & 0x7FFFFFFF);
|
var hash = (uint)(key.GetHashCode() & 0x7FFFFFFF);
|
||||||
return Palette[(int)(hash % Palette.Count)];
|
return Palette[(int)(hash % Palette.Count)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tell-spezifischer Icon-Pool. 7 visuell distinkte FontAwesome-Glyphen
|
||||||
|
/// die im Tell-Kontext sinnvoll wirken (envelope = Tell-Default, star/
|
||||||
|
/// heart/bell = personalisiert, bookmark/flag/fire = markiert/wichtig).
|
||||||
|
/// Bewusst kein cog/comment/users — die wären für System-/Group-Tabs
|
||||||
|
/// reserviert und würden im Tell-Bereich verwirrend wirken.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly IReadOnlyList<string> IconPool = new[]
|
||||||
|
{
|
||||||
|
"envelope",
|
||||||
|
"star",
|
||||||
|
"heart",
|
||||||
|
"bell",
|
||||||
|
"bookmark",
|
||||||
|
"flag",
|
||||||
|
"fire",
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fallback-Icon bei ungültigem Input. "envelope" passt semantisch zum
|
||||||
|
/// Tell-Kontext besser als das alte hardcoded "clock".
|
||||||
|
/// </summary>
|
||||||
|
public const string IconFallback = "envelope";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Liefert ein konsistentes Icon-Glyph für einen Tell-Partner.
|
||||||
|
/// Nutzt einen anderen Hash-Bias als For() (Color), damit Icon und
|
||||||
|
/// Color unabhängig variieren — gibt 7 × 12 = 84 distinct Combinations.
|
||||||
|
/// </summary>
|
||||||
|
public static string IconFor(string name, uint world)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name) || world == 0)
|
||||||
|
return IconFallback;
|
||||||
|
|
||||||
|
// Anderer Hash-Bias als For() (verschiedene Modulo-Basis): wir
|
||||||
|
// nutzen "world@name" statt "name@world" damit Icon und Color
|
||||||
|
// nicht synchron variieren. Ohne Bias-Trennung würden alle Tells
|
||||||
|
// mit derselben Color auch dasselbe Icon haben.
|
||||||
|
var key = $"{world}@{name}";
|
||||||
|
var hash = (uint)(key.GetHashCode() & 0x7FFFFFFF);
|
||||||
|
return IconPool[(int)(hash % IconPool.Count)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1591,6 +1591,26 @@ public sealed class ChatLogWindow : Window
|
|||||||
1.5f); // leichter Rounding
|
1.5f); // leichter Rounding
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// v1.2.0 — Unread-Dot oben rechts am Icon. Sichtbar ohne Hover, damit
|
||||||
|
// User Tabs mit ungelesenen Messages sofort erkennt. Aktive Tabs haben
|
||||||
|
// per Konvention Unread = 0 (LastTab-Branch in ChatLogWindow), daher
|
||||||
|
// kollidiert der Dot nicht mit der Active-Pill.
|
||||||
|
if (!isCurrentTab && tab.UnreadMode != UnreadMode.None && tab.Unread > 0)
|
||||||
|
{
|
||||||
|
var min = ImGui.GetItemRectMin();
|
||||||
|
var max = ImGui.GetItemRectMax();
|
||||||
|
const float dotRadius = 4f;
|
||||||
|
const float dotPadding = 3f;
|
||||||
|
var dotCenter = new Vector2(
|
||||||
|
max.X - dotRadius - dotPadding,
|
||||||
|
min.Y + dotRadius + dotPadding);
|
||||||
|
ImGui.GetWindowDrawList().AddCircleFilled(
|
||||||
|
dotCenter,
|
||||||
|
dotRadius,
|
||||||
|
ColourUtil.RgbaToAbgr(theme.Colors.StatusDanger),
|
||||||
|
12);
|
||||||
|
}
|
||||||
|
|
||||||
// Tooltip mit Tab-Name + Unread-Counter beim Hover.
|
// Tooltip mit Tab-Name + Unread-Counter beim Hover.
|
||||||
if (ImGui.IsItemHovered())
|
if (ImGui.IsItemHovered())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,17 +58,18 @@ internal static class TabIconGlyphResolver
|
|||||||
/// a) bekannter Glyph → diesen Glyph
|
/// a) bekannter Glyph → diesen Glyph
|
||||||
/// b) unbekannter Glyph → harter Fallback "hashtag" (User hat
|
/// b) unbekannter Glyph → harter Fallback "hashtag" (User hat
|
||||||
/// bewusst etwas gesetzt, also überstimmt das die Defaults)
|
/// bewusst etwas gesetzt, also überstimmt das die Defaults)
|
||||||
/// 2. Auto-Tell-Tab → "clock"
|
/// 2. Auto-Tell-Tab → <paramref name="autoTellGlyph"/> falls
|
||||||
|
/// übergeben, sonst "clock".
|
||||||
/// 3. Tab-Name-Default (<see cref="NameDefaults"/>-Lookup)
|
/// 3. Tab-Name-Default (<see cref="NameDefaults"/>-Lookup)
|
||||||
/// 4. Fallback "hashtag"
|
/// 4. Fallback "hashtag"
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ResolveGlyphName(Tab tab)
|
public static string ResolveGlyphName(Tab tab, string? autoTellGlyph = null)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(tab.Icon))
|
if (!string.IsNullOrWhiteSpace(tab.Icon))
|
||||||
return KnownGlyphs.Contains(tab.Icon) ? tab.Icon : "hashtag";
|
return KnownGlyphs.Contains(tab.Icon) ? tab.Icon : "hashtag";
|
||||||
|
|
||||||
if (tab.IsTempTab)
|
if (tab.IsTempTab)
|
||||||
return "clock";
|
return autoTellGlyph ?? "clock";
|
||||||
|
|
||||||
if (tab.Name is { } name && NameDefaults.TryGetValue(name, out var byName))
|
if (tab.Name is { } name && NameDefaults.TryGetValue(name, out var byName))
|
||||||
return byName;
|
return byName;
|
||||||
|
|||||||
@@ -53,7 +53,18 @@ internal static class TabIconMapping
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static FontAwesomeIcon Resolve(Tab tab)
|
public static FontAwesomeIcon Resolve(Tab tab)
|
||||||
{
|
{
|
||||||
var glyph = TabIconGlyphResolver.ResolveGlyphName(tab);
|
// v1.2.0 — Auto-Tell-Tabs bekommen ein per-Partner gehashtes
|
||||||
|
// Icon aus dem Tell-Pool. Damit unterscheiden sich parallele
|
||||||
|
// Tells nicht nur über die Color (For), sondern auch über die
|
||||||
|
// Glyph-Form. Berechnung bleibt hier (Dalamud-bound), weil
|
||||||
|
// TellTarget Dalamud-Imports hat.
|
||||||
|
string? autoTellGlyph = null;
|
||||||
|
if (tab.IsTempTab && tab.TellTarget != null && tab.TellTarget.IsSet())
|
||||||
|
{
|
||||||
|
autoTellGlyph = AutoTellTabTint.IconFor(tab.TellTarget.Name, tab.TellTarget.World);
|
||||||
|
}
|
||||||
|
|
||||||
|
var glyph = TabIconGlyphResolver.ResolveGlyphName(tab, autoTellGlyph);
|
||||||
return GlyphLookup.TryGetValue(glyph, out var icon)
|
return GlyphLookup.TryGetValue(glyph, out var icon)
|
||||||
? icon
|
? icon
|
||||||
: FontAwesomeIcon.Hashtag;
|
: FontAwesomeIcon.Hashtag;
|
||||||
|
|||||||
Reference in New Issue
Block a user