fix(tells): a tell no longer takes the keyboard mid-sentence
Reported by Carla: a tell arriving while you are typing pulls the focus away. The interruption is the visible half. The sharp half is that the input buffer belongs to the WINDOW while the send target is read off whatever tab is active at Enter -- so a line typed at one person could leave addressed to whoever just wrote, and in this game losing the keyboard means the next sentence walks the character around. Nothing is revealed now while any chat surface is mid-sentence, in any mode. The tab still appears and still carries its unread mark. The check lives in its own file because the answer has to be identical everywhere: it started inside the reveal plan, and a second pop-out path walked straight past it -- AutoTellTabsService opened windows off its own flag, at tab creation, a tick before the router was ever asked. Those two paths are one now. AutoTellTabsOpenAsPopout and TellAutoOpenMode were two settings for one decision, and the older one won every race, which is why the other looked inert. Config schema 28 carries the old flag forward so nobody's behaviour changes. "Off" went with it: it never stopped the tab from being created -- that is the auto-tell switch -- it only stopped the jump to it, which is what the switch below it does. Also in here, all from the same corner of the code: - Closing a tab was lost in the v2.0.0 rebuild. The trash entry lived in the retired ChatLogWindow menu, and the rebuilt one restored rename, sound, pop-out and pinning but not this. For tell tabs that left no way out at all: IsEditable keeps them out of the settings editor on purpose and points at the context menu, which could not close them either. Pinned tell tabs stay disabled with a tooltip rather than absent. - Re-anchoring the active tab used an unconditional Tabs[0] in three places, and Tabs[0] can be popped out -- so it ran OnTabActivated over a tab live in its own window and stripped its tell binding. With every tab popped, the seed and the re-anchor also fought each other every frame. - PinTab_LimitReached still pointed at "Promote to permanent", removed in May. Spanish said "Desija", which is not a word; Greek left "tell tabs" untranslated; pt-PT broke its own unpin verb. - Pop Out was a hardcoded English literal despite the key existing in all 25 languages since v1.5.6, and the tell-open modes were the last English display names in the plugin. - Segmented setting rows measured 200px flat, which cut German labels in half. They size to their longest label now. - Metrics.Scale still called GlobalScaleSafe. It is an alias for GlobalScale in current Dalamud, and dropping it clears the last compiler warning in the project.
This commit is contained in:
@@ -4,11 +4,14 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace HellionChat.Services;
|
||||
|
||||
// Routes an incoming tell to the configured TellAutoOpenMode (Off/Sidebar/
|
||||
// TopTab/Popout). Deliberately decoupled from AutoTellTabsService:
|
||||
// that service owns tab CREATION + lifecycle; this only REVEALS/pops the tab it
|
||||
// finds. Popout guards on pool.IsOpen so it never double-pops a tab the
|
||||
// AutoTellTabsOpenAsPopout path already opened. Subscribes to the resolved
|
||||
// Routes an incoming tell to the configured TellAutoOpenMode (Off/main window/
|
||||
// Popout). Deliberately decoupled from AutoTellTabsService: that service owns
|
||||
// tab CREATION + lifecycle; this is the SINGLE place that decides where a tell
|
||||
// becomes visible. Until v2.0.5 that service opened pop-outs too, off its own
|
||||
// AutoTellTabsOpenAsPopout flag, and won every race by firing at tab creation --
|
||||
// so this mode looked inert and the mid-sentence guard here could be walked
|
||||
// past. Popout still guards on pool.IsOpen for the already-open case.
|
||||
// Subscribes to the resolved
|
||||
// MessageManager.MessageProcessed stream (a resolved Message), not the raw
|
||||
// IChatGui event, and defers the reveal one tick so the tab exists regardless of
|
||||
// subscriber order. Wired by TellRouterServiceInitHostedService.
|
||||
@@ -84,24 +87,17 @@ internal sealed class TellRouterService : IDisposable
|
||||
var reveal = TabLifecycleHelpers.PlanTellReveal(
|
||||
mode,
|
||||
Plugin.Config.TellAutoOpenSwitchAlways,
|
||||
Plugin.Instance.ChannelPopoutPool.IsOpen(tab.Identifier)
|
||||
Plugin.Instance.ChannelPopoutPool.IsOpen(tab.Identifier),
|
||||
Util.ChatInputBusy.Any()
|
||||
);
|
||||
|
||||
switch (reveal)
|
||||
{
|
||||
case TabLifecycleHelpers.TellReveal.MainWindow:
|
||||
// The mode also picks the layout, so Sidebar vs TopTab are
|
||||
// actually distinct outcomes, not the same ActivateTab.
|
||||
var wantLayout =
|
||||
mode == TellAutoOpenMode.TopTab
|
||||
? MainWindowLayoutMode.TopTabs
|
||||
: MainWindowLayoutMode.Sidebar;
|
||||
if (Plugin.Config.MainWindowLayoutMode != wantLayout)
|
||||
{
|
||||
Plugin.Config.MainWindowLayoutMode = wantLayout;
|
||||
Plugin.Instance.SaveConfig();
|
||||
}
|
||||
|
||||
// Deliberately does NOT touch MainWindowLayoutMode. It used to
|
||||
// force the layout to match this mode and SAVE it, so a single
|
||||
// incoming tell permanently undid the tab placement the user
|
||||
// had chosen under Window -> Layout (Flo, 23.08.2026).
|
||||
Plugin.Instance.MainWindow?.ActivateTab(tab);
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user