-
Notifications
You must be signed in to change notification settings - Fork 290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Chat: preserve unsent chat messages when switching tabs #5847
base: main
Are you sure you want to change the base?
Changes from all commits
c313ad4
2a84329
fdce59a
36500c1
ff038cb
b527447
8e8759f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,20 @@ | ||
import { type AuthStatus, type ClientCapabilities, CodyIDE } from '@sourcegraph/cody-shared' | ||
import { | ||
type AuthStatus, | ||
type ChatMessage, | ||
type ClientCapabilities, | ||
CodyIDE, | ||
type SerializedPromptEditorValue, | ||
} from '@sourcegraph/cody-shared' | ||
import type React from 'react' | ||
import { type ComponentProps, type FunctionComponent, useMemo, useRef } from 'react' | ||
import { | ||
type ComponentProps, | ||
type FunctionComponent, | ||
useCallback, | ||
useEffect, | ||
useMemo, | ||
useRef, | ||
useState, | ||
} from 'react' | ||
import type { ConfigurationSubsetForWebview, LocalEnv } from '../src/chat/protocol' | ||
import styles from './App.module.css' | ||
import { Chat } from './Chat' | ||
|
@@ -55,6 +69,39 @@ export const CodyPanel: FunctionComponent< | |
}) => { | ||
const tabContainerRef = useRef<HTMLDivElement>(null) | ||
|
||
const [activeTranscript, setActiveTranscript] = useState<ChatMessage[] | undefined>(transcript) | ||
const [storedTranscriptState, setStoredTranscriptState] = useState(transcript) | ||
|
||
// Update the Transcript State for each input box value change. | ||
const updateEditorStateOnChange = useCallback( | ||
(index: number, newEditorValue: SerializedPromptEditorValue) => { | ||
setStoredTranscriptState(prev => { | ||
const updated = [...prev] | ||
updated[index] = { | ||
...updated[index], | ||
editorState: newEditorValue.editorState, | ||
speaker: 'human', | ||
} | ||
return updated | ||
}) | ||
}, | ||
[] | ||
) | ||
|
||
// Reset transcripts on new transcript change. | ||
useEffect(() => { | ||
setActiveTranscript(undefined) | ||
setStoredTranscriptState(transcript) | ||
}, [transcript]) | ||
|
||
// Set the current transcript to the transcript with the last stored editor states when switching to a different tab. | ||
// This ensures the editor states are preserved when switching back to the chat tab. | ||
useEffect(() => { | ||
if (view !== View.Chat) { | ||
setActiveTranscript(storedTranscriptState) | ||
} | ||
}, [view, storedTranscriptState]) | ||
|
||
return ( | ||
<TabViewContext.Provider value={useMemo(() => ({ view, setView }), [view, setView])}> | ||
<TabRoot | ||
|
@@ -76,9 +123,10 @@ export const CodyPanel: FunctionComponent< | |
<TabContainer value={view} ref={tabContainerRef}> | ||
{view === View.Chat && ( | ||
<Chat | ||
transcript={activeTranscript ?? transcript} | ||
updateEditorStateOnChange={updateEditorStateOnChange} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the activeTranscript ?? transcript won't work when we want to preserve input text in the follow up message There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we are only saving the input text state but we don't want to use it until the user has switched to another tab. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, but do we want to preserve text in the following scenario?
|
||
chatEnabled={chatEnabled} | ||
messageInProgress={messageInProgress} | ||
transcript={transcript} | ||
vscodeAPI={vscodeAPI} | ||
guardrails={attributionEnabled ? guardrails : undefined} | ||
showIDESnippetActions={showIDESnippetActions} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is the most weak spot of this change, syncing state might be very fragile and unsafe.
I guess because of this we have UI flashes, I checked it manually and I was able to see some UI
delays (when you submit the message but don't see the loading UI below the input)
The main case with switching from the welcome chat screen to history and back to chat produces
a chat UI with no welcome UI
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was the expected behavior to me because the user has already typed something in with the updated state, so transcript.length is no longer 0, which would not trigger the welcome message. I agree it's confusing though. will update it to change that.