diff --git a/src-web/components/RecentResponsesDropdown.tsx b/src-web/components/RecentResponsesDropdown.tsx index fa88b6d6..c29232b0 100644 --- a/src-web/components/RecentResponsesDropdown.tsx +++ b/src-web/components/RecentResponsesDropdown.tsx @@ -1,4 +1,5 @@ import type { HttpResponse } from '@yaakapp/api'; +import { useCopyHttpResponse } from '../hooks/useCopyHttpResponse'; import { useDeleteHttpResponse } from '../hooks/useDeleteHttpResponse'; import { useDeleteHttpResponses } from '../hooks/useDeleteHttpResponses'; import { useSaveResponse } from '../hooks/useSaveResponse'; @@ -8,7 +9,6 @@ import { Icon } from './core/Icon'; import { IconButton } from './core/IconButton'; import { HStack } from './core/Stacks'; import { StatusTag } from './core/StatusTag'; -import { useCopyHttpResponse } from './useCopyHttpResponse'; interface Props { responses: HttpResponse[]; diff --git a/src-web/components/RequestPane.tsx b/src-web/components/RequestPane.tsx index 987e9e7a..42cd96d1 100644 --- a/src-web/components/RequestPane.tsx +++ b/src-web/components/RequestPane.tsx @@ -8,6 +8,7 @@ import { useContentTypeFromHeaders } from '../hooks/useContentTypeFromHeaders'; import { useImportCurl } from '../hooks/useImportCurl'; import { useIsResponseLoading } from '../hooks/useIsResponseLoading'; import { usePinnedHttpResponse } from '../hooks/usePinnedHttpResponse'; +import { useRequestEditorEvent } from '../hooks/useRequestEditor'; import { useRequests } from '../hooks/useRequests'; import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey'; import { useSendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest'; @@ -42,7 +43,6 @@ import { FormMultipartEditor } from './FormMultipartEditor'; import { FormUrlencodedEditor } from './FormUrlencodedEditor'; import { GraphQLEditor } from './GraphQLEditor'; import { HeadersEditor } from './HeadersEditor'; -import { useOnFocusParamsTab } from './RequestEditorContext'; import { useToast } from './ToastContext'; import { UrlBar } from './UrlBar'; import { UrlParametersEditor } from './UrlParameterEditor'; @@ -298,7 +298,7 @@ export const RequestPane = memo(function RequestPane({ const { updateKey } = useRequestUpdateKey(activeRequestId ?? null); const importCurl = useImportCurl(); - useOnFocusParamsTab(() => { + useRequestEditorEvent('focus_http_request_params_tab', () => { setActiveTab(TAB_PARAMS); }); diff --git a/src-web/components/UrlParameterEditor.tsx b/src-web/components/UrlParameterEditor.tsx index af9613d7..3e5eb885 100644 --- a/src-web/components/UrlParameterEditor.tsx +++ b/src-web/components/UrlParameterEditor.tsx @@ -1,8 +1,8 @@ import type { HttpRequest } from '@yaakapp/api'; +import { useRequestEditorEvent } from '../hooks/useRequestEditor'; import type { PairEditorRef } from './core/PairEditor'; import { PairOrBulkEditor } from './core/PairOrBulkEditor'; import { VStack } from './core/Stacks'; -import { useOnFocusParamValue } from './RequestEditorContext'; import { useRef } from 'react'; type Props = { @@ -14,7 +14,8 @@ type Props = { export function UrlParametersEditor({ pairs, forceUpdateKey, onChange }: Props) { const pairEditor = useRef(null); - useOnFocusParamValue( + useRequestEditorEvent( + 'focus_http_request_param_value', (name) => { const pairIndex = pairs.findIndex((p) => p.name === name); if (pairIndex >= 0) { diff --git a/src-web/components/core/Editor/Editor.tsx b/src-web/components/core/Editor/Editor.tsx index 2d4bf6d6..d15adcb2 100644 --- a/src-web/components/core/Editor/Editor.tsx +++ b/src-web/components/core/Editor/Editor.tsx @@ -19,10 +19,10 @@ import { } from 'react'; import { useActiveEnvironmentVariables } from '../../../hooks/useActiveEnvironmentVariables'; import { parseTemplate } from '../../../hooks/useParseTemplate'; +import { useRequestEditor } from '../../../hooks/useRequestEditor'; import { useSettings } from '../../../hooks/useSettings'; import { useTemplateFunctions } from '../../../hooks/useTemplateFunctions'; import { useDialog } from '../../DialogContext'; -import { useRequestEditor } from '../../RequestEditorContext'; import { TemplateFunctionDialog } from '../../TemplateFunctionDialog'; import { TemplateVariableDialog } from '../../TemplateVariableDialog'; import { IconButton } from '../IconButton'; diff --git a/src-web/components/useCopyHttpResponse.ts b/src-web/hooks/useCopyHttpResponse.ts similarity index 90% rename from src-web/components/useCopyHttpResponse.ts rename to src-web/hooks/useCopyHttpResponse.ts index b10ddd05..d208427f 100644 --- a/src-web/components/useCopyHttpResponse.ts +++ b/src-web/hooks/useCopyHttpResponse.ts @@ -1,6 +1,6 @@ import { useMutation } from '@tanstack/react-query'; import type { HttpResponse } from '@yaakapp/api'; -import { useCopy } from '../hooks/useCopy'; +import { useCopy } from './useCopy'; import { getResponseBodyText } from '../lib/responseBody'; export function useCopyHttpResponse(response: HttpResponse) { diff --git a/src-web/hooks/useRequestEditor.tsx b/src-web/hooks/useRequestEditor.tsx new file mode 100644 index 00000000..d9442c5c --- /dev/null +++ b/src-web/hooks/useRequestEditor.tsx @@ -0,0 +1,65 @@ +import EventEmitter from 'eventemitter3'; +import type { DependencyList } from 'react'; +import { useCallback, useEffect } from 'react'; + +type EventDataMap = { + focus_http_request_param_value: string; + focus_http_request_params_tab: undefined; +}; + +export function useRequestEditorEvent< + Event extends keyof EventDataMap, + Data extends EventDataMap[Event], +>(event: Event, fn: (data: Data) => void, deps?: DependencyList) { + useEffect(() => { + emitter.on(event, fn); + return () => { + emitter.off(event, fn); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, deps); +} + +export function useRequestEditor() { + const focusParamsTab = useCallback(() => { + emitter.emit('focus_http_request_params_tab', undefined); + }, []); + + const focusParamValue = useCallback( + (name: string) => { + focusParamsTab(); + setTimeout(() => emitter.emit('focus_http_request_param_value', name), 50); + }, + [focusParamsTab], + ); + + return { + focusParamValue, + focusParamsTab, + }; +} + +const emitter = new (class RequestEditorEventEmitter { + #emitter: EventEmitter = new EventEmitter(); + + emit( + event: Event, + data: Data, + ) { + this.#emitter.emit(event, data); + } + + on( + event: Event, + fn: (data: Data) => void, + ) { + this.#emitter.on(event, fn); + } + + off( + event: Event, + fn: (data: Data) => void, + ) { + this.#emitter.off(event, fn); + } +})();