import { IconClock } from "@tabler/icons-react"; import { useCallback, useLayoutEffect, useRef, useState } from "react"; import type { Task } from "../types"; import { ImageGallery } from "./ImageGallery"; import { ReplyImagePreview } from "./ReplyImagePreview"; import { formatWorkedDuration } from "../time.js"; import { ReplyMarkdown } from "./ReplyMarkdown"; const hidePromptImage = () => null; export function CollapsedMarkdown({ text }: { text: string }) { const content = useRef(null); const [expanded, setExpanded] = useState(false); const [clipped, setClipped] = useState(false); useLayoutEffect(() => { const element = content.current; if (!element || expanded) return; const measure = () => setClipped(element.scrollHeight > element.clientHeight + 1); measure(); const observer = new ResizeObserver(measure); observer.observe(element); return () => observer.disconnect(); }, [text, expanded]); return <>
{(clipped || expanded) && } ; } export function TurnContent({ task, compact = false, loadImage, workedDurationMs, onLightboxChange, onAnnotationChange }: { task: Task; compact?: boolean; loadImage?: (task: Task, url?: string) => Promise; workedDurationMs?: number | null; onLightboxChange?: (opened: boolean) => void; onAnnotationChange?: (id: string, opened: boolean) => void }) { const currentTask = useRef(task); currentTask.current = task; const renderImage = useCallback((url: string, alt: string) => loadImage ? : null, [task.id, task.turnId, loadImage, onLightboxChange]); const prompt = compact ? task.promptExcerpt : task.promptText ?? task.promptExcerpt; const reply = compact ? task.replyExcerpt : task.replyText ?? task.replyExcerpt; if (compact) { const text = task.status === "working" ? prompt : reply; return text ?
: null; } const promptImages = task.promptImages ?? (task.promptImage ? [task.promptImage] : []); const duration = workedDurationMs ?? task.observed?.latestTurnDurationMs; return
{prompt &&
{task.inputSource === "scheduled" && } {loadImage && promptImages.length > 0 && }
} {reply && <>
{duration != null && Number.isFinite(duration) && duration >= 0 ? `Worked for ${formatWorkedDuration(duration)}` : null}
}
; }