mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
fix: prevent sidebar opening in multi-window VS Code setups (#5485)
- Add logic to detect multi-window scenarios in focusPanel utility - Prevent automatic sidebar activation when user is working in different window - Add comprehensive tests for focusPanel functionality - Maintain backward compatibility with existing behavior Fixes #5485
This commit is contained in:
parent
cb4652e45e
commit
a591dcb77f
2 changed files with 171 additions and 2 deletions
127
src/utils/__tests__/focusPanel.test.ts
Normal file
127
src/utils/__tests__/focusPanel.test.ts
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
import { describe, it, expect, vi, beforeEach } from "vitest"
|
||||
import * as vscode from "vscode"
|
||||
import { focusPanel } from "../focusPanel"
|
||||
import { ClineProvider } from "../../core/webview/ClineProvider"
|
||||
|
||||
// Mock vscode module
|
||||
vi.mock("vscode", () => ({
|
||||
commands: {
|
||||
executeCommand: vi.fn(),
|
||||
},
|
||||
window: {
|
||||
activeTextEditor: undefined,
|
||||
visibleTextEditors: [],
|
||||
},
|
||||
ViewColumn: {
|
||||
Active: 1,
|
||||
},
|
||||
}))
|
||||
|
||||
// Mock ClineProvider
|
||||
vi.mock("../../core/webview/ClineProvider", () => ({
|
||||
ClineProvider: {
|
||||
sideBarId: "roo-code.SidebarProvider",
|
||||
getVisibleInstance: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
// Mock Package
|
||||
vi.mock("../../shared/package", () => ({
|
||||
Package: {
|
||||
name: "roo-code",
|
||||
},
|
||||
}))
|
||||
|
||||
describe("focusPanel", () => {
|
||||
const mockExecuteCommand = vi.mocked(vscode.commands.executeCommand)
|
||||
const mockGetVisibleInstance = vi.mocked(ClineProvider.getVisibleInstance)
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
// Reset window state
|
||||
;(vscode.window as any).activeTextEditor = undefined
|
||||
;(vscode.window as any).visibleTextEditors = []
|
||||
})
|
||||
|
||||
describe("when panels exist", () => {
|
||||
it("should reveal tab panel when it exists but is not active", async () => {
|
||||
const mockTabPanel = {
|
||||
active: false,
|
||||
reveal: vi.fn(),
|
||||
} as any
|
||||
|
||||
await focusPanel(mockTabPanel, undefined)
|
||||
|
||||
expect(mockTabPanel.reveal).toHaveBeenCalledWith(1, false)
|
||||
expect(mockExecuteCommand).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("should focus sidebar panel when it exists", async () => {
|
||||
const mockSidebarPanel = {} as any
|
||||
|
||||
await focusPanel(undefined, mockSidebarPanel)
|
||||
|
||||
expect(mockExecuteCommand).toHaveBeenCalledWith("roo-code.SidebarProvider.focus")
|
||||
})
|
||||
|
||||
it("should prefer tab panel over sidebar panel when both exist", async () => {
|
||||
const mockTabPanel = {
|
||||
active: false,
|
||||
reveal: vi.fn(),
|
||||
} as any
|
||||
const mockSidebarPanel = {} as any
|
||||
|
||||
await focusPanel(mockTabPanel, mockSidebarPanel)
|
||||
|
||||
expect(mockTabPanel.reveal).toHaveBeenCalledWith(1, false)
|
||||
expect(mockExecuteCommand).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe("when no panels exist", () => {
|
||||
it("should open sidebar when there is a visible Roo Code instance", async () => {
|
||||
mockGetVisibleInstance.mockReturnValue({} as any)
|
||||
|
||||
await focusPanel(undefined, undefined)
|
||||
|
||||
expect(mockExecuteCommand).toHaveBeenCalledWith("workbench.view.extension.roo-code-ActivityBar")
|
||||
})
|
||||
|
||||
it("should open sidebar when there is an active editor (user is working in this window)", async () => {
|
||||
mockGetVisibleInstance.mockReturnValue(undefined)
|
||||
;(vscode.window as any).activeTextEditor = { document: { fileName: "test.ts" } }
|
||||
|
||||
await focusPanel(undefined, undefined)
|
||||
|
||||
expect(mockExecuteCommand).toHaveBeenCalledWith("workbench.view.extension.roo-code-ActivityBar")
|
||||
})
|
||||
|
||||
it("should open sidebar when there are visible editors (user is working in this window)", async () => {
|
||||
mockGetVisibleInstance.mockReturnValue(undefined)
|
||||
;(vscode.window as any).visibleTextEditors = [{ document: { fileName: "test.ts" } }]
|
||||
|
||||
await focusPanel(undefined, undefined)
|
||||
|
||||
expect(mockExecuteCommand).toHaveBeenCalledWith("workbench.view.extension.roo-code-ActivityBar")
|
||||
})
|
||||
|
||||
it("should NOT open sidebar when no visible instance and no editors (multi-window scenario)", async () => {
|
||||
mockGetVisibleInstance.mockReturnValue(undefined)
|
||||
// No active editor and no visible editors (default state)
|
||||
|
||||
await focusPanel(undefined, undefined)
|
||||
|
||||
expect(mockExecuteCommand).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("should open sidebar when detection fails (fallback to existing behavior)", async () => {
|
||||
mockGetVisibleInstance.mockImplementation(() => {
|
||||
throw new Error("Test error")
|
||||
})
|
||||
|
||||
await focusPanel(undefined, undefined)
|
||||
|
||||
expect(mockExecuteCommand).toHaveBeenCalledWith("workbench.view.extension.roo-code-ActivityBar")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
@ -15,8 +15,14 @@ export async function focusPanel(
|
|||
const panel = tabPanel || sidebarPanel
|
||||
|
||||
if (!panel) {
|
||||
// If no panel is open, open the sidebar
|
||||
await vscode.commands.executeCommand(`workbench.view.extension.${Package.name}-ActivityBar`)
|
||||
// Check if we should open the sidebar - avoid opening in multi-window scenarios
|
||||
// where the user might be working in a different VS Code window
|
||||
const shouldOpenSidebar = await shouldAllowSidebarActivation()
|
||||
|
||||
if (shouldOpenSidebar) {
|
||||
// If no panel is open, open the sidebar
|
||||
await vscode.commands.executeCommand(`workbench.view.extension.${Package.name}-ActivityBar`)
|
||||
}
|
||||
} else if (panel === tabPanel && !panel.active) {
|
||||
// For tab panels, use reveal to focus
|
||||
panel.reveal(vscode.ViewColumn.Active, false)
|
||||
|
|
@ -25,3 +31,39 @@ export async function focusPanel(
|
|||
await vscode.commands.executeCommand(`${ClineProvider.sideBarId}.focus`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if we should allow automatic sidebar activation
|
||||
* This helps prevent unwanted sidebar opening in multi-window VS Code setups
|
||||
* @returns Promise<boolean> - true if sidebar activation is allowed
|
||||
*/
|
||||
async function shouldAllowSidebarActivation(): Promise<boolean> {
|
||||
try {
|
||||
// Check if there's a visible Roo Code instance already
|
||||
const visibleProvider = ClineProvider.getVisibleInstance()
|
||||
if (visibleProvider) {
|
||||
// If there's already a visible provider, it's safe to open the sidebar
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if the current window has focus and is the active window
|
||||
// This helps prevent opening sidebar when user is working in another window
|
||||
const activeEditor = vscode.window.activeTextEditor
|
||||
const visibleEditors = vscode.window.visibleTextEditors
|
||||
|
||||
// If there are active editors in this window, it's likely the user's current working window
|
||||
if (activeEditor || visibleEditors.length > 0) {
|
||||
return true
|
||||
}
|
||||
|
||||
// If no editors are visible and no Roo Code instance is visible,
|
||||
// be conservative and don't auto-open the sidebar to avoid disrupting
|
||||
// the user's workflow in other windows
|
||||
return false
|
||||
} catch (error) {
|
||||
// If there's any error in detection, err on the side of caution
|
||||
// and allow sidebar activation to maintain existing functionality
|
||||
console.warn("Error in shouldAllowSidebarActivation:", error)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue