feat(Proxy Settings): Improve Proxy experience (#7664)

* Improve check for updates button

* Create a new settings tab for Proxy settings

* display the status bar on the auth views and update indicator for when proxy is on

* update e2e
This commit is contained in:
James Gatz 2024-07-04 15:08:27 +02:00 committed by GitHub
parent f5886d3908
commit 8c66a9b3c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 269 additions and 194 deletions

View File

@ -355,6 +355,7 @@ test.describe('pre-request features tests', async () => {
// update proxy configuration
await page.locator('[data-testid="settings-button"]').click();
await page.locator('text=Insomnia Preferences').first().click();
await page.getByRole('tab', { name: 'Proxy' }).click();
await page.locator('text=Enable proxy').click();
await page.locator('[name="httpProxy"]').fill('localhost:1111');
await page.locator('[name="httpsProxy"]').fill('localhost:2222');

View File

@ -1,11 +1,8 @@
import React, { FC, ReactNode, useEffect, useState } from 'react';
import React, { useEffect, useState } from 'react';
interface Props {
children: ReactNode;
className?: string | null;
}
import { Icon } from './icon';
export const CheckForUpdatesButton: FC<Props> = ({ children, className }) => {
export const CheckForUpdatesButton = () => {
const [disabled, setDisabled] = useState(false);
const [status, setStatus] = useState('');
@ -16,9 +13,10 @@ export const CheckForUpdatesButton: FC<Props> = ({ children, className }) => {
unsubscribe();
};
});
return (
<button
className={className ?? ''}
className="flex items-center gap-2 btn btn--outlined btn--super-compact"
disabled={disabled}
onClick={() => {
window.main.manualUpdateCheck();
@ -27,7 +25,8 @@ export const CheckForUpdatesButton: FC<Props> = ({ children, className }) => {
setDisabled(true);
}}
>
{status || children}
<Icon className={status && 'animate-spin'} icon="refresh" />
{status || 'Check now'}
</button>
);
};

View File

@ -7,10 +7,13 @@ import { ModalBody } from '../base/modal-body';
import { ModalHeader } from '../base/modal-header';
import { PanelContainer, TabItem, Tabs } from '../base/tabs';
import { AI } from '../settings/ai';
import { BooleanSetting } from '../settings/boolean-setting';
import { General } from '../settings/general';
import { ImportExport } from '../settings/import-export';
import { MaskedSetting } from '../settings/masked-setting';
import { Plugins } from '../settings/plugins';
import { Shortcuts } from '../settings/shortcuts';
import { TextSetting } from '../settings/text-setting';
import { ThemePanel } from '../settings/theme-panel';
import { showModal } from './index';
@ -27,7 +30,7 @@ export const TAB_INDEX_AI = 'ai';
export const SettingsModal = forwardRef<SettingsModalHandle, ModalProps>((props, ref) => {
const [defaultTabKey, setDefaultTabKey] = useState('general');
const { userSession } = useRootLoaderData();
const { userSession, settings } = useRootLoaderData();
const modalRef = useRef<ModalHandle>(null);
useImperativeHandle(ref, () => ({
@ -52,8 +55,41 @@ export const SettingsModal = forwardRef<SettingsModalHandle, ModalProps>((props,
<ModalBody noScroll>
<Tabs aria-label="Insomnia Settings" defaultSelectedKey={defaultTabKey}>
<TabItem key="general" title="General">
<General />
</TabItem>
<TabItem key="proxy" title="Proxy">
<PanelContainer className="pad">
<General />
<h2 className='font-bold pt-5 pb-2 text-lg sticky top-0 left-0 bg-[--color-bg] z-10'>Network Proxy</h2>
<BooleanSetting
label="Enable proxy"
setting="proxyEnabled"
help="If checked, enables a global network proxy on all requests sent through Insomnia. This proxy supports Basic Auth, digest, and NTLM authentication."
/>
<div className="form-row pad-top-sm">
<MaskedSetting
label='Proxy for HTTP'
setting='httpProxy'
help="Enter a HTTP or SOCKS4/5 proxy starting with appropriate prefix from the following (http://, socks4://, socks5://)"
placeholder="localhost:8005"
disabled={!settings.proxyEnabled}
/>
<MaskedSetting
label='Proxy for HTTPS'
setting='httpsProxy'
help="Enter a HTTPS or SOCKS4/5 proxy starting with appropriate prefix from the following (https://, socks4://, socks5://)"
placeholder="localhost:8005"
disabled={!settings.proxyEnabled}
/>
<TextSetting
label="No proxy"
setting="noProxy"
help="Enter a comma-separated list of hostnames that dont require a proxy."
placeholder="localhost,127.0.0.1"
disabled={!settings.proxyEnabled}
/>
</div>
</PanelContainer>
</TabItem>
<TabItem key="data" title="Data">
@ -87,4 +123,4 @@ export const SettingsModal = forwardRef<SettingsModalHandle, ModalProps>((props,
);
});
SettingsModal.displayName = 'SettingsModal';
export const showSettingsModal = () => showModal(SettingsModal);
export const showSettingsModal = (options?: { tab?: string }) => showModal(SettingsModal, options);

View File

@ -39,10 +39,8 @@ export const BooleanSetting: FC<{
return (
<>
<div className="form-control form-control--thin">
<label className="inline-block">
{label}
{help && <HelpTooltip className="space-left">{help}</HelpTooltip>}
<div className="">
<label className="flex items-center gap-2">
<input
checked={Boolean(settings[setting])}
name={setting}
@ -50,6 +48,8 @@ export const BooleanSetting: FC<{
type="checkbox"
disabled={disabled}
/>
{label}
{help && <HelpTooltip className="space-left">{help}</HelpTooltip>}
</label>
</div>

View File

@ -18,7 +18,6 @@ import { Link } from '../base/link';
import { CheckForUpdatesButton } from '../check-for-updates-button';
import { BooleanSetting } from './boolean-setting';
import { EnumSetting } from './enum-setting';
import { MaskedSetting } from './masked-setting';
import { NumberSetting } from './number-setting';
import { TextSetting } from './text-setting';
@ -30,8 +29,10 @@ export const General: FC = () => {
const isLoggedIn = Boolean(userSession.id);
return (
<div className="pad-bottom">
<div className="row-fill row-fill--top">
<div className="relative p-4">
<h2 className='font-bold pt-5 pb-2 text-lg sticky top-0 left-0 bg-[--color-bg] z-10'>Application</h2>
<div className="">
<div>
<BooleanSetting
label="Use bulk header editor"
@ -77,8 +78,7 @@ export const General: FC = () => {
/>
</div>
<hr className="pad-top" />
<h2>Font</h2>
<h2 className='font-bold pt-5 pb-2 text-lg sticky top-0 left-0 bg-[--color-bg] z-10'>Font</h2>
<div className="row-fill row-fill--top">
<div>
@ -158,9 +158,7 @@ export const General: FC = () => {
/>
</div>
<hr className="pad-top" />
<h2>Request / Response</h2>
<h2 className='font-bold pt-5 pb-2 text-lg sticky top-0 left-0 bg-[--color-bg] z-10'>Request / Response</h2>
<div className="row-fill row-fill--top">
<div>
@ -246,9 +244,7 @@ export const General: FC = () => {
/>
</div>
<hr className="pad-top" />
<h2>Security</h2>
<h2 className='font-bold pt-5 pb-2 text-lg sticky top-0 left-0 bg-[--color-bg] z-10'>Security</h2>
<div className="form-row pad-top-sm">
<BooleanSetting
label="Clear OAuth 2 session on start"
@ -273,50 +269,11 @@ export const General: FC = () => {
/>
</div>
<hr className="pad-top" />
<h2>Network Proxy</h2>
<BooleanSetting
label="Enable proxy"
setting="proxyEnabled"
help="If checked, enables a global network proxy on all requests sent through Insomnia. This proxy supports Basic Auth, digest, and NTLM authentication."
/>
<div className="form-row pad-top-sm">
<MaskedSetting
label='Proxy for HTTP'
setting='httpProxy'
help="Enter a HTTP or SOCKS4/5 proxy starting with appropriate prefix from the following (http://, socks4://, socks5://)"
placeholder="localhost:8005"
disabled={!settings.proxyEnabled}
/>
<MaskedSetting
label='Proxy for HTTPS'
setting='httpsProxy'
help="Enter a HTTPS or SOCKS4/5 proxy starting with appropriate prefix from the following (https://, socks4://, socks5://)"
placeholder="localhost:8005"
disabled={!settings.proxyEnabled}
/>
<TextSetting
label="No proxy"
setting="noProxy"
help="Enter a comma-separated list of hostnames that dont require a proxy."
placeholder="localhost,127.0.0.1"
disabled={!settings.proxyEnabled}
/>
</div>
{updatesSupported() && (
<Fragment>
<hr className="pad-top" />
<div>
<div className="pull-right">
<CheckForUpdatesButton className="btn btn--outlined btn--super-duper-compact">
Check now
</CheckForUpdatesButton>
</div>
<h2>Software Updates</h2>
<h2 className='font-bold pt-5 pb-2 text-lg sticky top-0 left-0 bg-[--color-bg] z-10'>Software Updates</h2>
<div className="w-full">
<CheckForUpdatesButton />
</div>
<BooleanSetting
label="Automatically download and install updates"
@ -346,8 +303,7 @@ export const General: FC = () => {
/></>
)}
<hr className="pad-top" />
<h2>Plugins</h2>
<h2 className='font-bold pt-5 pb-2 text-lg sticky top-0 left-0 bg-[--color-bg] z-10'>Plugins</h2>
<TextSetting
label="Additional Plugin Path"
setting="pluginPath"

View File

@ -6,7 +6,6 @@ import { invariant } from '../../utils/invariant';
import { SegmentEvent } from '../analytics';
import { getLoginUrl, submitAuthCode } from '../auth-session-provider';
import { Icon } from '../components/icon';
import { showSettingsModal } from '../components/modals/settings-modal';
import { Button } from '../components/themed-button';
export const action: ActionFunction = async ({
@ -153,13 +152,6 @@ const Authorize = () => {
<Icon icon="arrow-left" />
<span>Go Back</span>
</Button>
<Button
data-testid="settings-button-auth-authorize"
className="px-4 py-1 h-full flex items-center justify-center gap-2 aria-pressed:bg-[--hl-sm] text-[--color-font] text-xs hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all"
onClick={showSettingsModal}
>
<Icon icon="gear" /> Preferences
</Button>
</div>
</div>
);

View File

@ -5,8 +5,6 @@ import { ActionFunction, redirect, useFetcher, useNavigate } from 'react-router-
import { SegmentEvent } from '../analytics';
import { getLoginUrl } from '../auth-session-provider';
import { Icon } from '../components/icon';
import { showModal } from '../components/modals';
import { SettingsModal } from '../components/modals/settings-modal';
const GoogleIcon = (props: React.ReactSVGElement['props']) => {
return (
@ -62,102 +60,104 @@ const Login = () => {
return (
<div
className='flex flex-col gap-[--padding-md]'
className='flex flex-col gap-[--padding-lg]'
>
<p className='text-center text-[--color-font] text-2xl py-[--padding-md]'>
Get started for free
</p>
<div className="font-extrabold text-sm [text-wrap:balance]">
<span className="text-indigo-300 inline-flex flex-col h-[calc(theme(fontSize.sm)*theme(lineHeight.tight))] overflow-hidden">
<ul className="block animate-text-slide-4 text-right leading-tight [&_li]:block">
<li>Debug</li>
<li>Design</li>
<li>Test</li>
<li>Mock</li>
<li aria-hidden="true">Debug</li>
</ul>
</span>
<span className='ml-1 text-[--color-font]'>APIs locally, on Git or in the Cloud.</span>
<div className='flex flex-col gap-[--padding-md]'>
<p className='text-center text-[--color-font] text-2xl py-[--padding-md]'>
Get started for free
</p>
<div className="font-extrabold text-sm [text-wrap:balance]">
<span className="text-indigo-300 inline-flex flex-col h-[calc(theme(fontSize.sm)*theme(lineHeight.tight))] overflow-hidden">
<ul className="block animate-text-slide-4 text-right leading-tight [&_li]:block">
<li>Debug</li>
<li>Design</li>
<li>Test</li>
<li>Mock</li>
<li aria-hidden="true">Debug</li>
</ul>
</span>
<span className='ml-1 text-[--color-font]'>APIs locally, on Git or in the Cloud.</span>
</div>
<Button
aria-label='Continue with Google'
onPress={() => {
login('google');
}}
className="w-full items-center border border-solid border-[--hl-md] flex justify-center gap-[--padding-md] aria-pressed:bg-[--hl-sm] rounded-md text-[--color-font] hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all text-base"
>
<div className='w-[40px] h-[35px] border-r border-solid border-[--hl-sm] flex items-center justify-center bg-[--hl-xs]'>
<GoogleIcon width="1em" />
</div>
<span className='flex-1 items'>
Continue with Google
</span>
</Button>
<Button
aria-label='Continue with GitHub'
onPress={() => {
login('github');
}}
className="w-full items-center border border-solid border-[--hl-md] flex justify-center gap-[--padding-md] aria-pressed:bg-[--hl-sm] rounded-md text-[--color-font] hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all text-base"
>
<div className='w-[40px] h-[35px] border-r border-solid border-[--hl-sm] flex items-center justify-center bg-[--hl-xs]'>
<Icon icon={['fab', 'github']} />
</div>
<span className='flex-1 items'>
Continue with GitHub
</span>
</Button>
<Button
aria-label='Continue with Email'
onPress={() => {
login('email');
}}
className="w-full items-center border border-solid border-[--hl-md] flex justify-center gap-[--padding-md] aria-pressed:bg-[--hl-sm] rounded-md text-[--color-font] hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all text-base"
>
<div className='w-[40px] h-[35px] border-r border-solid border-[--hl-sm] flex items-center justify-center bg-[--hl-xs]'>
<Icon icon="envelope" />
</div>
<span className='flex-1 items'>
Continue with Email
</span>
</Button>
<Button
aria-label='Continue with SSO'
onPress={() => {
login('sso');
}}
className="w-full items-center border border-solid border-[--hl-md] flex justify-center gap-[--padding-md] aria-pressed:bg-[--hl-sm] rounded-md text-[--color-font] hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all text-base"
>
<div className='w-[40px] h-[35px] border-r border-solid border-[--hl-sm] flex items-center justify-center bg-[--hl-xs]'>
<Icon icon="key" />
</div>
<span className='flex-1 items'>
Continue with SSO
</span>
</Button>
<p className='text-[rgba(var(--color-font-rgb),0.8)] text-xs text-center'>
By signing up or using Insomnia, you agree to the{' '}
<a
className='font-bold outline-none transition-colors hover:text-[--color-font] focus:text-[--color-font]'
href="https://insomnia.rest/terms"
rel="noreferrer"
>
terms of service
</a>{' '}
and{' '}
<a
className='font-bold outline-none transition-colors hover:text-[--color-font] focus:text-[--color-font]'
href="https://insomnia.rest/privacy"
rel="noreferrer"
>
privacy policy
</a>
.
</p>
</div>
<Button
aria-label='Continue with Google'
onPress={() => {
login('google');
}}
className="w-full items-center border border-solid border-[--hl-md] flex justify-center gap-[--padding-md] aria-pressed:bg-[--hl-sm] rounded-md text-[--color-font] hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all text-base"
>
<div className='w-[40px] h-[35px] border-r border-solid border-[--hl-sm] flex items-center justify-center bg-[--hl-xs]'>
<GoogleIcon width="1em" />
</div>
<span className='flex-1 items'>
Continue with Google
</span>
</Button>
<Button
aria-label='Continue with GitHub'
onPress={() => {
login('github');
}}
className="w-full items-center border border-solid border-[--hl-md] flex justify-center gap-[--padding-md] aria-pressed:bg-[--hl-sm] rounded-md text-[--color-font] hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all text-base"
>
<div className='w-[40px] h-[35px] border-r border-solid border-[--hl-sm] flex items-center justify-center bg-[--hl-xs]'>
<Icon icon={['fab', 'github']} />
</div>
<span className='flex-1 items'>
Continue with GitHub
</span>
</Button>
<Button
aria-label='Continue with Email'
onPress={() => {
login('email');
}}
className="w-full items-center border border-solid border-[--hl-md] flex justify-center gap-[--padding-md] aria-pressed:bg-[--hl-sm] rounded-md text-[--color-font] hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all text-base"
>
<div className='w-[40px] h-[35px] border-r border-solid border-[--hl-sm] flex items-center justify-center bg-[--hl-xs]'>
<Icon icon="envelope" />
</div>
<span className='flex-1 items'>
Continue with Email
</span>
</Button>
<Button
aria-label='Continue with SSO'
onPress={() => {
login('sso');
}}
className="w-full items-center border border-solid border-[--hl-md] flex justify-center gap-[--padding-md] aria-pressed:bg-[--hl-sm] rounded-md text-[--color-font] hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all text-base"
>
<div className='w-[40px] h-[35px] border-r border-solid border-[--hl-sm] flex items-center justify-center bg-[--hl-xs]'>
<Icon icon="key" />
</div>
<span className='flex-1 items'>
Continue with SSO
</span>
</Button>
<p className='text-[rgba(var(--color-font-rgb),0.8)] text-xs text-center'>
By signing up or using Insomnia, you agree to the{' '}
<a
className='font-bold outline-none transition-colors hover:text-[--color-font] focus:text-[--color-font]'
href="https://insomnia.rest/terms"
rel="noreferrer"
>
terms of service
</a>{' '}
and{' '}
<a
className='font-bold outline-none transition-colors hover:text-[--color-font] focus:text-[--color-font]'
href="https://insomnia.rest/privacy"
rel="noreferrer"
>
privacy policy
</a>
.
</p>
<div className='flex gap-[--padding-md] justify-between'>
<div className='flex justify-center'>
<Button
onPress={() => {
window.main.trackSegmentEvent({
@ -175,18 +175,6 @@ const Login = () => {
Use the local Scratch Pad
</span>
</Button>
<Button
onPress={() => showModal(SettingsModal)}
aria-label='Preferences'
className='flex transition-colors justify-center text-[rgba(var(--color-font-rgb),0.8)] text-sm gap-[--padding-xs] hover:text-[--color-font] focus:text-[--color-font]'
>
<div>
<Icon icon="cog" />
</div>
<span>
Preferences
</span>
</Button>
</div>
</div>
);

View File

@ -1,11 +1,31 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { Button, Link, Tooltip, TooltipTrigger } from 'react-aria-components';
import { Outlet } from 'react-router-dom';
import { Hotkey } from '../components/hotkey';
import { Icon } from '../components/icon';
import { InsomniaLogo } from '../components/insomnia-icon';
import { showSettingsModal } from '../components/modals/settings-modal';
import { TrailLinesContainer } from '../components/trail-lines-container';
import { useRootLoaderData } from './root';
const Auth = () => {
const { userSession, settings } = useRootLoaderData();
const [status, setStatus] = useState<'online' | 'offline'>('online');
useEffect(() => {
const handleOnline = () => setStatus('online');
const handleOffline = () => setStatus('offline');
window.addEventListener('online', handleOnline);
window.addEventListener('offline', handleOffline);
return () => {
window.removeEventListener('online', handleOnline);
window.removeEventListener('offline', handleOffline);
};
}, []);
return (
<div className='grid [grid-template-rows:1fr_30px] w-full h-full'>
<div className='relative h-full w-full text-center flex bg-[--color-bg]'>
<TrailLinesContainer>
<div className='flex flex-col justify-center items-center h-full min-h-[450px]'>
@ -25,6 +45,86 @@ const Auth = () => {
</div>
</TrailLinesContainer>
</div>
<div className="relative flex items-center overflow-hidden">
<div className='flex w-full h-full items-center justify-between'>
<div className="flex h-full">
<TooltipTrigger>
<Button
data-testid="settings-button"
className="px-4 py-1 h-full flex items-center justify-center gap-2 aria-pressed:bg-[--hl-sm] text-[--color-font] text-xs hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all"
onPress={() => showSettingsModal()}
>
<Icon icon="gear" /> Preferences
</Button>
<Tooltip
placement="top"
offset={8}
className="border flex items-center gap-2 select-none text-sm min-w-max border-solid border-[--hl-sm] shadow-lg bg-[--color-bg] text-[--color-font] px-4 py-2 rounded-md overflow-y-auto max-h-[85vh] focus:outline-none"
>
Preferences
<Hotkey
keyBindings={
settings.hotKeyRegistry.preferences_showGeneral
}
/>
</Tooltip>
</TooltipTrigger>
</div>
<div className='flex items-center gap-2 divide divide-y-[--hl-sm]'>
<TooltipTrigger>
<Button
className="px-4 py-1 h-full flex items-center justify-center gap-2 aria-pressed:bg-[--hl-sm] text-[--color-font] text-xs hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all"
onPress={() => {
if (settings.proxyEnabled) {
showSettingsModal({
tab: 'proxy',
});
}
}}
>
<Icon
icon="circle"
className={
userSession
? status === 'online'
? 'text-[--color-success]'
: 'text-[--color-danger]'
: ''
}
/>{' '}
{userSession
? status.charAt(0).toUpperCase() + status.slice(1)
: 'Log in to see your projects'}
{settings.proxyEnabled ? ' via proxy' : ''}
</Button>
<Tooltip
placement="top"
offset={8}
className="border flex items-center gap-2 select-none text-sm min-w-max border-solid border-[--hl-sm] shadow-lg bg-[--color-bg] text-[--color-font] px-4 py-2 rounded-md overflow-y-auto max-h-[85vh] focus:outline-none"
>
{userSession
? status === 'online' ? 'You have connectivity to the Internet' + (settings.proxyEnabled ? ' via the configured proxy' : '') + '.'
: 'You are offline. Connect to sync your data.'
: 'Login to Insomnia to unlock the full product experience.'}
</Tooltip>
</TooltipTrigger>
<span className='w-[1px] h-full bg-[--hl-sm]' />
<Link>
<a
className="flex focus:outline-none focus:underline gap-1 items-center text-xs text-[--color-font] px-[--padding-md]"
href="https://konghq.com/"
>
Made with
<Icon className="text-[--color-surprise-font]" icon="heart" /> by
Kong
</a>
</Link>
</div>
</div>
</div>
</div>
);
};

View File

@ -400,7 +400,6 @@ const OrganizationRoute = () => {
projectId?: string;
workspaceId?: string;
};
const [status, setStatus] = useState<'online' | 'offline'>('online');
useEffect(() => {
const isIdleAndUninitialized = untrackedProjectsFetcher.state === 'idle' && !untrackedProjectsFetcher.data;
@ -412,7 +411,7 @@ const OrganizationRoute = () => {
const untrackedProjects = untrackedProjectsFetcher.data?.untrackedProjects || [];
const untrackedWorkspaces = untrackedProjectsFetcher.data?.untrackedWorkspaces || [];
const hasUntrackedData = untrackedProjects.length > 0 || untrackedWorkspaces.length > 0;
const [status, setStatus] = useState<'online' | 'offline'>('online');
useEffect(() => {
const handleOnline = () => setStatus('online');
const handleOffline = () => setStatus('offline');
@ -737,7 +736,7 @@ const OrganizationRoute = () => {
<Button
data-testid="settings-button"
className="px-4 py-1 h-full flex items-center justify-center gap-2 aria-pressed:bg-[--hl-sm] text-[--color-font] text-xs hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all"
onPress={showSettingsModal}
onPress={() => showSettingsModal()}
>
<Icon icon="gear" /> Preferences
</Button>
@ -799,6 +798,11 @@ const OrganizationRoute = () => {
className="px-4 py-1 h-full flex items-center justify-center gap-2 aria-pressed:bg-[--hl-sm] text-[--color-font] text-xs hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all"
onPress={() => {
!user && navigate('/auth/login');
if (settings.proxyEnabled) {
showSettingsModal({
tab: 'proxy',
});
}
}}
>
<Icon
@ -814,6 +818,7 @@ const OrganizationRoute = () => {
{user
? status.charAt(0).toUpperCase() + status.slice(1)
: 'Log in to see your projects'}
{status === 'online' && settings.proxyEnabled ? ' via proxy' : ''}
</Button>
<Tooltip
placement="top"
@ -821,11 +826,9 @@ const OrganizationRoute = () => {
className="border flex items-center gap-2 select-none text-sm min-w-max border-solid border-[--hl-sm] shadow-lg bg-[--color-bg] text-[--color-font] px-4 py-2 rounded-md overflow-y-auto max-h-[85vh] focus:outline-none"
>
{user
? `You are ${status === 'online'
? 'securely connected to Insomnia Cloud.'
: 'offline. Connect to sync your data.'
}`
: 'Log in to Insomnia to sync your data.'}
? status === 'online' ? 'You have connectivity to the Internet' + (settings.proxyEnabled ? ' via the configured proxy' : '') + '.'
: 'You are offline. Connect to sync your data.'
: 'Log in to Insomnia to unlock the full product experience.'}
</Tooltip>
</TooltipTrigger>
<span className='w-[1px] h-full bg-[--hl-sm]' />