diff --git a/packages/insomnia/src/models/helpers/__tests__/query-all-workspace-urls.test.ts b/packages/insomnia/src/models/helpers/__tests__/query-all-workspace-urls.test.ts index 899f0b2ec..8e20c641a 100644 --- a/packages/insomnia/src/models/helpers/__tests__/query-all-workspace-urls.test.ts +++ b/packages/insomnia/src/models/helpers/__tests__/query-all-workspace-urls.test.ts @@ -11,8 +11,8 @@ describe('queryAllWorkspaceUrls', () => { const w = await models.workspace.create({ name: 'Workspace', }); - await expect(queryAllWorkspaceUrls(w, models.request.type)).resolves.toHaveLength(0); - await expect(queryAllWorkspaceUrls(w, models.grpcRequest.type)).resolves.toHaveLength(0); + await expect(queryAllWorkspaceUrls(w._id, models.request.type)).resolves.toHaveLength(0); + await expect(queryAllWorkspaceUrls(w._id, models.grpcRequest.type)).resolves.toHaveLength(0); }); it('should return urls and exclude that of the selected request', async () => { @@ -78,17 +78,17 @@ describe('queryAllWorkspaceUrls', () => { url: 'diff.url', }); // All items - await expect(queryAllWorkspaceUrls(w, models.request.type)).resolves.toStrictEqual( + await expect(queryAllWorkspaceUrls(w._id, models.request.type)).resolves.toStrictEqual( expect.arrayContaining([r1.url, r2.url]), ); - await expect(queryAllWorkspaceUrls(w, models.grpcRequest.type)).resolves.toStrictEqual( + await expect(queryAllWorkspaceUrls(w._id, models.grpcRequest.type)).resolves.toStrictEqual( expect.arrayContaining([gr1.url, gr2.url]), ); // Ignore url of the selected request id - await expect(queryAllWorkspaceUrls(w, models.request.type, r1._id)).resolves.toStrictEqual( + await expect(queryAllWorkspaceUrls(w._id, models.request.type, r1._id)).resolves.toStrictEqual( expect.arrayContaining([r2.url]), ); - await expect(queryAllWorkspaceUrls(w, models.grpcRequest.type, gr1._id)).resolves.toStrictEqual( + await expect(queryAllWorkspaceUrls(w._id, models.grpcRequest.type, gr1._id)).resolves.toStrictEqual( expect.arrayContaining([gr2.url]), ); }); diff --git a/packages/insomnia/src/models/helpers/query-all-workspace-urls.ts b/packages/insomnia/src/models/helpers/query-all-workspace-urls.ts index 6019ad54c..f22e6ce24 100644 --- a/packages/insomnia/src/models/helpers/query-all-workspace-urls.ts +++ b/packages/insomnia/src/models/helpers/query-all-workspace-urls.ts @@ -1,13 +1,16 @@ import { database as db } from '../../common/database'; +import * as models from '../../models'; +import { invariant } from '../../utils/invariant'; import { GrpcRequest, type as GrpcRequestType } from '../grpc-request'; import { Request, type as RequestType } from '../request'; -import { Workspace } from '../workspace'; export const queryAllWorkspaceUrls = async ( - workspace: Workspace | null, + workspaceId: string, reqType: typeof RequestType | typeof GrpcRequestType, reqId = 'n/a', ): Promise => { + const workspace = await models.workspace.getById(workspaceId); + invariant(workspace, `Workspace ${workspaceId} not found`); const docs = await db.withDescendants(workspace, reqType) as (Request | GrpcRequest)[]; const urls = docs .filter( diff --git a/packages/insomnia/src/ui/components/base/editable.tsx b/packages/insomnia/src/ui/components/base/editable.tsx index 7a2b513a3..11d0b897b 100644 --- a/packages/insomnia/src/ui/components/base/editable.tsx +++ b/packages/insomnia/src/ui/components/base/editable.tsx @@ -23,7 +23,7 @@ interface Props { className?: string; fallbackValue?: string; onEditStart?: () => void; - onSubmit: (value?: string) => void; + onSubmit: (value: string) => void; preventBlank?: boolean; renderReadView?: (value: string | undefined, props: any) => ReactElement; singleClick?: boolean; @@ -63,7 +63,7 @@ export const Editable: FC = ({ const handleEditEnd = useCallback(() => { if (shouldSave(value, inputRef.current?.value.trim(), preventBlank)) { // Don't run onSubmit for values that haven't been changed - onSubmit(inputRef.current?.value.trim()); + onSubmit(inputRef.current?.value.trim() || ''); } // This timeout prevents the UI from showing the old value after submit. diff --git a/packages/insomnia/src/ui/components/dropdowns/environments-dropdown.tsx b/packages/insomnia/src/ui/components/dropdowns/environments-dropdown.tsx index 17b71f2e7..568c6b218 100644 --- a/packages/insomnia/src/ui/components/dropdowns/environments-dropdown.tsx +++ b/packages/insomnia/src/ui/components/dropdowns/environments-dropdown.tsx @@ -3,7 +3,6 @@ import { useSelector } from 'react-redux'; import * as models from '../../../models'; import type { Environment } from '../../../models/environment'; -import type { Workspace } from '../../../models/workspace'; import { selectActiveWorkspaceMeta, selectEnvironments, selectHotKeyRegistry } from '../../redux/selectors'; import { type DropdownHandle, Dropdown } from '../base/dropdown/dropdown'; import { DropdownButton } from '../base/dropdown/dropdown-button'; @@ -17,12 +16,12 @@ import { Tooltip } from '../tooltip'; interface Props { activeEnvironment?: Environment | null; - workspace: Workspace; + workspaceId: string; } export const EnvironmentsDropdown: FC = ({ activeEnvironment, - workspace, + workspaceId, }) => { const environments = useSelector(selectEnvironments); const hotKeyRegistry = useSelector(selectHotKeyRegistry); @@ -38,7 +37,7 @@ export const EnvironmentsDropdown: FC = ({ }); // NOTE: Base environment might not exist if the users hasn't managed environments yet. - const baseEnvironment = environments.find(environment => environment.parentId === workspace._id); + const baseEnvironment = environments.find(environment => environment.parentId === workspaceId); const subEnvironments = environments .filter(environment => environment.parentId === (baseEnvironment && baseEnvironment._id)) .sort((e1, e2) => e1.metaSortKey - e2.metaSortKey); diff --git a/packages/insomnia/src/ui/components/editors/body/body-editor.tsx b/packages/insomnia/src/ui/components/editors/body/body-editor.tsx index 11357cfbc..f0abbcce0 100644 --- a/packages/insomnia/src/ui/components/editors/body/body-editor.tsx +++ b/packages/insomnia/src/ui/components/editors/body/body-editor.tsx @@ -22,7 +22,6 @@ import { newBodyFormUrlEncoded, newBodyRaw, } from '../../../../models/request'; -import type { Settings } from '../../../../models/settings'; import type { Workspace } from '../../../../models/workspace'; import { NunjucksEnabledProvider } from '../../../context/nunjucks/nunjucks-enabled-context'; import { AskModal } from '../../modals/ask-modal'; @@ -38,35 +37,28 @@ import { UrlEncodedEditor } from './url-encoded-editor'; interface Props { request: Request; workspace: Workspace; - settings: Settings; environmentId: string; } export const BodyEditor: FC = ({ request, workspace, - settings, environmentId, }) => { const handleRawChange = useCallback((rawValue: string) => { - const oldContentType = request.body.mimeType || ''; - const body = newBodyRaw(rawValue, oldContentType); - models.request.update(request, { body }); + models.request.update(request, { body: newBodyRaw(rawValue, request.body.mimeType || '') }); }, [request]); const handleGraphQLChange = useCallback((content: string) => { - const body = newBodyRaw(content, CONTENT_TYPE_GRAPHQL); - models.request.update(request, { body }); + models.request.update(request, { body: newBodyRaw(content, CONTENT_TYPE_GRAPHQL) }); }, [request]); const handleFormUrlEncodedChange = useCallback((parameters: RequestBodyParameter[]) => { - const body = newBodyFormUrlEncoded(parameters); - models.request.update(request, { body }); + models.request.update(request, { body: newBodyFormUrlEncoded(parameters) }); }, [request]); const handleFormChange = useCallback((parameters: RequestBodyParameter[]) => { - const body = newBodyForm(parameters); - models.request.update(request, { body }); + models.request.update(request, { body: newBodyForm(parameters) }); }, [request]); const handleFileChange = async (path: string) => { @@ -118,7 +110,7 @@ export const BodyEditor: FC = ({ } else if (mimeType === CONTENT_TYPE_FILE) { return ; } else if (mimeType === CONTENT_TYPE_GRAPHQL) { - return ; + return ; } else if (!isBodyEmpty) { const contentType = getContentTypeFromHeaders(request.headers) || mimeType; return ; diff --git a/packages/insomnia/src/ui/components/editors/body/form-editor.tsx b/packages/insomnia/src/ui/components/editors/body/form-editor.tsx index 638adf4f9..9a67c6ff4 100644 --- a/packages/insomnia/src/ui/components/editors/body/form-editor.tsx +++ b/packages/insomnia/src/ui/components/editors/body/form-editor.tsx @@ -3,7 +3,12 @@ import React, { FC } from 'react'; import { KeyValueEditor } from '../../key-value-editor/key-value-editor'; interface Props { - onChange: Function; + onChange: (c: { + name: string; + value: string; + description?: string; + disabled?: boolean; + }[]) => void; parameters: any[]; } diff --git a/packages/insomnia/src/ui/components/editors/body/graph-ql-editor.tsx b/packages/insomnia/src/ui/components/editors/body/graph-ql-editor.tsx index a26de06a9..a5c08fdfe 100644 --- a/packages/insomnia/src/ui/components/editors/body/graph-ql-editor.tsx +++ b/packages/insomnia/src/ui/components/editors/body/graph-ql-editor.tsx @@ -10,6 +10,7 @@ import { Maybe } from 'graphql-language-service'; import prettier from 'prettier'; import React, { FC, useEffect, useRef, useState } from 'react'; import ReactDOM from 'react-dom'; +import { useSelector } from 'react-redux'; import { jarFromCookies } from '../../../../common/cookies'; import { markdownToHTML } from '../../../../common/markdown-to-html'; @@ -18,11 +19,11 @@ import { getRenderContext, render, RENDER_PURPOSE_SEND } from '../../../../commo import type { ResponsePatch } from '../../../../main/network/libcurl-promise'; import * as models from '../../../../models'; import type { Request } from '../../../../models/request'; -import type { Settings } from '../../../../models/settings'; import { axiosRequest } from '../../../../network/axios-request'; import { jsonPrettify } from '../../../../utils/prettify/json'; import { setDefaultProtocol } from '../../../../utils/url/protocol'; import { buildQueryStringFromParams, joinUrlAndQueryString } from '../../../../utils/url/querystring'; +import { selectSettings } from '../../../redux/selectors'; import { Dropdown } from '../../base/dropdown/dropdown'; import { DropdownButton } from '../../base/dropdown/dropdown-button'; import { DropdownDivider } from '../../base/dropdown/dropdown-divider'; @@ -151,7 +152,6 @@ interface GraphQLBody { interface Props { onChange: (value: string) => void; request: Request; - settings: Settings; environmentId: string; className?: string; uniquenessKey?: string; @@ -172,7 +172,6 @@ interface State { export const GraphQLEditor: FC = ({ request, environmentId, - settings, onChange, className, uniquenessKey, @@ -252,12 +251,13 @@ export const GraphQLEditor: FC = ({ }; }, [environmentId, request._id, request.url, workspaceId]); + const { editorIndentWithTabs, editorIndentSize } = useSelector(selectSettings); const beautifyRequestBody = () => { const { body } = state; const prettyQuery = prettier.format(body.query, { parser: 'graphql', - useTabs: settings.editorIndentWithTabs, - tabWidth: settings.editorIndentSize, + useTabs: editorIndentWithTabs, + tabWidth: editorIndentSize, }); const prettyVariables = body.variables && JSON.parse(jsonPrettify(JSON.stringify(body.variables))); changeQuery(prettyQuery); diff --git a/packages/insomnia/src/ui/components/editors/body/url-encoded-editor.tsx b/packages/insomnia/src/ui/components/editors/body/url-encoded-editor.tsx index 2c630aff4..6b5f56483 100644 --- a/packages/insomnia/src/ui/components/editors/body/url-encoded-editor.tsx +++ b/packages/insomnia/src/ui/components/editors/body/url-encoded-editor.tsx @@ -3,7 +3,12 @@ import React, { FC } from 'react'; import { KeyValueEditor } from '../../key-value-editor/key-value-editor'; interface Props { - onChange: Function; + onChange: (c: { + name: string; + value: string; + description?: string; + disabled?: boolean; + }[]) => void; parameters: any[]; } diff --git a/packages/insomnia/src/ui/components/key-value-editor/key-value-editor.tsx b/packages/insomnia/src/ui/components/key-value-editor/key-value-editor.tsx index 2f2257c99..aea55808a 100644 --- a/packages/insomnia/src/ui/components/key-value-editor/key-value-editor.tsx +++ b/packages/insomnia/src/ui/components/key-value-editor/key-value-editor.tsx @@ -33,7 +33,12 @@ interface Props { isDisabled?: boolean; isWebSocketRequest?: boolean; namePlaceholder?: string; - onChange: Function; + onChange: (c: { + name: string; + value: string; + description?: string; + disabled?: boolean; + }[]) => void; pairs: Pair[]; valuePlaceholder?: string; } diff --git a/packages/insomnia/src/ui/components/modals/settings-modal.tsx b/packages/insomnia/src/ui/components/modals/settings-modal.tsx index 56d7d9833..8e9d87b56 100644 --- a/packages/insomnia/src/ui/components/modals/settings-modal.tsx +++ b/packages/insomnia/src/ui/components/modals/settings-modal.tsx @@ -1,9 +1,7 @@ import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react'; -import { useSelector } from 'react-redux'; import * as session from '../../../account/session'; import { getAppVersion, getProductName } from '../../../common/constants'; -import { selectSettings } from '../../redux/selectors'; import { type ModalHandle, Modal, ModalProps } from '../base/modal'; import { ModalBody } from '../base/modal-body'; import { ModalHeader } from '../base/modal-header'; @@ -26,7 +24,6 @@ export const TAB_INDEX_SHORTCUTS = 'keyboard'; export const TAB_INDEX_THEMES = 'themes'; export const TAB_INDEX_PLUGINS = 'plugins'; export const SettingsModal = forwardRef((props, ref) => { - const settings = useSelector(selectSettings); const [defaultTabKey, setDefaultTabKey] = useState('general'); const modalRef = useRef(null); const email = session.isLoggedIn() ? session.getFullName() : null; @@ -79,7 +76,7 @@ export const SettingsModal = forwardRef((props, - + diff --git a/packages/insomnia/src/ui/components/panes/grpc-request-pane.tsx b/packages/insomnia/src/ui/components/panes/grpc-request-pane.tsx index 82212a483..2fa003b98 100644 --- a/packages/insomnia/src/ui/components/panes/grpc-request-pane.tsx +++ b/packages/insomnia/src/ui/components/panes/grpc-request-pane.tsx @@ -138,10 +138,7 @@ export const GrpcRequestPane: FunctionComponent = ({ defaultValue={activeRequest.url} placeholder="grpcb.in:9000" onChange={url => models.grpcRequest.update(activeRequest, { url })} - getAutocompleteConstants={async () => { - const workspace = await models.workspace.getById(workspaceId); - return queryAllWorkspaceUrls(workspace, models.grpcRequest.type, activeRequest._id); - }} + getAutocompleteConstants={() => queryAllWorkspaceUrls(workspaceId, models.grpcRequest.type, activeRequest._id)} /> diff --git a/packages/insomnia/src/ui/components/panes/request-pane.tsx b/packages/insomnia/src/ui/components/panes/request-pane.tsx index d45ce8b1f..14acb5883 100644 --- a/packages/insomnia/src/ui/components/panes/request-pane.tsx +++ b/packages/insomnia/src/ui/components/panes/request-pane.tsx @@ -88,10 +88,6 @@ export const RequestPane: FC = ({ handleEditDescription(true); }, [handleEditDescription]); - const autocompleteUrls = useCallback(() => { - return queryAllWorkspaceUrls(workspace, models.request.type, request?._id); - }, [workspace, request]); - const handleUpdateSettingsUseBulkHeaderEditor = useCallback(() => { models.settings.update(settings, { useBulkHeaderEditor:!settings.useBulkHeaderEditor }); }, [settings]); @@ -178,7 +174,7 @@ export const RequestPane: FC = ({ ref={requestUrlBarRef} uniquenessKey={uniqueKey} onUrlChange={updateRequestUrl} - handleAutocompleteUrls={autocompleteUrls} + handleAutocompleteUrls={() => queryAllWorkspaceUrls(workspace._id, models.request.type, request?._id)} nunjucksPowerUserMode={settings.nunjucksPowerUserMode} request={request} setLoading={setLoading} @@ -192,7 +188,6 @@ export const RequestPane: FC = ({ request={request} workspace={workspace} environmentId={environmentId} - settings={settings} /> }> diff --git a/packages/insomnia/src/ui/components/settings/plugins.tsx b/packages/insomnia/src/ui/components/settings/plugins.tsx index 9006fd670..ccc7587c8 100644 --- a/packages/insomnia/src/ui/components/settings/plugins.tsx +++ b/packages/insomnia/src/ui/components/settings/plugins.tsx @@ -1,5 +1,6 @@ import * as path from 'path'; import React, { FC, useEffect, useState } from 'react'; +import { useSelector } from 'react-redux'; import { NPM_PACKAGE_BASE, @@ -8,21 +9,17 @@ import { import { docsPlugins } from '../../../common/documentation'; import { clickLink, getDataDirectory } from '../../../common/electron-helpers'; import * as models from '../../../models'; -import type { Settings } from '../../../models/settings'; import { createPlugin } from '../../../plugins/create'; import type { Plugin } from '../../../plugins/index'; import { getPlugins } from '../../../plugins/index'; import { reload } from '../../../templating/index'; +import { selectSettings } from '../../redux/selectors'; import { CopyButton } from '../base/copy-button'; import { Link } from '../base/link'; import { HelpTooltip } from '../help-tooltip'; import { showAlert, showPrompt } from '../modals'; import { Button } from '../themed-button'; -interface Props { - settings: Settings; -} - interface State { plugins: Plugin[]; npmPluginValue: string; @@ -31,7 +28,7 @@ interface State { isInstallingFromNpm: boolean; isRefreshingPlugins: boolean; } -export const Plugins: FC = ({ settings }) => { +export const Plugins: FC = () => { const [state, setState] = useState({ plugins: [], npmPluginValue: '', @@ -48,6 +45,7 @@ export const Plugins: FC = ({ settings }) => { isRefreshingPlugins, npmPluginValue, } = state; + const settings = useSelector(selectSettings); useEffect(() => { refreshPlugins(); diff --git a/packages/insomnia/src/ui/components/sidebar-layout.tsx b/packages/insomnia/src/ui/components/sidebar-layout.tsx index 2deb8eeb9..b505d3325 100644 --- a/packages/insomnia/src/ui/components/sidebar-layout.tsx +++ b/packages/insomnia/src/ui/components/sidebar-layout.tsx @@ -192,7 +192,7 @@ export const SidebarLayout: FC = ({ renderPaneTwo, renderPageSidebar, }) => { - const settings = useSelector(selectSettings); + const { forceVerticalLayout } = useSelector(selectSettings); const activeWorkspaceMeta = useSelector(selectActiveWorkspaceMeta); const reduxPaneHeight = useSelector(selectPaneHeight); const reduxPaneWidth = useSelector(selectPaneWidth); @@ -359,7 +359,7 @@ export const SidebarLayout: FC = ({ {