feat(window): close other / left / right project tabs from the window-group tab menu (#965)

Right-clicking a project tab in a merged window group offers Close Other Tabs, Close Tabs to the Left and Close Tabs to the Right (left/right disabled at the ends); the same commands are in the Command Palette and can take shortcuts.

The backend closes the projects one at a time, focusing each so its own unsaved-changes prompt is visible, as Quit does. Cancelling a prompt stops the batch and leaves that project and the rest open; the clicked tab stays and is selected when the batch finishes. Starting Quit clears a pending batch.

Closes #942.

Co-authored-by: jaw52 <[email protected]>
Цей коміт міститься в:
Jaw authored and GitHub committed 2026-11-03 17:57:42 +08:00
1 джерело ecdd43a55a
коміт 291fa9affe
11 files changed
+184 -4

No files matched your search

+2 -1
Переглянути файл
@@ -125,10 +125,11 @@ async function onCloseRequested(deps: CloseDeps): Promise<boolean> {
},
deps,
);
if (!ok && ctx.quitting) await commands.appCancelQuit();
if (!ok) await (ctx.quitting ? commands.appCancelQuit() : commands.windowGroupCancelClose());
return ok;
} catch (e) {
maybeEditorService()?.cancelClose?.();
void commands.windowGroupCancelClose().catch(() => {});
deps.onSaveFailed(e);
return false;
} finally {
+36 -1
Переглянути файл
@@ -23,7 +23,7 @@ import { connectRemote, isRemoteWindow } from "@/platform/remote";
import { holdSplash } from "@/platform/splash";
import { editorService, maybeEditorService, notifications } from "@/workbench/contributions";
import { chooseProjectWindow } from "@/workbench/projectWindow";
import { cycleWindowTab } from "@/platform/windowGroups";
import { cycleWindowTab, useWindowGroup } from "@/platform/windowGroups";
import { showWorkspaceDialog } from "./WorkspaceDialog";
export const LAUNCH_EVENT = "openidea://launch";
@@ -222,6 +222,20 @@ export async function consumeLaunch(): Promise<void> {
}
}
/** Closes the project tabs on `side` of the `arg` tab (default: the current one), keeping that tab. */
function closeProjectTabs(side: "others" | "left" | "right"): Action["run"] {
return async ({ arg }) => {
const tabs = useWindowGroup.getState().tabs;
const keep = typeof arg === "string" ? arg : tabs.find((tab) => tab.current)?.label;
const index = tabs.findIndex((tab) => tab.label === keep);
if (!keep || index < 0) return;
const labels = tabs
.filter((_, i) => (side === "left" ? i < index : side === "right" ? i > index : i !== index))
.map((tab) => tab.label);
if (labels.length) await call(commands.windowGroupCloseTabs(keep, labels));
};
}
export function windowActions(): Action[] {
return [
{
@@ -302,6 +316,27 @@ export function windowActions(): Action[] {
if (typeof arg === "string") await call(commands.windowGroupClose(arg));
},
},
{
id: "window.closeOtherTabs",
title: "Close Other Project Tabs",
category: t("app.category.window"),
when: "windowGrouped",
run: closeProjectTabs("others"),
},
{
id: "window.closeTabsToLeft",
title: "Close Project Tabs to the Left",
category: t("app.category.window"),
when: "windowGrouped",
run: closeProjectTabs("left"),
},
{
id: "window.closeTabsToRight",
title: "Close Project Tabs to the Right",
category: t("app.category.window"),
when: "windowGrouped",
run: closeProjectTabs("right"),
},
{
id: "window.reorderTabs",
title: "Reorder Project Tabs",