From 016a345d4f2d1dda65b15fbffaa5cce04dc645a8 Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Thu, 24 Jul 2025 17:58:10 -0500 Subject: [PATCH] fix: improve edit message functionality and add translations - Add TypeScript documentation for hasSeenEditWarningInSessionRef - Rename ref to hasSeenEditWarningInSessionRef for clarity - Consolidate edit warning logic into handleEditMessageDialog callback - Simplify double-click handler to use native React onDoubleClick event - Remove select-none class to allow text selection while maintaining double-click edit - Add tooltips for double-click area and edit button - Add translations for new tooltip strings in all 17 supported languages - Fix duplicate key errors in translation 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/id/chat.json | 8 +-- webview-ui/src/i18n/locales/it/chat.json | 8 +-- webview-ui/src/i18n/locales/ja/chat.json | 8 +-- webview-ui/src/i18n/locales/ko/chat.json | 10 ++-- webview-ui/src/i18n/locales/nl/chat.json | 8 +-- webview-ui/src/i18n/locales/pl/chat.json | 8 +-- webview-ui/src/i18n/locales/pt-BR/chat.json | 8 +-- webview-ui/src/i18n/locales/ru/chat.json | 8 +-- webview-ui/src/i18n/locales/tr/chat.json | 8 +-- webview-ui/src/i18n/locales/vi/chat.json | 8 +-- webview-ui/src/i18n/locales/zh-CN/chat.json | 8 +-- webview-ui/src/i18n/locales/zh-TW/chat.json | 4 +- 20 files changed, 139 insertions(+), 79 deletions(-) diff --git a/webview-ui/src/App.tsx b/webview-ui/src/App.tsx index b505a85250..8e0c2220e2 100644 --- a/webview-ui/src/App.tsx +++ b/webview-ui/src/App.tsx @@ -91,8 +91,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, @@ -126,6 +130,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 @@ -161,30 +191,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) @@ -281,8 +295,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 37ec59a478..7db38eaf6b 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) @@ -1058,6 +1068,7 @@ export const ChatRowContent = ({ ) case "user_feedback": + // For user feedback messages, always allow editing return (
{isEditing ? ( @@ -1083,19 +1094,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")}>