Merge pull request #90 from deansheather/dean/autohide-improvements

feat: autohide improvements
This commit is contained in:
Infi
2024-07-21 14:37:27 +02:00
committed by GitHub
11 changed files with 296 additions and 112 deletions
+20 -20
View File
@@ -3,6 +3,7 @@ using ChatTwo.Code;
using ChatTwo.GameFunctions.Types; using ChatTwo.GameFunctions.Types;
using ChatTwo.Resources; using ChatTwo.Resources;
using ChatTwo.Ui; using ChatTwo.Ui;
using ChatTwo.Util;
using Dalamud.Configuration; using Dalamud.Configuration;
using Dalamud.Game.ClientState.Keys; using Dalamud.Game.ClientState.Keys;
using ImGuiNET; using ImGuiNET;
@@ -43,6 +44,10 @@ internal class Configuration : IPluginConfiguration
public bool HideInBattle; public bool HideInBattle;
public bool HideWhenInactive; public bool HideWhenInactive;
public int InactivityHideTimeout = 10; public int InactivityHideTimeout = 10;
public bool InactivityHideActiveDuringBattle = true;
public Dictionary<ChatType, ChatSource> InactivityHideChannels = TabsUtil.AllChannels();
public bool InactivityHideExtraChatAll = true;
public HashSet<Guid> InactivityHideExtraChatChannels = [];
public bool ShowHideButton = true; public bool ShowHideButton = true;
public bool NativeItemTooltips = true; public bool NativeItemTooltips = true;
public bool PrettierTimestamps = true; public bool PrettierTimestamps = true;
@@ -106,6 +111,10 @@ internal class Configuration : IPluginConfiguration
HideInBattle = other.HideInBattle; HideInBattle = other.HideInBattle;
HideWhenInactive = other.HideWhenInactive; HideWhenInactive = other.HideWhenInactive;
InactivityHideTimeout = other.InactivityHideTimeout; InactivityHideTimeout = other.InactivityHideTimeout;
InactivityHideActiveDuringBattle = other.InactivityHideActiveDuringBattle;
InactivityHideChannels = other.InactivityHideChannels.ToDictionary(entry => entry.Key, entry => entry.Value);
InactivityHideExtraChatAll = other.InactivityHideExtraChatAll;
InactivityHideExtraChatChannels = other.InactivityHideExtraChatChannels.ToHashSet();
ShowHideButton = other.ShowHideButton; ShowHideButton = other.ShowHideButton;
NativeItemTooltips = other.NativeItemTooltips; NativeItemTooltips = other.NativeItemTooltips;
PrettierTimestamps = other.PrettierTimestamps; PrettierTimestamps = other.PrettierTimestamps;
@@ -188,6 +197,7 @@ internal class Tab
public HashSet<Guid> ExtraChatChannels = []; public HashSet<Guid> ExtraChatChannels = [];
public UnreadMode UnreadMode = UnreadMode.Unseen; public UnreadMode UnreadMode = UnreadMode.Unseen;
public bool UnhideOnActivity;
public bool DisplayTimestamp = true; public bool DisplayTimestamp = true;
public InputChannel? Channel; public InputChannel? Channel;
public bool PopOut; public bool PopOut;
@@ -199,7 +209,7 @@ internal class Tab
public uint Unread; public uint Unread;
[NonSerialized] [NonSerialized]
public long LastMessageTime; public long LastActivity;
[NonSerialized] [NonSerialized]
public MessageList Messages = new(); public MessageList Messages = new();
@@ -210,31 +220,20 @@ internal class Tab
[NonSerialized] [NonSerialized]
public Guid Identifier = Guid.NewGuid(); public Guid Identifier = Guid.NewGuid();
internal bool Matches(Message message) internal bool Matches(Message message) => message.Matches(ChatCodes, ExtraChatAll, ExtraChatChannels);
{
if (message.ExtraChatChannel != Guid.Empty)
return ExtraChatAll || ExtraChatChannels.Contains(message.ExtraChatChannel);
return message.Code.Type.IsGm()
|| ChatCodes.TryGetValue(message.Code.Type, out var sources)
&& (message.Code.Source is 0 or (ChatSource) 1
|| sources.HasFlag(message.Code.Source));
}
internal void AddMessage(Message message, bool unread = true) internal void AddMessage(Message message, bool unread = true)
{ {
Messages.AddPrune(message, MessageManager.MessageDisplayLimit); Messages.AddPrune(message, MessageManager.MessageDisplayLimit);
if (unread) if (!unread)
{ return;
Unread += 1; Unread += 1;
LastMessageTime = Environment.TickCount64;
} if (message.Matches(Plugin.Config.InactivityHideChannels, Plugin.Config.InactivityHideExtraChatAll, Plugin.Config.InactivityHideExtraChatChannels))
LastActivity = Environment.TickCount64;
} }
internal void Clear() internal void Clear() => Messages.Clear();
{
Messages.Clear();
}
internal Tab Clone() internal Tab Clone()
{ {
@@ -245,6 +244,7 @@ internal class Tab
ExtraChatAll = ExtraChatAll, ExtraChatAll = ExtraChatAll,
ExtraChatChannels = ExtraChatChannels.ToHashSet(), ExtraChatChannels = ExtraChatChannels.ToHashSet(),
UnreadMode = UnreadMode, UnreadMode = UnreadMode,
UnhideOnActivity = UnhideOnActivity,
DisplayTimestamp = DisplayTimestamp, DisplayTimestamp = DisplayTimestamp,
Channel = Channel, Channel = Channel,
PopOut = PopOut, PopOut = PopOut,
+2 -4
View File
@@ -10,8 +10,6 @@ using FFXIVClientStructs.FFXIV.Client.UI;
using ImGuiNET; using ImGuiNET;
using ModifierFlag = ChatTwo.GameFunctions.Types.ModifierFlag; using ModifierFlag = ChatTwo.GameFunctions.Types.ModifierFlag;
using ModifierFlag = ChatTwo.GameFunctions.Types.ModifierFlag;
namespace ChatTwo.GameFunctions; namespace ChatTwo.GameFunctions;
internal enum KeyboardSource { internal enum KeyboardSource {
@@ -95,8 +93,8 @@ internal unsafe class KeybindManager : IDisposable {
// List of keys that can be used as a part of keybinds while the chat is // List of keys that can be used as a part of keybinds while the chat is
// focused WITHOUT modifiers. All other keys can only be used if their // focused WITHOUT modifiers. All other keys can only be used if their
// configured keybind contains modifiers. This allows for using e.g. F11 to // configured keybind contains modifiers (except only SHIFT). This allows
// change chat channel while typing. // for using e.g. F11 to change chat channel while typing.
private static readonly IReadOnlyCollection<VirtualKey> ModifierlessChatKeys = new[] private static readonly IReadOnlyCollection<VirtualKey> ModifierlessChatKeys = new[]
{ {
// VirtualKey.NO_KEY, // VirtualKey.NO_KEY,
+11
View File
@@ -124,6 +124,17 @@ internal partial class Message
return new Message(0, 0, code, [], content, new SeString(), new SeString()); return new Message(0, 0, code, [], content, new SeString(), new SeString());
} }
internal bool Matches(Dictionary<ChatType, ChatSource> channels, bool allExtraChatChannels, HashSet<Guid> extraChatChannels)
{
if (ExtraChatChannel != Guid.Empty)
return allExtraChatChannels || extraChatChannels.Contains(ExtraChatChannel);
return Code.Type.IsGm()
|| channels.TryGetValue(Code.Type, out var sources)
&& (Code.Source is 0 or (ChatSource) 1
|| sources.HasFlag(Code.Source));
}
private int GenerateHash() private int GenerateHash()
{ {
return SortCode.GetHashCode() return SortCode.GetHashCode()
+73 -1
View File
@@ -2481,7 +2481,7 @@ namespace ChatTwo.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Hide the chat after a configurable period of inactivity. The current tab and any tabs with unread indicators enabled are considered for activity.. /// Looks up a localized string similar to Hide the chat after a configurable period of inactivity. The current tab and any other tabs with the setting enabled are considered for activity..
/// </summary> /// </summary>
internal static string Options_HideWhenInactive_Description { internal static string Options_HideWhenInactive_Description {
get { get {
@@ -2534,6 +2534,69 @@ namespace ChatTwo.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to When disabled, the chat log will stay active during battle..
/// </summary>
internal static string Options_InactivityHideActiveDuringBattle_Description {
get {
return ResourceManager.GetString("Options_InactivityHideActiveDuringBattle_Description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Enable inactivity hide during battle.
/// </summary>
internal static string Options_InactivityHideActiveDuringBattle_Name {
get {
return ResourceManager.GetString("Options_InactivityHideActiveDuringBattle_Name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Select All.
/// </summary>
internal static string Options_InactivityHideChannels_All_Label {
get {
return ResourceManager.GetString("Options_InactivityHideChannels_All_Label", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Hold Ctrl+Shift to click..
/// </summary>
internal static string Options_InactivityHideChannels_Button_Tooltip {
get {
return ResourceManager.GetString("Options_InactivityHideChannels_Button_Tooltip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Which chat channels should be considered for activity. Other channels will not restore the chat regardless of which tab they occur in..
/// </summary>
internal static string Options_InactivityHideChannels_Description {
get {
return ResourceManager.GetString("Options_InactivityHideChannels_Description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Chat channels considered for activity.
/// </summary>
internal static string Options_InactivityHideChannels_Name {
get {
return ResourceManager.GetString("Options_InactivityHideChannels_Name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Unselect All.
/// </summary>
internal static string Options_InactivityHideChannels_None_Label {
get {
return ResourceManager.GetString("Options_InactivityHideChannels_None_Label", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to How long to wait (in seconds) before considering the chat log inactive.. /// Looks up a localized string similar to How long to wait (in seconds) before considering the chat log inactive..
/// </summary> /// </summary>
@@ -3137,6 +3200,15 @@ namespace ChatTwo.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Unhide the chat window on activity.
/// </summary>
internal static string Options_Tabs_InactivityBehaviour {
get {
return ResourceManager.GetString("Options_Tabs_InactivityBehaviour", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Use different opacity than main window. /// Looks up a localized string similar to Use different opacity than main window.
/// </summary> /// </summary>
+25 -1
View File
@@ -220,6 +220,9 @@
<data name="Options_Tabs_UnreadMode"> <data name="Options_Tabs_UnreadMode">
<value>Unread mode</value> <value>Unread mode</value>
</data> </data>
<data name="Options_Tabs_InactivityBehaviour">
<value>Unhide the chat window on activity</value>
</data>
<data name="Options_Tabs_NoInputChannel"> <data name="Options_Tabs_NoInputChannel">
<value>&lt;None&gt;</value> <value>&lt;None&gt;</value>
</data> </data>
@@ -410,7 +413,7 @@
<value>Hide when inactive</value> <value>Hide when inactive</value>
</data> </data>
<data name="Options_HideWhenInactive_Description"> <data name="Options_HideWhenInactive_Description">
<value>Hide the chat after a configurable period of inactivity. The current tab and any tabs with unread indicators enabled are considered for activity.</value> <value>Hide the chat after a configurable period of inactivity. The current tab and any other tabs with the setting enabled are considered for activity.</value>
</data> </data>
<data name="Options_InactivityHideTimeout_Name"> <data name="Options_InactivityHideTimeout_Name">
<value>Inactivity timeout</value> <value>Inactivity timeout</value>
@@ -418,6 +421,27 @@
<data name="Options_InactivityHideTimeout_Description"> <data name="Options_InactivityHideTimeout_Description">
<value>How long to wait (in seconds) before considering the chat log inactive.</value> <value>How long to wait (in seconds) before considering the chat log inactive.</value>
</data> </data>
<data name="Options_InactivityHideActiveDuringBattle_Name" xml:space="preserve">
<value>Enable inactivity hide during battle</value>
</data>
<data name="Options_InactivityHideActiveDuringBattle_Description" xml:space="preserve">
<value>When disabled, the chat log will stay active during battle.</value>
</data>
<data name="Options_InactivityHideChannels_Name">
<value>Chat channels considered for activity</value>
</data>
<data name="Options_InactivityHideChannels_Description">
<value>Which chat channels should be considered for activity. Other channels will not restore the chat regardless of which tab they occur in.</value>
</data>
<data name="Options_InactivityHideChannels_All_Label">
<value>Select All</value>
</data>
<data name="Options_InactivityHideChannels_None_Label">
<value>Unselect All</value>
</data>
<data name="Options_InactivityHideChannels_Button_Tooltip">
<value>Hold Ctrl+Shift to click.</value>
</data>
<data name="Options_KeybindMode_Name"> <data name="Options_KeybindMode_Name">
<value>Keybind mode</value> <value>Keybind mode</value>
</data> </data>
+11 -8
View File
@@ -87,7 +87,7 @@ public sealed class ChatLogWindow : Window
private bool PlayedClosingSound = true; private bool PlayedClosingSound = true;
private long FrameTime; // set every frame private long FrameTime; // set every frame
private long LastActivityTime = Environment.TickCount64; internal long LastActivityTime = Environment.TickCount64;
private readonly ExcelSheet<World> WorldSheet; private readonly ExcelSheet<World> WorldSheet;
private readonly ExcelSheet<LogFilter> LogFilterSheet; private readonly ExcelSheet<LogFilter> LogFilterSheet;
@@ -348,7 +348,10 @@ public sealed class ChatLogWindow : Window
return height; return height;
} }
internal void ChangeTab(int index) => WantedTab = index; internal void ChangeTab(int index) {
WantedTab = index;
LastActivityTime = FrameTime;
}
internal void ChangeTabDelta(int offset) internal void ChangeTabDelta(int offset)
{ {
@@ -373,7 +376,7 @@ public sealed class ChatLogWindow : Window
SetChannel(tab.Channel ?? tab.PreviousChannel); SetChannel(tab.Channel ?? tab.PreviousChannel);
} }
private static bool InBattle => Plugin.Condition[ConditionFlag.InCombat]; internal static bool InBattle => Plugin.Condition[ConditionFlag.InCombat];
private static bool GposeActive => Plugin.Condition[ConditionFlag.WatchingCutscene]; private static bool GposeActive => Plugin.Condition[ConditionFlag.WatchingCutscene];
private static bool CutsceneActive => Plugin.Condition[ConditionFlag.OccupiedInCutSceneEvent] || Plugin.Condition[ConditionFlag.WatchingCutscene78]; private static bool CutsceneActive => Plugin.Condition[ConditionFlag.OccupiedInCutSceneEvent] || Plugin.Condition[ConditionFlag.WatchingCutscene78];
@@ -448,7 +451,8 @@ public sealed class ChatLogWindow : Window
FrameTime = Environment.TickCount64; FrameTime = Environment.TickCount64;
if (IsHidden) if (IsHidden)
return false; return false;
if (!Plugin.Config.HideWhenInactive || Activate)
if (!Plugin.Config.HideWhenInactive || (!Plugin.Config.InactivityHideActiveDuringBattle && InBattle) || Activate)
{ {
LastActivityTime = FrameTime; LastActivityTime = FrameTime;
return true; return true;
@@ -456,11 +460,10 @@ public sealed class ChatLogWindow : Window
var currentTab = CurrentTab; // local to avoid calling the getter repeatedly var currentTab = CurrentTab; // local to avoid calling the getter repeatedly
var lastActivityTime = Plugin.Config.Tabs var lastActivityTime = Plugin.Config.Tabs
.Where(tab => tab.UnreadMode is not UnreadMode.None || tab == currentTab) .Where(tab => !tab.PopOut && (tab.UnhideOnActivity || tab == currentTab))
.Select(tab => tab.LastMessageTime) .Select(tab => tab.LastActivity)
.DefaultIfEmpty(0) .Append(LastActivityTime)
.Max(); .Max();
lastActivityTime = Math.Max(lastActivityTime, LastActivityTime);
return FrameTime - lastActivityTime <= 1000 * Plugin.Config.InactivityHideTimeout; return FrameTime - lastActivityTime <= 1000 * Plugin.Config.InactivityHideTimeout;
} }
+20 -1
View File
@@ -12,6 +12,9 @@ internal class Popout : Window
private readonly Tab Tab; private readonly Tab Tab;
private readonly int Idx; private readonly int Idx;
private long FrameTime; // set every frame
private long LastActivityTime = Environment.TickCount64;
public Popout(ChatLogWindow chatLogWindow, Tab tab, int idx) : base($"{tab.Name}##popout") public Popout(ChatLogWindow chatLogWindow, Tab tab, int idx) : base($"{tab.Name}##popout")
{ {
ChatLogWindow = chatLogWindow; ChatLogWindow = chatLogWindow;
@@ -34,7 +37,20 @@ internal class Popout : Window
public override bool DrawConditions() public override bool DrawConditions()
{ {
return !ChatLogWindow.IsHidden; FrameTime = Environment.TickCount64;
if (ChatLogWindow.IsHidden)
return false;
if (!Plugin.Config.HideWhenInactive || (!Plugin.Config.InactivityHideActiveDuringBattle && ChatLogWindow.InBattle) || !Tab.UnhideOnActivity)
{
LastActivityTime = FrameTime;
return true;
}
// Activity in the tab, this popout window, or the main chat log window.
var lastActivityTime = Math.Max(Tab.LastActivity, LastActivityTime);
lastActivityTime = Math.Max(lastActivityTime, ChatLogWindow.LastActivityTime);
return FrameTime - lastActivityTime <= 1000 * Plugin.Config.InactivityHideTimeout;
} }
public override void PreDraw() public override void PreDraw()
@@ -65,6 +81,9 @@ internal class Popout : Window
var handler = ChatLogWindow.HandlerLender.Borrow(); var handler = ChatLogWindow.HandlerLender.Borrow();
ChatLogWindow.DrawMessageLog(Tab, handler, ImGui.GetContentRegionAvail().Y, false); ChatLogWindow.DrawMessageLog(Tab, handler, ImGui.GetContentRegionAvail().Y, false);
if (ImGui.IsWindowHovered(ImGuiHoveredFlags.ChildWindows))
LastActivityTime = FrameTime;
} }
public override void PostDraw() public override void PostDraw()
+46 -2
View File
@@ -1,5 +1,6 @@
using ChatTwo.Resources; using ChatTwo.Resources;
using ChatTwo.Util; using ChatTwo.Util;
using Dalamud.Interface.Utility.Raii;
using ImGuiNET; using ImGuiNET;
namespace ChatTwo.Ui.SettingsTabs; namespace ChatTwo.Ui.SettingsTabs;
@@ -37,27 +38,70 @@ internal sealed class Display : ISettingsTab
ImGuiUtil.OptionCheckbox(ref Mutable.HideInBattle, Language.Options_HideInBattle_Name, Language.Options_HideInBattle_Description); ImGuiUtil.OptionCheckbox(ref Mutable.HideInBattle, Language.Options_HideInBattle_Name, Language.Options_HideInBattle_Description);
ImGui.Spacing(); ImGui.Spacing();
ImGui.Separator();
ImGui.Spacing();
ImGuiUtil.OptionCheckbox(ref Mutable.HideWhenInactive, Language.Options_HideWhenInactive_Name, Language.Options_HideWhenInactive_Description); ImGuiUtil.OptionCheckbox(ref Mutable.HideWhenInactive, Language.Options_HideWhenInactive_Name, Language.Options_HideWhenInactive_Description);
ImGui.Spacing(); ImGui.Spacing();
if (Mutable.HideWhenInactive) if (Mutable.HideWhenInactive)
{ {
using var _ = ImRaii.PushIndent();
ImGuiUtil.InputIntVertical(Language.Options_InactivityHideTimeout_Name, ImGuiUtil.InputIntVertical(Language.Options_InactivityHideTimeout_Name,
Language.Options_InactivityHideTimeout_Description, ref Mutable.InactivityHideTimeout, 1, 10); Language.Options_InactivityHideTimeout_Description, ref Mutable.InactivityHideTimeout, 1, 10);
// Enforce a minimum of 2 seconds to avoid people soft locking // Enforce a minimum of 2 seconds to avoid people soft locking
// themselves. // themselves.
Mutable.InactivityHideTimeout = Math.Max(2, Mutable.InactivityHideTimeout); Mutable.InactivityHideTimeout = Math.Max(2, Mutable.InactivityHideTimeout);
ImGui.Spacing(); ImGui.Spacing();
// This setting conflicts with HideInBattle, so it's disabled.
using (ImRaii.Disabled(Mutable.HideInBattle))
{
ImGuiUtil.OptionCheckbox(ref Mutable.InactivityHideActiveDuringBattle,
Language.Options_InactivityHideActiveDuringBattle_Name,
Language.Options_InactivityHideActiveDuringBattle_Description);
ImGui.Spacing();
}
using var channelTree = ImRaii.TreeNode(Language.Options_InactivityHideChannels_Name);
if (channelTree.Success)
{
if (ImGuiUtil.CtrlShiftButton(Language.Options_InactivityHideChannels_All_Label,
Language.Options_InactivityHideChannels_Button_Tooltip))
{
Mutable.InactivityHideChannels = TabsUtil.AllChannels();
Mutable.InactivityHideExtraChatAll = true;
Mutable.InactivityHideExtraChatChannels = [];
}
ImGui.SameLine();
if (ImGuiUtil.CtrlShiftButton(Language.Options_InactivityHideChannels_None_Label,
Language.Options_InactivityHideChannels_Button_Tooltip))
{
Mutable.InactivityHideChannels = new();
Mutable.InactivityHideExtraChatAll = false;
Mutable.InactivityHideExtraChatChannels = [];
}
ImGui.Spacing();
ImGuiUtil.ChannelSelector(Language.Options_Tabs_Channels, Mutable.InactivityHideChannels);
ImGuiUtil.ExtraChatSelector(Language.Options_Tabs_ExtraChatChannels,
ref Mutable.InactivityHideExtraChatAll, Mutable.InactivityHideExtraChatChannels);
}
ImGui.Spacing();
} }
ImGui.Separator();
ImGui.Spacing();
ImGuiUtil.OptionCheckbox(ref Mutable.PrettierTimestamps, Language.Options_PrettierTimestamps_Name, Language.Options_PrettierTimestamps_Description); ImGuiUtil.OptionCheckbox(ref Mutable.PrettierTimestamps, Language.Options_PrettierTimestamps_Name, Language.Options_PrettierTimestamps_Description);
if (Mutable.PrettierTimestamps) if (Mutable.PrettierTimestamps)
{ {
ImGui.TreePush(); using var _ = ImRaii.PushIndent();
ImGuiUtil.OptionCheckbox(ref Mutable.MoreCompactPretty, Language.Options_MoreCompactPretty_Name, Language.Options_MoreCompactPretty_Description); ImGuiUtil.OptionCheckbox(ref Mutable.MoreCompactPretty, Language.Options_MoreCompactPretty_Name, Language.Options_MoreCompactPretty_Description);
ImGuiUtil.OptionCheckbox(ref Mutable.HideSameTimestamps, Language.Options_HideSameTimestamps_Name, Language.Options_HideSameTimestamps_Description); ImGuiUtil.OptionCheckbox(ref Mutable.HideSameTimestamps, Language.Options_HideSameTimestamps_Name, Language.Options_HideSameTimestamps_Description);
ImGui.TreePop();
} }
ImGui.Spacing(); ImGui.Spacing();
+5 -75
View File
@@ -108,6 +108,9 @@ internal sealed class Tabs : ISettingsTab
} }
} }
if (Mutable.HideWhenInactive)
ImGui.Checkbox(Language.Options_Tabs_InactivityBehaviour, ref tab.UnhideOnActivity);
ImGui.Checkbox(Language.Options_Tabs_NoInput, ref tab.InputDisabled); ImGui.Checkbox(Language.Options_Tabs_NoInput, ref tab.InputDisabled);
if (!tab.InputDisabled) if (!tab.InputDisabled)
{ {
@@ -124,81 +127,8 @@ internal sealed class Tabs : ISettingsTab
} }
} }
using (var channelNode = ImRaii.TreeNode(Language.Options_Tabs_Channels)) ImGuiUtil.ChannelSelector(Language.Options_Tabs_Channels, tab.ChatCodes);
{ ImGuiUtil.ExtraChatSelector(Language.Options_Tabs_ExtraChatChannels, ref tab.ExtraChatAll, tab.ExtraChatChannels);
if (channelNode)
{
foreach (var (header, types) in ChatTypeExt.SortOrder)
{
using var headerNode = ImRaii.TreeNode(header + $"##{i}");
if (!headerNode.Success)
continue;
foreach (var type in types)
{
if (type.IsGm())
continue;
var enabled = tab.ChatCodes.ContainsKey(type);
if (ImGui.Checkbox($"##{type.Name()}-{i}", ref enabled))
{
if (enabled)
tab.ChatCodes[type] = ChatSourceExt.All;
else
tab.ChatCodes.Remove(type);
}
ImGui.SameLine();
if (!type.HasSource())
{
ImGui.TextUnformatted(type.Name());
continue;
}
using var typeNode = ImRaii.TreeNode($"{type.Name()}##{i}");
if (!typeNode.Success)
continue;
tab.ChatCodes.TryGetValue(type, out var sourcesEnum);
var sources = (uint) sourcesEnum;
foreach (var source in Enum.GetValues<ChatSource>())
if (ImGui.CheckboxFlags(source.Name(), ref sources, (uint) source))
tab.ChatCodes[type] = (ChatSource) sources;
}
}
}
}
if (Plugin.ExtraChat.ChannelNames.Count <= 0)
continue;
using var extraTree = ImRaii.TreeNode(Language.Options_Tabs_ExtraChatChannels);
if (!extraTree.Success)
continue;
ImGui.Checkbox(Language.Options_Tabs_ExtraChatAll, ref tab.ExtraChatAll);
ImGui.Separator();
if (tab.ExtraChatAll)
ImGui.BeginDisabled();
foreach (var (id, name) in Plugin.ExtraChat.ChannelNames)
{
var enabled = tab.ExtraChatChannels.Contains(id);
if (!ImGui.Checkbox($"{name}##ec-{id}", ref enabled))
continue;
if (enabled)
tab.ExtraChatChannels.Add(id);
else
tab.ExtraChatChannels.Remove(id);
}
if (tab.ExtraChatAll)
ImGui.EndDisabled();
} }
if (toRemove > -1) if (toRemove > -1)
+75
View File
@@ -1,5 +1,6 @@
using System.Numerics; using System.Numerics;
using System.Text; using System.Text;
using ChatTwo.Code;
using ChatTwo.GameFunctions.Types; using ChatTwo.GameFunctions.Types;
using ChatTwo.Resources; using ChatTwo.Resources;
using Dalamud.Game.ClientState.Keys; using Dalamud.Game.ClientState.Keys;
@@ -549,6 +550,80 @@ internal static class ImGuiUtil
return new EndUnconditionally(ImGui.PopTextWrapPos, true); return new EndUnconditionally(ImGui.PopTextWrapPos, true);
} }
public static void ChannelSelector(string headerText, Dictionary<ChatType, ChatSource> chatCodes)
{
using var channelNode = ImRaii.TreeNode(headerText);
if (!channelNode)
return;
foreach (var (header, types) in ChatTypeExt.SortOrder)
{
using var headerNode = ImRaii.TreeNode(header);
if (!headerNode.Success)
continue;
foreach (var type in types)
{
if (type.IsGm())
continue;
var enabled = chatCodes.ContainsKey(type);
if (ImGui.Checkbox($"##{type.Name()}", ref enabled))
{
if (enabled)
chatCodes[type] = ChatSourceExt.All;
else
chatCodes.Remove(type);
}
ImGui.SameLine();
if (!type.HasSource())
{
ImGui.TextUnformatted(type.Name());
continue;
}
using var typeNode = ImRaii.TreeNode($"{type.Name()}");
if (!typeNode.Success)
continue;
chatCodes.TryGetValue(type, out var sourcesEnum);
var sources = (uint)sourcesEnum;
foreach (var source in Enum.GetValues<ChatSource>())
if (ImGui.CheckboxFlags(source.Name(), ref sources, (uint)source))
chatCodes[type] = (ChatSource)sources;
}
}
}
public static void ExtraChatSelector(string headerText, ref bool all, HashSet<Guid> extraChatChannels)
{
if (Plugin.ExtraChat.ChannelNames.Count <= 0)
return;
using var extraTree = ImRaii.TreeNode(headerText);
if (!extraTree.Success)
return;
ImGui.Checkbox(Language.Options_Tabs_ExtraChatAll, ref all);
ImGui.Separator();
using var _ = ImRaii.Disabled(all);
foreach (var (id, name) in Plugin.ExtraChat.ChannelNames)
{
var enabled = extraChatChannels.Contains(id);
if (!ImGui.Checkbox($"{name}##ec-{id}", ref enabled))
continue;
if (enabled)
extraChatChannels.Add(id);
else
extraChatChannels.Remove(id);
}
}
// Used to avoid pops if condition is false for Push. // Used to avoid pops if condition is false for Push.
private static void Nop() { } private static void Nop() { }
} }
+8
View File
@@ -4,6 +4,14 @@ using ChatTwo.Resources;
namespace ChatTwo.Util; namespace ChatTwo.Util;
internal static class TabsUtil { internal static class TabsUtil {
internal static Dictionary<ChatType, ChatSource> AllChannels()
{
var channels = new Dictionary<ChatType, ChatSource>();
foreach (var chatType in Enum.GetValues<ChatType>())
channels[chatType] = ChatSourceExt.All;
return channels;
}
internal static Tab VanillaGeneral => new() { internal static Tab VanillaGeneral => new() {
Name = Language.Tabs_Presets_General, Name = Language.Tabs_Presets_General,
ChatCodes = new Dictionary<ChatType, ChatSource> { ChatCodes = new Dictionary<ChatType, ChatSource> {