Browse Source

fix: improve save button activation in prompts settings (#5780) (#8267)

Co-authored-by: MuriloFP <[email protected]>
Co-authored-by: Roo Code <[email protected]>
Co-authored-by: daniel-lxs <[email protected]>
roomote[bot] 3 months ago
parent
commit
1de480b383

+ 9 - 8
webview-ui/src/components/modes/ModesView.tsx

@@ -849,7 +849,7 @@ const ModesView = ({ onDone }: ModesViewProps) => {
 							})()}
 							onChange={(e) => {
 								const value =
-									(e as unknown as CustomEvent)?.detail?.target?.value ||
+									(e as unknown as CustomEvent)?.detail?.target?.value ??
 									((e as any).target as HTMLTextAreaElement).value
 								const customMode = findModeBySlug(visualMode, customModes)
 								if (customMode) {
@@ -904,7 +904,7 @@ const ModesView = ({ onDone }: ModesViewProps) => {
 							})()}
 							onChange={(e) => {
 								const value =
-									(e as unknown as CustomEvent)?.detail?.target?.value ||
+									(e as unknown as CustomEvent)?.detail?.target?.value ??
 									((e as any).target as HTMLTextAreaElement).value
 								const customMode = findModeBySlug(visualMode, customModes)
 								if (customMode) {
@@ -959,7 +959,7 @@ const ModesView = ({ onDone }: ModesViewProps) => {
 							})()}
 							onChange={(e) => {
 								const value =
-									(e as unknown as CustomEvent)?.detail?.target?.value ||
+									(e as unknown as CustomEvent)?.detail?.target?.value ??
 									((e as any).target as HTMLTextAreaElement).value
 								const customMode = findModeBySlug(visualMode, customModes)
 								if (customMode) {
@@ -1118,14 +1118,15 @@ const ModesView = ({ onDone }: ModesViewProps) => {
 							})()}
 							onChange={(e) => {
 								const value =
-									(e as unknown as CustomEvent)?.detail?.target?.value ||
+									(e as unknown as CustomEvent)?.detail?.target?.value ??
 									((e as any).target as HTMLTextAreaElement).value
 								const customMode = findModeBySlug(visualMode, customModes)
 								if (customMode) {
 									// For custom modes, update the JSON file
 									updateCustomMode(visualMode, {
 										...customMode,
-										customInstructions: value.trim() || undefined,
+										// Preserve empty string; only treat null/undefined as unset
+										customInstructions: value ?? undefined,
 										source: customMode.source || "global",
 									})
 								} else {
@@ -1335,12 +1336,12 @@ const ModesView = ({ onDone }: ModesViewProps) => {
 						value={customInstructions || ""}
 						onChange={(e) => {
 							const value =
-								(e as unknown as CustomEvent)?.detail?.target?.value ||
+								(e as unknown as CustomEvent)?.detail?.target?.value ??
 								((e as any).target as HTMLTextAreaElement).value
-							setCustomInstructions(value || undefined)
+							setCustomInstructions(value ?? undefined)
 							vscode.postMessage({
 								type: "customInstructions",
-								text: value.trim() || undefined,
+								text: value ?? undefined,
 							})
 						}}
 						rows={4}

+ 5 - 4
webview-ui/src/components/modes/__tests__/ModesView.spec.tsx

@@ -223,12 +223,13 @@ describe("PromptsView", () => {
 		const changeEvent = new Event("change", { bubbles: true })
 		fireEvent(textarea, changeEvent)
 
-		// The component calls setCustomInstructions with value || undefined
-		// Since empty string is falsy, it should be undefined
-		expect(setCustomInstructions).toHaveBeenCalledWith(undefined)
+		// The component calls setCustomInstructions with value ?? undefined
+		// With nullish coalescing, empty string is preserved (not treated as nullish)
+		expect(setCustomInstructions).toHaveBeenCalledWith("")
+		// The postMessage call will have multiple calls, we need to check the right one
 		expect(vscode.postMessage).toHaveBeenCalledWith({
 			type: "customInstructions",
-			text: undefined,
+			text: "", // empty string is now preserved with ?? operator
 		})
 	})
 

+ 29 - 8
webview-ui/src/components/settings/PromptsSettings.tsx

@@ -69,14 +69,31 @@ const PromptsSettings = ({
 	}, [])
 
 	const updateSupportPrompt = (type: SupportPromptType, value: string | undefined) => {
+		// Don't trim during editing to preserve intentional whitespace
+		// Use nullish coalescing to preserve empty strings
+		const finalValue = value ?? undefined
+
 		if (type === "CONDENSE") {
-			setCustomCondensingPrompt(value || supportPrompt.default.CONDENSE)
+			setCustomCondensingPrompt(finalValue ?? supportPrompt.default.CONDENSE)
 			vscode.postMessage({
 				type: "updateCondensingPrompt",
-				text: value || supportPrompt.default.CONDENSE,
+				text: finalValue ?? supportPrompt.default.CONDENSE,
 			})
+			// Also update the customSupportPrompts to trigger change detection
+			const updatedPrompts = { ...customSupportPrompts }
+			if (finalValue === undefined) {
+				delete updatedPrompts[type]
+			} else {
+				updatedPrompts[type] = finalValue
+			}
+			setCustomSupportPrompts(updatedPrompts)
 		} else {
-			const updatedPrompts = { ...customSupportPrompts, [type]: value }
+			const updatedPrompts = { ...customSupportPrompts }
+			if (finalValue === undefined) {
+				delete updatedPrompts[type]
+			} else {
+				updatedPrompts[type] = finalValue
+			}
 			setCustomSupportPrompts(updatedPrompts)
 		}
 	}
@@ -88,6 +105,10 @@ const PromptsSettings = ({
 				type: "updateCondensingPrompt",
 				text: supportPrompt.default.CONDENSE,
 			})
+			// Also update the customSupportPrompts to trigger change detection
+			const updatedPrompts = { ...customSupportPrompts }
+			delete updatedPrompts[type]
+			setCustomSupportPrompts(updatedPrompts)
 		} else {
 			const updatedPrompts = { ...customSupportPrompts }
 			delete updatedPrompts[type]
@@ -97,7 +118,8 @@ const PromptsSettings = ({
 
 	const getSupportPromptValue = (type: SupportPromptType): string => {
 		if (type === "CONDENSE") {
-			return customCondensingPrompt || supportPrompt.default.CONDENSE
+			// Preserve empty string - only fall back to default when value is nullish
+			return customCondensingPrompt ?? supportPrompt.default.CONDENSE
 		}
 		return supportPrompt.get(customSupportPrompts, type)
 	}
@@ -158,12 +180,11 @@ const PromptsSettings = ({
 					<VSCodeTextArea
 						resize="vertical"
 						value={getSupportPromptValue(activeSupportOption)}
-						onChange={(e) => {
+						onInput={(e) => {
 							const value =
-								(e as unknown as CustomEvent)?.detail?.target?.value ||
+								(e as unknown as CustomEvent)?.detail?.target?.value ??
 								((e as any).target as HTMLTextAreaElement).value
-							const trimmedValue = value.trim()
-							updateSupportPrompt(activeSupportOption, trimmedValue || undefined)
+							updateSupportPrompt(activeSupportOption, value)
 						}}
 						rows={6}
 						className="w-full"