MCPcopy Index your code
hub / github.com/winfunc/opcode / SessionOutputViewer

Function SessionOutputViewer

src/components/SessionOutputViewer.tsx:40–680  ·  view source on GitHub ↗
({ session, onClose, className }: SessionOutputViewerProps)

Source from the content-addressed store, hash-verified

38}
39
40export function SessionOutputViewer({ session, onClose, className }: SessionOutputViewerProps) {
41 const [messages, setMessages] = useState<ClaudeStreamMessage[]>([]);
42 const [rawJsonlOutput, setRawJsonlOutput] = useState<string[]>([]);
43 const [loading, setLoading] = useState(false);
44 const [isFullscreen, setIsFullscreen] = useState(false);
45 const [refreshing, setRefreshing] = useState(false);
46 const [toast, setToast] = useState<{ message: string; type: "success" | "error" } | null>(null);
47 const [copyPopoverOpen, setCopyPopoverOpen] = useState(false);
48 const [hasUserScrolled, setHasUserScrolled] = useState(false);
49
50 const scrollAreaRef = useRef<HTMLDivElement>(null);
51 const outputEndRef = useRef<HTMLDivElement>(null);
52 const fullscreenScrollRef = useRef<HTMLDivElement>(null);
53 const fullscreenMessagesEndRef = useRef<HTMLDivElement>(null);
54 const unlistenRefs = useRef<UnlistenFn[]>([]);
55 const { getCachedOutput, setCachedOutput } = useOutputCache();
56
57 // Auto-scroll logic similar to AgentExecution
58 const isAtBottom = () => {
59 const container = isFullscreen ? fullscreenScrollRef.current : scrollAreaRef.current;
60 if (container) {
61 const { scrollTop, scrollHeight, clientHeight } = container;
62 const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
63 return distanceFromBottom < 1;
64 }
65 return true;
66 };
67
68 const scrollToBottom = () => {
69 if (!hasUserScrolled) {
70 const endRef = isFullscreen ? fullscreenMessagesEndRef.current : outputEndRef.current;
71 if (endRef) {
72 endRef.scrollIntoView({ behavior: 'smooth' });
73 }
74 }
75 };
76
77 // Clean up listeners on unmount
78 useEffect(() => {
79 return () => {
80 unlistenRefs.current.forEach(unlisten => unlisten());
81 };
82 }, []);
83
84 // Auto-scroll when messages change
85 useEffect(() => {
86 const shouldAutoScroll = !hasUserScrolled || isAtBottom();
87 if (shouldAutoScroll) {
88 scrollToBottom();
89 }
90 }, [messages, hasUserScrolled, isFullscreen]);
91
92
93 const loadOutput = async (skipCache = false) => {
94 if (!session.id) return;
95
96 try {
97 // Check cache first if not skipping cache

Callers

nothing calls this directly

Calls 4

useOutputCacheFunction · 0.90
isAtBottomFunction · 0.70
scrollToBottomFunction · 0.70
loadOutputFunction · 0.70

Tested by

no test coverage detected