diff --git a/packages/insomnia/src/ui/components/dropdowns/workspace-sync-dropdown.tsx b/packages/insomnia/src/ui/components/dropdowns/workspace-sync-dropdown.tsx index 34145d0f9..1fc5443d7 100644 --- a/packages/insomnia/src/ui/components/dropdowns/workspace-sync-dropdown.tsx +++ b/packages/insomnia/src/ui/components/dropdowns/workspace-sync-dropdown.tsx @@ -3,6 +3,7 @@ import React from 'react'; import { useFetcher, useParams, useRouteLoaderData } from 'react-router-dom'; import { isRemoteProject } from '../../../models/project'; +import { useLoaderDeferData } from '../../hooks/use-loader-defer-data'; import type { OrganizationFeatureLoaderData } from '../../routes/organization'; import { useRootLoaderData } from '../../routes/root'; import type { WorkspaceLoaderData } from '../../routes/workspace'; @@ -30,11 +31,11 @@ export const WorkspaceSyncDropdown: FC = () => { } }, [organizationId, permissionsFetcher]); - const { features } = permissionsFetcher.data || { - features: { - gitSync: { enabled: false, reason: 'Insomnia API unreachable' }, - }, - }; + const { featuresPromise } = permissionsFetcher.data || {}; + const [features = { + gitSync: { enabled: false, reason: 'Insomnia API unreachable' }, + }] = useLoaderDeferData(featuresPromise); + if (!userSession.id) { return null; } diff --git a/packages/insomnia/src/ui/components/modals/workspace-environments-edit-modal.tsx b/packages/insomnia/src/ui/components/modals/workspace-environments-edit-modal.tsx index 3c09ebb07..d1e758ec6 100644 --- a/packages/insomnia/src/ui/components/modals/workspace-environments-edit-modal.tsx +++ b/packages/insomnia/src/ui/components/modals/workspace-environments-edit-modal.tsx @@ -7,6 +7,7 @@ import { docsTemplateTags } from '../../../common/documentation'; import { debounce } from '../../../common/misc'; import type { Environment } from '../../../models/environment'; import { isRemoteProject } from '../../../models/project'; +import { useLoaderDeferData } from '../../hooks/use-loader-defer-data'; import type { OrganizationFeatureLoaderData } from '../../routes/organization'; import type { WorkspaceLoaderData } from '../../routes/workspace'; import { EditableInput } from '../editable-input'; @@ -31,11 +32,11 @@ export const WorkspaceEnvironmentsEditModal = ({ onClose }: { } }, [organizationId, permissionsFetcher]); - const { features } = permissionsFetcher.data || { - features: { - gitSync: { enabled: false, reason: 'Insomnia API unreachable' }, - }, - }; + const { featuresPromise } = permissionsFetcher.data || {}; + const [features = { + gitSync: { enabled: false, reason: 'Insomnia API unreachable' }, + }] = useLoaderDeferData(featuresPromise); + const createEnvironmentFetcher = useFetcher(); const deleteEnvironmentFetcher = useFetcher(); const updateEnvironmentFetcher = useFetcher(); diff --git a/packages/insomnia/src/ui/hooks/use-loader-defer-data.ts b/packages/insomnia/src/ui/hooks/use-loader-defer-data.ts index abc64993f..6c1944cec 100644 --- a/packages/insomnia/src/ui/hooks/use-loader-defer-data.ts +++ b/packages/insomnia/src/ui/hooks/use-loader-defer-data.ts @@ -25,7 +25,7 @@ export const useLoaderDeferData = (deferedDataPromise?: Promise, keepStale setData(data); } catch (err) { setError(err); - console.log('Failed to load defered data', err); + console.warn('Failed to load defered data', err); } })(); }, [deferedDataPromise, keepStaleDataKey]); diff --git a/packages/insomnia/src/ui/routes/environments.tsx b/packages/insomnia/src/ui/routes/environments.tsx index 614e07008..9880bc245 100644 --- a/packages/insomnia/src/ui/routes/environments.tsx +++ b/packages/insomnia/src/ui/routes/environments.tsx @@ -15,6 +15,7 @@ import { EnvironmentEditor, type EnvironmentEditorHandle, type EnvironmentInfo } import { Icon } from '../components/icon'; import { useDocBodyKeyboardShortcuts } from '../components/keydown-binder'; import { showAlert } from '../components/modals'; +import { useLoaderDeferData } from '../hooks/use-loader-defer-data'; import type { OrganizationFeatureLoaderData } from './organization'; import type { WorkspaceLoaderData } from './workspace'; @@ -34,11 +35,10 @@ const Environments = () => { } }, [organizationId, permissionsFetcher]); - const { features } = permissionsFetcher.data || { - features: { - gitSync: { enabled: false, reason: 'Insomnia API unreachable' }, - }, - }; + const { featuresPromise } = permissionsFetcher.data || {}; + const [features = { + gitSync: { enabled: false, reason: 'Insomnia API unreachable' }, + }] = useLoaderDeferData(featuresPromise); const createEnvironmentFetcher = useFetcher(); const deleteEnvironmentFetcher = useFetcher(); diff --git a/packages/insomnia/src/ui/routes/organization.tsx b/packages/insomnia/src/ui/routes/organization.tsx index 85443062d..4229cf91e 100644 --- a/packages/insomnia/src/ui/routes/organization.tsx +++ b/packages/insomnia/src/ui/routes/organization.tsx @@ -312,9 +312,9 @@ export interface StorageRule { } export interface OrganizationFeatureLoaderData { - features: FeatureList; - billing: Billing; - storage: 'cloud_plus_local' | 'cloud_only' | 'local_only'; + featuresPromise: Promise; + billingPromise: Promise; + storagePromise: Promise<'cloud_plus_local' | 'cloud_only' | 'local_only'>; } export const organizationPermissionsLoader: LoaderFunction = async ({ params }): Promise => { @@ -334,9 +334,9 @@ export const organizationPermissionsLoader: LoaderFunction = async ({ params }): if (isScratchpadOrganizationId(organizationId)) { return { - features: fallbackFeatures, - billing: fallbackBilling, - storage: fallbackStorage, + featuresPromise: Promise.resolve(fallbackFeatures), + billingPromise: Promise.resolve(fallbackBilling), + storagePromise: Promise.resolve(fallbackStorage), }; } @@ -348,28 +348,27 @@ export const organizationPermissionsLoader: LoaderFunction = async ({ params }): } try { - const response = await insomniaFetch<{ features: FeatureList; billing: Billing } | undefined>({ + const featuresResponse = insomniaFetch<{ features: FeatureList; billing: Billing } | undefined>({ method: 'GET', path: `/v1/organizations/${organizationId}/features`, sessionId, }); - const ruleResponse = await insomniaFetch({ + const ruleResponse = insomniaFetch({ method: 'GET', path: `/v1/organizations/${organizationId}/storage-rule`, sessionId, }); - const storage = ruleResponse?.storage || fallbackStorage; return { - features: response?.features || fallbackFeatures, - billing: response?.billing || fallbackBilling, - storage, + featuresPromise: featuresResponse.then(res => res?.features || fallbackFeatures), + billingPromise: featuresResponse.then(res => res?.billing || fallbackBilling), + storagePromise: ruleResponse.then(res => res?.storage || fallbackStorage), }; } catch (err) { return { - features: fallbackFeatures, - billing: fallbackBilling, - storage: fallbackStorage, + featuresPromise: Promise.resolve(fallbackFeatures), + billingPromise: Promise.resolve(fallbackBilling), + storagePromise: Promise.resolve(fallbackStorage), }; } }; diff --git a/packages/insomnia/src/ui/routes/project.tsx b/packages/insomnia/src/ui/routes/project.tsx index 47e41efa3..85b29d48b 100644 --- a/packages/insomnia/src/ui/routes/project.tsx +++ b/packages/insomnia/src/ui/routes/project.tsx @@ -612,16 +612,16 @@ const ProjectRoute: FC = () => { }, [organizationId, permissionsFetcher.load]); const { currentPlan } = useRouteLoaderData('/organization') as OrganizationLoaderData; - const { features, billing, storage } = permissionsFetcher.data || { - features: { - gitSync: { enabled: false, reason: 'Insomnia API unreachable' }, - orgBasicRbac: { enabled: false, reason: 'Insomnia API unreachable' }, - }, - billing: { - isActive: true, - }, - storage: 'cloud_plus_local', - }; + + const { featuresPromise, billingPromise, storagePromise } = permissionsFetcher.data || {}; + const [features = { + gitSync: { enabled: false, reason: 'Insomnia API unreachable' }, + orgBasicRbac: { enabled: false, reason: 'Insomnia API unreachable' }, + }] = useLoaderDeferData(featuresPromise); + const [billing = { + isActive: true, + }] = useLoaderDeferData(billingPromise); + const [storage = 'cloud_plus_local'] = useLoaderDeferData(storagePromise); const [projectListFilter, setProjectListFilter] = useLocalStorage(`${organizationId}:project-list-filter`, ''); const [workspaceListFilter, setWorkspaceListFilter] = useLocalStorage(`${projectId}:workspace-list-filter`, ''); const [workspaceListScope, setWorkspaceListScope] = useLocalStorage(`${projectId}:workspace-list-scope`, 'all');