diff --git a/webview-ui/src/components/prompts/PromptsView.tsx b/webview-ui/src/components/prompts/PromptsView.tsx index 61c61490e7..c399f79156 100644 --- a/webview-ui/src/components/prompts/PromptsView.tsx +++ b/webview-ui/src/components/prompts/PromptsView.tsx @@ -60,6 +60,13 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { customModes, } = useExtensionState() + // Use a local state to track the visually active mode + // This prevents flickering when switching modes rapidly by: + // 1. Updating the UI immediately when a mode is clicked + // 2. Not syncing with the backend mode state (which would cause flickering) + // 3. Still sending the mode change to the backend for persistence + const [visualMode, setVisualMode] = useState(mode) + // Memoize modes to preserve array order const modes = useMemo(() => getAllModes(customModes), [customModes]) @@ -126,22 +133,25 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { // Handle mode switching with explicit state initialization const handleModeSwitch = useCallback( (modeConfig: ModeConfig) => { - if (modeConfig.slug === mode) return // Prevent unnecessary updates + if (modeConfig.slug === visualMode) return // Prevent unnecessary updates + + // Immediately update visual state for instant feedback + setVisualMode(modeConfig.slug) - // First switch the mode + // Then send the mode change message to the backend switchMode(modeConfig.slug) // Exit tools edit mode when switching modes setIsToolsEditMode(false) }, - [mode, switchMode, setIsToolsEditMode], + [visualMode, switchMode, setIsToolsEditMode], ) // Helper function to get current mode's config const getCurrentMode = useCallback((): ModeConfig | undefined => { - const findMode = (m: ModeConfig): boolean => m.slug === mode + const findMode = (m: ModeConfig): boolean => m.slug === visualMode return customModes?.find(findMode) || modes.find(findMode) - }, [mode, customModes, modes]) + }, [visualMode, customModes, modes]) // Helper function to safely access mode properties const getModeProperty = ( @@ -472,7 +482,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
{modes.map((modeConfig) => { - const isActive = mode === modeConfig.slug + const isActive = visualMode === modeConfig.slug return (
{ - const customMode = findModeBySlug(mode, customModes) - const prompt = customModePrompts?.[mode] as PromptComponent - return customMode?.roleDefinition ?? prompt?.roleDefinition ?? getRoleDefinition(mode) + const customMode = findModeBySlug(visualMode, customModes) + const prompt = customModePrompts?.[visualMode] as PromptComponent + return customMode?.roleDefinition ?? prompt?.roleDefinition ?? getRoleDefinition(visualMode) })()} onChange={(e) => { const value = (e as CustomEvent)?.detail?.target?.value || ((e as any).target as HTMLTextAreaElement).value - const customMode = findModeBySlug(mode, customModes) + const customMode = findModeBySlug(visualMode, customModes) if (customMode) { // For custom modes, update the JSON file - updateCustomMode(mode, { + updateCustomMode(visualMode, { ...customMode, roleDefinition: value.trim() || "", source: customMode.source || "global", }) } else { // For built-in modes, update the prompts - updateAgentPrompt(mode, { + updateAgentPrompt(visualMode, { roleDefinition: value.trim() || undefined, }) } @@ -617,7 +627,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
{t("prompts:tools.title")}
- {findModeBySlug(mode, customModes) && ( + {findModeBySlug(visualMode, customModes) && ( )}
- {!findModeBySlug(mode, customModes) && ( + {!findModeBySlug(visualMode, customModes) && (
{t("prompts:tools.builtInModesText")}
)} - {isToolsEditMode && findModeBySlug(mode, customModes) ? ( + {isToolsEditMode && findModeBySlug(visualMode, customModes) ? (
{availableGroups.map((group) => { const currentMode = getCurrentMode() - const isCustomMode = findModeBySlug(mode, customModes) + const isCustomMode = findModeBySlug(visualMode, customModes) const customMode = isCustomMode const isGroupEnabled = isCustomMode ? customMode?.groups?.some((g) => getGroupName(g) === group) @@ -710,7 +720,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { marginBottom: "4px", }}>
{t("prompts:customInstructions.title")}
- {!findModeBySlug(mode, customModes) && ( + {!findModeBySlug(visualMode, customModes) && (
{ - const customMode = findModeBySlug(mode, customModes) - const prompt = customModePrompts?.[mode] as PromptComponent + const customMode = findModeBySlug(visualMode, customModes) + const prompt = customModePrompts?.[visualMode] as PromptComponent return ( customMode?.customInstructions ?? prompt?.customInstructions ?? @@ -750,18 +760,18 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { const value = (e as CustomEvent)?.detail?.target?.value || ((e as any).target as HTMLTextAreaElement).value - const customMode = findModeBySlug(mode, customModes) + const customMode = findModeBySlug(visualMode, customModes) if (customMode) { // For custom modes, update the JSON file - updateCustomMode(mode, { + updateCustomMode(visualMode, { ...customMode, customInstructions: value.trim() || undefined, source: customMode.source || "global", }) } else { // For built-in modes, update the prompts - const existingPrompt = customModePrompts?.[mode] as PromptComponent - updateAgentPrompt(mode, { + const existingPrompt = customModePrompts?.[visualMode] as PromptComponent + updateAgentPrompt(visualMode, { ...existingPrompt, customInstructions: value.trim(), })