diff --git a/packages/insomnia-app/app/common/get-workspace-label.ts b/packages/insomnia-app/app/common/get-workspace-label.ts index e12a8d789..8b00a746a 100644 --- a/packages/insomnia-app/app/common/get-workspace-label.ts +++ b/packages/insomnia-app/app/common/get-workspace-label.ts @@ -1,5 +1,5 @@ import { isDesign, Workspace } from '../models/workspace'; import { strings } from './strings'; -export const getWorkspaceLabel = (w: Workspace) => - isDesign(w) ? strings.document : strings.collection; +export const getWorkspaceLabel = (workspace: Workspace) => + isDesign(workspace) ? strings.document : strings.collection; diff --git a/packages/insomnia-app/app/ui/components/activity-toggle.tsx b/packages/insomnia-app/app/ui/components/activity-toggle.tsx index 72d61be2c..69c2ebe8a 100644 --- a/packages/insomnia-app/app/ui/components/activity-toggle.tsx +++ b/packages/insomnia-app/app/ui/components/activity-toggle.tsx @@ -1,17 +1,18 @@ import { MultiSwitch } from 'insomnia-components'; -import React, { FunctionComponent } from 'react'; +import React, { FunctionComponent, useCallback } from 'react'; +import { useSelector } from 'react-redux'; import type { GlobalActivity } from '../../common/constants'; import { ACTIVITY_DEBUG, ACTIVITY_SPEC, ACTIVITY_UNIT_TEST } from '../../common/constants'; -import type { Workspace } from '../../models/workspace'; +import { isDesign } from '../../models/workspace'; +import { selectActiveActivity, selectActiveWorkspace } from '../redux/selectors'; +import { HandleActivityChange } from './wrapper'; interface Props { - activity: GlobalActivity; - handleActivityChange: (options: {workspaceId?: string; nextActivity: GlobalActivity}) => Promise; - workspace: Workspace; + handleActivityChange: HandleActivityChange; } -export const ActivityToggle: FunctionComponent = ({ activity, handleActivityChange, workspace }) => { +export const ActivityToggle: FunctionComponent = ({ handleActivityChange }) => { const choices = [ { label: 'Design', @@ -27,12 +28,27 @@ export const ActivityToggle: FunctionComponent = ({ activity, handleActiv }, ]; + const activeActivity = useSelector(selectActiveActivity); + const activeWorkspace = useSelector(selectActiveWorkspace); + + const onChange = useCallback((nextActivity: GlobalActivity) => { + handleActivityChange({ workspaceId: activeWorkspace?._id, nextActivity }); + }, [handleActivityChange, activeWorkspace]); + + if (!activeActivity) { + return null; + } + + if (!activeWorkspace || !isDesign(activeWorkspace)) { + return null; + } + return ( handleActivityChange({ workspaceId: workspace._id, nextActivity })} + onChange={onChange} choices={choices} - selectedValue={activity} + selectedValue={activeActivity} /> ); }; diff --git a/packages/insomnia-app/app/ui/components/dropdowns/workspace-dropdown.tsx b/packages/insomnia-app/app/ui/components/dropdowns/workspace-dropdown.tsx index bc8e1fc34..2aa1694f7 100644 --- a/packages/insomnia-app/app/ui/components/dropdowns/workspace-dropdown.tsx +++ b/packages/insomnia-app/app/ui/components/dropdowns/workspace-dropdown.tsx @@ -1,7 +1,7 @@ import { autoBindMethodsForReact } from 'class-autobind-decorator'; import classnames from 'classnames'; -import { HotKeyRegistry } from 'insomnia-common'; import React, { PureComponent } from 'react'; +import { connect } from 'react-redux'; import { AUTOBIND_CFG } from '../../../common/constants'; import { database as db } from '../../../common/database'; @@ -9,15 +9,15 @@ import { getWorkspaceLabel } from '../../../common/get-workspace-label'; import { hotKeyRefs } from '../../../common/hotkeys'; import { executeHotKey } from '../../../common/hotkeys-listener'; import { RENDER_PURPOSE_NO_RENDER } from '../../../common/render'; -import { ApiSpec } from '../../../models/api-spec'; -import type { Environment } from '../../../models/environment'; -import { Project } from '../../../models/project'; import { isRequest } from '../../../models/request'; import { isRequestGroup } from '../../../models/request-group'; import { isDesign, Workspace } from '../../../models/workspace'; import type { WorkspaceAction } from '../../../plugins'; import { ConfigGenerator, getConfigGenerators, getWorkspaceActions } from '../../../plugins'; import * as pluginContexts from '../../../plugins/context'; +import { RootState } from '../../redux/modules'; +import { selectIsLoading } from '../../redux/modules/global'; +import { selectActiveApiSpec, selectActiveEnvironment, selectActiveProject, selectActiveWorkspace, selectActiveWorkspaceName, selectSettings } from '../../redux/selectors'; import { Dropdown } from '../base/dropdown/dropdown'; import { DropdownButton } from '../base/dropdown/dropdown-button'; import { DropdownDivider } from '../base/dropdown/dropdown-divider'; @@ -29,13 +29,9 @@ import { showGenerateConfigModal } from '../modals/generate-config-modal'; import { SettingsModal, TAB_INDEX_EXPORT } from '../modals/settings-modal'; import { WorkspaceSettingsModal } from '../modals/workspace-settings-modal'; -interface Props { - activeEnvironment: Environment | null; - activeWorkspace: Workspace; - activeWorkspaceName?: string; - activeApiSpec: ApiSpec; - activeProject: Project; - hotKeyRegistry: HotKeyRegistry; +type ReduxProps = ReturnType; + +interface Props extends ReduxProps { isLoading: boolean; className?: string; } @@ -47,7 +43,7 @@ interface State { } @autoBindMethodsForReact(AUTOBIND_CFG) -export class WorkspaceDropdown extends PureComponent { +export class UnconnectedWorkspaceDropdown extends PureComponent { _dropdown: Dropdown | null = null; state: State = { actionPlugins: [], @@ -55,31 +51,31 @@ export class WorkspaceDropdown extends PureComponent { loadingActions: {}, }; - async _handlePluginClick(p: WorkspaceAction) { + async _handlePluginClick({ action, plugin, label }: WorkspaceAction, workspace: Workspace) { this.setState(state => ({ - loadingActions: { ...state.loadingActions, [p.label]: true }, + loadingActions: { ...state.loadingActions, [label]: true }, })); - const { activeEnvironment, activeWorkspace, activeProject } = this.props; + const { activeEnvironment, activeProject } = this.props; try { const activeEnvironmentId = activeEnvironment ? activeEnvironment._id : null; const context = { ...(pluginContexts.app.init(RENDER_PURPOSE_NO_RENDER) as Record), ...pluginContexts.data.init(activeProject._id), - ...(pluginContexts.store.init(p.plugin) as Record), + ...(pluginContexts.store.init(plugin) as Record), ...(pluginContexts.network.init(activeEnvironmentId) as Record), }; - const docs = await db.withDescendants(activeWorkspace); + const docs = await db.withDescendants(workspace); const requests = docs .filter(isRequest) .filter(doc => ( !doc.isPrivate )); const requestGroups = docs.filter(isRequestGroup); - await p.action(context, { + await action(context, { requestGroups, requests, - workspace: activeWorkspace, + workspace, }); } catch (err) { showError({ @@ -89,7 +85,7 @@ export class WorkspaceDropdown extends PureComponent { } this.setState(state => ({ - loadingActions: { ...state.loadingActions, [p.label]: false }, + loadingActions: { ...state.loadingActions, [label]: false }, })); this._dropdown?.hide(); } @@ -123,6 +119,9 @@ export class WorkspaceDropdown extends PureComponent { async _handleGenerateConfig(label: string) { const { activeApiSpec } = this.props; + if (!activeApiSpec) { + return; + } showGenerateConfigModal({ apiSpec: activeApiSpec, activeTabLabel: label, @@ -140,6 +139,11 @@ export class WorkspaceDropdown extends PureComponent { } = this.props; const classes = classnames(className, 'wide', 'workspace-dropdown'); const { actionPlugins, loadingActions, configGeneratorPlugins } = this.state; + if (!activeWorkspace) { + console.error('warning: tried to render WorkspaceDropdown without an activeWorkspace'); + return null; + } + return ( { {actionPlugins.map((p: WorkspaceAction) => ( this._handlePluginClick(p)} + onClick={() => this._handlePluginClick(p, activeWorkspace)} stayOpenAfterClick > {loadingActions[p.label] ? ( @@ -210,3 +214,15 @@ export class WorkspaceDropdown extends PureComponent { ); } } + +const mapStateToProps = (state: RootState) => ({ + activeEnvironment: selectActiveEnvironment(state), + activeWorkspace: selectActiveWorkspace(state), + activeWorkspaceName: selectActiveWorkspaceName(state), + activeApiSpec: selectActiveApiSpec(state), + activeProject: selectActiveProject(state), + hotKeyRegistry: selectSettings(state).hotKeyRegistry, + isLoading: selectIsLoading(state), +}); + +export const WorkspaceDropdown = connect(mapStateToProps)(UnconnectedWorkspaceDropdown); diff --git a/packages/insomnia-app/app/ui/components/page-layout.tsx b/packages/insomnia-app/app/ui/components/page-layout.tsx index 7e306dd5d..cc51c772c 100644 --- a/packages/insomnia-app/app/ui/components/page-layout.tsx +++ b/packages/insomnia-app/app/ui/components/page-layout.tsx @@ -1,8 +1,9 @@ -import { autoBindMethodsForReact } from 'class-autobind-decorator'; import classnames from 'classnames'; -import React, { forwardRef, PureComponent, ReactNode } from 'react'; +import React, { FC, forwardRef, ReactNode, useCallback } from 'react'; +import { useSelector } from 'react-redux'; -import { AUTOBIND_CFG } from '../../common/constants'; +import { selectIsLoading } from '../redux/modules/global'; +import { selectActiveEnvironment, selectActiveGitRepository, selectSettings, selectUnseenWorkspaces, selectWorkspacesForActiveProject } from '../redux/selectors'; import { ErrorBoundary } from './error-boundary'; import { Sidebar } from './sidebar/sidebar'; import type { WrapperProps } from './wrapper'; @@ -26,168 +27,164 @@ interface Props { renderPaneTwo?: () => ReactNode; } -@autoBindMethodsForReact(AUTOBIND_CFG) -export class PageLayout extends PureComponent { - // Special request updaters - _handleStartDragSidebar(e: React.MouseEvent) { - e.preventDefault(); - const { handleStartDragSidebar } = this.props.wrapperProps; - handleStartDragSidebar(e); - } +export const PageLayout: FC = ({ + renderPaneOne, + renderPaneTwo, + renderPageBody, + renderPageHeader, + renderPageSidebar, + wrapperProps, +}) => { + const activeEnvironment = useSelector(selectActiveEnvironment); + const activeGitRepository = useSelector(selectActiveGitRepository); + const isLoading = useSelector(selectIsLoading); + const settings = useSelector(selectSettings); + const unseenWorkspaces = useSelector(selectUnseenWorkspaces); + const workspaces = useSelector(selectWorkspacesForActiveProject); - render() { - const { - renderPaneOne, - renderPaneTwo, - renderPageBody, - renderPageHeader, - renderPageSidebar, - wrapperProps, - } = this.props; - const { - activeEnvironment, - activeGitRepository, - gitVCS, - handleInitializeEntities, - handleResetDragSidebar, - handleSetActiveEnvironment, - sidebarRef, - requestPaneRef, - responsePaneRef, - handleStartDragPaneHorizontal, - handleResetDragPaneHorizontal, - handleStartDragPaneVertical, - handleResetDragPaneVertical, - isLoading, - paneHeight, - paneWidth, - settings, - sidebarHidden, - sidebarWidth, - unseenWorkspaces, - workspaces, - } = wrapperProps; - const realSidebarWidth = sidebarHidden ? 0 : sidebarWidth; - const paneTwo = renderPaneTwo?.(); - const gridRows = paneTwo - ? `auto minmax(0, ${paneHeight}fr) 0 minmax(0, ${1 - paneHeight}fr)` - : 'auto 1fr'; - const gridColumns = + const { + gitVCS, + handleInitializeEntities, + handleResetDragSidebar, + handleStartDragSidebar, + handleSetActiveEnvironment, + sidebarRef, + requestPaneRef, + responsePaneRef, + handleStartDragPaneHorizontal, + handleResetDragPaneHorizontal, + handleStartDragPaneVertical, + handleResetDragPaneVertical, + paneHeight, + paneWidth, + sidebarHidden, + sidebarWidth, + } = wrapperProps; + + // Special request updaters + const startDragSidebar = useCallback((event: React.MouseEvent) => { + event.preventDefault(); + handleStartDragSidebar(event); + }, [handleStartDragSidebar]); + + const realSidebarWidth = sidebarHidden ? 0 : sidebarWidth; + const paneTwo = renderPaneTwo?.(); + const gridRows = paneTwo + ? `auto minmax(0, ${paneHeight}fr) 0 minmax(0, ${1 - paneHeight}fr)` + : 'auto 1fr'; + const gridColumns = `auto ${realSidebarWidth}rem 0 ` + `${paneTwo ? `minmax(0, ${paneWidth}fr) 0 minmax(0, ${1 - paneWidth}fr)` : '1fr'}`; - return ( -
- {renderPageHeader && {renderPageHeader()}} + }} + > + {renderPageHeader && {renderPageHeader()}} - {renderPageSidebar && ( - - + {renderPageSidebar && ( + + + +
+
+
+ + )} + {renderPageBody ? ( + {renderPageBody()} + ) : ( + <> + {renderPaneOne && ( + + + {renderPaneOne()} + + + )} + {paneTwo && ( + <> +
+
+
+ +
+
+
-
-
-
- - )} - {renderPageBody ? ( - {renderPageBody()} - ) : ( - <> - {renderPaneOne && ( - {renderPaneOne()} + {paneTwo} - )} - {paneTwo && ( - <> -
-
-
- -
-
-
- - - - {paneTwo} - - - - )} - - )} -
- ); - } -} + + )} + + )} +
+ ); +}; diff --git a/packages/insomnia-app/app/ui/components/sidebar/sidebar.tsx b/packages/insomnia-app/app/ui/components/sidebar/sidebar.tsx index 697c27b35..0e6571e31 100644 --- a/packages/insomnia-app/app/ui/components/sidebar/sidebar.tsx +++ b/packages/insomnia-app/app/ui/components/sidebar/sidebar.tsx @@ -17,7 +17,6 @@ interface Props { hidden: boolean; hotKeyRegistry: HotKeyRegistry; isLoading: boolean; - showEnvironmentsModal: (...args: any[]) => any; unseenWorkspaces: Workspace[]; width: number; workspaces: Workspace[]; diff --git a/packages/insomnia-app/app/ui/components/workspace-page-header.tsx b/packages/insomnia-app/app/ui/components/workspace-page-header.tsx index aeed44e6a..3664cc44c 100644 --- a/packages/insomnia-app/app/ui/components/workspace-page-header.tsx +++ b/packages/insomnia-app/app/ui/components/workspace-page-header.tsx @@ -1,74 +1,44 @@ import React, { FunctionComponent, ReactNode, useCallback } from 'react'; import { useSelector } from 'react-redux'; -import { ACTIVITY_HOME, GlobalActivity } from '../../common/constants'; -import { isDesign } from '../../models/workspace'; -import { selectActiveProjectName } from '../redux/selectors'; +import { ACTIVITY_HOME } from '../../common/constants'; +import { selectActiveActivity, selectActiveApiSpec, selectActiveProjectName, selectActiveWorkspace } from '../redux/selectors'; import { ActivityToggle } from './activity-toggle'; import { AppHeader } from './app-header'; import { WorkspaceDropdown } from './dropdowns/workspace-dropdown'; -import type { WrapperProps } from './wrapper'; +import { HandleActivityChange } from './wrapper'; interface Props { - wrapperProps: WrapperProps; - handleActivityChange: (options: {workspaceId?: string; nextActivity: GlobalActivity}) => Promise; + handleActivityChange: HandleActivityChange; gridRight: ReactNode; } export const WorkspacePageHeader: FunctionComponent = ({ gridRight, handleActivityChange, - wrapperProps: { - activeApiSpec, - activeWorkspace, - activeWorkspaceName, - activeProject, - activeEnvironment, - settings, - activity, - isLoading, - }, }) => { - const homeCallback = useCallback( - () => handleActivityChange({ workspaceId: activeWorkspace?._id, nextActivity: ACTIVITY_HOME }), - [activeWorkspace, handleActivityChange], - ); + const activeApiSpec = useSelector(selectActiveApiSpec); + const activeWorkspace = useSelector(selectActiveWorkspace); + const activity = useSelector(selectActiveActivity); + + const homeCallback = useCallback(() => { + handleActivityChange({ workspaceId: activeWorkspace?._id, nextActivity: ACTIVITY_HOME }); + }, [activeWorkspace, handleActivityChange]); const activeProjectName = useSelector(selectActiveProjectName); if (!activeWorkspace || !activeApiSpec || !activity) { return null; } - const workspace = ( - - ); - const crumbs = [ { id: 'project', node: activeProjectName, onClick: homeCallback }, - { id: 'workspace', node: workspace }, + { id: 'workspace', node: }, ]; return ( - ) - } + gridCenter={} gridRight={gridRight} /> ); diff --git a/packages/insomnia-app/app/ui/components/wrapper-debug.tsx b/packages/insomnia-app/app/ui/components/wrapper-debug.tsx index d6b67df5a..d812434e4 100644 --- a/packages/insomnia-app/app/ui/components/wrapper-debug.tsx +++ b/packages/insomnia-app/app/ui/components/wrapper-debug.tsx @@ -1,7 +1,7 @@ import { autoBindMethodsForReact } from 'class-autobind-decorator'; import React, { Fragment, PureComponent, ReactNode } from 'react'; -import { AUTOBIND_CFG, GlobalActivity, SortOrder } from '../../common/constants'; +import { AUTOBIND_CFG, SortOrder } from '../../common/constants'; import { isGrpcRequest } from '../../models/grpc-request'; import { isRemoteProject } from '../../models/project'; import { Request, RequestAuthentication, RequestBody, RequestHeader, RequestParameter } from '../../models/request'; @@ -19,12 +19,12 @@ import { ResponsePane } from './panes/response-pane'; import { SidebarChildren } from './sidebar/sidebar-children'; import { SidebarFilter } from './sidebar/sidebar-filter'; import { WorkspacePageHeader } from './workspace-page-header'; -import type { WrapperProps } from './wrapper'; +import type { HandleActivityChange, WrapperProps } from './wrapper'; interface Props { forceRefreshKey: number; gitSyncDropdown: ReactNode; - handleActivityChange: (options: {workspaceId?: string; nextActivity: GlobalActivity}) => Promise; + handleActivityChange: HandleActivityChange; handleChangeEnvironment: Function; handleDeleteResponse: Function; handleDeleteResponses: Function; @@ -54,18 +54,22 @@ interface Props { @autoBindMethodsForReact(AUTOBIND_CFG) export class WrapperDebug extends PureComponent { _renderPageHeader() { - const { wrapperProps, gitSyncDropdown, handleActivityChange } = this.props; - const { vcs, activeWorkspace, activeWorkspaceMeta, activeProject, syncItems, isLoggedIn } = this.props.wrapperProps; + const { gitSyncDropdown, handleActivityChange, wrapperProps: { + vcs, + activeWorkspace, + activeWorkspaceMeta, + activeProject, + syncItems, + isLoggedIn, + } } = this.props; if (!activeWorkspace) { return null; } const collection = isCollection(activeWorkspace); - const design = isDesign(activeWorkspace); let insomniaSync: ReactNode = null; - if (isLoggedIn && collection && isRemoteProject(activeProject) && vcs) { insomniaSync = { />; } - const gitSync = design && gitSyncDropdown; + const gitSync = isDesign(activeWorkspace) && gitSyncDropdown; const sync = insomniaSync || gitSync; return ( diff --git a/packages/insomnia-app/app/ui/components/wrapper-design.tsx b/packages/insomnia-app/app/ui/components/wrapper-design.tsx index 09a64ca66..42df79187 100644 --- a/packages/insomnia-app/app/ui/components/wrapper-design.tsx +++ b/packages/insomnia-app/app/ui/components/wrapper-design.tsx @@ -1,23 +1,24 @@ import { IRuleResult } from '@stoplight/spectral'; import { Button, Notice, NoticeTable } from 'insomnia-components'; import React, { createRef, FC, Fragment, ReactNode, RefObject, useCallback, useState } from 'react'; +import { useSelector } from 'react-redux'; import { useAsync, useDebounce } from 'react-use'; import styled from 'styled-components'; import SwaggerUI from 'swagger-ui-react'; import { parseApiSpec, ParsedApiSpec } from '../../common/api-specs'; -import type { GlobalActivity } from '../../common/constants'; import { initializeSpectral, isLintError } from '../../common/spectral'; import * as models from '../../models/index'; import { superFaint } from '../css/css-in-js'; import previewIcon from '../images/icn-eye.svg'; +import { selectActiveApiSpec, selectActiveWorkspace, selectActiveWorkspaceMeta } from '../redux/selectors'; import { CodeEditor, UnconnectedCodeEditor } from './codemirror/code-editor'; import { DesignEmptyState } from './design-empty-state'; import { ErrorBoundary } from './error-boundary'; import { PageLayout } from './page-layout'; import { SpecEditorSidebar } from './spec-editor/spec-editor-sidebar'; import { WorkspacePageHeader } from './workspace-page-header'; -import type { WrapperProps } from './wrapper'; +import type { HandleActivityChange, WrapperProps } from './wrapper'; const EmptySpaceHelper = styled.div({ ...superFaint, @@ -33,13 +34,12 @@ const spectral = initializeSpectral(); const RenderPageHeader: FC> = ({ gitSyncDropdown, handleActivityChange, - wrapperProps, }) => { - const { activeWorkspace, activeWorkspaceMeta } = wrapperProps; + const activeWorkspace = useSelector(selectActiveWorkspace); + const activeWorkspaceMeta = useSelector(selectActiveWorkspaceMeta); const previewHidden = Boolean(activeWorkspaceMeta?.previewHidden); const handleTogglePreview = useCallback(async () => { @@ -53,7 +53,6 @@ const RenderPageHeader: FC @@ -75,13 +74,8 @@ interface LintMessage { range: IRuleResult['range']; } -const RenderEditor: FC & { - editor: RefObject; -}> = ({ - editor, - wrapperProps, -}) => { - const { activeApiSpec } = wrapperProps; +const RenderEditor: FC<{ editor: RefObject }> = ({ editor }) => { + const activeApiSpec = useSelector(selectActiveApiSpec); const [forceRefreshCounter, setForceRefreshCounter] = useState(0); const [lintMessages, setLintMessages] = useState([]); const contents = activeApiSpec?.contents ?? ''; @@ -160,8 +154,9 @@ const RenderEditor: FC & { ); }; -const RenderPreview: FC> = ({ wrapperProps }) => { - const { activeApiSpec, activeWorkspaceMeta } = wrapperProps; +const RenderPreview: FC = () => { + const activeWorkspaceMeta = useSelector(selectActiveWorkspaceMeta); + const activeApiSpec = useSelector(selectActiveApiSpec); if (!activeApiSpec || activeWorkspaceMeta?.previewHidden) { return null; @@ -217,10 +212,8 @@ const RenderPreview: FC> = ({ wrapperProps }) => { ); }; -const RenderPageSidebar: FC & { editor: RefObject}> = ({ - editor, - wrapperProps: { activeApiSpec }, -}) => { +const RenderPageSidebar: FC<{ editor: RefObject}> = ({ editor }) => { + const activeApiSpec = useSelector(selectActiveApiSpec); const handleScrollToSelection = useCallback((chStart: number, chEnd: number, lineStart: number, lineEnd: number) => { if (!editor.current) { return; @@ -263,7 +256,7 @@ const RenderPageSidebar: FC & { editor: RefObject Promise; + handleActivityChange: HandleActivityChange; wrapperProps: WrapperProps; } @@ -278,29 +271,20 @@ export const WrapperDesign: FC = ({ - ), [gitSyncDropdown, handleActivityChange, wrapperProps]); + ), [gitSyncDropdown, handleActivityChange]); const renderEditor = useCallback(() => ( - - ), [editor, wrapperProps]); + + ), [editor]); const renderPreview = useCallback(() => ( - - ), [wrapperProps]); + + ), []); const renderPageSidebar = useCallback(() => ( - - ), [editor, wrapperProps]); + + ), [editor]); return ( Promise; + handleActivityChange: HandleActivityChange; wrapperProps: WrapperProps; } @@ -546,10 +545,9 @@ export class WrapperUnitTest extends PureComponent { } _renderPageHeader() { - const { wrapperProps, gitSyncDropdown, handleActivityChange } = this.props; + const { gitSyncDropdown, handleActivityChange } = this.props; return ( diff --git a/packages/insomnia-app/app/ui/components/wrapper.tsx b/packages/insomnia-app/app/ui/components/wrapper.tsx index c4c6f716d..f7dbf2ccf 100644 --- a/packages/insomnia-app/app/ui/components/wrapper.tsx +++ b/packages/insomnia-app/app/ui/components/wrapper.tsx @@ -122,6 +122,11 @@ export type WrapperProps = AppProps & { gitVCS: GitVCS | null; }; +export type HandleActivityChange = (options: { + workspaceId?: string; + nextActivity: GlobalActivity; +}) => Promise; + interface State { forceRefreshKey: number; activeGitBranch: string; @@ -213,7 +218,7 @@ export class Wrapper extends PureComponent { return null; } - async _handleWorkspaceActivityChange({ workspaceId, nextActivity }: {workspaceId?: string; nextActivity: GlobalActivity}) { + async _handleWorkspaceActivityChange({ workspaceId, nextActivity }: Parameters[0]): ReturnType { const { activity, activeApiSpec, handleSetActiveActivity } = this.props; // Remember last activity on workspace for later, but only if it isn't HOME diff --git a/packages/insomnia-app/app/ui/redux/modules/global.tsx b/packages/insomnia-app/app/ui/redux/modules/global.tsx index e807a95c6..306c5f570 100644 --- a/packages/insomnia-app/app/ui/redux/modules/global.tsx +++ b/packages/insomnia-app/app/ui/redux/modules/global.tsx @@ -44,6 +44,7 @@ import { TAB_INDEX_THEMES, } from '../../components/modals/settings-modal'; import { selectActiveProjectName, selectStats, selectWorkspacesForActiveProject } from '../selectors'; +import { RootState } from '.'; import { importUri } from './import'; import { activateWorkspace } from './workspace'; @@ -180,6 +181,8 @@ export const reducer = combineReducers({ isLoggedIn: loginStateChangeReducer, }); +export const selectIsLoading = (state: RootState) => state.global.isLoading; + // ~~~~~~~ // // ACTIONS // // ~~~~~~~ //