diff --git a/web-app/src/routes/threads/$threadId.tsx b/web-app/src/routes/threads/$threadId.tsx index fa7d6cc04..ebde4a233 100644 --- a/web-app/src/routes/threads/$threadId.tsx +++ b/web-app/src/routes/threads/$threadId.tsx @@ -5,6 +5,7 @@ import debounce from 'lodash.debounce' import cloneDeep from 'lodash.clonedeep' import { cn } from '@/lib/utils' import { ArrowDown } from 'lucide-react' +import { Play } from 'lucide-react' import HeaderPage from '@/containers/HeaderPage' import { useThreads } from '@/hooks/useThreads' @@ -22,6 +23,7 @@ import { useAppearance } from '@/hooks/useAppearance' import { useOutOfContextPromiseModal } from '@/containers/dialogs/OutOfContextDialog' import { ContentType, ThreadMessage } from '@janhq/core' import { useTranslation } from '@/i18n/react-i18next-compat' +import { useChat } from '@/hooks/useChat' // as route.threadsDetail export const Route = createFileRoute('/threads/$threadId')({ @@ -40,6 +42,7 @@ function ThreadDetail() { const { setMessages } = useMessages() const { streamingContent } = useAppState() const { appMainViewBgColor, chatWidth } = useAppearance() + const { sendMessage } = useChat() const { messages } = useMessages( useShallow((state) => ({ @@ -216,12 +219,24 @@ function ThreadDetail() { // eslint-disable-next-line react-hooks/exhaustive-deps }, []) + // used when there is a sent/added user message and no assistant message (error or manual deletion) + const generateAIResponse = () => { + const latestUserMessage = messages[messages.length - 1] + if (latestUserMessage?.content?.[0]?.text?.value) { + sendMessage(latestUserMessage.content[0].text.value, undefined, false) + } + } + const threadModel = useMemo(() => thread?.model, [thread]) if (!messages || !threadModel) return null const contextOverflowModalComponent = + const showScrollToBottomBtn = !isAtBottom && hasScrollbar + const showGenerateAIResponseBtn = + messages[messages.length - 1]?.role === 'user' && !streamingContent + return (
@@ -289,19 +304,31 @@ function ThreadDetail() { appMainViewBgColor.a === 1 ? 'from-main-view/20 bg-gradient-to-b to-main-view backdrop-blur' : 'bg-transparent', - !isAtBottom && hasScrollbar && 'visibility-visible opacity-100' + (showScrollToBottomBtn || showGenerateAIResponseBtn) && + 'visibility-visible opacity-100' )} > -
{ - scrollToBottom(true) - setIsUserScrolling(false) - }} - > -

{t('scrollToBottom')}

- -
+ {showScrollToBottomBtn && ( +
{ + scrollToBottom(true) + setIsUserScrolling(false) + }} + > +

{t('scrollToBottom')}

+ +
+ )} + {showGenerateAIResponseBtn && ( +
+

{t('Generate AI Response')}

+ +
+ )}