import type { HttpResponse } from "@yaakapp-internal/models"; import { useQueryClient } from "@tanstack/react-query"; import { languageFromContentType, type TextFilterApi, WebPageViewer } from "@yaakapp-internal/ui"; import type { CodeEditorProps } from "@yaakapp-internal/ui/editor"; import { useCallback } from "react"; import { useCopyHttpResponse } from "../../hooks/useCopyHttpResponse"; import { useRecentFilters } from "../../hooks/useRecentFilters"; import { responseBodyTextQuery, useResponseBodyText } from "../../hooks/useResponseBodyText"; import { useSaveResponse } from "../../hooks/useSaveResponse"; import { getContentTypeFromHeaders } from "../../lib/model_util"; import { IconButton } from "../core/IconButton"; import { EmptyStateText } from "../EmptyStateText"; import { RecentFiltersDropdown } from "./RecentFiltersDropdown"; import { TextViewer } from "./TextViewer"; interface Props { response: HttpResponse; pretty: boolean; textViewerClassName?: string; } export function HTMLOrTextViewer({ response, pretty, textViewerClassName }: Props) { const rawTextBody = useResponseBodyText({ response, filter: null }); const contentType = getContentTypeFromHeaders(response.headers); const language = languageFromContentType(contentType, rawTextBody.data ?? ""); if (rawTextBody.isLoading || response.state === "initialized") { return null; } if (language === "html" && pretty) { return ; } if (rawTextBody.data == null) { return Empty response; } return ( ); } interface HttpTextViewerProps { response: HttpResponse; text: string; language: CodeEditorProps["language"]; pretty: boolean; className?: string; } function HttpTextViewer({ response, text, language, pretty, className }: HttpTextViewerProps) { const queryClient = useQueryClient(); const filterStateKey = `response.body.${response.requestId}`; // Shares the response body query's cache, so applying and showing a filter cost one RPC const filterText = useCallback( (f: string) => queryClient.fetchQuery(responseBodyTextQuery({ response, filter: f })), [queryClient, response], ); const { recentFilters, addFilter, removeFilter, togglePin, clearFilters } = useRecentFilters(filterStateKey); const filterLeftSlot = useCallback( (filter: TextFilterApi) => (
), [recentFilters, removeFilter, togglePin, clearFilters], ); const saveResponse = useSaveResponse(response); const copyResponse = useCopyHttpResponse(response); const actionsDisabled = response.state !== "closed" && response.status >= 100; return ( saveResponse.mutate()} className="border !border-border-subtle" />, copyResponse.mutate()} className="border !border-border-subtle" />, ]} filterText={filterText} filterStateKey={filterStateKey} onFilterApplied={addFilter} filterLeftSlot={filterLeftSlot} /> ); }