fix: avoid lose title threads (#3307)
* fix: avoid lose title threads * fix: create cont default thread title
This commit is contained in:
parent
b43242b9b2
commit
a4f5fda104
1
web/constants/Threads.ts
Normal file
1
web/constants/Threads.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const defaultThreadTitle = 'New Thread'
|
||||||
@ -17,6 +17,8 @@ import {
|
|||||||
|
|
||||||
import { useAtomValue } from 'jotai'
|
import { useAtomValue } from 'jotai'
|
||||||
|
|
||||||
|
import { defaultThreadTitle } from '@/constants/Threads'
|
||||||
|
|
||||||
import { UpdateConfigMutationVariables } from './useEngineMutation'
|
import { UpdateConfigMutationVariables } from './useEngineMutation'
|
||||||
import { MessageCreateMutationVariables } from './useMessageCreateMutation'
|
import { MessageCreateMutationVariables } from './useMessageCreateMutation'
|
||||||
import { MessageDeleteMutationVariables } from './useMessageDeleteMutation'
|
import { MessageDeleteMutationVariables } from './useMessageDeleteMutation'
|
||||||
@ -80,7 +82,7 @@ const useCortex = () => {
|
|||||||
if (!assistants || assistants.length === 0) continue
|
if (!assistants || assistants.length === 0) continue
|
||||||
|
|
||||||
// @ts-expect-error each thread must have a title, else default to 'New Thread'
|
// @ts-expect-error each thread must have a title, else default to 'New Thread'
|
||||||
const title: string = thread['title'] ?? 'New Thread'
|
const title: string = thread['title'] ?? defaultThreadTitle
|
||||||
|
|
||||||
threads.push({
|
threads.push({
|
||||||
...thread,
|
...thread,
|
||||||
@ -227,7 +229,7 @@ const useCortex = () => {
|
|||||||
const thread: Thread = {
|
const thread: Thread = {
|
||||||
...createThreadResponse,
|
...createThreadResponse,
|
||||||
// @ts-expect-error each thread will have a title, else default to 'New Thread'
|
// @ts-expect-error each thread will have a title, else default to 'New Thread'
|
||||||
title: createThreadResponse.title ?? 'New Thread',
|
title: createThreadResponse.title ?? defaultThreadTitle,
|
||||||
assistants: [assistant],
|
assistants: [assistant],
|
||||||
}
|
}
|
||||||
return thread
|
return thread
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
|
|
||||||
|
import { defaultThreadTitle } from '@/constants/Threads'
|
||||||
|
|
||||||
import useAssistantQuery from './useAssistantQuery'
|
import useAssistantQuery from './useAssistantQuery'
|
||||||
|
|
||||||
import useCortex from './useCortex'
|
import useCortex from './useCortex'
|
||||||
@ -43,7 +45,7 @@ const useMigratingData = () => {
|
|||||||
console.error(`Ignore thread ${thread.id} because modelId is not found`)
|
console.error(`Ignore thread ${thread.id} because modelId is not found`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const threadTitle: string = thread.title ?? 'New Thread'
|
const threadTitle: string = thread.title ?? defaultThreadTitle
|
||||||
const instructions: string = thread.assistants[0]?.instructions ?? ''
|
const instructions: string = thread.assistants[0]?.instructions ?? ''
|
||||||
// currently, we don't have api support for creating thread with messages
|
// currently, we don't have api support for creating thread with messages
|
||||||
const cortexThread = await createThread(modelId, assistants[0])
|
const cortexThread = await createThread(modelId, assistants[0])
|
||||||
|
|||||||
@ -18,6 +18,8 @@ import { currentPromptAtom, editPromptAtom } from '@/containers/Providers/Jotai'
|
|||||||
|
|
||||||
import { toaster } from '@/containers/Toast'
|
import { toaster } from '@/containers/Toast'
|
||||||
|
|
||||||
|
import { defaultThreadTitle } from '@/constants/Threads'
|
||||||
|
|
||||||
import { inferenceErrorAtom } from '@/screens/HubScreen2/components/InferenceErrorModal'
|
import { inferenceErrorAtom } from '@/screens/HubScreen2/components/InferenceErrorModal'
|
||||||
|
|
||||||
import { showWarningMultipleModelModalAtom } from '@/screens/HubScreen2/components/WarningMultipleModelModal'
|
import { showWarningMultipleModelModalAtom } from '@/screens/HubScreen2/components/WarningMultipleModelModal'
|
||||||
@ -512,7 +514,7 @@ const useSendMessage = () => {
|
|||||||
if (!isValid) return
|
if (!isValid) return
|
||||||
|
|
||||||
let shouldSummarize =
|
let shouldSummarize =
|
||||||
activeThread!.title === 'New Thread' ||
|
activeThread!.title === defaultThreadTitle ||
|
||||||
activeThread!.title.trim() === ''
|
activeThread!.title.trim() === ''
|
||||||
const modelId = activeThread!.assistants[0].model
|
const modelId = activeThread!.assistants[0].model
|
||||||
|
|
||||||
|
|||||||
@ -1,23 +1,35 @@
|
|||||||
import { useCallback, memo } from 'react'
|
import { useCallback, memo } from 'react'
|
||||||
|
|
||||||
|
import { Thread } from '@janhq/core'
|
||||||
import { Button, Modal, ModalClose } from '@janhq/joi'
|
import { Button, Modal, ModalClose } from '@janhq/joi'
|
||||||
|
import { useSetAtom } from 'jotai'
|
||||||
import { Paintbrush } from 'lucide-react'
|
import { Paintbrush } from 'lucide-react'
|
||||||
|
|
||||||
|
import { defaultThreadTitle } from '@/constants/Threads'
|
||||||
|
|
||||||
|
import useCortex from '@/hooks/useCortex'
|
||||||
import useThreads from '@/hooks/useThreads'
|
import useThreads from '@/hooks/useThreads'
|
||||||
|
|
||||||
|
import { updateThreadTitleAtom } from '@/helpers/atoms/Thread.atom'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
threadId: string
|
thread: Thread
|
||||||
closeContextMenu?: () => void
|
closeContextMenu?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const ModalCleanThread = ({ threadId, closeContextMenu }: Props) => {
|
const ModalCleanThread = ({ thread, closeContextMenu }: Props) => {
|
||||||
const { cleanThread } = useThreads()
|
const { cleanThread } = useThreads()
|
||||||
|
const updateThreadTitle = useSetAtom(updateThreadTitleAtom)
|
||||||
|
const { updateThread } = useCortex()
|
||||||
|
|
||||||
const onCleanThreadClick = useCallback(
|
const onCleanThreadClick = useCallback(
|
||||||
(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
cleanThread(threadId)
|
cleanThread(thread.id)
|
||||||
|
updateThreadTitle(thread.id, defaultThreadTitle)
|
||||||
|
updateThread({ ...thread, title: defaultThreadTitle })
|
||||||
},
|
},
|
||||||
[cleanThread, threadId]
|
[cleanThread, thread, updateThread, updateThreadTitle]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -6,6 +6,8 @@ import { useAtomValue, useSetAtom } from 'jotai'
|
|||||||
import { MoreHorizontalIcon } from 'lucide-react'
|
import { MoreHorizontalIcon } from 'lucide-react'
|
||||||
import { twMerge } from 'tailwind-merge'
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
|
import { defaultThreadTitle } from '@/constants/Threads'
|
||||||
|
|
||||||
import useThreads from '@/hooks/useThreads'
|
import useThreads from '@/hooks/useThreads'
|
||||||
|
|
||||||
import ModalCleanThread from '../ModalCleanThread'
|
import ModalCleanThread from '../ModalCleanThread'
|
||||||
@ -29,6 +31,7 @@ const ThreadItem: React.FC<Props> = ({ thread }) => {
|
|||||||
const getThreadIdsShouldAnimateTitle = useAtomValue(
|
const getThreadIdsShouldAnimateTitle = useAtomValue(
|
||||||
getThreadIdsShouldAnimateTitleAtom
|
getThreadIdsShouldAnimateTitleAtom
|
||||||
)
|
)
|
||||||
|
|
||||||
const setEditMessage = useSetAtom(editMessageAtom)
|
const setEditMessage = useSetAtom(editMessageAtom)
|
||||||
const { setActiveThread } = useThreads()
|
const { setActiveThread } = useThreads()
|
||||||
const [contextMenu, setContextMenu] = useState<{
|
const [contextMenu, setContextMenu] = useState<{
|
||||||
@ -81,10 +84,13 @@ const ThreadItem: React.FC<Props> = ({ thread }) => {
|
|||||||
>
|
>
|
||||||
<div className="relative z-10 break-all p-2">
|
<div className="relative z-10 break-all p-2">
|
||||||
{getThreadIdsShouldAnimateTitle.includes(thread.id) ? (
|
{getThreadIdsShouldAnimateTitle.includes(thread.id) ? (
|
||||||
<TypingAnimated text={thread.title} speed={20} />
|
<TypingAnimated
|
||||||
|
text={thread.title || defaultThreadTitle}
|
||||||
|
speed={20}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<span className="line-clamp-1 group-hover/message:pr-6">
|
<span className="line-clamp-1 group-hover/message:pr-6">
|
||||||
{thread.title}
|
{thread.title || defaultThreadTitle}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -112,7 +118,7 @@ const ThreadItem: React.FC<Props> = ({ thread }) => {
|
|||||||
closeContextMenu={closeContextMenu}
|
closeContextMenu={closeContextMenu}
|
||||||
/>
|
/>
|
||||||
<ModalCleanThread
|
<ModalCleanThread
|
||||||
threadId={thread.id}
|
thread={thread}
|
||||||
closeContextMenu={closeContextMenu}
|
closeContextMenu={closeContextMenu}
|
||||||
/>
|
/>
|
||||||
<ModalDeleteThread
|
<ModalDeleteThread
|
||||||
|
|||||||
@ -10,15 +10,19 @@ const TypingAnimated: React.FC<Props> = ({ text, speed }) => {
|
|||||||
const [index, setIndex] = useState(0)
|
const [index, setIndex] = useState(0)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (index < text.length) {
|
const typingEffect = setInterval(() => {
|
||||||
const timeout = setTimeout(() => {
|
if (text.length) {
|
||||||
setDisplayedText(displayedText + text[index])
|
setDisplayedText(text.substring(0, index + 1))
|
||||||
setIndex(index + 1)
|
setIndex(index + 1)
|
||||||
}, speed)
|
} else {
|
||||||
|
clearInterval(typingEffect)
|
||||||
|
}
|
||||||
|
}, speed)
|
||||||
|
|
||||||
return () => clearTimeout(timeout)
|
return () => {
|
||||||
|
clearInterval(typingEffect)
|
||||||
}
|
}
|
||||||
}, [index, text, displayedText, speed])
|
}, [index, speed, text])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="line-clamp-1 group-hover/message:pr-6">
|
<span className="line-clamp-1 group-hover/message:pr-6">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user