fix: save state toggle input box setting (#3402)
* fix: save input box setting * fix: active icon state when model tab is active, and increased textarea instruction * chore: update button modal inference
This commit is contained in:
parent
e9c30450b9
commit
73ec5de001
@ -284,6 +284,7 @@ const ModelDropdown = ({
|
||||
{chatInputMode ? (
|
||||
<Badge
|
||||
theme="secondary"
|
||||
variant={open ? 'solid' : 'outline'}
|
||||
className="cursor-pointer"
|
||||
onClick={() => setOpen(!open)}
|
||||
>
|
||||
|
||||
@ -7,6 +7,7 @@ import {
|
||||
} from '@janhq/core'
|
||||
|
||||
import { atom } from 'jotai'
|
||||
import { atomWithStorage } from 'jotai/utils'
|
||||
|
||||
export const engineParamsUpdateAtom = atom<boolean>(false)
|
||||
|
||||
@ -131,3 +132,9 @@ export const setThreadModelParamsAtom = atom(
|
||||
set(threadModelParamsAtom, currentState)
|
||||
}
|
||||
)
|
||||
|
||||
const ACTIVE_SETTING_INPUT_BOX = 'activeSettingInputBox'
|
||||
export const activeSettingInputBoxAtom = atomWithStorage<boolean>(
|
||||
ACTIVE_SETTING_INPUT_BOX,
|
||||
false
|
||||
)
|
||||
|
||||
@ -11,7 +11,7 @@ import {
|
||||
Badge,
|
||||
useMediaQuery,
|
||||
} from '@janhq/joi'
|
||||
import { useAtom, useAtomValue, useSetAtom } from 'jotai'
|
||||
import { useAtom, useAtomValue } from 'jotai'
|
||||
import {
|
||||
FileTextIcon,
|
||||
ImageIcon,
|
||||
@ -40,6 +40,7 @@ import { experimentalFeatureEnabledAtom } from '@/helpers/atoms/AppConfig.atom'
|
||||
import { getCurrentChatMessagesAtom } from '@/helpers/atoms/ChatMessage.atom'
|
||||
import { spellCheckAtom } from '@/helpers/atoms/Setting.atom'
|
||||
import {
|
||||
activeSettingInputBoxAtom,
|
||||
activeThreadAtom,
|
||||
getActiveThreadIdAtom,
|
||||
isGeneratingResponseAtom,
|
||||
@ -52,10 +53,13 @@ const ChatInput = () => {
|
||||
const activeThread = useAtomValue(activeThreadAtom)
|
||||
const { stateModel } = useActiveModel()
|
||||
const messages = useAtomValue(getCurrentChatMessagesAtom)
|
||||
const [activeSetting, setActiveSetting] = useState(false)
|
||||
// const [activeSetting, setActiveSetting] = useState(false)
|
||||
const spellCheck = useAtomValue(spellCheckAtom)
|
||||
|
||||
const [currentPrompt, setCurrentPrompt] = useAtom(currentPromptAtom)
|
||||
const [activeSettingInputBox, setActiveSettingInputBox] = useAtom(
|
||||
activeSettingInputBoxAtom
|
||||
)
|
||||
const { sendChatMessage } = useSendChatMessage()
|
||||
|
||||
const activeThreadId = useAtomValue(getActiveThreadIdAtom)
|
||||
@ -70,7 +74,9 @@ const ChatInput = () => {
|
||||
const threadStates = useAtomValue(threadStatesAtom)
|
||||
const { stopInference } = useActiveModel()
|
||||
|
||||
const setActiveTabThreadRightPanel = useSetAtom(activeTabThreadRightPanelAtom)
|
||||
const [activeTabThreadRightPanel, setActiveTabThreadRightPanel] = useAtom(
|
||||
activeTabThreadRightPanelAtom
|
||||
)
|
||||
|
||||
const isStreamingResponse = Object.values(threadStates).some(
|
||||
(threadState) => threadState.waitingForResponse
|
||||
@ -106,12 +112,14 @@ const ChatInput = () => {
|
||||
|
||||
useEffect(() => {
|
||||
if (textareaRef.current?.clientHeight) {
|
||||
textareaRef.current.style.height = activeSetting ? '100px' : '40px'
|
||||
textareaRef.current.style.height = activeSettingInputBox
|
||||
? '100px'
|
||||
: '40px'
|
||||
textareaRef.current.style.height = textareaRef.current.scrollHeight + 'px'
|
||||
textareaRef.current.style.overflow =
|
||||
textareaRef.current.clientHeight >= 390 ? 'auto' : 'hidden'
|
||||
}
|
||||
}, [textareaRef.current?.clientHeight, currentPrompt, activeSetting])
|
||||
}, [textareaRef.current?.clientHeight, currentPrompt, activeSettingInputBox])
|
||||
|
||||
const onKeyDown = async (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {
|
||||
@ -162,11 +170,11 @@ const ChatInput = () => {
|
||||
'relative max-h-[400px] resize-none pr-20',
|
||||
fileUpload.length && 'rounded-t-none',
|
||||
experimentalFeature && 'pl-10',
|
||||
activeSetting && 'pb-14 pr-16'
|
||||
activeSettingInputBox && 'pb-14 pr-16'
|
||||
)}
|
||||
spellCheck={spellCheck}
|
||||
data-testid="txt-input-chat"
|
||||
style={{ height: activeSetting ? '100px' : '40px' }}
|
||||
style={{ height: activeSettingInputBox ? '100px' : '40px' }}
|
||||
ref={textareaRef}
|
||||
onKeyDown={onKeyDown}
|
||||
placeholder="Ask me anything"
|
||||
@ -237,7 +245,7 @@ const ChatInput = () => {
|
||||
ref={refAttachmentMenus}
|
||||
className={twMerge(
|
||||
'absolute bottom-14 left-0 z-30 w-36 cursor-pointer rounded-lg border border-[hsla(var(--app-border))] bg-[hsla(var(--app-bg))] py-1 shadow-sm',
|
||||
activeSetting && 'bottom-28'
|
||||
activeSettingInputBox && 'bottom-28'
|
||||
)}
|
||||
>
|
||||
<ul>
|
||||
@ -320,12 +328,12 @@ const ChatInput = () => {
|
||||
|
||||
<div className={twMerge('absolute right-3 top-1.5')}>
|
||||
<div className="flex items-center gap-x-4">
|
||||
{!activeSetting && (
|
||||
{!activeSettingInputBox && (
|
||||
<div className="flex h-8 items-center">
|
||||
<Button
|
||||
theme="icon"
|
||||
onClick={() => {
|
||||
setActiveSetting(!activeSetting)
|
||||
setActiveSettingInputBox(!activeSettingInputBox)
|
||||
}}
|
||||
>
|
||||
<SettingsIcon
|
||||
@ -378,7 +386,7 @@ const ChatInput = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{activeSetting && (
|
||||
{activeSettingInputBox && (
|
||||
<div
|
||||
className={twMerge(
|
||||
'absolute bottom-[6px] left-[1px] flex w-[calc(100%-2px)] items-center justify-between rounded-lg bg-[hsla(var(--textarea-bg))] p-3',
|
||||
@ -386,10 +394,14 @@ const ChatInput = () => {
|
||||
stateModel.loading && 'bg-transparent'
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-x-3">
|
||||
<div className="flex items-center gap-x-2">
|
||||
<ModelDropdown chatInputMode />
|
||||
<Button
|
||||
theme="icon"
|
||||
<Badge
|
||||
theme="secondary"
|
||||
className="flex cursor-pointer items-center gap-x-1"
|
||||
variant={
|
||||
activeTabThreadRightPanel === 'model' ? 'solid' : 'outline'
|
||||
}
|
||||
onClick={() => {
|
||||
setActiveTabThreadRightPanel('model')
|
||||
if (matches) {
|
||||
@ -403,11 +415,15 @@ const ChatInput = () => {
|
||||
size={16}
|
||||
className="flex-shrink-0 cursor-pointer text-[hsla(var(--text-secondary))]"
|
||||
/>
|
||||
</Button>
|
||||
<span>Inference</span>
|
||||
</Badge>
|
||||
{experimentalFeature && (
|
||||
<Badge
|
||||
className="flex cursor-pointer items-center gap-x-1"
|
||||
theme="secondary"
|
||||
variant={
|
||||
activeTabThreadRightPanel === 'tools' ? 'solid' : 'outline'
|
||||
}
|
||||
onClick={() => {
|
||||
setActiveTabThreadRightPanel('tools')
|
||||
if (matches) {
|
||||
@ -425,7 +441,10 @@ const ChatInput = () => {
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<Button theme="icon" onClick={() => setActiveSetting(false)}>
|
||||
<Button
|
||||
theme="icon"
|
||||
onClick={() => setActiveSettingInputBox(false)}
|
||||
>
|
||||
<ChevronUpIcon
|
||||
size={16}
|
||||
className="cursor-pointer text-[hsla(var(--text-secondary))]"
|
||||
|
||||
@ -207,6 +207,7 @@ const ThreadRightPanel = () => {
|
||||
id="assistant-instructions"
|
||||
placeholder="Eg. You are a helpful assistant."
|
||||
value={activeThread?.assistants[0].instructions ?? ''}
|
||||
rows={8}
|
||||
onChange={onAssistantInstructionChanged}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user