Restore pop-out exclusivity: hide popped tabs from main window + keybind/unread parity
This commit is contained in:
@@ -30,6 +30,7 @@ internal sealed class MainWindow : Window, IFocusableChatWindow
|
||||
private readonly Components.InputBar _input;
|
||||
private readonly Components.StatusBar _status;
|
||||
private readonly Lender<PayloadHandler> _handlerLender;
|
||||
private readonly ChannelPopoutPool _pool;
|
||||
|
||||
private Tab? _activeTab;
|
||||
|
||||
@@ -51,7 +52,8 @@ internal sealed class MainWindow : Window, IFocusableChatWindow
|
||||
Components.MessageList messages,
|
||||
Components.InputBar input,
|
||||
Components.StatusBar status,
|
||||
Lender<PayloadHandler> handlerLender
|
||||
Lender<PayloadHandler> handlerLender,
|
||||
ChannelPopoutPool pool
|
||||
)
|
||||
: base($"{Plugin.PluginName}###hellion-main")
|
||||
{
|
||||
@@ -62,6 +64,7 @@ internal sealed class MainWindow : Window, IFocusableChatWindow
|
||||
_input = input;
|
||||
_status = status;
|
||||
_handlerLender = handlerLender;
|
||||
_pool = pool;
|
||||
|
||||
Size = new Vector2(DefaultWidth, DefaultHeight);
|
||||
SizeCondition = ImGuiCond.FirstUseEver;
|
||||
@@ -176,7 +179,13 @@ internal sealed class MainWindow : Window, IFocusableChatWindow
|
||||
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)]);
|
||||
var nextIndex = TabLifecycleHelpers.NextMainTabIndex(
|
||||
idx,
|
||||
delta,
|
||||
tabs,
|
||||
t => _pool.IsOpen(t.Identifier)
|
||||
);
|
||||
ActivateTab(tabs[nextIndex]);
|
||||
}
|
||||
|
||||
// Internal accessors for self-tests so the probes can reach the live
|
||||
@@ -270,6 +279,25 @@ internal sealed class MainWindow : Window, IFocusableChatWindow
|
||||
TabLifecycleHelpers.OnTabActivated(reseed, active);
|
||||
}
|
||||
|
||||
// POP-1c: a popped-out tab must not stay the main window's active surface
|
||||
// (1.5.6 exclusivity). Re-anchor to the first non-popped tab the moment the
|
||||
// active one is popped; null when every tab is popped (POP-1d guards Draw).
|
||||
// Runs post-seed, before the sidebar/top-tab draw, so the popped tab never
|
||||
// renders. Idempotent: PickMainActiveTab returns the same reference once
|
||||
// settled, so OnTabActivated fires only on the pop frame.
|
||||
var visibleActive = TabLifecycleHelpers.PickMainActiveTab(
|
||||
_activeTab,
|
||||
Plugin.Config.Tabs,
|
||||
t => _pool.IsOpen(t.Identifier)
|
||||
);
|
||||
if (!ReferenceEquals(visibleActive, _activeTab))
|
||||
{
|
||||
var previousActive = _activeTab;
|
||||
_activeTab = visibleActive;
|
||||
if (visibleActive is not null)
|
||||
TabLifecycleHelpers.OnTabActivated(visibleActive, previousActive);
|
||||
}
|
||||
|
||||
// The active tab's messages are on screen, so it carries no unread badge
|
||||
// (1.5.6 convention: zero the current tab every frame so the dot only ever
|
||||
// shows on tabs you are NOT looking at).
|
||||
@@ -336,8 +364,8 @@ internal sealed class MainWindow : Window, IFocusableChatWindow
|
||||
)
|
||||
)
|
||||
{
|
||||
if (messages.Success)
|
||||
_messages.Draw(_activeTab!);
|
||||
if (messages.Success && _activeTab is not null)
|
||||
_messages.Draw(_activeTab);
|
||||
}
|
||||
|
||||
// Inside-mode inline render: measure first so PreviewHeight is fresh
|
||||
|
||||
Reference in New Issue
Block a user