|
'use client' |
|
|
|
import { useCallback, useEffect, useMemo, useState } from 'react' |
|
import { useAtom } from 'jotai' |
|
import Image from 'next/image' |
|
import { cn } from '@/lib/utils' |
|
import { ChatList } from '@/components/chat-list' |
|
import { ChatPanel } from '@/components/chat-panel' |
|
import { WelcomeScreen } from '@/components/welcome-screen' |
|
import { ChatScrollAnchor } from '@/components/chat-scroll-anchor' |
|
import { ToneSelector } from './tone-selector' |
|
import { ChatHeader } from './chat-header' |
|
import { ChatSuggestions } from './chat-suggestions' |
|
import { bingConversationStyleAtom } from '@/state' |
|
import { ButtonScrollToBottom } from '@/components/button-scroll-to-bottom' |
|
import StopIcon from '@/assets/images/stop.svg' |
|
import { useBing } from '@/lib/hooks/use-bing' |
|
import { ChatMessageModel } from '@/lib/bots/bing/types' |
|
import { ChatNotification } from './chat-notification' |
|
import { Settings } from './settings' |
|
|
|
export type ChatProps = React.ComponentProps<'div'> & { initialMessages?: ChatMessageModel[] } |
|
|
|
export default function Chat({ className }: ChatProps) { |
|
|
|
const [bingStyle, setBingStyle] = useAtom(bingConversationStyleAtom) |
|
const { |
|
messages, |
|
sendMessage, |
|
resetConversation, |
|
stopGenerating, |
|
setInput, |
|
bot, |
|
input, |
|
generating, |
|
isSpeaking, |
|
uploadImage, |
|
attachmentList, |
|
setAttachmentList, |
|
} = useBing() |
|
|
|
useEffect(() => { |
|
window.scrollTo({ |
|
top: document.body.offsetHeight, |
|
behavior: 'smooth' |
|
}) |
|
}, []) |
|
|
|
return ( |
|
<div className="flex flex-1 flex-col"> |
|
<Settings /> |
|
<div className={cn('flex-1 pb-16', className)}> |
|
<ChatHeader /> |
|
<WelcomeScreen setInput={setInput} /> |
|
<ToneSelector type={bingStyle} onChange={setBingStyle} /> |
|
{messages.length ? ( |
|
<> |
|
<ChatList messages={messages} /> |
|
<ChatScrollAnchor trackVisibility={generating} /> |
|
<ChatNotification message={messages.at(-1)} bot={bot} /> |
|
<ChatSuggestions setInput={setInput} suggestions={messages.at(-1)?.suggestedResponses} /> |
|
|
|
{generating ? ( |
|
<div className="flex h-10 items-center justify-center my-4"> |
|
<button |
|
onClick={stopGenerating} |
|
className="typing-control-item stop" |
|
> |
|
<Image alt="stop" src={StopIcon} width={24} className="mr-1" /> |
|
<span>停止响应</span> |
|
</button> |
|
</div> |
|
) : null} |
|
</> |
|
) : null} |
|
</div> |
|
<ChatPanel |
|
className="pt-24 z-10" |
|
isSpeaking={isSpeaking} |
|
generating={generating} |
|
sendMessage={sendMessage} |
|
input={input} |
|
setInput={setInput} |
|
resetConversation={resetConversation} |
|
uploadImage={uploadImage} |
|
attachmentList={attachmentList} |
|
setAttachmentList={setAttachmentList} |
|
/> |
|
<ButtonScrollToBottom /> |
|
</div> |
|
) |
|
} |
|
|