Add typing state IPC integration for enhanced Chat2 input handling
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
using ChatTwo.Code;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
|
||||
namespace ChatTwo.Ipc;
|
||||
|
||||
using ChatInputState = (bool InputVisible, bool InputFocused, bool HasText, bool IsTyping, int TextLength, ChatType ChannelType);
|
||||
|
||||
internal sealed class TypingIpc : IDisposable
|
||||
{
|
||||
private Plugin Plugin { get; }
|
||||
|
||||
private ICallGateProvider<ChatInputState> StateQueryGate { get; }
|
||||
private ICallGateProvider<ChatInputState, object?> StateChangedGate { get; }
|
||||
|
||||
private ChatInputState LastState;
|
||||
private bool HasState;
|
||||
|
||||
internal TypingIpc(Plugin plugin)
|
||||
{
|
||||
Plugin = plugin;
|
||||
|
||||
StateQueryGate = Plugin.Interface.GetIpcProvider<ChatInputState>("ChatTwo.GetChatInputState");
|
||||
StateChangedGate = Plugin.Interface.GetIpcProvider<ChatInputState, object?>("ChatTwo.ChatInputStateChanged");
|
||||
|
||||
StateQueryGate.RegisterFunc(GetState);
|
||||
}
|
||||
|
||||
private ChatInputState BuildState()
|
||||
{
|
||||
var log = Plugin.ChatLogWindow;
|
||||
var chat = log.Chat ?? string.Empty;
|
||||
var hasText = !string.IsNullOrWhiteSpace(chat);
|
||||
var usedChannel = Plugin.CurrentTab?.CurrentChannel;
|
||||
var inputChannel = usedChannel is not null
|
||||
? (usedChannel.UseTempChannel ? usedChannel.TempChannel : usedChannel.Channel)
|
||||
: InputChannel.Invalid;
|
||||
var channelType = inputChannel.ToChatType();
|
||||
|
||||
return (InputVisible: !log.IsHidden,
|
||||
InputFocused: log.InputFocused,
|
||||
HasText: hasText,
|
||||
IsTyping: log.InputFocused && hasText,
|
||||
TextLength: chat.Length,
|
||||
ChannelType: channelType);
|
||||
}
|
||||
|
||||
private ChatInputState GetState()
|
||||
=> BuildState();
|
||||
|
||||
internal void Update()
|
||||
{
|
||||
var state = BuildState();
|
||||
if (HasState && state.Equals(LastState))
|
||||
return;
|
||||
|
||||
HasState = true;
|
||||
LastState = state;
|
||||
StateChangedGate.SendMessage(state);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
StateQueryGate.UnregisterFunc();
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,7 @@ public sealed class Plugin : IDalamudPlugin
|
||||
internal MessageManager MessageManager { get; }
|
||||
internal IpcManager Ipc { get; }
|
||||
internal ExtraChat ExtraChat { get; }
|
||||
internal TypingIpc TypingIpc { get; }
|
||||
internal FontManager FontManager { get; }
|
||||
|
||||
internal ServerCore ServerCore { get; }
|
||||
@@ -97,6 +98,7 @@ public sealed class Plugin : IDalamudPlugin
|
||||
Commands = new Commands(this);
|
||||
Functions = new GameFunctions.GameFunctions(this);
|
||||
Ipc = new IpcManager();
|
||||
TypingIpc = new TypingIpc(this);
|
||||
ExtraChat = new ExtraChat(this);
|
||||
FontManager = new FontManager();
|
||||
|
||||
@@ -181,6 +183,7 @@ public sealed class Plugin : IDalamudPlugin
|
||||
DebuggerWindow?.Dispose();
|
||||
SeStringDebugger?.Dispose();
|
||||
|
||||
TypingIpc?.Dispose();
|
||||
ExtraChat?.Dispose();
|
||||
Ipc?.Dispose();
|
||||
MessageManager?.DisposeAsync().AsTask().Wait();
|
||||
@@ -193,8 +196,14 @@ public sealed class Plugin : IDalamudPlugin
|
||||
|
||||
private void Draw()
|
||||
{
|
||||
ChatLogWindow.BeginFrame();
|
||||
|
||||
if (Config.HideInLoadingScreens && Condition[ConditionFlag.BetweenAreas])
|
||||
{
|
||||
ChatLogWindow.FinalizeFrame();
|
||||
TypingIpc?.Update();
|
||||
return;
|
||||
}
|
||||
|
||||
ChatLogWindow.HideStateCheck();
|
||||
|
||||
@@ -205,6 +214,9 @@ public sealed class Plugin : IDalamudPlugin
|
||||
{
|
||||
WindowSystem.Draw();
|
||||
}
|
||||
|
||||
ChatLogWindow.FinalizeFrame();
|
||||
TypingIpc?.Update();
|
||||
}
|
||||
|
||||
internal void SaveConfig()
|
||||
|
||||
@@ -40,6 +40,7 @@ public sealed class ChatLogWindow : Window
|
||||
|
||||
internal bool FocusedPreview;
|
||||
internal bool Activate;
|
||||
internal bool InputFocused { get; private set; }
|
||||
private int ActivatePos = -1;
|
||||
internal string Chat = string.Empty;
|
||||
private readonly List<string> InputBacklog = [];
|
||||
@@ -72,6 +73,7 @@ public sealed class ChatLogWindow : Window
|
||||
private const uint ChatOpenSfx = 35u;
|
||||
private const uint ChatCloseSfx = 3u;
|
||||
private bool PlayedClosingSound = true;
|
||||
private bool DrewThisFrame;
|
||||
|
||||
private long FrameTime; // set every frame
|
||||
internal long LastActivityTime = Environment.TickCount64;
|
||||
@@ -430,6 +432,17 @@ public sealed class ChatLogWindow : Window
|
||||
IsHidden = false;
|
||||
}
|
||||
|
||||
internal void BeginFrame()
|
||||
{
|
||||
DrewThisFrame = false;
|
||||
}
|
||||
|
||||
internal void FinalizeFrame()
|
||||
{
|
||||
if (!DrewThisFrame)
|
||||
InputFocused = false;
|
||||
}
|
||||
|
||||
public override unsafe void PreOpenCheck()
|
||||
{
|
||||
Flags = ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse | ImGuiWindowFlags.NoFocusOnAppearing;
|
||||
@@ -500,6 +513,7 @@ public sealed class ChatLogWindow : Window
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
DrewThisFrame = true;
|
||||
try
|
||||
{
|
||||
DrawChatLog();
|
||||
@@ -618,6 +632,8 @@ public sealed class ChatLogWindow : Window
|
||||
ImGui.SetNextItemWidth(inputWidth);
|
||||
ImGui.InputTextWithHint("##chat2-input", isChatEnabled ? "": Language.ChatLog_DisabledInput, ref Chat, 500, flags, Callback);
|
||||
}
|
||||
var inputActive = ImGui.IsItemActive();
|
||||
InputFocused = isChatEnabled && inputActive;
|
||||
|
||||
var tooltipDraw = Plugin.Config.PreviewPosition is PreviewPosition.Tooltip && Plugin.InputPreview.IsDrawable;
|
||||
if (tooltipDraw && ImGui.IsItemHovered())
|
||||
@@ -655,14 +671,14 @@ public sealed class ChatLogWindow : Window
|
||||
}
|
||||
|
||||
// Process keybinds that have modifiers while the chat is focused.
|
||||
if (ImGui.IsItemActive())
|
||||
if (inputActive)
|
||||
{
|
||||
Plugin.Functions.KeybindManager.HandleKeybinds(KeyboardSource.ImGui, true, true);
|
||||
LastActivityTime = FrameTime;
|
||||
}
|
||||
|
||||
// Only trigger unfocused if we are currently not calling the auto complete
|
||||
if (!Activate && !ImGui.IsItemActive() && AutoCompleteInfo == null)
|
||||
if (!Activate && !inputActive && AutoCompleteInfo == null)
|
||||
{
|
||||
if (Plugin.Config.PlaySounds && !PlayedClosingSound)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user