import { useEffect, useRef, useState } from 'react'; import { ScrollArea } from '../components/ScrollArea'; import { HttpNetworkEntry } from '../state/model'; import { Section } from '../components/Section'; import { KeyValueGrid } from '../components/KeyValueGrid'; import { useOverrides } from '../state/hooks'; import { RequestOverride } from '../../shared/client'; import { OverrideResponse } from '../components/OverrideResponse'; import { Button } from '../components/Button'; import { Pencil } from 'lucide-react'; import { ViewToggle } from '../components/ViewToggle'; import { findRenderer, type RenderCtx, type ResponseView, } from '../response-renderers'; export type ResponseTabProps = { selectedRequest: HttpNetworkEntry; supportsOverrides?: boolean; // Sticky Preview/Raw preference is owned by the parent (SidePanel) // so it survives the `` remount that // happens on every request switch. Renderers without the requested // view fall back to their own `defaultView`. preferredView: ResponseView; onPreferredViewChange: (view: ResponseView) => void; onRequestResponseBody: (requestId: string) => void; }; export const ResponseTab = ({ selectedRequest, supportsOverrides = true, preferredView, onPreferredViewChange, onRequestResponseBody, }: ResponseTabProps) => { const onRequestResponseBodyRef = useRef(onRequestResponseBody); const overrides = useOverrides(); const [initialOverride, setInitialOverride] = useState< RequestOverride | undefined >(() => overrides.get(selectedRequest.request.url)); useEffect(() => { onRequestResponseBodyRef.current = onRequestResponseBody; }, [onRequestResponseBody]); useEffect(() => { if (onRequestResponseBodyRef.current) { onRequestResponseBodyRef.current(selectedRequest.id); } }, [selectedRequest.id]); const responseBody = selectedRequest.response?.body; const renderResponseBody = () => { if (!responseBody) { return (
No response body available for this request
); } const { type, data } = responseBody; const renderer = findRenderer(type, data); const activeView = renderer.views.includes(preferredView) ? preferredView : renderer.defaultView; const ctx: RenderCtx = { contentType: type, url: selectedRequest.request.url, headers: selectedRequest.response?.headers, size: selectedRequest.response?.size, }; // Override engaged: replace the whole panel with the override editor. // Only reachable for renderers that support override AND when the // user has clicked into the override flow. if ( supportsOverrides && renderer.supportsOverride && initialOverride !== undefined ) { return ( setInitialOverride(undefined)} /> ); } const canOverride = renderer.supportsOverride && supportsOverrides && typeof data === 'string'; const overrideAction = canOverride ? ( ) : null; const toggle = renderer.views.length > 1 ? ( ) : null; const sectionAction = toggle || overrideAction ? (
{toggle} {overrideAction}
) : null; return (
{renderer.render({ view: activeView, body: data, ctx })}
); }; return (
{renderResponseBody()}
); };