feat(keybind): cycle tabs and switch channel with pill sync
This commit is contained in:
@@ -501,20 +501,40 @@ internal unsafe class KeybindManager : IDisposable
|
||||
return;
|
||||
|
||||
Plugin.KeyState[currentBest.Item1] = false;
|
||||
if (!KeybindsToIntercept.ContainsKey(currentBest.Item2))
|
||||
if (!KeybindsToIntercept.TryGetValue(currentBest.Item2, out var info))
|
||||
return;
|
||||
|
||||
// Re-surface the chat-activation entry point retired in v1.6.0: a chat-open
|
||||
// keybind shows + focuses the window, restoring it from a user-hide or a
|
||||
// closed state. Channel/prefill routing from the bind stays out of scope.
|
||||
// closed state.
|
||||
Plugin.Instance.MainWindow?.ActivateChat();
|
||||
|
||||
// Direct channel-switch binds (CMD_SAY/PARTY/numbered linkshells/…): switch the
|
||||
// game channel AND mirror it onto the active tab so the input pill shows the
|
||||
// real send target (pill-sync, Flo decision 2026-06-15). Rotation binds (REPLY /
|
||||
// linkshell-cycle, Rotate != None) and the Permanent nuance stay deferred to the
|
||||
// keybind-routing follow-cycle.
|
||||
if (info.Channel is { } channel && info.Rotate == RotateMode.None)
|
||||
{
|
||||
Plugin.Instance.Functions.Chat.SetChannel(channel);
|
||||
if (Plugin.Instance.MainWindow?.ActiveTab is { } activeTab)
|
||||
{
|
||||
activeTab.CurrentChannel.SetChannel(channel);
|
||||
activeTab.CurrentChannel.TellTarget = null;
|
||||
activeTab.CurrentChannel.ResetTempChannel();
|
||||
}
|
||||
}
|
||||
|
||||
// Prefill text binds (CMD_COMMAND seeds "/"): drop the token into our input.
|
||||
if (info.Text is { } text)
|
||||
Plugin.Instance.InputBar.SetPendingMessage(text);
|
||||
}
|
||||
|
||||
// Tab-cycle dispatch is offline until the new chat layer surfaces a
|
||||
// ChangeTabDelta entry point and pop-out input bars come back online.
|
||||
// Cycle the main window's active tab. Pop-out input-bar focus-forward stays
|
||||
// deferred (no focus contract yet) — main-window tabs only.
|
||||
private void DispatchTabDelta(int delta)
|
||||
{
|
||||
_ = delta;
|
||||
Plugin.Instance.MainWindow?.ChangeTabDelta(delta);
|
||||
}
|
||||
|
||||
private static Keybind GetKeybind(string id)
|
||||
|
||||
@@ -160,6 +160,25 @@ internal sealed class MainWindow : Window
|
||||
TabLifecycleHelpers.OnTabActivated(tab, previous);
|
||||
}
|
||||
|
||||
// Tab-cycle entry point for the ChatTabForward/Backward keybinds. Empty list is a
|
||||
// no-op; a null active tab seeds tabs[0]; a single-tab cycle that lands on the
|
||||
// already-active tab is a no-op (ActivateTab early-returns on the same reference).
|
||||
// Routes through ActivateTab so the cycle strips stale tell state + re-derives the
|
||||
// channel exactly like a sidebar/top-tab click. Pop-out focus-forward stays
|
||||
// deferred (no focus contract) — main-window tabs only.
|
||||
internal void ChangeTabDelta(int delta)
|
||||
{
|
||||
var tabs = Plugin.Config.Tabs;
|
||||
if (tabs.Count == 0)
|
||||
return;
|
||||
|
||||
var idx = _activeTab is null ? 0 : tabs.IndexOf(_activeTab);
|
||||
if (idx < 0)
|
||||
idx = 0; // active tab not in the list (mid-strip) -> start from the first
|
||||
|
||||
ActivateTab(tabs[TabLifecycleHelpers.WrapTabIndex(idx, delta, tabs.Count)]);
|
||||
}
|
||||
|
||||
// Internal accessors for self-tests so the probes can reach the live
|
||||
// component without exposing them as public surface.
|
||||
internal Components.Sidebar GetSidebarForSelfTest() => _sidebar;
|
||||
|
||||
@@ -83,4 +83,15 @@ internal static class TabLifecycleHelpers
|
||||
tab.CurrentChannel.TellTarget = null;
|
||||
tab.CurrentChannel.ResetTempChannel();
|
||||
}
|
||||
|
||||
// Wrap-around tab index for keybind cycling. Pure so the Build-Suite can test the
|
||||
// wrap math without a live window. count == 0 returns 0 (the caller dead-zones
|
||||
// before activating); negative deltas wrap correctly via the double-mod.
|
||||
// TEST-MIRROR: ../../Hellion Build test/_Helpers/TabLifecycleHelpersTests.cs
|
||||
internal static int WrapTabIndex(int current, int delta, int count)
|
||||
{
|
||||
if (count <= 0)
|
||||
return 0;
|
||||
return ((current + delta) % count + count) % count;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user