|
1 | | -import { memo, useEffect, useMemo, useRef, useState } from 'react' |
| 1 | +import { memo, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react' |
2 | 2 | import PropTypes from 'prop-types' |
3 | 3 | import Browser from 'webextension-polyfill' |
4 | 4 | import InputBox from '../InputBox' |
5 | 5 | import ConversationItem from '../ConversationItem' |
6 | 6 | import { |
| 7 | + apiModeToModelName, |
7 | 8 | createElementAtPosition, |
8 | | - getApiModesStringArrayFromConfig, |
| 9 | + getApiModesFromConfig, |
| 10 | + isApiModeSelected, |
9 | 11 | isFirefox, |
10 | 12 | isMobile, |
11 | 13 | isSafari, |
@@ -61,33 +63,33 @@ function ConversationCard(props) { |
61 | 63 | const [completeDraggable, setCompleteDraggable] = useState(false) |
62 | 64 | // `.some` for multi mode models. e.g. bingFree4-balanced |
63 | 65 | const useForegroundFetch = bingWebModelKeys.some((n) => session.modelName.includes(n)) |
| 66 | + const [apiModes, setApiModes] = useState([]) |
64 | 67 |
|
65 | 68 | /** |
66 | 69 | * @type {[ConversationItemData[], (conversationItemData: ConversationItemData[]) => void]} |
67 | 70 | */ |
68 | | - const [conversationItemData, setConversationItemData] = useState( |
69 | | - (() => { |
70 | | - if (session.conversationRecords.length === 0) |
71 | | - if (props.question && triggered) |
72 | | - return [ |
73 | | - new ConversationItemData( |
74 | | - 'answer', |
75 | | - `<p class="gpt-loading">${t(`Waiting for response...`)}</p>`, |
76 | | - ), |
77 | | - ] |
78 | | - else return [] |
79 | | - else { |
80 | | - const ret = [] |
81 | | - for (const record of session.conversationRecords) { |
82 | | - ret.push(new ConversationItemData('question', record.question, true)) |
83 | | - ret.push(new ConversationItemData('answer', record.answer, true)) |
84 | | - } |
85 | | - return ret |
86 | | - } |
87 | | - })(), |
88 | | - ) |
| 71 | + const [conversationItemData, setConversationItemData] = useState([]) |
89 | 72 | const config = useConfig() |
90 | 73 |
|
| 74 | + useLayoutEffect(() => { |
| 75 | + if (session.conversationRecords.length === 0) { |
| 76 | + if (props.question && triggered) |
| 77 | + setConversationItemData([ |
| 78 | + new ConversationItemData( |
| 79 | + 'answer', |
| 80 | + `<p class="gpt-loading">${t(`Waiting for response...`)}</p>`, |
| 81 | + ), |
| 82 | + ]) |
| 83 | + } else { |
| 84 | + const ret = [] |
| 85 | + for (const record of session.conversationRecords) { |
| 86 | + ret.push(new ConversationItemData('question', record.question, true)) |
| 87 | + ret.push(new ConversationItemData('answer', record.answer, true)) |
| 88 | + } |
| 89 | + setConversationItemData(ret) |
| 90 | + } |
| 91 | + }, []) |
| 92 | + |
91 | 93 | useEffect(() => { |
92 | 94 | setCompleteDraggable(!isSafari() && !isFirefox() && !isMobile()) |
93 | 95 | }, []) |
@@ -118,6 +120,15 @@ function ConversationCard(props) { |
118 | 120 | } |
119 | 121 | }, [props.question, triggered]) // usually only triggered once |
120 | 122 |
|
| 123 | + useLayoutEffect(() => { |
| 124 | + setApiModes(getApiModesFromConfig(config, true)) |
| 125 | + }, [ |
| 126 | + config.activeApiModes, |
| 127 | + config.customApiModes, |
| 128 | + config.azureDeploymentName, |
| 129 | + config.ollamaModelName, |
| 130 | + ]) |
| 131 | + |
121 | 132 | /** |
122 | 133 | * @param {string} value |
123 | 134 | * @param {boolean} appended |
@@ -369,25 +380,32 @@ function ConversationCard(props) { |
369 | 380 | className="normal-button" |
370 | 381 | required |
371 | 382 | onChange={(e) => { |
372 | | - const modelName = e.target.value |
373 | | - const newSession = { ...session, modelName, aiName: modelNameToDesc(modelName, t) } |
| 383 | + const apiMode = apiModes[e.target.value] |
| 384 | + const modelName = apiModeToModelName(apiMode) |
| 385 | + const newSession = { |
| 386 | + ...session, |
| 387 | + modelName, |
| 388 | + apiMode, |
| 389 | + aiName: modelNameToDesc(modelName, t), |
| 390 | + } |
374 | 391 | if (config.autoRegenAfterSwitchModel && conversationItemData.length > 0) |
375 | 392 | getRetryFn(newSession)() |
376 | 393 | else setSession(newSession) |
377 | 394 | }} |
378 | 395 | > |
379 | | - {getApiModesStringArrayFromConfig(config, true).map((modelName) => { |
| 396 | + {apiModes.map((apiMode, index) => { |
| 397 | + const modelName = apiModeToModelName(apiMode) |
380 | 398 | const desc = modelNameToDesc(modelName, t) |
381 | | - if (desc) |
| 399 | + if (desc) { |
| 400 | + let selected |
| 401 | + if (isApiModeSelected(apiMode, session)) selected = true |
| 402 | + else selected = session.modelName === modelName |
382 | 403 | return ( |
383 | | - <option |
384 | | - value={modelName} |
385 | | - key={modelName} |
386 | | - selected={modelName === session.modelName} |
387 | | - > |
| 404 | + <option value={index} key={index} selected={selected}> |
388 | 405 | {desc} |
389 | 406 | </option> |
390 | 407 | ) |
| 408 | + } |
391 | 409 | })} |
392 | 410 | </select> |
393 | 411 | </span> |
|
0 commit comments