|
|
@@ -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 = <T extends keyof ModeConfig>(
|
|
|
@@ -472,7 +482,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
|
|
|
|
|
|
<div className="flex gap-2 items-center mb-3 flex-wrap py-1">
|
|
|
{modes.map((modeConfig) => {
|
|
|
- const isActive = mode === modeConfig.slug
|
|
|
+ const isActive = visualMode === modeConfig.slug
|
|
|
return (
|
|
|
<button
|
|
|
key={modeConfig.slug}
|
|
|
@@ -493,20 +503,20 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
|
|
|
|
|
|
<div style={{ marginBottom: "20px" }}>
|
|
|
{/* Only show name and delete for custom modes */}
|
|
|
- {mode && findModeBySlug(mode, customModes) && (
|
|
|
+ {visualMode && findModeBySlug(visualMode, customModes) && (
|
|
|
<div className="flex gap-3 mb-4">
|
|
|
<div className="flex-1">
|
|
|
<div className="font-bold mb-1">{t("prompts:createModeDialog.name.label")}</div>
|
|
|
<div className="flex gap-2">
|
|
|
<VSCodeTextField
|
|
|
- value={getModeProperty(findModeBySlug(mode, customModes), "name") ?? ""}
|
|
|
+ value={getModeProperty(findModeBySlug(visualMode, customModes), "name") ?? ""}
|
|
|
onChange={(e: Event | React.FormEvent<HTMLElement>) => {
|
|
|
const target =
|
|
|
(e as CustomEvent)?.detail?.target ||
|
|
|
((e as any).target as HTMLInputElement)
|
|
|
- const customMode = findModeBySlug(mode, customModes)
|
|
|
+ const customMode = findModeBySlug(visualMode, customModes)
|
|
|
if (customMode) {
|
|
|
- updateCustomMode(mode, {
|
|
|
+ updateCustomMode(visualMode, {
|
|
|
...customMode,
|
|
|
name: target.value,
|
|
|
source: customMode.source || "global",
|
|
|
@@ -522,7 +532,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
|
|
|
onClick={() => {
|
|
|
vscode.postMessage({
|
|
|
type: "deleteCustomMode",
|
|
|
- slug: mode,
|
|
|
+ slug: visualMode,
|
|
|
})
|
|
|
}}>
|
|
|
<span className="codicon codicon-trash"></span>
|
|
|
@@ -534,7 +544,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
|
|
|
<div style={{ marginBottom: "16px" }}>
|
|
|
<div className="flex justify-between items-center mb-1">
|
|
|
<div className="font-bold">{t("prompts:roleDefinition.title")}</div>
|
|
|
- {!findModeBySlug(mode, customModes) && (
|
|
|
+ {!findModeBySlug(visualMode, customModes) && (
|
|
|
<Button
|
|
|
variant="ghost"
|
|
|
size="icon"
|
|
|
@@ -555,25 +565,25 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
|
|
|
</div>
|
|
|
<VSCodeTextArea
|
|
|
value={(() => {
|
|
|
- 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) => {
|
|
|
<div className="mb-4">
|
|
|
<div className="flex justify-between items-center mb-1">
|
|
|
<div className="font-bold">{t("prompts:tools.title")}</div>
|
|
|
- {findModeBySlug(mode, customModes) && (
|
|
|
+ {findModeBySlug(visualMode, customModes) && (
|
|
|
<Button
|
|
|
variant="ghost"
|
|
|
size="icon"
|
|
|
@@ -632,16 +642,16 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
|
|
|
</Button>
|
|
|
)}
|
|
|
</div>
|
|
|
- {!findModeBySlug(mode, customModes) && (
|
|
|
+ {!findModeBySlug(visualMode, customModes) && (
|
|
|
<div className="text-sm text-vscode-descriptionForeground mb-2">
|
|
|
{t("prompts:tools.builtInModesText")}
|
|
|
</div>
|
|
|
)}
|
|
|
- {isToolsEditMode && findModeBySlug(mode, customModes) ? (
|
|
|
+ {isToolsEditMode && findModeBySlug(visualMode, customModes) ? (
|
|
|
<div className="grid grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-2">
|
|
|
{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",
|
|
|
}}>
|
|
|
<div style={{ fontWeight: "bold" }}>{t("prompts:customInstructions.title")}</div>
|
|
|
- {!findModeBySlug(mode, customModes) && (
|
|
|
+ {!findModeBySlug(visualMode, customModes) && (
|
|
|
<Button
|
|
|
variant="ghost"
|
|
|
size="icon"
|
|
|
@@ -738,8 +748,8 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
|
|
|
</div>
|
|
|
<VSCodeTextArea
|
|
|
value={(() => {
|
|
|
- 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(),
|
|
|
})
|