mirror of
https://github.com/Kong/insomnia
synced 2024-11-07 22:30:15 +00:00
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:
parent
f5886d3908
commit
8c66a9b3c2
@ -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');
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
@ -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 don’t 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);
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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 don’t 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"
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -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]' />
|
||||
|
Loading…
Reference in New Issue
Block a user