Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 37 additions & 7 deletions webview-ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ const App = () => {
messageTs: 0,
})

/**
* 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<boolean>(false)

const [editMessageDialogState, setEditMessageDialogState] = useState<EditMessageDialogState>({
isOpen: false,
messageTs: 0,
Expand Down Expand Up @@ -125,6 +132,32 @@ const App = () => {
const [currentSection, setCurrentSection] = useState<string | undefined>(undefined)
const [currentMarketplaceTab, setCurrentMarketplaceTab] = useState<string | undefined>(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
Expand Down Expand Up @@ -160,19 +193,14 @@ const App = () => {
}

if (message.type === "showEditMessageDialog" && message.messageTs && message.text) {
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)
Expand Down Expand Up @@ -283,6 +311,8 @@ const App = () => {
open={editMessageDialogState.isOpen}
onOpenChange={(open) => setEditMessageDialogState((prev) => ({ ...prev, isOpen: open }))}
onConfirm={() => {
// Mark that the user has seen the edit warning in this session
hasSeenEditWarningInSessionRef.current = true
vscode.postMessage({
type: "editMessageConfirm",
messageTs: editMessageDialogState.messageTs,
Expand Down
19 changes: 17 additions & 2 deletions webview-ui/src/components/chat/ChatRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<ClineApiReqInfo>(message.text)
Expand Down Expand Up @@ -1059,6 +1069,7 @@ export const ChatRowContent = ({
</div>
)
case "user_feedback":
// For user feedback messages, always allow editing
return (
<div className="bg-vscode-editor-background border rounded-xs p-1 overflow-hidden whitespace-pre-wrap">
{isEditing ? (
Expand All @@ -1083,15 +1094,19 @@ export const ChatRowContent = ({
</div>
) : (
<div className="flex justify-between">
<div className="flex-grow px-2 py-1 wrap-anywhere">
<div
className="flex-grow px-2 py-1 wrap-anywhere cursor-pointer"
onDoubleClick={handleDoubleClick}
title={t("chat:editMessage.doubleClickToEdit")}>
<Mention text={message.text} withShadow />
</div>
<div className="flex">
<Button
variant="ghost"
size="icon"
className="shrink-0 hidden"
className="shrink-0"
disabled={isStreaming}
title={t("chat:editMessage.editButton")}
onClick={(e) => {
e.stopPropagation()
handleEditClick()
Expand Down
8 changes: 5 additions & 3 deletions webview-ui/src/i18n/locales/ca/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions webview-ui/src/i18n/locales/de/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/en/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@
"tooltip": "Cancel the current operation"
},
"editMessage": {
"placeholder": "Edit your message..."
"placeholder": "Edit your message...",
"doubleClickToEdit": "Double-click to edit message",
"editButton": "Edit message"
},
"scrollToBottom": "Scroll to bottom of chat",
"about": "Generate, refactor, and debug code with AI assistance. Check out our <DocsLink>documentation</DocsLink> to learn more.",
Expand Down
8 changes: 5 additions & 3 deletions webview-ui/src/i18n/locales/es/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions webview-ui/src/i18n/locales/fr/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions webview-ui/src/i18n/locales/hi/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/id/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/it/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/ja/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/ko/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/nl/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/pl/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/pt-BR/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/ru/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/tr/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/vi/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/zh-CN/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/zh-TW/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.