Skip to content

Commit 1bbba76

Browse files
committed
More progress
1 parent a210924 commit 1bbba76

File tree

4 files changed

+42
-45
lines changed

4 files changed

+42
-45
lines changed

webview-ui/src/components/ui/chat/ChatMessage.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { useMemo } from "react"
22
import { CopyIcon, CheckIcon } from "@radix-ui/react-icons"
3-
import { BrainCircuit, CircleUserRound } from "lucide-react"
3+
import { BrainCircuit, CircleUserRound, Loader2 } from "lucide-react"
44

55
import { cn } from "@/lib/utils"
66
import { useClipboard } from "@/components/ui/hooks"
77
import { Badge } from "@/components/ui"
88
import { Markdown } from "@/components/ui/markdown"
99

10-
import { BadgeData, ChatHandler, Message, MessageAnnotationType } from "./types"
10+
import { BadgeData, Message, MessageAnnotationType } from "./types"
1111
import { ChatMessageProvider } from "./ChatMessageProvider"
1212
import { useChatUI } from "./useChatUI"
1313
import { useChatMessage } from "./useChatMessage"
@@ -16,11 +16,9 @@ interface ChatMessageProps {
1616
message: Message
1717
isLast: boolean
1818
isHeaderVisible: boolean
19-
isLoading?: boolean
20-
append?: ChatHandler["append"]
2119
}
2220

23-
export function ChatMessage({ message, isLast, isHeaderVisible, isLoading, append }: ChatMessageProps) {
21+
export function ChatMessage({ message, isLast, isHeaderVisible }: ChatMessageProps) {
2422
const badges = useMemo(
2523
() =>
2624
message.annotations
@@ -103,3 +101,12 @@ function ChatMessageActions() {
103101
</div>
104102
)
105103
}
104+
105+
export function ChatMessageLoading({ message = "asdf" }: { message?: string }) {
106+
return (
107+
<div className="flex flex-row items-center justify-end px-5 py-2">
108+
<Loader2 className="h-4 w-4 animate-spin opacity-25" />
109+
{message && <div className="ml-2 text-sm text-muted-foreground">{message}</div>}
110+
</div>
111+
)
112+
}
Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,43 @@
1-
import { useEffect, useRef } from "react"
1+
import { useCallback, useEffect, useMemo, useRef } from "react"
22
import { Virtuoso, VirtuosoHandle } from "react-virtuoso"
33

44
import { useChatUI } from "./useChatUI"
5-
import { ChatMessage } from "./ChatMessage"
5+
import { ChatMessage, ChatMessageLoading } from "./ChatMessage"
66

77
export function ChatMessages() {
8-
const { messages, isLoading, append } = useChatUI()
9-
const messageCount = messages.length
8+
const { messages, isLoading, loadingMessage } = useChatUI()
109
const virtuoso = useRef<VirtuosoHandle>(null)
1110

11+
const totalCount = useMemo(() => messages.length + (isLoading ? 1 : 0), [messages, isLoading])
12+
1213
useEffect(() => {
1314
if (!virtuoso.current) {
1415
return
1516
}
1617

1718
requestAnimationFrame(() =>
18-
virtuoso.current?.scrollToIndex({ index: messageCount - 1, align: "end", behavior: "smooth" }),
19+
virtuoso.current?.scrollToIndex({ index: totalCount - 1, align: "end", behavior: "smooth" }),
1920
)
20-
}, [messageCount])
21-
22-
return (
23-
<Virtuoso
24-
ref={virtuoso}
25-
data={messages}
26-
totalCount={messageCount}
27-
itemContent={(index, message) => (
28-
<ChatMessage
29-
key={index}
30-
message={message}
31-
isHeaderVisible={
32-
!!message.annotations?.length || index === 0 || messages[index - 1].role !== message.role
33-
}
34-
isLast={index === messageCount - 1}
35-
isLoading={isLoading}
36-
append={append}
37-
/>
38-
)}
39-
/>
21+
}, [totalCount])
22+
23+
const itemContent = useCallback(
24+
(index: number) => {
25+
const isFirst = index === 0
26+
const isLast = index === totalCount - 1
27+
28+
if (isLoading && isLast) {
29+
return <ChatMessageLoading key={index} message={loadingMessage} />
30+
}
31+
32+
const message = messages[index]
33+
34+
const isHeaderVisible =
35+
!!message.annotations?.length || isFirst || messages[index - 1].role !== message.role
36+
37+
return <ChatMessage key={index} message={message} isHeaderVisible={isHeaderVisible} isLast={isLast} />
38+
},
39+
[messages, isLoading, loadingMessage, totalCount],
4040
)
41+
42+
return <Virtuoso ref={virtuoso} totalCount={totalCount} itemContent={itemContent} />
4143
}

webview-ui/src/features/deep-research/GetStarted.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export const GetStarted = () => {
7171
}, [errors.providerId, errors.providerApiKey, errors.firecrawlApiKey])
7272

7373
return (
74-
<div className="flex flex-col gap-4 w-full max-w-sm p-4">
74+
<div className="flex flex-col gap-4 w-full max-w-md p-4">
7575
<Hero />
7676
<FormProvider {...form}>
7777
<form onSubmit={handleSubmit(onSubmit)} className="flex flex-col gap-4">
@@ -243,7 +243,7 @@ export const GetStarted = () => {
243243

244244
const Hero = () => {
245245
return (
246-
<div className="flex flex-col gap-4 w-full max-w-sm">
246+
<div className="flex flex-col gap-4 w-full">
247247
<div className="flex flex-col items-center justify-center gap-2">
248248
<div className="flex flex-row items-center justify-center gap-2">
249249
<BrainCircuit className="text-muted" />

webview-ui/src/features/deep-research/Session.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { useRef } from "react"
22
import { useMount } from "react-use"
33
import { Cross2Icon, ReaderIcon, RocketIcon, TriangleDownIcon, TriangleUpIcon } from "@radix-ui/react-icons"
4-
import { Loader2 } from "lucide-react"
54

65
import { Button, Progress } from "@/components/ui"
76
import { Chat } from "@/components/ui/chat"
@@ -14,7 +13,6 @@ export const Session = () => {
1413
const initialized = useRef(false)
1514
const { session } = useSession()
1615
const { status, progress, tokenUsage, start, ...handler } = useDeepResearch()
17-
const { isLoading, loadingMessage } = handler
1816

1917
useMount(() => {
2018
if (session && !initialized.current) {
@@ -29,8 +27,7 @@ export const Session = () => {
2927

3028
return (
3129
<>
32-
<Chat handler={handler} className="pt-10 pr-[1px]">
33-
{isLoading && <Loading message={loadingMessage} />}
30+
<Chat assistantName="Deep Research (β)" handler={handler} className="pt-10 pr-[1px]">
3431
{status === "aborted" && <Aborted />}
3532
{(status === "research" || status === "done") && (
3633
<ProgressBar status={status} progress={progress} tokenUsage={tokenUsage} />
@@ -62,15 +59,6 @@ function Header() {
6259
)
6360
}
6461

65-
function Loading({ message }: { message?: string }) {
66-
return (
67-
<div className="flex flex-row items-center justify-end px-5 py-2">
68-
<Loader2 className="h-4 w-4 animate-spin opacity-25" />
69-
{message && <div className="ml-2 text-sm text-muted-foreground">{message}</div>}
70-
</div>
71-
)
72-
}
73-
7462
function Aborted() {
7563
const { setSession } = useSession()
7664
const { reset } = useDeepResearch()

0 commit comments

Comments
 (0)