This commit is contained in:
josc146
2024-08-04 13:37:43 +08:00
parent 817385f080
commit 226fb108a1
21 changed files with 115 additions and 124 deletions
+52 -28
View File
@@ -9,6 +9,7 @@ import {
DesktopDownloadIcon,
LinkExternalIcon,
MoveToBottomIcon,
SearchIcon,
} from '@primer/octicons-react'
import { Pin, WindowDesktop, XLg } from 'react-bootstrap-icons'
import FileSaver from 'file-saver'
@@ -46,6 +47,7 @@ function ConversationCard(props) {
const { t } = useTranslation()
const [isReady, setIsReady] = useState(!props.question)
const [port, setPort] = useState(() => Browser.runtime.connect())
const [triggered, setTriggered] = useState(!props.waitForTrigger)
const [session, setSession] = useState(props.session)
const windowSize = useClampWindowSize([750, 1500], [250, 1100])
const bodyRef = useRef(null)
@@ -59,7 +61,7 @@ function ConversationCard(props) {
const [conversationItemData, setConversationItemData] = useState(
(() => {
if (session.conversationRecords.length === 0)
if (props.question)
if (props.question && triggered)
return [
new ConversationItemData(
'answer',
@@ -102,12 +104,12 @@ function ConversationCard(props) {
useEffect(async () => {
// when the page is responsive, session may accumulate redundant data and needs to be cleared after remounting and before making a new request
if (props.question) {
if (props.question && triggered) {
const newSession = initSession({ ...session, question: props.question })
setSession(newSession)
await postMessage({ session: newSession })
}
}, [props.question]) // usually only triggered once
}, [props.question, triggered]) // usually only triggered once
/**
* @param {string} value
@@ -516,32 +518,53 @@ function ConversationCard(props) {
/>
))}
</div>
<InputBox
enabled={isReady}
postMessage={postMessage}
reverseResizeDir={props.pageMode}
onSubmit={async (question) => {
const newQuestion = new ConversationItemData('question', question)
const newAnswer = new ConversationItemData(
'answer',
`<p class="gpt-loading">${t('Waiting for response...')}</p>`,
)
setConversationItemData([...conversationItemData, newQuestion, newAnswer])
setIsReady(false)
{props.waitForTrigger && !triggered ? (
<p
className="manual-btn"
style={{ display: 'flex', justifyContent: 'center' }}
onClick={() => {
setConversationItemData([
new ConversationItemData(
'answer',
`<p class="gpt-loading">${t(`Waiting for response...`)}</p>`,
),
])
setTriggered(true)
setIsReady(false)
}}
>
<span className="icon-and-text">
<SearchIcon size="small" /> {t('Ask ChatGPT')}
</span>
</p>
) : (
<InputBox
enabled={isReady}
postMessage={postMessage}
reverseResizeDir={props.pageMode}
onSubmit={async (question) => {
const newQuestion = new ConversationItemData('question', question)
const newAnswer = new ConversationItemData(
'answer',
`<p class="gpt-loading">${t('Waiting for response...')}</p>`,
)
setConversationItemData([...conversationItemData, newQuestion, newAnswer])
setIsReady(false)
const newSession = { ...session, question, isRetry: false }
setSession(newSession)
try {
await postMessage({ session: newSession })
} catch (e) {
updateAnswer(e, false, 'error')
}
bodyRef.current.scrollTo({
top: bodyRef.current.scrollHeight,
behavior: 'instant',
})
}}
/>
const newSession = { ...session, question, isRetry: false }
setSession(newSession)
try {
await postMessage({ session: newSession })
} catch (e) {
updateAnswer(e, false, 'error')
}
bodyRef.current.scrollTo({
top: bodyRef.current.scrollHeight,
behavior: 'instant',
})
}}
/>
)}
</div>
)
}
@@ -557,6 +580,7 @@ ConversationCard.propTypes = {
onDock: PropTypes.func,
notClampSize: PropTypes.bool,
pageMode: PropTypes.bool,
waitForTrigger: PropTypes.bool,
}
export default memo(ConversationCard)
+1 -1
View File
@@ -5,7 +5,7 @@ import ReadButton from '../ReadButton'
import PropTypes from 'prop-types'
import MarkdownRender from '../MarkdownRender/markdown.jsx'
import { useTranslation } from 'react-i18next'
import { isUsingCustomModel, isUsingOllamaModel } from '../../config/index.mjs'
import { isUsingCustomModel } from '../../config/index.mjs'
import { useConfig } from '../../hooks/use-config.mjs'
function AnswerTitle({ descName, modelName }) {
+3 -2
View File
@@ -22,7 +22,7 @@ function FloatingToolbar(props) {
const windowSize = useClampWindowSize([750, 1500], [0, Infinity])
const config = useConfig(() => {
setRender(true)
if (!triggered) {
if (!triggered && selection) {
props.container.style.position = 'absolute'
setTimeout(() => {
const left = Math.min(
@@ -49,7 +49,7 @@ function FloatingToolbar(props) {
if (!render) return <div />
if (triggered) {
if (triggered || (prompt && !selection)) {
const updatePosition = () => {
const newPosition = setElementPositionInViewport(props.container, position.x, position.y)
if (position.x !== newPosition.x || position.y !== newPosition.y) setPosition(newPosition) // clear extra virtual position offset
@@ -106,6 +106,7 @@ function FloatingToolbar(props) {
dockable={props.dockable}
onDock={onDock}
onUpdate={onUpdate}
waitForTrigger={prompt && !triggered && !selection}
/>
</div>
</div>