summaryrefslogtreecommitdiff
path: root/src/components/proxies
diff options
context:
space:
mode:
authorMatain <[email protected]>2022-06-12 23:34:56 +0800
committerMatain <[email protected]>2022-06-12 23:34:56 +0800
commitea5d7cf003eeef30cb7bbe789c6ba7f314bf1ce4 (patch)
treebff1bd7b0e8e8eb753d373b57f007bbe97f96c76 /src/components/proxies
parent4fd2c8f646e48dd0c07d0c2041de52e9a4f8bc82 (diff)
parent38571da24ac54137564be5e41b7a409009e2ee10 (diff)
Merge branch 'master' of https://github.com/haishanh/yacd into haishanh-master
Diffstat (limited to 'src/components/proxies')
-rw-r--r--src/components/proxies/ClosePrevConns.tsx9
-rw-r--r--src/components/proxies/Proxies.tsx20
-rw-r--r--src/components/proxies/Proxy.module.scss36
-rw-r--r--src/components/proxies/Proxy.tsx106
-rw-r--r--src/components/proxies/ProxyGroup.module.scss10
-rw-r--r--src/components/proxies/ProxyGroup.tsx80
-rw-r--r--src/components/proxies/ProxyLatency.tsx4
-rw-r--r--src/components/proxies/ProxyList.module.scss4
-rw-r--r--src/components/proxies/ProxyList.tsx7
-rw-r--r--src/components/proxies/ProxyPageFab.tsx7
-rw-r--r--src/components/proxies/ProxyProvider.module.scss20
-rw-r--r--src/components/proxies/ProxyProvider.tsx84
-rw-r--r--src/components/proxies/ProxyProviderList.tsx6
-rw-r--r--src/components/proxies/Settings.tsx6
-rw-r--r--src/components/proxies/hooks.tsx12
-rw-r--r--src/components/proxies/proxies.hooks.tsx9
16 files changed, 200 insertions, 220 deletions
diff --git a/src/components/proxies/ClosePrevConns.tsx b/src/components/proxies/ClosePrevConns.tsx
index 5617efe..f26a5e9 100644
--- a/src/components/proxies/ClosePrevConns.tsx
+++ b/src/components/proxies/ClosePrevConns.tsx
@@ -10,10 +10,7 @@ type Props = {
onClickSecondaryButton?: () => void;
};
-export function ClosePrevConns({
- onClickPrimaryButton,
- onClickSecondaryButton,
-}: Props) {
+export function ClosePrevConns({ onClickPrimaryButton, onClickSecondaryButton }: Props) {
const primaryButtonRef = useRef<HTMLButtonElement>(null);
const secondaryButtonRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
@@ -33,8 +30,8 @@ export function ClosePrevConns({
<div onKeyDown={handleKeyDown}>
<h2>Close Connections?</h2>
<p>
- Click "Yes" to close those connections that are still using the old
- selected proxy in this group
+ Click "Yes" to close those connections that are still using the old selected proxy in this
+ group
</p>
<div style={{ height: 30 }} />
<FlexCenter>
diff --git a/src/components/proxies/Proxies.tsx b/src/components/proxies/Proxies.tsx
index c1606dd..12d3cb2 100644
--- a/src/components/proxies/Proxies.tsx
+++ b/src/components/proxies/Proxies.tsx
@@ -35,9 +35,7 @@ function Proxies({
apiConfig,
showModalClosePrevConns,
}) {
- const refFetchedTimestamp = useRef<{ startAt?: number; completeAt?: number }>(
- {}
- );
+ const refFetchedTimestamp = useRef<{ startAt?: number; completeAt?: number }>({});
const fetchProxiesHooked = useCallback(() => {
refFetchedTimestamp.current.startAt = Date.now();
@@ -75,10 +73,7 @@ function Proxies({
return (
<>
- <BaseModal
- isOpen={isSettingsModalOpen}
- onRequestClose={closeSettingsModal}
- >
+ <BaseModal isOpen={isSettingsModalOpen} onRequestClose={closeSettingsModal}>
<Settings />
</BaseModal>
<div className={s0.topBar}>
@@ -110,15 +105,8 @@ function Proxies({
</div>
<ProxyProviderList items={proxyProviders} />
<div style={{ height: 60 }} />
- <ProxyPageFab
- dispatch={dispatch}
- apiConfig={apiConfig}
- proxyProviders={proxyProviders}
- />
- <BaseModal
- isOpen={showModalClosePrevConns}
- onRequestClose={closeModalClosePrevConns}
- >
+ <ProxyPageFab dispatch={dispatch} apiConfig={apiConfig} proxyProviders={proxyProviders} />
+ <BaseModal isOpen={showModalClosePrevConns} onRequestClose={closeModalClosePrevConns}>
<ClosePrevConns
onClickPrimaryButton={() => closePrevConnsAndTheModal(apiConfig)}
onClickSecondaryButton={closeModalClosePrevConns}
diff --git a/src/components/proxies/Proxy.module.scss b/src/components/proxies/Proxy.module.scss
index 4507a07..72087cf 100644
--- a/src/components/proxies/Proxy.module.scss
+++ b/src/components/proxies/Proxy.module.scss
@@ -15,7 +15,7 @@
border: 1px solid var(--color-focus-blue);
}
- max-width: 280px;
+ max-width: 200px;
@media (--breakpoint-not-small) {
min-width: 200px;
border-radius: 10px;
@@ -34,7 +34,7 @@
transition: transform 0.2s ease-in-out;
cursor: pointer;
&:hover {
- transform: translateY(-2px);
+ border-color: hsl(0deg, 0%, var(--card-hover-border-lightness));
}
}
}
@@ -58,19 +58,37 @@
width: 100%;
margin-bottom: 5px;
font-size: 0.85em;
- @media (--breakpoint-not-small) {
- font-size: 0.85em;
- }
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
.proxySmall {
- width: 11px;
- height: 11px;
+ --size: 13px;
+ width: var(--size);
+ height: var(--size);
border-radius: 50%;
- border: 1px solid var(--color-background);
+ position: relative;
&.now {
- border-color: var(--color-text-secondary);
+ --size: 15px;
+ &:before {
+ --size-dot: 7px;
+ content: '';
+ position: absolute;
+ width: var(--size-dot);
+ height: var(--size-dot);
+ background-color: #fff;
+ // For non-primitive proxy type like "Selector", "LoadBalance", "DIRECT", etc. we are using a transparent
+ // background, and this selected indicator has a white background. In "light" them mode, the constrast
+ // between the bg of the indicator and the "background" is too small. In that case we want to add a
+ // border around this indicator so it's more distinguishable.
+ border: 1px solid var(--color-proxy-dot-selected-ind-bo);
+ border-radius: 4px;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ }
}
&.selectable {
diff --git a/src/components/proxies/Proxy.tsx b/src/components/proxies/Proxy.tsx
index 424d320..47a3d54 100644
--- a/src/components/proxies/Proxy.tsx
+++ b/src/components/proxies/Proxy.tsx
@@ -1,6 +1,8 @@
+import { TooltipPopup, useTooltip } from '@reach/tooltip';
import cx from 'clsx';
import * as React from 'react';
-import { keyCodes } from 'src/misc/keycode';
+
+import { State } from '$src/store/types';
import { getDelay, getProxies, NonProxyTypes } from '../../store/proxies';
import { connect } from '../StateProvider';
@@ -20,11 +22,7 @@ const colorMap = {
na: '#909399',
};
-function getLabelColor({
- number,
-}: {
- number?: number;
-} = {}) {
+function getLabelColor({ number }: { number?: number } = {}) {
if (number === 0) {
return colorMap.na;
} else if (number < 200) {
@@ -37,39 +35,25 @@ function getLabelColor({
return colorMap.na;
}
-function getProxyDotBackgroundColor(
- latency: {
- number?: number;
- },
- proxyType: string
-) {
+function getProxyDotStyle(latency: { number?: number }, proxyType: string) {
if (NonProxyTypes.indexOf(proxyType) > -1) {
- return 'linear-gradient(135deg, white 15%, #999 15% 30%, white 30% 45%, #999 45% 60%, white 60% 75%, #999 75% 90%, white 90% 100%)';
+ return { border: '1px dotted #777' };
}
- return getLabelColor(latency);
+ const bg = getLabelColor(latency);
+ return { background: bg };
}
type ProxyProps = {
name: string;
now?: boolean;
proxy: any;
- latency: any;
+ latency?: { number?: number };
isSelectable?: boolean;
onClick?: (proxyName: string) => unknown;
};
-function ProxySmallImpl({
- now,
- name,
- proxy,
- latency,
- isSelectable,
- onClick,
-}: ProxyProps) {
- const color = useMemo(() => getProxyDotBackgroundColor(latency, proxy.type), [
- latency,
- proxy,
- ]);
+function ProxySmallImpl({ now, name, proxy, latency, isSelectable, onClick }: ProxyProps) {
+ const style = useMemo(() => getProxyDotStyle(latency, proxy.type), [latency, proxy]);
const title = useMemo(() => {
let ret = name;
if (latency && typeof latency.number === 'number') {
@@ -83,17 +67,12 @@ function ProxySmallImpl({
}, [name, onClick, isSelectable]);
const className = useMemo(() => {
- return cx(s0.proxySmall, {
- [s0.now]: now,
- [s0.selectable]: isSelectable,
- });
+ return cx(s0.proxySmall, { [s0.now]: now, [s0.selectable]: isSelectable });
}, [isSelectable, now]);
const handleKeyDown = React.useCallback(
(e: React.KeyboardEvent) => {
- if (e.keyCode === keyCodes.Enter) {
- doSelect();
- }
+ if (e.key === 'Enter') doSelect();
},
[doSelect]
);
@@ -102,7 +81,7 @@ function ProxySmallImpl({
<div
title={title}
className={className}
- style={{ background: color }}
+ style={style}
onClick={doSelect}
onKeyDown={handleKeyDown}
role={isSelectable ? 'menuitem' : ''}
@@ -115,33 +94,46 @@ function formatProxyType(t: string) {
return t;
}
-function ProxyImpl({
- now,
- name,
- proxy,
- latency,
- isSelectable,
- onClick,
-}: ProxyProps) {
+const positionProxyNameTooltip = (triggerRect: { left: number; top: number }) => {
+ return {
+ left: triggerRect.left + window.scrollX - 5,
+ top: triggerRect.top + window.scrollY - 38,
+ };
+};
+
+function ProxyNameTooltip({ children, label, 'aria-label': ariaLabel }) {
+ const [trigger, tooltip] = useTooltip();
+ return (
+ <>
+ {React.cloneElement(children, trigger)}
+ <TooltipPopup
+ {...tooltip}
+ label={label}
+ aria-label={ariaLabel}
+ position={positionProxyNameTooltip}
+ />
+ </>
+ );
+}
+
+function ProxyImpl({ now, name, proxy, latency, isSelectable, onClick }: ProxyProps) {
const color = useMemo(() => getLabelColor(latency), [latency]);
const doSelect = React.useCallback(() => {
isSelectable && onClick && onClick(name);
}, [name, onClick, isSelectable]);
const handleKeyDown = React.useCallback(
(e: React.KeyboardEvent) => {
- if (e.keyCode === keyCodes.Enter) {
- doSelect();
- }
+ if (e.key === 'Enter') doSelect();
},
[doSelect]
);
const className = useMemo(() => {
return cx(s0.proxy, {
[s0.now]: now,
- [s0.error]: latency && latency.error,
+ // [s0.error]: latency && latency.error,
[s0.selectable]: isSelectable,
});
- }, [isSelectable, now, latency]);
+ }, [isSelectable, now]);
return (
<div
@@ -151,26 +143,26 @@ function ProxyImpl({
onKeyDown={handleKeyDown}
role={isSelectable ? 'menuitem' : ''}
>
- <div className={s0.proxyName}>{name}</div>
+ <div className={s0.proxyName}>
+ <ProxyNameTooltip label={name} aria-label={'proxy name: ' + name}>
+ <span>{name}</span>
+ </ProxyNameTooltip>
+ </div>
<div className={s0.row}>
<span className={s0.proxyType} style={{ opacity: now ? 0.6 : 0.2 }}>
{formatProxyType(proxy.type)}
</span>
- {latency && latency.number ? (
- <ProxyLatency number={latency.number} color={color} />
- ) : null}
+ <ProxyLatency number={latency?.number} color={color} />
</div>
</div>
);
}
-const mapState = (s: any, { name }) => {
+const mapState = (s: State, { name }) => {
const proxies = getProxies(s);
const delay = getDelay(s);
- return {
- proxy: proxies[name],
- latency: delay[name],
- };
+ const proxy = proxies[name] || { name, type: 'Unknown', history: [] };
+ return { proxy, latency: delay[name] };
};
export const Proxy = connect(mapState)(ProxyImpl);
diff --git a/src/components/proxies/ProxyGroup.module.scss b/src/components/proxies/ProxyGroup.module.scss
index 5409ea8..85b68b6 100644
--- a/src/components/proxies/ProxyGroup.module.scss
+++ b/src/components/proxies/ProxyGroup.module.scss
@@ -2,10 +2,12 @@
margin-bottom: 12px;
}
-.zapWrapper {
- width: 20px;
- height: 20px;
+.groupHead {
display: flex;
+ flex-wrap: wrap;
align-items: center;
- justify-content: center;
+}
+
+.action {
+ margin: 0 5px;
}
diff --git a/src/components/proxies/ProxyGroup.tsx b/src/components/proxies/ProxyGroup.tsx
index 633a4b9..e8ebadf 100644
--- a/src/components/proxies/ProxyGroup.tsx
+++ b/src/components/proxies/ProxyGroup.tsx
@@ -1,30 +1,37 @@
+import Tooltip from '@reach/tooltip';
import * as React from 'react';
-import { Zap } from 'react-feather';
-import { useQuery } from 'react-query';
-import * as proxiesAPI from '$src/api/proxies';
-import { fetchVersion } from '$src/api/version';
-import { getCollapsibleIsOpen, getHideUnavailableProxies, getProxySortBy } from '$src/store/app';
-import { fetchProxies, getProxies, switchProxy } from '$src/store/proxies';
+import { useState2 } from '$src/hooks/basic';
+import { DelayMapping, DispatchFn, ProxiesMapping, State } from '$src/store/types';
+import { ClashAPIConfig } from '$src/types';
+import { getCollapsibleIsOpen, getHideUnavailableProxies, getProxySortBy } from '../../store/app';
+import { fetchProxies, getProxies, switchProxy } from '../../store/proxies';
import Button from '../Button';
import CollapsibleSectionHeader from '../CollapsibleSectionHeader';
+import { ZapAnimated } from '../shared/ZapAnimated';
import { connect, useStoreActions } from '../StateProvider';
import { useFilteredAndSorted } from './hooks';
import s0 from './ProxyGroup.module.scss';
import { ProxyList, ProxyListSummaryView } from './ProxyList';
+import { fetchVersion } from '$src/api/version';
+import { useQuery } from 'react-query';
+const { createElement, useCallback, useMemo } = React;
-const { createElement, useCallback, useMemo, useState } = React;
-
-
-function ZapWrapper() {
- return (
- <div className={s0.zapWrapper}>
- <Zap size={16} />
- </div>
- );
-}
+type ProxyGroupImplProps = {
+ name: string;
+ all: string[];
+ delay: DelayMapping;
+ hideUnavailableProxies: boolean;
+ proxySortBy: string;
+ proxies: ProxiesMapping;
+ type: string;
+ now: string;
+ isOpen: boolean;
+ apiConfig: ClashAPIConfig;
+ dispatch: DispatchFn;
+};
function ProxyGroupImpl({
name,
@@ -38,14 +45,8 @@ function ProxyGroupImpl({
isOpen,
apiConfig,
dispatch,
-}) {
- const all = useFilteredAndSorted(
- allItems,
- delay,
- hideUnavailableProxies,
- proxySortBy,
- proxies
- );
+}: ProxyGroupImplProps) {
+ const all = useFilteredAndSorted(allItems, delay, hideUnavailableProxies, proxySortBy, proxies);
const { data: version } = useQuery(['/version', apiConfig], () =>
fetchVersion('/version',apiConfig)
@@ -63,15 +64,17 @@ function ProxyGroupImpl({
}, [isOpen, updateCollapsibleIsOpen, name]);
const itemOnTapCallback = useCallback(
- (proxyName) => {
+ (proxyName: string) => {
if (!isSelectable) return;
dispatch(switchProxy(apiConfig, name, proxyName));
},
[apiConfig, dispatch, name, isSelectable]
);
- const [isTestingLatency, setIsTestingLatency] = useState(false);
+
+ const testingLatency = useState2(false);
const testLatency = useCallback(async () => {
- setIsTestingLatency(true);
+ if (testingLatency.value) return;
+ testingLatency.set(true);
try {
if (version.meta==true){
await proxiesAPI.requestDelayForProxyGroup(apiConfig,name);
@@ -87,7 +90,7 @@ function ProxyGroupImpl({
return (
<div className={s0.group}>
- <div style={{ display: 'flex', alignItems: 'center' }}>
+ <div className={s0.groupHead}>
<CollapsibleSectionHeader
name={name}
type={type}
@@ -95,14 +98,13 @@ function ProxyGroupImpl({
qty={all.length}
isOpen={isOpen}
/>
- <Button
- title="Test latency"
- kind="minimal"
- onClick={testLatency}
- isLoading={isTestingLatency}
- >
- <ZapWrapper />
- </Button>
+ <div className={s0.action}>
+ <Tooltip label={'Test latency'}>
+ <Button kind="circular" onClick={testLatency}>
+ <ZapAnimated animate={testingLatency.value} size={16} />
+ </Button>
+ </Tooltip>
+ </div>
</div>
{createElement(isOpen ? ProxyList : ProxyListSummaryView, {
all,
@@ -114,7 +116,7 @@ function ProxyGroupImpl({
);
}
-export const ProxyGroup = connect((s, { name, delay }) => {
+export const ProxyGroup = connect((s: State, { name, delay }) => {
const proxies = getProxies(s);
const collapsibleIsOpen = getCollapsibleIsOpen(s);
const proxySortBy = getProxySortBy(s);
@@ -133,3 +135,7 @@ export const ProxyGroup = connect((s, { name, delay }) => {
isOpen: collapsibleIsOpen[`proxyGroup:${name}`],
};
})(ProxyGroupImpl);
+function setIsTestingLatency (arg0: boolean) {
+ throw new Error('Function not implemented.');
+}
+
diff --git a/src/components/proxies/ProxyLatency.tsx b/src/components/proxies/ProxyLatency.tsx
index 48e55af..29036d5 100644
--- a/src/components/proxies/ProxyLatency.tsx
+++ b/src/components/proxies/ProxyLatency.tsx
@@ -3,14 +3,14 @@ import * as React from 'react';
import s0 from './ProxyLatency.module.scss';
type ProxyLatencyProps = {
- number: number;
+ number?: number;
color: string;
};
export function ProxyLatency({ number, color }: ProxyLatencyProps) {
return (
<span className={s0.proxyLatency} style={{ color }}>
- <span>{number} ms</span>
+ {typeof number === 'number' && number !== 0 ? number + ' ms' : ' '}
</span>
);
}
diff --git a/src/components/proxies/ProxyList.module.scss b/src/components/proxies/ProxyList.module.scss
index 1814929..12fea7e 100644
--- a/src/components/proxies/ProxyList.module.scss
+++ b/src/components/proxies/ProxyList.module.scss
@@ -6,8 +6,10 @@
}
.listSummaryView {
- margin: 8px 0;
+ margin: 14px 0;
display: grid;
grid-template-columns: repeat(auto-fill, 13px);
grid-gap: 10px;
+ place-items: center;
+ max-width: 900px;
}
diff --git a/src/components/proxies/ProxyList.tsx b/src/components/proxies/ProxyList.tsx
index a86bb88..3856c68 100644
--- a/src/components/proxies/ProxyList.tsx
+++ b/src/components/proxies/ProxyList.tsx
@@ -11,12 +11,7 @@ type ProxyListProps = {
show?: boolean;
};
-export function ProxyList({
- all,
- now,
- isSelectable,
- itemOnTapCallback,
-}: ProxyListProps) {
+export function ProxyList({ all, now, isSelectable, itemOnTapCallback }: ProxyListProps) {
const proxies = all;
return (
diff --git a/src/components/proxies/ProxyPageFab.tsx b/src/components/proxies/ProxyPageFab.tsx
index 7cc6d03..44e446f 100644
--- a/src/components/proxies/ProxyPageFab.tsx
+++ b/src/components/proxies/ProxyPageFab.tsx
@@ -2,12 +2,7 @@ import * as React from 'react';
import { Zap } from 'react-feather';
import { useTranslation } from 'react-i18next';
import { useUpdateProviderItems } from 'src/components/proxies/proxies.hooks';
-import {
- Action,
- Fab,
- IsFetching,
- position as fabPosition,
-} from 'src/components/shared/Fab';
+import { Action, Fab, IsFetching, position as fabPosition } from 'src/components/shared/Fab';
import { RotateIcon } from 'src/components/shared/RotateIcon';
import { requestDelayAll } from 'src/store/proxies';
import { DispatchFn, FormattedProxyProvider } from 'src/store/types';
diff --git a/src/components/proxies/ProxyProvider.module.scss b/src/components/proxies/ProxyProvider.module.scss
index 534305b..bc66bca 100644
--- a/src/components/proxies/ProxyProvider.module.scss
+++ b/src/components/proxies/ProxyProvider.module.scss
@@ -5,21 +5,25 @@
}
}
-.body {
+.main {
padding: 10px 15px;
@media (--breakpoint-not-small) {
padding: 10px 40px;
}
}
-.actionFooter {
+.head {
display: flex;
- button {
- margin: 0 5px;
- &:first-child {
- margin-left: 0;
- }
- }
+ align-items: center;
+ flex-wrap: wrap;
+}
+
+.action {
+ margin: 0 5px;
+ display: grid;
+ grid-template-columns: auto auto;
+ gap: 10px;
+ place-items: center;
}
.refresh {
diff --git a/src/components/proxies/ProxyProvider.tsx b/src/components/proxies/ProxyProvider.tsx
index 055a572..7939190 100644
--- a/src/components/proxies/ProxyProvider.tsx
+++ b/src/components/proxies/ProxyProvider.tsx
@@ -1,8 +1,8 @@
+import Tooltip from '@reach/tooltip';
import { formatDistance } from 'date-fns';
import * as React from 'react';
-import { RotateCw, Zap } from 'react-feather';
+import { RotateCw } from 'react-feather';
import Button from 'src/components/Button';
-import Collapsible from 'src/components/Collapsible';
import CollapsibleSectionHeader from 'src/components/CollapsibleSectionHeader';
import { useUpdateProviderItem } from 'src/components/proxies/proxies.hooks';
import { connect, useStoreActions } from 'src/components/StateProvider';
@@ -14,17 +14,20 @@ import {
getProxySortBy,
} from 'src/store/app';
import { getDelay, healthcheckProviderByName } from 'src/store/proxies';
-import { DelayMapping } from 'src/store/types';
+import { DelayMapping, State } from 'src/store/types';
+import { useState2 } from '$src/hooks/basic';
+
+import { ZapAnimated } from '../shared/ZapAnimated';
import { useFilteredAndSorted } from './hooks';
import { ProxyList, ProxyListSummaryView } from './ProxyList';
import s from './ProxyProvider.module.scss';
-const { useState, useCallback } = React;
+const { useCallback } = React;
type Props = {
name: string;
- proxies: Array<string>;
+ proxies: string[];
delay: DelayMapping;
hideUnavailableProxies: boolean;
proxySortBy: string;
@@ -48,21 +51,17 @@ function ProxyProviderImpl({
dispatch,
apiConfig,
}: Props) {
- const proxies = useFilteredAndSorted(
- all,
- delay,
- hideUnavailableProxies,
- proxySortBy
- );
- const [isHealthcheckLoading, setIsHealthcheckLoading] = useState(false);
+ const proxies = useFilteredAndSorted(all, delay, hideUnavailableProxies, proxySortBy);
+ const checkingHealth = useState2(false);
const updateProvider = useUpdateProviderItem({ dispatch, apiConfig, name });
- const healthcheckProvider = useCallback(async () => {
- setIsHealthcheckLoading(true);
- await dispatch(healthcheckProviderByName(apiConfig, name));
- setIsHealthcheckLoading(false);
- }, [apiConfig, dispatch, name, setIsHealthcheckLoading]);
+ const healthcheckProvider = useCallback(() => {
+ if (checkingHealth.value) return;
+ checkingHealth.set(true);
+ const stop = () => checkingHealth.set(false);
+ dispatch(healthcheckProviderByName(apiConfig, name)).then(stop, stop);
+ }, [apiConfig, dispatch, name, checkingHealth]);
const {
app: { updateCollapsibleIsOpen },
@@ -74,34 +73,33 @@ function ProxyProviderImpl({
const timeAgo = formatDistance(new Date(updatedAt), new Date());
return (
- <div className={s.body}>
- <CollapsibleSectionHeader
- name={name}
- toggle={toggle}
- type={vehicleType}
- isOpen={isOpen}
- qty={proxies.length}
- />
+ <div className={s.main}>
+ <div className={s.head}>
+ <CollapsibleSectionHeader
+ name={name}
+ toggle={toggle}
+ type={vehicleType}
+ isOpen={isOpen}
+ qty={proxies.length}
+ />
+
+ <div className={s.action}>
+ <Tooltip label={'Update'}>
+ <Button kind="circular" onClick={updateProvider}>
+ <Refresh />
+ </Button>
+ </Tooltip>
+ <Tooltip label={'Health Check'}>
+ <Button kind="circular" onClick={healthcheckProvider}>
+ <ZapAnimated animate={checkingHealth.value} size={16} />
+ </Button>
+ </Tooltip>
+ </div>
+ </div>
<div className={s.updatedAt}>
<small>Updated {timeAgo} ago</small>
</div>
- {/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ children: Element[]; isOpen: boolean; }' i... Remove this comment to see the full error message */}
- <Collapsible isOpen={isOpen}>
- <ProxyList all={proxies} />
- <div className={s.actionFooter}>
- <Button text="Update" start={<Refresh />} onClick={updateProvider} />
- <Button
- text="Health Check"
- start={<Zap size={16} />}
- onClick={healthcheckProvider}
- isLoading={isHealthcheckLoading}
- />
- </div>
- </Collapsible>
- {/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ children: Element; isOpen: boolean; }' is ... Remove this comment to see the full error message */}
- <Collapsible isOpen={!isOpen}>
- <ProxyListSummaryView all={proxies} />
- </Collapsible>
+ {isOpen ? <ProxyList all={proxies} /> : <ProxyListSummaryView all={proxies} />}
</div>
);
}
@@ -132,7 +130,7 @@ function Refresh() {
);
}
-const mapState = (s, { proxies, name }) => {
+const mapState = (s: State, { proxies, name }) => {
const hideUnavailableProxies = getHideUnavailableProxies(s);
const delay = getDelay(s);
const collapsibleIsOpen = getCollapsibleIsOpen(s);
diff --git a/src/components/proxies/ProxyProviderList.tsx b/src/components/proxies/ProxyProviderList.tsx
index 1528f37..754eeac 100644
--- a/src/components/proxies/ProxyProviderList.tsx
+++ b/src/components/proxies/ProxyProviderList.tsx
@@ -3,11 +3,7 @@ import ContentHeader from 'src/components/ContentHeader';
import { ProxyProvider } from 'src/components/proxies/ProxyProvider';
import { FormattedProxyProvider } from 'src/store/types';
-export function ProxyProviderList({
- items,
-}: {
- items: FormattedProxyProvider[];
-}) {
+export function ProxyProviderList({ items }: { items: FormattedProxyProvider[] }) {
if (items.length === 0) return null;
return (
diff --git a/src/components/proxies/Settings.tsx b/src/components/proxies/Settings.tsx
index 5e1ff98..55e18fe 100644
--- a/src/components/proxies/Settings.tsx
+++ b/src/components/proxies/Settings.tsx
@@ -2,11 +2,7 @@ import * as React from 'react';
import { useTranslation } from 'react-i18next';
import Select from 'src/components/shared/Select';
-import {
- getAutoCloseOldConns,
- getHideUnavailableProxies,
- getProxySortBy,
-} from '../../store/app';
+import { getAutoCloseOldConns, getHideUnavailableProxies, getProxySortBy } from '../../store/app';
import { connect, useStoreActions } from '../StateProvider';
import Switch from '../SwitchThemed';
import s from './Settings.module.scss';
diff --git a/src/components/proxies/hooks.tsx b/src/components/proxies/hooks.tsx
index 861c0e5..a43dc0e 100644
--- a/src/components/proxies/hooks.tsx
+++ b/src/components/proxies/hooks.tsx
@@ -45,22 +45,14 @@ const getSortDelay = (
const ProxySortingFns = {
Natural: (proxies: string[]) => proxies,
- LatencyAsc: (
- proxies: string[],
- delay: DelayMapping,
- proxyMapping?: ProxiesMapping
- ) => {
+ LatencyAsc: (proxies: string[], delay: DelayMapping, proxyMapping?: ProxiesMapping) => {
return proxies.sort((a, b) => {
const d1 = getSortDelay(delay[a], proxyMapping && proxyMapping[a]);
const d2 = getSortDelay(delay[b], proxyMapping && proxyMapping[b]);
return d1 - d2;
});
},
- LatencyDesc: (
- proxies: string[],
- delay: DelayMapping,
- proxyMapping?: ProxiesMapping
- ) => {
+ LatencyDesc: (proxies: string[], delay: DelayMapping, proxyMapping?: ProxiesMapping) => {
return proxies.sort((a, b) => {
const d1 = getSortDelay(delay[a], proxyMapping && proxyMapping[a]);
const d2 = getSortDelay(delay[b], proxyMapping && proxyMapping[b]);
diff --git a/src/components/proxies/proxies.hooks.tsx b/src/components/proxies/proxies.hooks.tsx
index ec51c9b..20695ac 100644
--- a/src/components/proxies/proxies.hooks.tsx
+++ b/src/components/proxies/proxies.hooks.tsx
@@ -14,11 +14,10 @@ export function useUpdateProviderItem({
apiConfig: ClashAPIConfig;
name: string;
}) {
- return useCallback(() => dispatch(updateProviderByName(apiConfig, name)), [
- apiConfig,
- dispatch,
- name,
- ]);
+ return useCallback(
+ () => dispatch(updateProviderByName(apiConfig, name)),
+ [apiConfig, dispatch, name]
+ );
}
export function useUpdateProviderItems({