| '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> | |
| ) | |
| } | |