Files
HellionChat/HellionChat/Ui/SettingsTabs/Chat.cs
T
JonKazama-Hellion 1d3b429f1b
Security / scan (push) Successful in 23s
Build / Build (Release) (push) Successful in 31s
Forge Announce / Post changelog to Hellion Forge (push) Successful in 6s
Release / Build and attach release ZIP (push) Successful in 41s
style(format): apply csharpier and markdownlint reflow
2026-05-23 09:07:01 +02:00

424 lines
16 KiB
C#

using System.Numerics;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using HellionChat.Resources;
using HellionChat.Util;
namespace HellionChat.Ui.SettingsTabs;
// Six sections: Messages, Input & preview, Auto-tell tabs, Emotes, Links & tooltips, Novice network.
internal sealed class Chat : ISettingsTab
{
private Plugin Plugin { get; }
private Configuration Mutable { get; }
public string Name => HellionStrings.Settings_Tab_Chat + "###tabs-chat";
private SearchSelector.SelectorPopupOptions WordPopupOptions;
// Tracks which EmoteCache state WordPopupOptions was built for so we
// don't refill every frame when FilteredSheet is empty.
private EmoteCache.LoadingState? WordPopupOptionsBuiltFor;
internal Chat(Plugin plugin, Configuration mutable)
{
Plugin = plugin;
Mutable = mutable;
WordPopupOptions = RefillSheet();
WordPopupOptionsBuiltFor = EmoteCache.State;
}
private SearchSelector.SelectorPopupOptions RefillSheet() =>
new SearchSelector.SelectorPopupOptions
{
FilteredSheet = EmoteCache
.SortedCodeArray.Where(w => !Mutable.BlockedEmotes.Contains(w))
.ToArray(),
};
public void Draw(bool sectionJustEntered)
{
DrawMessagesSection(sectionJustEntered);
ImGui.Spacing();
DrawInputPreviewSection(sectionJustEntered);
ImGui.Spacing();
DrawAutoTellTabsSection(sectionJustEntered);
ImGui.Spacing();
DrawEmotesSection(sectionJustEntered);
ImGui.Spacing();
DrawLinksTooltipsSection(sectionJustEntered);
ImGui.Spacing();
DrawNoviceNetworkSection(sectionJustEntered);
}
private void DrawMessagesSection(bool sectionJustEntered)
{
if (sectionJustEntered)
ImGui.SetNextItemOpen(false);
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_Messages);
if (!tree.Success)
return;
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
{
// Checkboxes first.
ImGui.Checkbox(
Language.Options_CollapseDuplicateMessages_Name,
ref Mutable.CollapseDuplicateMessages
);
ImGuiUtil.HelpMarker(Language.Options_CollapseDuplicateMessages_Description);
// Conditional child: only visible when parent is on (R4).
if (Mutable.CollapseDuplicateMessages)
{
ImGui.Checkbox(
Language.Options_CollapseDuplicateMsgUniqueLink_Name,
ref Mutable.CollapseKeepUniqueLinks
);
ImGuiUtil.HelpMarker(Language.Options_CollapseDuplicateMsgUniqueLink_Description);
}
ImGui.Checkbox(
HellionStrings.Settings_Chat_NotifyFailedTell_Name,
ref Mutable.NotifyFailedTell
);
ImGuiUtil.HelpMarker(HellionStrings.Settings_Chat_NotifyFailedTell_Description);
ImGui.Checkbox(
HellionStrings.Settings_Chat_NotifyPluginDisclosure_Name,
ref Mutable.NotifyPluginDisclosure
);
ImGuiUtil.HelpMarker(HellionStrings.Settings_Chat_NotifyPluginDisclosure_Description);
// Dropdowns after checkboxes (R3).
// UI-7: name display options.
using (
var combo = ImGuiUtil.BeginComboVertical(
HellionStrings.Settings_Chat_WorldSuffix_Name,
Mutable.WorldSuffixMode.Name()
)
)
{
if (combo.Success)
{
foreach (var mode in Enum.GetValues<WorldSuffixMode>())
{
if (ImGui.Selectable(mode.Name(), Mutable.WorldSuffixMode == mode))
Mutable.WorldSuffixMode = mode;
}
}
}
ImGuiUtil.HelpMarker(HellionStrings.Settings_Chat_WorldSuffix_Description);
using (
var combo = ImGuiUtil.BeginComboVertical(
HellionStrings.Settings_Chat_NameForm_Name,
Mutable.NameFormMode.Name()
)
)
{
if (combo.Success)
{
foreach (var mode in Enum.GetValues<NameFormMode>())
{
if (ImGui.Selectable(mode.Name(), Mutable.NameFormMode == mode))
Mutable.NameFormMode = mode;
}
}
}
ImGuiUtil.HelpMarker(HellionStrings.Settings_Chat_NameForm_Description);
}
}
private void DrawInputPreviewSection(bool sectionJustEntered)
{
if (sectionJustEntered)
ImGui.SetNextItemOpen(false);
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_InputPreview);
if (!tree.Success)
return;
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
{
// Checkboxes first.
ImGui.Checkbox(
HellionStrings.Settings_Chat_SymbolPicker_Enable_Name,
ref Mutable.SymbolPickerEnabled
);
ImGuiUtil.HelpMarker(HellionStrings.Settings_Chat_SymbolPicker_Enable_Description);
ImGui.Checkbox(Language.Options_PreviewOnlyIf_Name, ref Mutable.OnlyPreviewIf);
ImGuiUtil.HelpMarker(Language.Options_PreviewOnlyIf_Description);
// Dropdown after checkboxes (R3).
using (
var combo = ImGuiUtil.BeginComboVertical(
Language.Options_Preview_Name,
Mutable.PreviewPosition.Name()
)
)
{
if (combo)
{
foreach (var position in Enum.GetValues<PreviewPosition>())
{
if (ImGui.Selectable(position.Name(), Mutable.PreviewPosition == position))
Mutable.PreviewPosition = position;
}
}
}
ImGuiUtil.HelpMarker(Language.Options_Preview_Description);
// Number input last (R3).
if (
ImGuiUtil.InputIntVertical(
Language.Options_PreviewMinimum_Name,
Language.Options_PreviewMinimum_Description,
ref Mutable.PreviewMinimum
)
)
Mutable.PreviewMinimum = Math.Clamp(Mutable.PreviewMinimum, 1, 250);
}
}
private void DrawAutoTellTabsSection(bool sectionJustEntered)
{
if (sectionJustEntered)
ImGui.SetNextItemOpen(false);
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_AutoTellTabs);
if (!tree.Success)
return;
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
{
// Checkboxes first (R3).
ImGui.Checkbox(
HellionStrings.ChatLog_AutoTellTabs_Enable_Name,
ref Mutable.EnableAutoTellTabs
);
ImGuiUtil.HelpMarker(HellionStrings.ChatLog_AutoTellTabs_Enable_Description);
ImGui.Checkbox(
HellionStrings.ChatLog_AutoTellTabs_Compact_Name,
ref Mutable.AutoTellTabsCompactDisplay
);
ImGuiUtil.HelpMarker(HellionStrings.ChatLog_AutoTellTabs_Compact_Description);
ImGui.Checkbox(
HellionStrings.ChatLog_AutoTellTabs_OpenAsPopout_Name,
ref Mutable.AutoTellTabsOpenAsPopout
);
ImGuiUtil.HelpMarker(HellionStrings.ChatLog_AutoTellTabs_OpenAsPopout_Description);
ImGui.Checkbox(
HellionStrings.ChatLog_AutoTellTabs_GreetedToggle_Name,
ref Mutable.AutoTellTabsShowGreetedToggle
);
ImGuiUtil.HelpMarker(HellionStrings.ChatLog_AutoTellTabs_GreetedToggle_Description);
// Sliders after checkboxes (R3).
ImGui.SetNextItemWidth(200f * ImGuiHelpers.GlobalScale);
var limit = Mutable.AutoTellTabsLimit;
if (ImGui.SliderInt(HellionStrings.ChatLog_AutoTellTabs_Limit_Name, ref limit, 1, 50))
Mutable.AutoTellTabsLimit = limit;
ImGuiUtil.HelpMarker(HellionStrings.ChatLog_AutoTellTabs_Limit_Description);
ImGui.Spacing();
ImGuiUtil.HelpText(HellionStrings.ChatLog_AutoTellTabs_PreloadHint);
ImGui.Spacing();
ImGuiUtil.WarningText(HellionStrings.ChatLog_AutoTellTabs_ConflictHint);
ImGui.Spacing();
ImGui.Separator();
ImGui.Spacing();
var preload = Mutable.AutoTellTabsHistoryPreload;
ImGui.SetNextItemWidth(200f * ImGuiHelpers.GlobalScale);
if (
ImGui.SliderInt(
HellionStrings.Privacy_AutoTellTabs_Preload_Name,
ref preload,
0,
100
)
)
Mutable.AutoTellTabsHistoryPreload = preload;
ImGuiUtil.HelpMarker(HellionStrings.Privacy_AutoTellTabs_Preload_Description);
ImGui.Spacing();
ImGuiUtil.HelpText(HellionStrings.Privacy_AutoTellTabs_Preload_Hint);
}
}
private void DrawEmotesSection(bool sectionJustEntered)
{
if (sectionJustEntered)
ImGui.SetNextItemOpen(false);
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_Emotes);
if (!tree.Success)
return;
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
{
// Checkbox first (R3).
ImGui.Checkbox(Language.Options_ShowEmotes_Name, ref Mutable.ShowEmotes);
ImGuiUtil.HelpMarker(Language.Options_ShowEmotes_Desc);
ImGui.Spacing();
ImGui.TextUnformatted(Language.Options_Emote_BlockedEmotes);
ImGui.Spacing();
if (
EmoteCache.State is EmoteCache.LoadingState.Done
&& WordPopupOptions.FilteredSheet.Length == 0
&& WordPopupOptionsBuiltFor != EmoteCache.LoadingState.Done
)
{
WordPopupOptions = RefillSheet();
WordPopupOptionsBuiltFor = EmoteCache.LoadingState.Done;
}
// Button to add blocked emotes (R3 — button before table).
var buttonWidth = ImGui.GetContentRegionAvail().X / 3;
using (Plugin.FontManager.FontAwesome.Push())
ImGui.Button(FontAwesomeIcon.Plus.ToIconString(), new Vector2(buttonWidth, 0));
// OpenPopup on click because SelectorPopup uses ContextPopupItem
// which only triggers on right-click by default.
if (ImGui.IsItemClicked())
ImGui.OpenPopup("WordAddPopup");
if (SearchSelector.SelectorPopup("WordAddPopup", out var newWord, WordPopupOptions))
Mutable.BlockedEmotes.Add(newWord);
using (
var table = ImRaii.Table(
"##BlockedWords",
2,
ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersInner
)
)
{
if (table)
{
ImGui.TableSetupColumn(Language.Options_Emote_EmoteTable);
ImGui.TableSetupColumn("##Del", ImGuiTableColumnFlags.WidthStretch, 0.07f);
ImGui.TableHeadersRow();
foreach (var word in Mutable.BlockedEmotes.ToArray())
{
ImGui.TableNextColumn();
ImGui.TextUnformatted(word);
ImGui.TableNextColumn();
if (
ImGuiUtil.Button(
$"##{word}Del",
FontAwesomeIcon.Trash,
!ImGui.GetIO().KeyCtrl
)
)
Mutable.BlockedEmotes.Remove(word);
}
}
}
ImGui.Spacing();
ImGui.Separator();
ImGui.Spacing();
ImGui.TextUnformatted(Language.Options_Emote_EmoteStats);
ImGui.Spacing();
if (EmoteCache.State is EmoteCache.LoadingState.Done)
ImGui.TextColored(ImGuiColors.HealerGreen, Language.Options_Emote_Ready);
else
ImGui.TextColored(ImGuiColors.DPSRed, Language.Options_Emote_NotReady);
ImGui.TextUnformatted(
$"{Language.Options_Emote_Loaded} {EmoteCache.SortedCodeArray.Length}"
);
// 5-column loaded-emotes display table.
using (
var emoteTable = ImRaii.Table(
"##LoadedEmotes",
5,
ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersInner
)
)
{
if (emoteTable)
{
ImGui.TableSetupColumn("##word1");
ImGui.TableSetupColumn("##word2");
ImGui.TableSetupColumn("##word3");
ImGui.TableSetupColumn("##word4");
ImGui.TableSetupColumn("##word5");
foreach (var word in EmoteCache.SortedCodeArray)
{
ImGui.TableNextColumn();
ImGui.TextUnformatted(word);
}
}
}
}
}
private void DrawLinksTooltipsSection(bool sectionJustEntered)
{
if (sectionJustEntered)
ImGui.SetNextItemOpen(false);
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_LinksTooltips);
if (!tree.Success)
return;
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
{
ImGui.Checkbox(
Language.Options_NativeItemTooltips_Name,
ref Mutable.NativeItemTooltips
);
ImGuiUtil.HelpMarker(
string.Format(Language.Options_NativeItemTooltips_Description, Plugin.PluginName)
);
// Conditional slider: only shown when native tooltips are enabled (R4).
if (Mutable.NativeItemTooltips)
{
ImGuiUtil.DragFloatVertical(
Language.Options_TooltipOffset_Name,
Language.Options_TooltipOffset_Desc,
ref Mutable.TooltipOffset,
1,
0f,
400f,
$"{Mutable.TooltipOffset:N0}px",
ImGuiSliderFlags.AlwaysClamp
);
}
}
}
private void DrawNoviceNetworkSection(bool sectionJustEntered)
{
if (sectionJustEntered)
ImGui.SetNextItemOpen(false);
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_NoviceNetwork);
if (!tree.Success)
return;
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
{
ImGui.Checkbox(Language.Options_ShowNoviceNetwork_Name, ref Mutable.ShowNoviceNetwork);
ImGuiUtil.HelpMarker(Language.Options_ShowNoviceNetwork_Description);
}
}
}