import { linter } from "@codemirror/lint"; import type { HttpRequest } from "@yaakapp-internal/models"; import { patchModel } from "@yaakapp-internal/models"; import { useCallback, useMemo } from "react"; import { fireAndForget } from "../lib/fireAndForget"; import { useKeyValue } from "../hooks/useKeyValue"; import { textLikelyContainsJsonComments } from "../lib/jsonComments"; import { Banner } from "./core/Banner"; import type { DropdownItem } from "./core/Dropdown"; import { Dropdown } from "./core/Dropdown"; import type { EditorProps } from "./core/Editor/Editor"; import { jsonParseLinter } from "./core/Editor/json-lint"; import { Editor } from "./core/Editor/LazyEditor"; import { Icon } from "./core/Icon"; import { IconButton } from "./core/IconButton"; import { IconTooltip } from "./core/IconTooltip"; interface Props { forceUpdateKey: string; heightMode: EditorProps["heightMode"]; request: HttpRequest; } export function JsonBodyEditor({ forceUpdateKey, heightMode, request }: Props) { const handleChange = useCallback( (text: string) => patchModel(request, { body: { ...request.body, text } }), [request], ); const autoFix = request.body?.sendJsonComments !== true; const lintExtension = useMemo( () => linter( jsonParseLinter( autoFix ? { allowComments: true, allowTrailingCommas: true } : { allowComments: false, allowTrailingCommas: false }, ), ), [autoFix], ); const hasComments = useMemo( () => textLikelyContainsJsonComments(request.body?.text ?? ""), [request.body?.text], ); const { value: bannerDismissed, set: setBannerDismissed } = useKeyValue({ namespace: "no_sync", key: ["json-fix-3", request.workspaceId], fallback: false, }); const handleToggleAutoFix = useCallback(() => { const newBody = { ...request.body }; if (autoFix) { newBody.sendJsonComments = true; } else { delete newBody.sendJsonComments; } fireAndForget(patchModel(request, { body: newBody })); }, [request, autoFix]); const handleDropdownOpen = useCallback(() => { if (!bannerDismissed) { fireAndForget(setBannerDismissed(true)); } }, [bannerDismissed, setBannerDismissed]); const showBanner = hasComments && autoFix && !bannerDismissed; const stripMessage = "Automatically strip comments and trailing commas before sending"; const actions = useMemo( () => [ showBanner && (

Auto-fix enabled

),
, leftSlot: ( ), }, ] satisfies DropdownItem[] } >
, ], [handleDropdownOpen, handleToggleAutoFix, autoFix, showBanner], ); return ( ); }