From 983deaf697712fb5c797be282672387ee965b9af Mon Sep 17 00:00:00 2001 From: Eric Wheeler Date: Tue, 22 Jul 2025 01:33:54 -0700 Subject: [PATCH 1/3] fix: persist edit warning dialog preference during session This change fixes the issue where the edit warning dialog appears on every edit, even after the user has already seen it once. The solution: 1. Uses a React ref to store the preference in memory during the session 2. Bypasses the dialog if the user has already seen it 3. Adds double-click functionality to user messages for quick editing The preference is reset when the VS Code window is reloaded, ensuring users are reminded of the warning after a restart. Fixes: #6058 Signed-off-by: Eric Wheeler --- webview-ui/src/App.tsx | 28 +++++++++++++++++----- webview-ui/src/components/chat/ChatRow.tsx | 7 +++++- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/webview-ui/src/App.tsx b/webview-ui/src/App.tsx index 3782242707c..3cf578a4824 100644 --- a/webview-ui/src/App.tsx +++ b/webview-ui/src/App.tsx @@ -93,6 +93,9 @@ const App = () => { messageTs: 0, }) + // Track if the user has seen the edit warning - using ref to persist across renders + const hasSeenEditWarningRef = useRef(false) + const [editMessageDialogState, setEditMessageDialogState] = useState({ isOpen: false, messageTs: 0, @@ -160,12 +163,23 @@ const App = () => { } if (message.type === "showEditMessageDialog" && message.messageTs && message.text) { - setEditMessageDialogState({ - isOpen: true, - messageTs: message.messageTs, - text: message.text, - images: message.images || [], - }) + // If the user has already seen the warning, skip the dialog and directly edit + if (hasSeenEditWarningRef.current) { + vscode.postMessage({ + type: "editMessageConfirm", + messageTs: message.messageTs, + text: message.text, + images: message.images || [], + }) + } else { + // Show the warning dialog for the first time + setEditMessageDialogState({ + isOpen: true, + messageTs: message.messageTs, + text: message.text, + images: message.images || [], + }) + } } if (message.type === "acceptInput") { @@ -283,6 +297,8 @@ const App = () => { open={editMessageDialogState.isOpen} onOpenChange={(open) => setEditMessageDialogState((prev) => ({ ...prev, isOpen: open }))} onConfirm={() => { + // Mark that the user has seen the edit warning + hasSeenEditWarningRef.current = true vscode.postMessage({ type: "editMessageConfirm", messageTs: editMessageDialogState.messageTs, diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index 4fa921f4435..43058491d20 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -1083,7 +1083,12 @@ export const ChatRowContent = ({ ) : (
-
+
{ + e.stopPropagation() + handleEditClick() + }}>
From dc1e36f4b8f6e692e75445dd99b30a9f94595f8c Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Thu, 24 Jul 2025 17:58:10 -0500 Subject: [PATCH 2/3] fix: resolve merge conflicts in i18n locale files --- webview-ui/src/App.tsx | 58 +++++++++++++-------- webview-ui/src/components/chat/ChatRow.tsx | 22 +++++--- webview-ui/src/i18n/locales/ca/chat.json | 8 +-- webview-ui/src/i18n/locales/de/chat.json | 8 +-- webview-ui/src/i18n/locales/en/chat.json | 4 +- webview-ui/src/i18n/locales/es/chat.json | 8 +-- webview-ui/src/i18n/locales/fr/chat.json | 8 +-- webview-ui/src/i18n/locales/hi/chat.json | 8 +-- webview-ui/src/i18n/locales/zh-TW/chat.json | 4 +- 9 files changed, 83 insertions(+), 45 deletions(-) diff --git a/webview-ui/src/App.tsx b/webview-ui/src/App.tsx index 3cf578a4824..7e863cf9bf6 100644 --- a/webview-ui/src/App.tsx +++ b/webview-ui/src/App.tsx @@ -93,8 +93,12 @@ const App = () => { messageTs: 0, }) - // Track if the user has seen the edit warning - using ref to persist across renders - const hasSeenEditWarningRef = useRef(false) + /** + * Tracks whether the user has seen the edit warning dialog during the current session. + * Uses a ref to persist the value across renders without triggering re-renders. + * Resets when the VS Code window is reloaded. + */ + const hasSeenEditWarningInSessionRef = useRef(false) const [editMessageDialogState, setEditMessageDialogState] = useState({ isOpen: false, @@ -128,6 +132,32 @@ const App = () => { const [currentSection, setCurrentSection] = useState(undefined) const [currentMarketplaceTab, setCurrentMarketplaceTab] = useState(undefined) + /** + * Handles the edit message dialog logic, determining whether to show the warning + * or proceed directly to editing based on session state. + */ + const handleEditMessageDialog = useCallback((message: ExtensionMessage) => { + if (!message.messageTs || !message.text) return + + // If the user has already seen the warning in this session, skip the dialog + if (hasSeenEditWarningInSessionRef.current) { + vscode.postMessage({ + type: "editMessageConfirm", + messageTs: message.messageTs, + text: message.text, + images: message.images || [], + }) + } else { + // Show the warning dialog for the first time in this session + setEditMessageDialogState({ + isOpen: true, + messageTs: message.messageTs, + text: message.text, + images: message.images || [], + }) + } + }, []) + const onMessage = useCallback( (e: MessageEvent) => { const message: ExtensionMessage = e.data @@ -163,30 +193,14 @@ const App = () => { } if (message.type === "showEditMessageDialog" && message.messageTs && message.text) { - // If the user has already seen the warning, skip the dialog and directly edit - if (hasSeenEditWarningRef.current) { - vscode.postMessage({ - type: "editMessageConfirm", - messageTs: message.messageTs, - text: message.text, - images: message.images || [], - }) - } else { - // Show the warning dialog for the first time - setEditMessageDialogState({ - isOpen: true, - messageTs: message.messageTs, - text: message.text, - images: message.images || [], - }) - } + handleEditMessageDialog(message) } if (message.type === "acceptInput") { chatViewRef.current?.acceptInput() } }, - [switchTab], + [switchTab, handleEditMessageDialog], ) useEvent("message", onMessage) @@ -297,8 +311,8 @@ const App = () => { open={editMessageDialogState.isOpen} onOpenChange={(open) => setEditMessageDialogState((prev) => ({ ...prev, isOpen: open }))} onConfirm={() => { - // Mark that the user has seen the edit warning - hasSeenEditWarningRef.current = true + // Mark that the user has seen the edit warning in this session + hasSeenEditWarningInSessionRef.current = true vscode.postMessage({ type: "editMessageConfirm", messageTs: editMessageDialogState.messageTs, diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index 43058491d20..37bc543dd7d 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -177,6 +177,16 @@ export const ChatRowContent = ({ vscode.postMessage({ type: "selectImages", context: "edit", messageTs: message.ts }) }, [message.ts]) + // Simple double-click handler + const handleDoubleClick = useCallback( + (e: React.MouseEvent) => { + e.stopPropagation() + e.preventDefault() + handleEditClick() + }, + [handleEditClick], + ) + const [cost, apiReqCancelReason, apiReqStreamingFailedMessage] = useMemo(() => { if (message.text !== null && message.text !== undefined && message.say === "api_req_started") { const info = safeJsonParse(message.text) @@ -1059,6 +1069,7 @@ export const ChatRowContent = ({
) case "user_feedback": + // For user feedback messages, always allow editing return (
{isEditing ? ( @@ -1084,19 +1095,18 @@ export const ChatRowContent = ({ ) : (
{ - e.stopPropagation() - handleEditClick() - }}> + className="flex-grow px-2 py-1 wrap-anywhere cursor-pointer" + onDoubleClick={handleDoubleClick} + title={t("chat:editMessage.doubleClickToEdit")}>