Skip to content

Commit b31aac1

Browse files
committed
refactor: eliminate code duplication between openClineInNewTab and openClineInThisTab
- Extract common initialization logic to initializeClineTabProvider() - Extract common panel setup to setupClinePanel() - Both functions now share ~95% of their code through these helpers - Reduces maintenance burden and ensures consistency
1 parent 2fef294 commit b31aac1

File tree

1 file changed

+64
-83
lines changed

1 file changed

+64
-83
lines changed

src/activate/registerCommands.ts

Lines changed: 64 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,14 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
224224
},
225225
})
226226

227-
export const openClineInNewTab = async ({ context, outputChannel }: Omit<RegisterCommandOptions, "provider">) => {
228-
// (This example uses webviewProvider activation event which is necessary to
229-
// deserialize cached webview, but since we use retainContextWhenHidden, we
230-
// don't need to use that event).
231-
// https://github.com/microsoft/vscode-extension-samples/blob/main/webview-sample/src/extension.ts
227+
/**
228+
* Common initialization for Roo Code tab panels
229+
*/
230+
async function initializeClineTabProvider(
231+
context: vscode.ExtensionContext,
232+
outputChannel: vscode.OutputChannel,
233+
): Promise<ClineProvider> {
232234
const contextProxy = await ContextProxy.getInstance(context)
233-
const codeIndexManager = CodeIndexManager.getInstance(context)
234235

235236
// Get the existing MDM service instance to ensure consistent policy enforcement
236237
let mdmService: MdmService | undefined
@@ -241,57 +242,76 @@ export const openClineInNewTab = async ({ context, outputChannel }: Omit<Registe
241242
mdmService = undefined
242243
}
243244

244-
const tabProvider = new ClineProvider(context, outputChannel, "editor", contextProxy, mdmService)
245-
const lastCol = Math.max(...vscode.window.visibleTextEditors.map((editor) => editor.viewColumn || 0))
246-
247-
// Check if there are any visible text editors, otherwise open a new group
248-
// to the right.
249-
const hasVisibleEditors = vscode.window.visibleTextEditors.length > 0
250-
251-
if (!hasVisibleEditors) {
252-
await vscode.commands.executeCommand("workbench.action.newGroupRight")
253-
}
254-
255-
const targetCol = hasVisibleEditors ? Math.max(lastCol + 1, 1) : vscode.ViewColumn.Two
256-
257-
const newPanel = vscode.window.createWebviewPanel(ClineProvider.tabPanelId, "Roo Code", targetCol, {
258-
enableScripts: true,
259-
retainContextWhenHidden: true,
260-
localResourceRoots: [context.extensionUri],
261-
})
245+
return new ClineProvider(context, outputChannel, "editor", contextProxy, mdmService)
246+
}
262247

263-
// Save as tab type panel.
264-
setPanel(newPanel, "tab")
248+
/**
249+
* Common panel setup for Roo Code webview panels
250+
*/
251+
function setupClinePanel(
252+
panel: vscode.WebviewPanel,
253+
context: vscode.ExtensionContext,
254+
tabProvider: ClineProvider,
255+
): void {
256+
// Save as tab type panel
257+
setPanel(panel, "tab")
265258

266-
// TODO: Use better svg icon with light and dark variants (see
267-
// https://stackoverflow.com/questions/58365687/vscode-extension-iconpath).
268-
newPanel.iconPath = {
259+
// Set the icon
260+
panel.iconPath = {
269261
light: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "panel_light.png"),
270262
dark: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "panel_dark.png"),
271263
}
272264

273-
await tabProvider.resolveWebviewView(newPanel)
265+
// Resolve the webview
266+
tabProvider.resolveWebviewView(panel)
274267

275268
// Add listener for visibility changes to notify webview
276-
newPanel.onDidChangeViewState(
269+
panel.onDidChangeViewState(
277270
(e) => {
278-
const panel = e.webviewPanel
279-
if (panel.visible) {
280-
panel.webview.postMessage({ type: "action", action: "didBecomeVisible" }) // Use the same message type as in SettingsView.tsx
271+
const webviewPanel = e.webviewPanel
272+
if (webviewPanel.visible) {
273+
webviewPanel.webview.postMessage({ type: "action", action: "didBecomeVisible" })
281274
}
282275
},
283-
null, // First null is for `thisArgs`
284-
context.subscriptions, // Register listener for disposal
276+
null,
277+
context.subscriptions,
285278
)
286279

287-
// Handle panel closing events.
288-
newPanel.onDidDispose(
280+
// Handle panel closing events
281+
panel.onDidDispose(
289282
() => {
290283
setPanel(undefined, "tab")
291284
},
292285
null,
293-
context.subscriptions, // Also register dispose listener
286+
context.subscriptions,
294287
)
288+
}
289+
290+
export const openClineInNewTab = async ({ context, outputChannel }: Omit<RegisterCommandOptions, "provider">) => {
291+
// (This example uses webviewProvider activation event which is necessary to
292+
// deserialize cached webview, but since we use retainContextWhenHidden, we
293+
// don't need to use that event).
294+
// https://github.com/microsoft/vscode-extension-samples/blob/main/webview-sample/src/extension.ts
295+
const tabProvider = await initializeClineTabProvider(context, outputChannel)
296+
const lastCol = Math.max(...vscode.window.visibleTextEditors.map((editor) => editor.viewColumn || 0))
297+
298+
// Check if there are any visible text editors, otherwise open a new group
299+
// to the right.
300+
const hasVisibleEditors = vscode.window.visibleTextEditors.length > 0
301+
302+
if (!hasVisibleEditors) {
303+
await vscode.commands.executeCommand("workbench.action.newGroupRight")
304+
}
305+
306+
const targetCol = hasVisibleEditors ? Math.max(lastCol + 1, 1) : vscode.ViewColumn.Two
307+
308+
const newPanel = vscode.window.createWebviewPanel(ClineProvider.tabPanelId, "Roo Code", targetCol, {
309+
enableScripts: true,
310+
retainContextWhenHidden: true,
311+
localResourceRoots: [context.extensionUri],
312+
})
313+
314+
await setupClinePanel(newPanel, context, tabProvider)
295315

296316
// Lock the editor group so clicking on files doesn't open them over the panel.
297317
await delay(100)
@@ -300,20 +320,11 @@ export const openClineInNewTab = async ({ context, outputChannel }: Omit<Registe
300320
return tabProvider
301321
}
302322

323+
/**
324+
* Opens Roo Code in the current active tab, replacing its content
325+
*/
303326
export const openClineInThisTab = async ({ context, outputChannel }: Omit<RegisterCommandOptions, "provider">) => {
304-
const contextProxy = await ContextProxy.getInstance(context)
305-
const codeIndexManager = CodeIndexManager.getInstance(context)
306-
307-
// Get the existing MDM service instance to ensure consistent policy enforcement
308-
let mdmService: MdmService | undefined
309-
try {
310-
mdmService = MdmService.getInstance()
311-
} catch (error) {
312-
// MDM service not initialized, which is fine - extension can work without it
313-
mdmService = undefined
314-
}
315-
316-
const tabProvider = new ClineProvider(context, outputChannel, "editor", contextProxy, mdmService)
327+
const tabProvider = await initializeClineTabProvider(context, outputChannel)
317328

318329
// Get the active text editor's view column, or use the first column if no editor is active
319330
const activeColumn = vscode.window.activeTextEditor?.viewColumn || vscode.ViewColumn.One
@@ -330,37 +341,7 @@ export const openClineInThisTab = async ({ context, outputChannel }: Omit<Regist
330341
},
331342
)
332343

333-
// Save as tab type panel
334-
setPanel(newPanel, "tab")
335-
336-
// Set the icon
337-
newPanel.iconPath = {
338-
light: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "panel_light.png"),
339-
dark: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "panel_dark.png"),
340-
}
341-
342-
await tabProvider.resolveWebviewView(newPanel)
343-
344-
// Add listener for visibility changes to notify webview
345-
newPanel.onDidChangeViewState(
346-
(e) => {
347-
const panel = e.webviewPanel
348-
if (panel.visible) {
349-
panel.webview.postMessage({ type: "action", action: "didBecomeVisible" })
350-
}
351-
},
352-
null,
353-
context.subscriptions,
354-
)
355-
356-
// Handle panel closing events
357-
newPanel.onDidDispose(
358-
() => {
359-
setPanel(undefined, "tab")
360-
},
361-
null,
362-
context.subscriptions,
363-
)
344+
await setupClinePanel(newPanel, context, tabProvider)
364345

365346
return tabProvider
366347
}

0 commit comments

Comments
 (0)