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