-
Notifications
You must be signed in to change notification settings - Fork 2.1k
fix: improve button click handling during extension initialization #7037
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 all commits
d4c514b
85a857f
2c51307
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 | ||||
---|---|---|---|---|---|---|
|
@@ -19,13 +19,40 @@ import { t } from "../i18n" | |||||
|
||||||
/** | ||||||
* Helper to get the visible ClineProvider instance or log if not found. | ||||||
* Shows user-friendly error message when provider is not available. | ||||||
*/ | ||||||
export function getVisibleProviderOrLog(outputChannel: vscode.OutputChannel): ClineProvider | undefined { | ||||||
const visibleProvider = ClineProvider.getVisibleInstance() | ||||||
export async function getVisibleProviderOrLog(outputChannel: vscode.OutputChannel): Promise<ClineProvider | undefined> { | ||||||
let visibleProvider = ClineProvider.getVisibleInstance() | ||||||
|
||||||
// If no visible provider, try to activate the sidebar view first | ||||||
if (!visibleProvider) { | ||||||
outputChannel.appendLine("No visible Roo Code instance found, attempting to activate sidebar view...") | ||||||
|
||||||
try { | ||||||
// Try to focus the sidebar view which should trigger provider creation | ||||||
await vscode.commands.executeCommand(`${Package.name}.SidebarProvider.focus`) | ||||||
|
||||||
// Wait a bit for the view to initialize | ||||||
await new Promise((resolve) => setTimeout(resolve, 500)) | ||||||
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 timeout values between this file (500ms on line 36) and ClineProvider.ts (500ms twice for total 1s) are inconsistent. Consider using a shared constant like PROVIDER_INIT_TIMEOUT_MS = 500 for better maintainability. This would make it clearer what the intended initialization strategy is. |
||||||
|
||||||
// Try to get the provider again | ||||||
visibleProvider = ClineProvider.getVisibleInstance() | ||||||
} catch (error) { | ||||||
outputChannel.appendLine(`Failed to activate sidebar view: ${error}`) | ||||||
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. Consider type-checking the error before logging:
Suggested change
This ensures better type safety when accessing error properties. |
||||||
} | ||||||
} | ||||||
|
||||||
if (!visibleProvider) { | ||||||
outputChannel.appendLine("Cannot find any visible Roo Code instances.") | ||||||
outputChannel.appendLine("Cannot find any visible Roo Code instances after activation attempt.") | ||||||
// Show user-friendly error message only if not in test environment | ||||||
if (typeof vscode.window.showErrorMessage === "function") { | ||||||
vscode.window.showErrorMessage( | ||||||
"Roo Code is still initializing. Please wait a moment and try again, or restart VS Code if the issue persists.", | ||||||
) | ||||||
} | ||||||
return undefined | ||||||
} | ||||||
|
||||||
return visibleProvider | ||||||
} | ||||||
|
||||||
|
@@ -74,8 +101,8 @@ export const registerCommands = (options: RegisterCommandOptions) => { | |||||
|
||||||
const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOptions): Record<CommandId, any> => ({ | ||||||
activationCompleted: () => {}, | ||||||
accountButtonClicked: () => { | ||||||
const visibleProvider = getVisibleProviderOrLog(outputChannel) | ||||||
accountButtonClicked: async () => { | ||||||
const visibleProvider = await getVisibleProviderOrLog(outputChannel) | ||||||
|
||||||
if (!visibleProvider) { | ||||||
return | ||||||
|
@@ -86,7 +113,7 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt | |||||
visibleProvider.postMessageToWebview({ type: "action", action: "accountButtonClicked" }) | ||||||
}, | ||||||
plusButtonClicked: async () => { | ||||||
const visibleProvider = getVisibleProviderOrLog(outputChannel) | ||||||
const visibleProvider = await getVisibleProviderOrLog(outputChannel) | ||||||
|
||||||
if (!visibleProvider) { | ||||||
return | ||||||
|
@@ -101,8 +128,8 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt | |||||
// This ensures the focus happens after the view has switched | ||||||
await visibleProvider.postMessageToWebview({ type: "action", action: "focusInput" }) | ||||||
}, | ||||||
mcpButtonClicked: () => { | ||||||
const visibleProvider = getVisibleProviderOrLog(outputChannel) | ||||||
mcpButtonClicked: async () => { | ||||||
const visibleProvider = await getVisibleProviderOrLog(outputChannel) | ||||||
|
||||||
if (!visibleProvider) { | ||||||
return | ||||||
|
@@ -112,8 +139,8 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt | |||||
|
||||||
visibleProvider.postMessageToWebview({ type: "action", action: "mcpButtonClicked" }) | ||||||
}, | ||||||
promptsButtonClicked: () => { | ||||||
const visibleProvider = getVisibleProviderOrLog(outputChannel) | ||||||
promptsButtonClicked: async () => { | ||||||
const visibleProvider = await getVisibleProviderOrLog(outputChannel) | ||||||
|
||||||
if (!visibleProvider) { | ||||||
return | ||||||
|
@@ -129,8 +156,8 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt | |||||
return openClineInNewTab({ context, outputChannel }) | ||||||
}, | ||||||
openInNewTab: () => openClineInNewTab({ context, outputChannel }), | ||||||
settingsButtonClicked: () => { | ||||||
const visibleProvider = getVisibleProviderOrLog(outputChannel) | ||||||
settingsButtonClicked: async () => { | ||||||
const visibleProvider = await getVisibleProviderOrLog(outputChannel) | ||||||
|
||||||
if (!visibleProvider) { | ||||||
return | ||||||
|
@@ -142,8 +169,8 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt | |||||
// Also explicitly post the visibility message to trigger scroll reliably | ||||||
visibleProvider.postMessageToWebview({ type: "action", action: "didBecomeVisible" }) | ||||||
}, | ||||||
historyButtonClicked: () => { | ||||||
const visibleProvider = getVisibleProviderOrLog(outputChannel) | ||||||
historyButtonClicked: async () => { | ||||||
const visibleProvider = await getVisibleProviderOrLog(outputChannel) | ||||||
|
||||||
if (!visibleProvider) { | ||||||
return | ||||||
|
@@ -153,8 +180,8 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt | |||||
|
||||||
visibleProvider.postMessageToWebview({ type: "action", action: "historyButtonClicked" }) | ||||||
}, | ||||||
marketplaceButtonClicked: () => { | ||||||
const visibleProvider = getVisibleProviderOrLog(outputChannel) | ||||||
marketplaceButtonClicked: async () => { | ||||||
const visibleProvider = await getVisibleProviderOrLog(outputChannel) | ||||||
if (!visibleProvider) return | ||||||
visibleProvider.postMessageToWebview({ type: "action", action: "marketplaceButtonClicked" }) | ||||||
}, | ||||||
|
@@ -178,7 +205,7 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt | |||||
await promptForCustomStoragePath() | ||||||
}, | ||||||
importSettings: async (filePath?: string) => { | ||||||
const visibleProvider = getVisibleProviderOrLog(outputChannel) | ||||||
const visibleProvider = await getVisibleProviderOrLog(outputChannel) | ||||||
if (!visibleProvider) { | ||||||
return | ||||||
} | ||||||
|
@@ -212,8 +239,8 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt | |||||
outputChannel.appendLine(`Error focusing panel: ${error}`) | ||||||
} | ||||||
}, | ||||||
acceptInput: () => { | ||||||
const visibleProvider = getVisibleProviderOrLog(outputChannel) | ||||||
acceptInput: async () => { | ||||||
const visibleProvider = await getVisibleProviderOrLog(outputChannel) | ||||||
|
||||||
if (!visibleProvider) { | ||||||
return | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -469,15 +469,26 @@ export class ClineProvider | |
|
||
// If no visible provider, try to show the sidebar view | ||
if (!visibleProvider) { | ||
await vscode.commands.executeCommand(`${Package.name}.SidebarProvider.focus`) | ||
// Wait briefly for the view to become visible | ||
await delay(100) | ||
visibleProvider = ClineProvider.getVisibleInstance() | ||
try { | ||
await vscode.commands.executeCommand(`${Package.name}.SidebarProvider.focus`) | ||
// Wait a bit longer for the view to become visible and initialize | ||
await delay(500) | ||
visibleProvider = ClineProvider.getVisibleInstance() | ||
|
||
// If still not visible, wait a bit more as initialization might be slow | ||
if (!visibleProvider) { | ||
await delay(500) | ||
visibleProvider = ClineProvider.getVisibleInstance() | ||
} | ||
} catch (error) { | ||
console.error(`Failed to activate Roo Code sidebar: ${error}`) | ||
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. Is the double console output intentional? You have both console.error here and console.warn on line 490. Since the error is already being handled, perhaps one logging method would be sufficient? |
||
} | ||
} | ||
|
||
// If still no visible provider, return | ||
// If still no visible provider, return undefined | ||
if (!visibleProvider) { | ||
return | ||
console.warn("Could not get or create a visible ClineProvider instance") | ||
return undefined | ||
} | ||
|
||
return visibleProvider | ||
|
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.
The JSDoc could be more explicit about the retry behavior. Consider updating it to mention that it 'Attempts to activate the sidebar view if no provider is visible, with retry logic.'