diff --git a/ChatTwo.Tests/ChatTwo.Tests.csproj b/ChatTwo.Tests/ChatTwo.Tests.csproj
index 2771b9e..8c20f47 100644
--- a/ChatTwo.Tests/ChatTwo.Tests.csproj
+++ b/ChatTwo.Tests/ChatTwo.Tests.csproj
@@ -2,7 +2,7 @@
net8.0-windows
-
+
false
@@ -17,10 +17,40 @@
-
-
- ..\..\AppData\Roaming\XIVLauncher\addon\Hooks\dev\Dalamud.dll
-
-
-
-
\ No newline at end of file
+
+ $(AppData)\XIVLauncher\addon\Hooks\dev
+
+
+
+ $(DALAMUD_HOME)
+
+
+
+ $(HOME)/dalamud
+
+
+
+
+ $(DalamudLibPath)\Dalamud.dll
+ false
+
+
+ $(DalamudLibPath)\FFXIVClientStructs.dll
+ false
+
+
+ $(DalamudLibPath)\ImGui.NET.dll
+ false
+
+
+ $(DalamudLibPath)\Lumina.dll
+ false
+
+
+ $(DalamudLibPath)\Lumina.Excel.dll
+ false
+
+
+
+
+
diff --git a/ChatTwo/Configuration.cs b/ChatTwo/Configuration.cs
index 3a697bf..a630c91 100755
--- a/ChatTwo/Configuration.cs
+++ b/ChatTwo/Configuration.cs
@@ -198,6 +198,9 @@ internal class Tab
[NonSerialized]
public HashSet TrackedMessageIds = new();
+ [NonSerialized]
+ public InputChannel? PreviousChannel;
+
~Tab() { MessagesMutex.Dispose(); }
internal bool Contains(Message message) {
diff --git a/ChatTwo/GameFunctions/Chat.cs b/ChatTwo/GameFunctions/Chat.cs
index 38f7fc7..15b5959 100755
--- a/ChatTwo/GameFunctions/Chat.cs
+++ b/ChatTwo/GameFunctions/Chat.cs
@@ -162,6 +162,7 @@ internal sealed unsafe class Chat : IDisposable
internal bool UsesTellTempChannel { get; set; }
internal InputChannel? PreviousChannel { get; private set; }
+ private bool DirectChat;
private long LastRefresh;
internal Chat(Plugin plugin)
@@ -372,10 +373,10 @@ internal sealed unsafe class Chat : IDisposable
if (LastRefresh + 5 * 1000 < Environment.TickCount64)
{
UpdateKeybinds();
+ DirectChat = Plugin.GameConfig.TryGet(UiControlOption.DirectChat, out bool option) && option;
LastRefresh = Environment.TickCount64;
}
-
var modifierState = (ModifierFlag) 0;
foreach (var modifier in Enum.GetValues())
{
@@ -390,6 +391,18 @@ internal sealed unsafe class Chat : IDisposable
if (!Keybinds.TryGetValue(toIntercept, out var keybind))
continue;
+ // Vanilla input has focus, so we ignore Ready Chat and Ready Command keybind
+ if (toIntercept is "CMD_CHAT" or "CMD_COMMAND")
+ {
+ // Vanilla text input has focus
+ if (RaptureAtkModule.Instance()->AtkModule.IsTextInputActive())
+ continue;
+
+ // Direct chat option is selected
+ if (DirectChat)
+ continue;
+ }
+
void Intercept(VirtualKey key, ModifierFlag modifier)
{
if (!Plugin.KeyState.IsVirtualKeyValid(key))
@@ -450,38 +463,32 @@ internal sealed unsafe class Chat : IDisposable
if (eventId != 0x31 || value == null || value->UInt is not (0x05 or 0x0C))
return ChatLogRefreshHook!.Original(log, eventId, value);
- if (Plugin.GameConfig.TryGet(UiControlOption.DirectChat, out bool option) && option)
+ if (DirectChat && CurrentCharacter != null)
{
- if (CurrentCharacter != null)
+ // FIXME: this whole system sucks
+ // FIXME v2: I hate everything about this, but it works
+ Plugin.Framework.RunOnTick(() =>
{
- // FIXME: this whole system sucks
- // FIXME v2: I hate everything about this, but it works
- Plugin.Framework.RunOnTick(() =>
+ string? input = null;
+
+ var utf8Bytes = MemoryHelper.ReadRaw((nint) CurrentCharacter, 2);
+ var chars = Encoding.UTF8.GetString(utf8Bytes).ToCharArray();
+ if (chars.Length == 0)
+ return;
+
+ var c = chars[0];
+ if (c != '\0' && !char.IsControl(c))
+ input = c.ToString();
+
+ try
{
- string? input = null;
-
- var utf8Bytes = MemoryHelper.ReadRaw((nint) CurrentCharacter, 2);
- var chars = Encoding.UTF8.GetString(utf8Bytes).ToCharArray();
- if (chars.Length == 0)
- return;
-
- var c = chars[0];
- if (c != '\0' && !char.IsControl(c))
- input = c.ToString();
-
- try
- {
- var args = new ChatActivatedArgs(new ChannelSwitchInfo(null)) {
- Input = input,
- };
- Activated?.Invoke(args);
- }
- catch (Exception ex)
- {
- Plugin.Log.Error(ex, "Error in chat Activated event");
- }
- });
- }
+ Activated?.Invoke(new ChatActivatedArgs(new ChannelSwitchInfo(null)) { Input = input, });
+ }
+ catch (Exception ex)
+ {
+ Plugin.Log.Error(ex, "Error in chat Activated event");
+ }
+ });
}
string? addIfNotPresent = null;
@@ -496,10 +503,7 @@ internal sealed unsafe class Chat : IDisposable
try
{
- var args = new ChatActivatedArgs(new ChannelSwitchInfo(null)) {
- AddIfNotPresent = addIfNotPresent,
- };
- Activated?.Invoke(args);
+ Activated?.Invoke(new ChatActivatedArgs(new ChannelSwitchInfo(null)) { AddIfNotPresent = addIfNotPresent, });
}
catch (Exception ex)
{
diff --git a/ChatTwo/Ui/ChatLogWindow.cs b/ChatTwo/Ui/ChatLogWindow.cs
index ea015e2..2b43c99 100644
--- a/ChatTwo/Ui/ChatLogWindow.cs
+++ b/ChatTwo/Ui/ChatLogWindow.cs
@@ -387,6 +387,21 @@ public sealed class ChatLogWindow : Window, IUiComponent
}
}
+ private void TabChannelSwitch(Tab tab)
+ {
+ // Save the previous channel to restore it later
+ var current = CurrentTab;
+ if (current is { Channel: null })
+ current.PreviousChannel = Plugin.Functions.Chat.Channel.channel;
+
+ // Channel will be null if PreviousChannel is used
+ var channel = tab.Channel ?? tab.PreviousChannel;
+
+ // Channel being null it doesn't have a default, and we never selected this channel before
+ if (channel != null)
+ SetChannel(tab.Channel ?? tab.PreviousChannel);
+ }
+
private bool CutsceneActive => Plugin.Condition[ConditionFlag.OccupiedInCutSceneEvent] || Plugin.Condition[ConditionFlag.WatchingCutscene78];
private bool GposeActive => Plugin.Condition[ConditionFlag.WatchingCutscene];
@@ -1036,12 +1051,11 @@ public sealed class ChatLogWindow : Window, IUiComponent
currentTab = tabI;
var switchedTab = LastTab != tabI;
+ if (switchedTab)
+ TabChannelSwitch(tab);
LastTab = tabI;
tab.Unread = 0;
- if (switchedTab && tab.Channel.HasValue)
- SetChannel(tab.Channel.Value);
-
DrawMessageLog(tab, PayloadHandler, GetRemainingHeightForMessageLog(), switchedTab);
ImGui.EndTabItem();
@@ -1083,10 +1097,9 @@ public sealed class ChatLogWindow : Window, IUiComponent
currentTab = tabI;
switchedTab = LastTab != tabI;
+ if (switchedTab)
+ TabChannelSwitch(tab);
LastTab = tabI;
-
- if (switchedTab && tab.Channel.HasValue)
- SetChannel(tab.Channel.Value);
}
}