-
Notifications
You must be signed in to change notification settings - Fork 2.1k
feat: add "Roo Code: Open in This Tab" command #7051
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -129,6 +129,7 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt | |
return openClineInNewTab({ context, outputChannel }) | ||
}, | ||
openInNewTab: () => openClineInNewTab({ context, outputChannel }), | ||
openInThisTab: () => openClineInThisTab({ context, outputChannel }), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The command registration looks good, following the same pattern as openInNewTab. |
||
settingsButtonClicked: () => { | ||
const visibleProvider = getVisibleProviderOrLog(outputChannel) | ||
|
||
|
@@ -223,13 +224,14 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt | |
}, | ||
}) | ||
|
||
export const openClineInNewTab = async ({ context, outputChannel }: Omit<RegisterCommandOptions, "provider">) => { | ||
// (This example uses webviewProvider activation event which is necessary to | ||
// deserialize cached webview, but since we use retainContextWhenHidden, we | ||
// don't need to use that event). | ||
// https://github.com/microsoft/vscode-extension-samples/blob/main/webview-sample/src/extension.ts | ||
/** | ||
* Common initialization for Roo Code tab panels | ||
*/ | ||
async function initializeClineTabProvider( | ||
context: vscode.ExtensionContext, | ||
outputChannel: vscode.OutputChannel, | ||
): Promise<ClineProvider> { | ||
const contextProxy = await ContextProxy.getInstance(context) | ||
const codeIndexManager = CodeIndexManager.getInstance(context) | ||
|
||
// Get the existing MDM service instance to ensure consistent policy enforcement | ||
let mdmService: MdmService | undefined | ||
|
@@ -240,7 +242,57 @@ export const openClineInNewTab = async ({ context, outputChannel }: Omit<Registe | |
mdmService = undefined | ||
} | ||
|
||
const tabProvider = new ClineProvider(context, outputChannel, "editor", contextProxy, mdmService) | ||
return new ClineProvider(context, outputChannel, "editor", contextProxy, mdmService) | ||
} | ||
|
||
/** | ||
* Common panel setup for Roo Code webview panels | ||
*/ | ||
function setupClinePanel( | ||
panel: vscode.WebviewPanel, | ||
context: vscode.ExtensionContext, | ||
tabProvider: ClineProvider, | ||
): void { | ||
// Save as tab type panel | ||
setPanel(panel, "tab") | ||
|
||
// Set the icon | ||
panel.iconPath = { | ||
light: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "panel_light.png"), | ||
dark: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "panel_dark.png"), | ||
} | ||
|
||
// Resolve the webview | ||
tabProvider.resolveWebviewView(panel) | ||
|
||
// Add listener for visibility changes to notify webview | ||
panel.onDidChangeViewState( | ||
(e) => { | ||
const webviewPanel = e.webviewPanel | ||
if (webviewPanel.visible) { | ||
webviewPanel.webview.postMessage({ type: "action", action: "didBecomeVisible" }) | ||
} | ||
}, | ||
null, | ||
context.subscriptions, | ||
) | ||
|
||
// Handle panel closing events | ||
panel.onDidDispose( | ||
() => { | ||
setPanel(undefined, "tab") | ||
}, | ||
null, | ||
context.subscriptions, | ||
) | ||
} | ||
|
||
export const openClineInNewTab = async ({ context, outputChannel }: Omit<RegisterCommandOptions, "provider">) => { | ||
// (This example uses webviewProvider activation event which is necessary to | ||
// deserialize cached webview, but since we use retainContextWhenHidden, we | ||
// don't need to use that event). | ||
// https://github.com/microsoft/vscode-extension-samples/blob/main/webview-sample/src/extension.ts | ||
const tabProvider = await initializeClineTabProvider(context, outputChannel) | ||
const lastCol = Math.max(...vscode.window.visibleTextEditors.map((editor) => editor.viewColumn || 0)) | ||
|
||
// Check if there are any visible text editors, otherwise open a new group | ||
|
@@ -259,42 +311,37 @@ export const openClineInNewTab = async ({ context, outputChannel }: Omit<Registe | |
localResourceRoots: [context.extensionUri], | ||
}) | ||
|
||
// Save as tab type panel. | ||
setPanel(newPanel, "tab") | ||
await setupClinePanel(newPanel, context, tabProvider) | ||
|
||
// TODO: Use better svg icon with light and dark variants (see | ||
// https://stackoverflow.com/questions/58365687/vscode-extension-iconpath). | ||
newPanel.iconPath = { | ||
light: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "panel_light.png"), | ||
dark: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "panel_dark.png"), | ||
} | ||
|
||
await tabProvider.resolveWebviewView(newPanel) | ||
// Lock the editor group so clicking on files doesn't open them over the panel. | ||
await delay(100) | ||
await vscode.commands.executeCommand("workbench.action.lockEditorGroup") | ||
|
||
// Add listener for visibility changes to notify webview | ||
newPanel.onDidChangeViewState( | ||
(e) => { | ||
const panel = e.webviewPanel | ||
if (panel.visible) { | ||
panel.webview.postMessage({ type: "action", action: "didBecomeVisible" }) // Use the same message type as in SettingsView.tsx | ||
} | ||
}, | ||
null, // First null is for `thisArgs` | ||
context.subscriptions, // Register listener for disposal | ||
) | ||
return tabProvider | ||
} | ||
|
||
// Handle panel closing events. | ||
newPanel.onDidDispose( | ||
() => { | ||
setPanel(undefined, "tab") | ||
/** | ||
* Opens Roo Code in the current active tab, replacing its content | ||
*/ | ||
export const openClineInThisTab = async ({ context, outputChannel }: Omit<RegisterCommandOptions, "provider">) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I notice there's significant code duplication between this new function and Also, is it intentional that this function doesn't lock the editor group like |
||
const tabProvider = await initializeClineTabProvider(context, outputChannel) | ||
|
||
// Get the active text editor's view column, or use the first column if no editor is active | ||
const activeColumn = vscode.window.activeTextEditor?.viewColumn || vscode.ViewColumn.One | ||
|
||
// Create the webview panel in the current tab/column | ||
const newPanel = vscode.window.createWebviewPanel( | ||
ClineProvider.tabPanelId, | ||
"Roo Code", | ||
{ viewColumn: activeColumn, preserveFocus: false }, | ||
{ | ||
enableScripts: true, | ||
retainContextWhenHidden: true, | ||
localResourceRoots: [context.extensionUri], | ||
}, | ||
null, | ||
context.subscriptions, // Also register dispose listener | ||
) | ||
|
||
// Lock the editor group so clicking on files doesn't open them over the panel. | ||
await delay(100) | ||
await vscode.commands.executeCommand("workbench.action.lockEditorGroup") | ||
await setupClinePanel(newPanel, context, tabProvider) | ||
|
||
return tabProvider | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -115,6 +115,11 @@ | |
"title": "%command.openInNewTab.title%", | ||
"category": "%configuration.title%" | ||
}, | ||
{ | ||
"command": "roo-cline.openInThisTab", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Command definition looks good and follows the existing pattern. |
||
"title": "%command.openInThisTab.title%", | ||
"category": "%configuration.title%" | ||
}, | ||
{ | ||
"command": "roo-cline.explainCode", | ||
"title": "%command.explainCode.title%", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
"command.settings.title": "Settings", | ||
"command.documentation.title": "Documentation", | ||
"command.openInNewTab.title": "Open In New Tab", | ||
"command.openInThisTab.title": "Open In This Tab", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. English localization added correctly. Should we also update the other language files in the locales directory (zh-CN, ja, etc.) with translations for this new command title? |
||
"command.explainCode.title": "Explain Code", | ||
"command.fixCode.title": "Fix Code", | ||
"command.improveCode.title": "Improve Code", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good addition to the command IDs list. The placement is logical, right after the related 'openInNewTab' command.