mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
fix: prevent UI freeze when showing save dialogs
- Created safeDialogs utility with non-blocking wrappers for showSaveDialog and showOpenDialog - Updated all save/open dialog calls to use the safe wrappers - Uses setImmediate to defer dialog calls to next event loop iteration - Prevents VSCode UI from freezing on macOS with certain configurations Fixes #6870
This commit is contained in:
parent
ad0e33e2d9
commit
c101ed9507
5 changed files with 60 additions and 10 deletions
|
|
@ -5,6 +5,7 @@ import fs from "fs/promises"
|
|||
|
||||
import * as vscode from "vscode"
|
||||
import { z, ZodError } from "zod"
|
||||
import { showSaveDialogSafe, showOpenDialogSafe } from "../../utils/safeDialogs"
|
||||
|
||||
import { globalSettingsSchema } from "@roo-code/types"
|
||||
import { TelemetryService } from "@roo-code/telemetry"
|
||||
|
|
@ -109,7 +110,7 @@ export async function importSettingsFromPath(
|
|||
* @returns Promise resolving to import result
|
||||
*/
|
||||
export const importSettings = async ({ providerSettingsManager, contextProxy, customModesManager }: ImportOptions) => {
|
||||
const uris = await vscode.window.showOpenDialog({
|
||||
const uris = await showOpenDialogSafe({
|
||||
filters: { JSON: ["json"] },
|
||||
canSelectMany: false,
|
||||
})
|
||||
|
|
@ -143,7 +144,7 @@ export const importSettingsFromFile = async (
|
|||
}
|
||||
|
||||
export const exportSettings = async ({ providerSettingsManager, contextProxy }: ExportOptions) => {
|
||||
const uri = await vscode.window.showSaveDialog({
|
||||
const uri = await showSaveDialogSafe({
|
||||
filters: { JSON: ["json"] },
|
||||
defaultUri: vscode.Uri.file(path.join(os.homedir(), "Documents", "roo-code-settings.json")),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import * as fs from "fs/promises"
|
|||
import pWaitFor from "p-wait-for"
|
||||
import * as vscode from "vscode"
|
||||
import * as yaml from "yaml"
|
||||
import { showSaveDialogSafe, showOpenDialogSafe } from "../../utils/safeDialogs"
|
||||
|
||||
import {
|
||||
type Language,
|
||||
|
|
@ -1791,8 +1792,8 @@ export const webviewMessageHandler = async (
|
|||
}
|
||||
}
|
||||
|
||||
// Show save dialog
|
||||
const saveUri = await vscode.window.showSaveDialog({
|
||||
// Show save dialog using safe wrapper to prevent UI freezing
|
||||
const saveUri = await showSaveDialogSafe({
|
||||
defaultUri,
|
||||
filters: {
|
||||
"YAML files": ["yaml", "yml"],
|
||||
|
|
@ -1866,8 +1867,8 @@ export const webviewMessageHandler = async (
|
|||
}
|
||||
}
|
||||
|
||||
// Show file picker to select YAML file
|
||||
const fileUri = await vscode.window.showOpenDialog({
|
||||
// Show file picker to select YAML file using safe wrapper to prevent UI freezing
|
||||
const fileUri = await showOpenDialogSafe({
|
||||
canSelectFiles: true,
|
||||
canSelectFolders: false,
|
||||
canSelectMany: false,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Anthropic } from "@anthropic-ai/sdk"
|
|||
import os from "os"
|
||||
import * as path from "path"
|
||||
import * as vscode from "vscode"
|
||||
import { showSaveDialogSafe } from "../../utils/safeDialogs"
|
||||
|
||||
export async function downloadTask(dateTs: number, conversationHistory: Anthropic.MessageParam[]) {
|
||||
// File name
|
||||
|
|
@ -28,8 +29,8 @@ export async function downloadTask(dateTs: number, conversationHistory: Anthropi
|
|||
})
|
||||
.join("---\n\n")
|
||||
|
||||
// Prompt user for save location
|
||||
const saveUri = await vscode.window.showSaveDialog({
|
||||
// Prompt user for save location using safe wrapper to prevent UI freezing
|
||||
const saveUri = await showSaveDialogSafe({
|
||||
filters: { Markdown: ["md"] },
|
||||
defaultUri: vscode.Uri.file(path.join(os.homedir(), "Downloads", fileName)),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import * as os from "os"
|
|||
import * as vscode from "vscode"
|
||||
import { getWorkspacePath } from "../../utils/path"
|
||||
import { t } from "../../i18n"
|
||||
import { showSaveDialogSafe } from "../../utils/safeDialogs"
|
||||
|
||||
export async function openImage(dataUri: string, options?: { values?: { action?: string } }) {
|
||||
const matches = dataUri.match(/^data:image\/([a-zA-Z]+);base64,(.+)$/)
|
||||
|
|
@ -67,8 +68,8 @@ export async function saveImage(dataUri: string) {
|
|||
const defaultFileName = `mermaid_diagram_${Date.now()}.${format}`
|
||||
const defaultUri = vscode.Uri.file(path.join(defaultPath, defaultFileName))
|
||||
|
||||
// Show save dialog
|
||||
const saveUri = await vscode.window.showSaveDialog({
|
||||
// Show save dialog using safe wrapper to prevent UI freezing
|
||||
const saveUri = await showSaveDialogSafe({
|
||||
filters: {
|
||||
Images: [format],
|
||||
"All Files": ["*"],
|
||||
|
|
|
|||
46
src/utils/safeDialogs.ts
Normal file
46
src/utils/safeDialogs.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import * as vscode from "vscode"
|
||||
|
||||
/**
|
||||
* Wraps vscode.window.showSaveDialog in a non-blocking way to prevent UI freezing
|
||||
* This addresses the issue where the save dialog can cause the entire VSCode UI to freeze
|
||||
* on certain systems (particularly macOS with specific configurations).
|
||||
*
|
||||
* @param options - The save dialog options
|
||||
* @returns Promise that resolves to the selected URI or undefined if cancelled
|
||||
*/
|
||||
export async function showSaveDialogSafe(options: vscode.SaveDialogOptions): Promise<vscode.Uri | undefined> {
|
||||
// Use setImmediate to defer the dialog call to the next iteration of the event loop
|
||||
// This prevents the UI thread from being blocked
|
||||
return new Promise<vscode.Uri | undefined>((resolve) => {
|
||||
setImmediate(async () => {
|
||||
try {
|
||||
const result = await vscode.window.showSaveDialog(options)
|
||||
resolve(result)
|
||||
} catch (error) {
|
||||
console.error("Error showing save dialog:", error)
|
||||
resolve(undefined)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps vscode.window.showOpenDialog in a non-blocking way to prevent UI freezing
|
||||
*
|
||||
* @param options - The open dialog options
|
||||
* @returns Promise that resolves to the selected URIs or undefined if cancelled
|
||||
*/
|
||||
export async function showOpenDialogSafe(options: vscode.OpenDialogOptions): Promise<vscode.Uri[] | undefined> {
|
||||
// Use setImmediate to defer the dialog call to the next iteration of the event loop
|
||||
return new Promise<vscode.Uri[] | undefined>((resolve) => {
|
||||
setImmediate(async () => {
|
||||
try {
|
||||
const result = await vscode.window.showOpenDialog(options)
|
||||
resolve(result)
|
||||
} catch (error) {
|
||||
console.error("Error showing open dialog:", error)
|
||||
resolve(undefined)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue