import { invoke } from '@tauri-apps/api'; import { appWindow } from '@tauri-apps/api/window'; import classNames from 'classnames'; import type { CSSProperties } from 'react'; import { memo, useCallback, useMemo, useState } from 'react'; import { createGlobalState } from 'react-use'; import { useActiveRequest } from '../hooks/useActiveRequest'; import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey'; import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent'; import { useUpdateRequest } from '../hooks/useUpdateRequest'; import { tryFormatJson } from '../lib/formatters'; import type { HttpHeader, HttpRequest } from '../lib/models'; import { AUTH_TYPE_BASIC, AUTH_TYPE_BEARER, AUTH_TYPE_NONE, BODY_TYPE_GRAPHQL, BODY_TYPE_JSON, BODY_TYPE_NONE, BODY_TYPE_XML, } from '../lib/models'; import { BasicAuth } from './BasicAuth'; import { BearerAuth } from './BearerAuth'; import { CountBadge } from './core/CountBadge'; import { Editor } from './core/Editor'; import type { TabItem } from './core/Tabs/Tabs'; import { TabContent, Tabs } from './core/Tabs/Tabs'; import { EmptyStateText } from './EmptyStateText'; import { GraphQLEditor } from './GraphQLEditor'; import { HeaderEditor } from './HeaderEditor'; import { ParametersEditor } from './ParameterEditor'; import { UrlBar } from './UrlBar'; import { useActiveEnvironmentId } from '../hooks/useActiveEnvironmentId'; interface Props { style?: CSSProperties; fullHeight: boolean; className?: string; } const useActiveTab = createGlobalState('body'); export const RequestPane = memo(function RequestPane({ style, fullHeight, className }: Props) { const activeRequest = useActiveRequest(); const activeRequestId = activeRequest?.id ?? null; const activeEnvironmentId = useActiveEnvironmentId(); const updateRequest = useUpdateRequest(activeRequestId); const [activeTab, setActiveTab] = useActiveTab(); const [forceUpdateHeaderEditorKey, setForceUpdateHeaderEditorKey] = useState(0); const { updateKey: forceUpdateKey } = useRequestUpdateKey(activeRequest?.id ?? null); const tabs: TabItem[] = useMemo( () => activeRequest === null ? [] : [ { value: 'body', options: { value: activeRequest.bodyType, items: [ { label: 'JSON', value: BODY_TYPE_JSON }, { label: 'XML', value: BODY_TYPE_XML }, { label: 'GraphQL', value: BODY_TYPE_GRAPHQL }, { type: 'separator' }, { label: 'No Body', shortLabel: 'Body', value: BODY_TYPE_NONE }, ], onChange: async (bodyType) => { const patch: Partial = { bodyType }; if (bodyType === BODY_TYPE_NONE) { patch.headers = activeRequest?.headers.filter( (h) => h.name.toLowerCase() !== 'content-type', ); } else if (bodyType == BODY_TYPE_GRAPHQL || bodyType === BODY_TYPE_JSON) { patch.method = 'POST'; patch.headers = [ ...(activeRequest?.headers.filter( (h) => h.name.toLowerCase() !== 'content-type', ) ?? []), { name: 'Content-Type', value: 'application/json', enabled: true, }, ]; } // Force update header editor so any changed headers are reflected setTimeout(() => setForceUpdateHeaderEditorKey((u) => u + 1), 100); await updateRequest.mutate(patch); }, }, }, // { value: 'params', label: 'URL Params' }, { value: 'headers', label: (
Headers h.name).length} />
), }, { value: 'auth', label: 'Auth', options: { value: activeRequest.authenticationType, items: [ { label: 'Basic Auth', shortLabel: 'Basic', value: AUTH_TYPE_BASIC }, { label: 'Bearer Token', shortLabel: 'Bearer', value: AUTH_TYPE_BEARER }, { type: 'separator' }, { label: 'No Authentication', shortLabel: 'Auth', value: AUTH_TYPE_NONE }, ], onChange: async (authenticationType) => { let authentication: HttpRequest['authentication'] = activeRequest?.authentication; if (authenticationType === AUTH_TYPE_BASIC) { authentication = { username: authentication.username ?? '', password: authentication.password ?? '', }; } else if (authenticationType === AUTH_TYPE_BEARER) { authentication = { token: authentication.token ?? '', }; } await updateRequest.mutate({ authenticationType, authentication }); }, }, }, ], [activeRequest, updateRequest], ); const handleBodyChange = useCallback( (body: string) => updateRequest.mutate({ body }), [updateRequest], ); const handleHeadersChange = useCallback( (headers: HttpHeader[]) => updateRequest.mutate({ headers }), [updateRequest], ); useListenToTauriEvent( 'send_request', async ({ windowLabel }) => { if (windowLabel !== appWindow.label) return; await invoke('send_request', { requestId: activeRequestId, environmentId: activeEnvironmentId }); }, [activeRequestId, activeEnvironmentId], ); return (
{activeRequest && ( <> {activeRequest.authenticationType === AUTH_TYPE_BASIC ? ( ) : activeRequest.authenticationType === AUTH_TYPE_BEARER ? ( ) : ( No Authentication {activeRequest.authenticationType} )} null} /> {activeRequest.bodyType === BODY_TYPE_JSON ? ( tryFormatJson(v)} /> ) : activeRequest.bodyType === BODY_TYPE_XML ? ( ) : activeRequest.bodyType === BODY_TYPE_GRAPHQL ? ( ) : ( No Body )} )}
); });