File size: 1,777 Bytes
48eafa7
 
 
 
df790cc
48eafa7
 
 
df790cc
 
 
 
 
 
 
 
48eafa7
 
df790cc
 
 
48eafa7
 
 
 
df790cc
 
 
 
 
48eafa7
 
 
 
df790cc
 
a686c43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48eafa7
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
"use client";

import { useEffect, useRef } from "react";
import { useChatStore } from "@/lib/chatStore";
import type { SourceDoc } from "@/lib/types";
import { AssistantMessage, ErrorMessage, UserMessage } from "./Message";
import { Thinking } from "./Thinking";

export function Thread({
  onOpenSource,
}: {
  onOpenSource?: (doc: SourceDoc, index: number) => void;
}) {
  const conv = useChatStore((s) =>
    s.activeId ? s.conversations[s.activeId] : null
  );
  const ref = useRef<HTMLDivElement | null>(null);

  // Auto-scroll to bottom on new turns / when streaming tokens arrive
  const turns = conv?.turns ?? [];
  const lastTurn = turns[turns.length - 1];
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    el.scrollTo({ top: el.scrollHeight, behavior: "smooth" });
  }, [
    turns.length,
    lastTurn?.pending,
    lastTurn?.response?.answer?.length,
  ]);

  if (!conv || conv.turns.length === 0) return null;

  return (
    <div ref={ref} className="flex-1 overflow-y-auto min-h-0">
      <div className="min-h-full flex flex-col justify-end max-w-[920px] mx-auto px-4 sm:px-6 py-8 space-y-6">
        {conv.turns.map((t) => {
          const hasAnswer = Boolean(t.response?.answer);
          const showThinking = t.pending && !hasAnswer && !t.error;
          const showAnswer = !!t.response && (hasAnswer || !t.pending);
          return (
            <div key={t.id} className="space-y-4">
              <UserMessage text={t.question} />
              {showThinking && <Thinking />}
              {t.error && <ErrorMessage turn={t} />}
              {showAnswer && (
                <AssistantMessage turn={t} onOpenSource={onOpenSource} />
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}