added: test latency button for each proxy group
This commit is contained in:
parent
07082c5b09
commit
bf17be6a65
18 changed files with 216 additions and 177 deletions
|
@ -8,7 +8,7 @@ import s0 from './Button.module.css';
|
||||||
const { memo, forwardRef, useCallback } = React;
|
const { memo, forwardRef, useCallback } = React;
|
||||||
|
|
||||||
type ButtonInternalProps = {
|
type ButtonInternalProps = {
|
||||||
children?: React.ReactChildren;
|
children?: React.ReactNode;
|
||||||
label?: string;
|
label?: string;
|
||||||
text?: string;
|
text?: string;
|
||||||
start?: React.ReactElement | (() => React.ReactElement);
|
start?: React.ReactElement | (() => React.ReactElement);
|
||||||
|
|
|
@ -19,7 +19,7 @@ const Proxies = React.lazy(() =>
|
||||||
/* webpackChunkName: "proxies" */
|
/* webpackChunkName: "proxies" */
|
||||||
/* webpackPrefetch: true */
|
/* webpackPrefetch: true */
|
||||||
/* webpackPreload: true */
|
/* webpackPreload: true */
|
||||||
'./Proxies'
|
'./proxies/Proxies'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
const Rules = React.lazy(() =>
|
const Rules = React.lazy(() =>
|
||||||
|
@ -38,7 +38,7 @@ const routes = [
|
||||||
['logs', '/logs', <Logs />],
|
['logs', '/logs', <Logs />],
|
||||||
['proxies', '/proxies', <Proxies />],
|
['proxies', '/proxies', <Proxies />],
|
||||||
['rules', '/rules', <Rules />],
|
['rules', '/rules', <Rules />],
|
||||||
__DEV__ ? ['style', '/style', <StyleGuide />] : false
|
__DEV__ ? ['style', '/style', <StyleGuide />] : false,
|
||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
|
|
||||||
const Root = () => (
|
const Root = () => (
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { connect } from './StateProvider';
|
import { connect } from '../StateProvider';
|
||||||
|
|
||||||
import Button from './Button';
|
import Button from '../Button';
|
||||||
import ContentHeader from './ContentHeader';
|
import ContentHeader from '../ContentHeader';
|
||||||
import ProxyGroup from './ProxyGroup';
|
import { ProxyGroup } from './ProxyGroup';
|
||||||
import BaseModal from './shared/BaseModal';
|
import BaseModal from '../shared/BaseModal';
|
||||||
import Settings from './proxies/Settings';
|
import Settings from './Settings';
|
||||||
import Equalizer from './svg/Equalizer';
|
import Equalizer from '../svg/Equalizer';
|
||||||
import { Zap } from 'react-feather';
|
import { Zap } from 'react-feather';
|
||||||
|
|
||||||
import ProxyProviderList from './ProxyProviderList';
|
import { ProxyProviderList } from './ProxyProviderList';
|
||||||
import { Fab, position as fabPosition } from './shared/Fab';
|
import { Fab, position as fabPosition } from '../shared/Fab';
|
||||||
|
|
||||||
import s0 from './Proxies.module.css';
|
import s0 from './Proxies.module.css';
|
||||||
|
|
||||||
|
@ -21,13 +21,15 @@ import {
|
||||||
getProxyProviders,
|
getProxyProviders,
|
||||||
fetchProxies,
|
fetchProxies,
|
||||||
requestDelayAll,
|
requestDelayAll,
|
||||||
} from '../store/proxies';
|
} from '../../store/proxies';
|
||||||
import { getClashAPIConfig } from '../store/app';
|
import { getClashAPIConfig } from '../../store/app';
|
||||||
|
|
||||||
const { useState, useEffect, useCallback, useRef } = React;
|
const { useState, useEffect, useCallback, useRef } = React;
|
||||||
|
|
||||||
function Proxies({ dispatch, groupNames, delay, proxyProviders, apiConfig }) {
|
function Proxies({ dispatch, groupNames, delay, proxyProviders, apiConfig }) {
|
||||||
const refFetchedTimestamp = useRef({});
|
const refFetchedTimestamp = useRef<{ startAt?: number; completeAt?: number }>(
|
||||||
|
{}
|
||||||
|
);
|
||||||
const [isTestingLatency, setIsTestingLatency] = useState(false);
|
const [isTestingLatency, setIsTestingLatency] = useState(false);
|
||||||
const requestDelayAllFn = useCallback(() => {
|
const requestDelayAllFn = useCallback(() => {
|
||||||
if (isTestingLatency) return;
|
if (isTestingLatency) return;
|
||||||
|
@ -40,9 +42,9 @@ function Proxies({ dispatch, groupNames, delay, proxyProviders, apiConfig }) {
|
||||||
}, [apiConfig, dispatch, isTestingLatency]);
|
}, [apiConfig, dispatch, isTestingLatency]);
|
||||||
|
|
||||||
const fetchProxiesHooked = useCallback(() => {
|
const fetchProxiesHooked = useCallback(() => {
|
||||||
refFetchedTimestamp.current.startAt = new Date();
|
refFetchedTimestamp.current.startAt = Date.now();
|
||||||
dispatch(fetchProxies(apiConfig)).then(() => {
|
dispatch(fetchProxies(apiConfig)).then(() => {
|
||||||
refFetchedTimestamp.current.completeAt = new Date();
|
refFetchedTimestamp.current.completeAt = Date.now();
|
||||||
});
|
});
|
||||||
}, [apiConfig, dispatch]);
|
}, [apiConfig, dispatch]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -53,7 +55,7 @@ function Proxies({ dispatch, groupNames, delay, proxyProviders, apiConfig }) {
|
||||||
const fn = () => {
|
const fn = () => {
|
||||||
if (
|
if (
|
||||||
refFetchedTimestamp.current.startAt &&
|
refFetchedTimestamp.current.startAt &&
|
||||||
new Date() - refFetchedTimestamp.current.startAt > 3e4 // 30s
|
Date.now() - refFetchedTimestamp.current.startAt > 3e4 // 30s
|
||||||
) {
|
) {
|
||||||
fetchProxiesHooked();
|
fetchProxiesHooked();
|
||||||
}
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
import React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import cx from 'clsx';
|
import cx from 'clsx';
|
||||||
|
|
||||||
import { connect } from './StateProvider';
|
import { connect } from '../StateProvider';
|
||||||
import ProxyLatency from './ProxyLatency';
|
import { ProxyLatency } from './ProxyLatency';
|
||||||
|
import { getProxies, getDelay } from '../../store/proxies';
|
||||||
import { getProxies, getDelay } from '../store/proxies';
|
|
||||||
|
|
||||||
import s0 from './Proxy.module.css';
|
import s0 from './Proxy.module.css';
|
||||||
|
|
||||||
|
@ -21,7 +21,11 @@ const colorMap = {
|
||||||
na: '#909399',
|
na: '#909399',
|
||||||
};
|
};
|
||||||
|
|
||||||
function getLabelColor({ number } = {}) {
|
function getLabelColor({
|
||||||
|
number,
|
||||||
|
}: {
|
||||||
|
number?: number;
|
||||||
|
} = {}) {
|
||||||
if (number < 200) {
|
if (number < 200) {
|
||||||
return colorMap.good;
|
return colorMap.good;
|
||||||
} else if (number < 400) {
|
} else if (number < 400) {
|
||||||
|
@ -32,27 +36,11 @@ function getLabelColor({ number } = {}) {
|
||||||
return colorMap.na;
|
return colorMap.na;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
const colors = {
|
|
||||||
Direct: '#408b43',
|
|
||||||
Fallback: '#3483e8',
|
|
||||||
Selector: '#387cec',
|
|
||||||
Vmess: '#ca3487',
|
|
||||||
Shadowsocks: '#1a7dc0',
|
|
||||||
Socks5: '#2a477a',
|
|
||||||
URLTest: '#3483e8',
|
|
||||||
Http: '#d3782d'
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
type ProxyProps = {
|
type ProxyProps = {
|
||||||
name: string,
|
name: string;
|
||||||
now?: boolean,
|
now?: boolean;
|
||||||
|
proxy: any;
|
||||||
// connect injected
|
latency: any;
|
||||||
// TODO refine type
|
|
||||||
proxy: any,
|
|
||||||
latency: any,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function ProxySmallImpl({ now, name, latency }: ProxyProps) {
|
function ProxySmallImpl({ now, name, latency }: ProxyProps) {
|
||||||
|
@ -73,7 +61,7 @@ function ProxySmallImpl({ now, name, latency }: ProxyProps) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Proxy({ now, name, proxy, latency }: ProxyProps) {
|
function ProxyImpl({ now, name, proxy, latency }: ProxyProps) {
|
||||||
const color = useMemo(() => getLabelColor(latency), [latency]);
|
const color = useMemo(() => getLabelColor(latency), [latency]);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -95,7 +83,7 @@ function Proxy({ now, name, proxy, latency }: ProxyProps) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapState = (s, { name }) => {
|
const mapState = (s: any, { name }) => {
|
||||||
const proxies = getProxies(s);
|
const proxies = getProxies(s);
|
||||||
const delay = getDelay(s);
|
const delay = getDelay(s);
|
||||||
return {
|
return {
|
||||||
|
@ -104,5 +92,5 @@ const mapState = (s, { name }) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapState)(Proxy);
|
export const Proxy = connect(mapState)(ProxyImpl);
|
||||||
export const ProxySmall = connect(mapState)(ProxySmallImpl);
|
export const ProxySmall = connect(mapState)(ProxySmallImpl);
|
11
src/components/proxies/ProxyGroup.module.css
Normal file
11
src/components/proxies/ProxyGroup.module.css
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
.header {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zapWrapper {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
|
@ -1,28 +1,37 @@
|
||||||
import React from 'react';
|
import * as React from 'react';
|
||||||
import cx from 'clsx';
|
|
||||||
import memoizeOne from 'memoize-one';
|
import memoizeOne from 'memoize-one';
|
||||||
|
import { Zap } from 'react-feather';
|
||||||
|
|
||||||
import { connect, useStoreActions } from './StateProvider';
|
import { connect, useStoreActions } from '../StateProvider';
|
||||||
import { getProxies } from '../store/proxies';
|
import { getProxies } from '../../store/proxies';
|
||||||
import {
|
import {
|
||||||
getCollapsibleIsOpen,
|
getCollapsibleIsOpen,
|
||||||
getProxySortBy,
|
getProxySortBy,
|
||||||
getHideUnavailableProxies,
|
getHideUnavailableProxies,
|
||||||
} from '../store/app';
|
} from '../../store/app';
|
||||||
import CollapsibleSectionHeader from './CollapsibleSectionHeader';
|
import { switchProxy } from '../../store/proxies';
|
||||||
import Proxy, { ProxySmall } from './Proxy';
|
import CollapsibleSectionHeader from '../CollapsibleSectionHeader';
|
||||||
|
import Button from '../Button';
|
||||||
|
import { ProxyList, ProxyListSummaryView } from './ProxyList';
|
||||||
|
|
||||||
import s0 from './ProxyGroup.module.css';
|
import s0 from './ProxyGroup.module.css';
|
||||||
|
|
||||||
import { switchProxy } from '../store/proxies';
|
const { useCallback, useMemo, useState } = React;
|
||||||
|
|
||||||
const { useCallback, useMemo } = React;
|
function ZapWrapper() {
|
||||||
|
return (
|
||||||
|
<div className={s0.zapWrapper}>
|
||||||
|
<Zap size={16} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function ProxyGroup({ name, all, type, now, isOpen, apiConfig, dispatch }) {
|
function ProxyGroupImpl({ name, all, type, now, isOpen, apiConfig, dispatch }) {
|
||||||
const isSelectable = useMemo(() => type === 'Selector', [type]);
|
const isSelectable = useMemo(() => type === 'Selector', [type]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
app: { updateCollapsibleIsOpen },
|
app: { updateCollapsibleIsOpen },
|
||||||
|
proxies: { requestDelayForProxies },
|
||||||
} = useStoreActions();
|
} = useStoreActions();
|
||||||
|
|
||||||
const toggle = useCallback(() => {
|
const toggle = useCallback(() => {
|
||||||
|
@ -37,8 +46,18 @@ function ProxyGroup({ name, all, type, now, isOpen, apiConfig, dispatch }) {
|
||||||
[apiConfig, dispatch, name, isSelectable]
|
[apiConfig, dispatch, name, isSelectable]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [isTestingLatency, setIsTestingLatency] = useState(false);
|
||||||
|
const testLatency = useCallback(async () => {
|
||||||
|
setIsTestingLatency(true);
|
||||||
|
try {
|
||||||
|
await requestDelayForProxies(apiConfig, all);
|
||||||
|
} catch (err) {}
|
||||||
|
setIsTestingLatency(false);
|
||||||
|
}, [all, apiConfig, requestDelayForProxies]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={s0.group}>
|
<div className={s0.group}>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||||
<CollapsibleSectionHeader
|
<CollapsibleSectionHeader
|
||||||
name={name}
|
name={name}
|
||||||
type={type}
|
type={type}
|
||||||
|
@ -46,6 +65,14 @@ function ProxyGroup({ name, all, type, now, isOpen, apiConfig, dispatch }) {
|
||||||
qty={all.length}
|
qty={all.length}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
/>
|
/>
|
||||||
|
<Button
|
||||||
|
kind="minimal"
|
||||||
|
onClick={testLatency}
|
||||||
|
isLoading={isTestingLatency}
|
||||||
|
>
|
||||||
|
<ZapWrapper />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
{isOpen ? (
|
{isOpen ? (
|
||||||
<ProxyList
|
<ProxyList
|
||||||
all={all}
|
all={all}
|
||||||
|
@ -60,45 +87,6 @@ function ProxyGroup({ name, all, type, now, isOpen, apiConfig, dispatch }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProxyListProps = {
|
|
||||||
all: string[],
|
|
||||||
now?: string,
|
|
||||||
isSelectable?: boolean,
|
|
||||||
itemOnTapCallback?: (string) => void,
|
|
||||||
show?: boolean,
|
|
||||||
};
|
|
||||||
export function ProxyList({
|
|
||||||
all,
|
|
||||||
now,
|
|
||||||
isSelectable,
|
|
||||||
itemOnTapCallback,
|
|
||||||
sortedAll,
|
|
||||||
}: ProxyListProps) {
|
|
||||||
const proxies = sortedAll || all;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={s0.list}>
|
|
||||||
{proxies.map((proxyName) => {
|
|
||||||
const proxyClassName = cx(s0.proxy, {
|
|
||||||
[s0.proxySelectable]: isSelectable,
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={proxyClassName}
|
|
||||||
key={proxyName}
|
|
||||||
onClick={() => {
|
|
||||||
if (!isSelectable || !itemOnTapCallback) return;
|
|
||||||
itemOnTapCallback(proxyName);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Proxy name={proxyName} now={proxyName === now} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const getSortDelay = (d, w) => {
|
const getSortDelay = (d, w) => {
|
||||||
if (d === undefined) {
|
if (d === undefined) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -172,36 +160,7 @@ export const filterAvailableProxiesAndSort = memoizeOne(
|
||||||
filterAvailableProxiesAndSortImpl
|
filterAvailableProxiesAndSortImpl
|
||||||
);
|
);
|
||||||
|
|
||||||
export function ProxyListSummaryView({
|
export const ProxyGroup = connect((s, { name, delay }) => {
|
||||||
all,
|
|
||||||
now,
|
|
||||||
isSelectable,
|
|
||||||
itemOnTapCallback,
|
|
||||||
}: ProxyListProps) {
|
|
||||||
return (
|
|
||||||
<div className={s0.list}>
|
|
||||||
{all.map((proxyName) => {
|
|
||||||
const proxyClassName = cx(s0.proxy, {
|
|
||||||
[s0.proxySelectable]: isSelectable,
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={proxyClassName}
|
|
||||||
key={proxyName}
|
|
||||||
onClick={() => {
|
|
||||||
if (!isSelectable || !itemOnTapCallback) return;
|
|
||||||
itemOnTapCallback(proxyName);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ProxySmall name={proxyName} now={proxyName === now} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect((s, { name, delay }) => {
|
|
||||||
const proxies = getProxies(s);
|
const proxies = getProxies(s);
|
||||||
const collapsibleIsOpen = getCollapsibleIsOpen(s);
|
const collapsibleIsOpen = getCollapsibleIsOpen(s);
|
||||||
const proxySortBy = getProxySortBy(s);
|
const proxySortBy = getProxySortBy(s);
|
||||||
|
@ -220,4 +179,4 @@ export default connect((s, { name, delay }) => {
|
||||||
now,
|
now,
|
||||||
isOpen: collapsibleIsOpen[`proxyGroup:${name}`],
|
isOpen: collapsibleIsOpen[`proxyGroup:${name}`],
|
||||||
};
|
};
|
||||||
})(ProxyGroup);
|
})(ProxyGroupImpl);
|
|
@ -1,13 +1,13 @@
|
||||||
import React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import s0 from './ProxyLatency.module.css';
|
import s0 from './ProxyLatency.module.css';
|
||||||
|
|
||||||
type ProxyLatencyProps = {
|
type ProxyLatencyProps = {
|
||||||
number: number,
|
number: number;
|
||||||
color: string
|
color: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ProxyLatency({ number, color }: ProxyLatencyProps) {
|
export function ProxyLatency({ number, color }: ProxyLatencyProps) {
|
||||||
return (
|
return (
|
||||||
<span className={s0.proxyLatency} style={{ color }}>
|
<span className={s0.proxyLatency} style={{ color }}>
|
||||||
<span>{number} ms</span>
|
<span>{number} ms</span>
|
|
@ -1,7 +1,3 @@
|
||||||
.header {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list {
|
.list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
75
src/components/proxies/ProxyList.tsx
Normal file
75
src/components/proxies/ProxyList.tsx
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import cx from 'clsx';
|
||||||
|
|
||||||
|
import { Proxy, ProxySmall } from './Proxy';
|
||||||
|
|
||||||
|
import s from './ProxyList.module.css';
|
||||||
|
|
||||||
|
type ProxyListProps = {
|
||||||
|
all: string[];
|
||||||
|
now?: string;
|
||||||
|
isSelectable?: boolean;
|
||||||
|
itemOnTapCallback?: (x: string) => void;
|
||||||
|
show?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function ProxyList({
|
||||||
|
all,
|
||||||
|
now,
|
||||||
|
isSelectable,
|
||||||
|
itemOnTapCallback,
|
||||||
|
}: ProxyListProps) {
|
||||||
|
const proxies = all;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={s.list}>
|
||||||
|
{proxies.map((proxyName) => {
|
||||||
|
const proxyClassName = cx(s.proxy, {
|
||||||
|
[s.proxySelectable]: isSelectable,
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={proxyClassName}
|
||||||
|
key={proxyName}
|
||||||
|
onClick={() => {
|
||||||
|
if (!isSelectable || !itemOnTapCallback) return;
|
||||||
|
itemOnTapCallback(proxyName);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Proxy name={proxyName} now={proxyName === now} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ProxyListSummaryView({
|
||||||
|
all,
|
||||||
|
now,
|
||||||
|
isSelectable,
|
||||||
|
itemOnTapCallback,
|
||||||
|
}: ProxyListProps) {
|
||||||
|
return (
|
||||||
|
<div className={s.list}>
|
||||||
|
{all.map((proxyName) => {
|
||||||
|
const proxyClassName = cx(s.proxy, {
|
||||||
|
[s.proxySelectable]: isSelectable,
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={proxyClassName}
|
||||||
|
key={proxyName}
|
||||||
|
onClick={() => {
|
||||||
|
if (!isSelectable || !itemOnTapCallback) return;
|
||||||
|
itemOnTapCallback(proxyName);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ProxySmall name={proxyName} now={proxyName === now} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,45 +1,43 @@
|
||||||
import React from 'react';
|
import * as React from 'react';
|
||||||
import { RotateCw, Zap } from 'react-feather';
|
import { RotateCw, Zap } from 'react-feather';
|
||||||
import { formatDistance } from 'date-fns';
|
import { formatDistance } from 'date-fns';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
import { connect, useStoreActions } from './StateProvider';
|
import { connect, useStoreActions } from '../StateProvider';
|
||||||
import Collapsible from './Collapsible';
|
import Collapsible from '../Collapsible';
|
||||||
import CollapsibleSectionHeader from './CollapsibleSectionHeader';
|
import CollapsibleSectionHeader from '../CollapsibleSectionHeader';
|
||||||
import {
|
import { filterAvailableProxiesAndSort } from './ProxyGroup';
|
||||||
ProxyList,
|
import { ProxyList, ProxyListSummaryView } from './ProxyList';
|
||||||
ProxyListSummaryView,
|
import Button from '../Button';
|
||||||
filterAvailableProxiesAndSort,
|
|
||||||
} from './ProxyGroup';
|
|
||||||
import Button from './Button';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getClashAPIConfig,
|
getClashAPIConfig,
|
||||||
getCollapsibleIsOpen,
|
getCollapsibleIsOpen,
|
||||||
getProxySortBy,
|
getProxySortBy,
|
||||||
getHideUnavailableProxies,
|
getHideUnavailableProxies,
|
||||||
} from '../store/app';
|
} from '../../store/app';
|
||||||
import {
|
import {
|
||||||
getDelay,
|
getDelay,
|
||||||
updateProviderByName,
|
updateProviderByName,
|
||||||
healthcheckProviderByName,
|
healthcheckProviderByName,
|
||||||
} from '../store/proxies';
|
} from '../../store/proxies';
|
||||||
|
|
||||||
import s from './ProxyProvider.module.css';
|
import s from './ProxyProvider.module.css';
|
||||||
|
|
||||||
const { useState, useCallback } = React;
|
const { useState, useCallback } = React;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
name: string,
|
name: string;
|
||||||
proxies: Array<string>,
|
proxies: Array<string>;
|
||||||
type: 'Proxy' | 'Rule',
|
type: 'Proxy' | 'Rule';
|
||||||
vehicleType: 'HTTP' | 'File' | 'Compatible',
|
vehicleType: 'HTTP' | 'File' | 'Compatible';
|
||||||
updatedAt?: string,
|
updatedAt?: string;
|
||||||
dispatch: (any) => void,
|
dispatch: (x: any) => Promise<any>;
|
||||||
isOpen: boolean,
|
isOpen: boolean;
|
||||||
|
apiConfig: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
function ProxyProvider({
|
function ProxyProviderImpl({
|
||||||
name,
|
name,
|
||||||
proxies,
|
proxies,
|
||||||
vehicleType,
|
vehicleType,
|
||||||
|
@ -63,9 +61,6 @@ function ProxyProvider({
|
||||||
app: { updateCollapsibleIsOpen },
|
app: { updateCollapsibleIsOpen },
|
||||||
} = useStoreActions();
|
} = useStoreActions();
|
||||||
|
|
||||||
// const [isCollapsibleOpen, setCollapsibleOpen] = useState(false);
|
|
||||||
// const toggle = useCallback(() => setCollapsibleOpen(x => !x), []);
|
|
||||||
|
|
||||||
const toggle = useCallback(() => {
|
const toggle = useCallback(() => {
|
||||||
updateCollapsibleIsOpen('proxyProvider', name, !isOpen);
|
updateCollapsibleIsOpen('proxyProvider', name, !isOpen);
|
||||||
}, [isOpen, updateCollapsibleIsOpen, name]);
|
}, [isOpen, updateCollapsibleIsOpen, name]);
|
||||||
|
@ -104,7 +99,6 @@ function ProxyProvider({
|
||||||
|
|
||||||
const button = {
|
const button = {
|
||||||
rest: { scale: 1 },
|
rest: { scale: 1 },
|
||||||
// hover: { scale: 1.1 },
|
|
||||||
pressed: { scale: 0.95 },
|
pressed: { scale: 0.95 },
|
||||||
};
|
};
|
||||||
const arrow = {
|
const arrow = {
|
||||||
|
@ -147,4 +141,4 @@ const mapState = (s, { proxies, name }) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapState)(ProxyProvider);
|
export const ProxyProvider = connect(mapState)(ProxyProviderImpl);
|
|
@ -1,16 +1,16 @@
|
||||||
import React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import ContentHeader from './ContentHeader';
|
import ContentHeader from '../ContentHeader';
|
||||||
import ProxyProvider from './ProxyProvider';
|
import { ProxyProvider } from './ProxyProvider';
|
||||||
|
|
||||||
function ProxyProviderList({ items }) {
|
export function ProxyProviderList({ items }) {
|
||||||
if (items.length === 0) return null;
|
if (items.length === 0) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ContentHeader title="Proxy Provider" />
|
<ContentHeader title="Proxy Provider" />
|
||||||
<div>
|
<div>
|
||||||
{items.map(item => (
|
{items.map((item) => (
|
||||||
<ProxyProvider
|
<ProxyProvider
|
||||||
key={item.name}
|
key={item.name}
|
||||||
name={item.name}
|
name={item.name}
|
||||||
|
@ -24,5 +24,3 @@ function ProxyProviderList({ items }) {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ProxyProviderList;
|
|
1
src/components/proxies/index.tsx
Normal file
1
src/components/proxies/index.tsx
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export { ProxyList } from './ProxyList';
|
|
@ -4,7 +4,7 @@ import {
|
||||||
updateAppConfig,
|
updateAppConfig,
|
||||||
updateCollapsibleIsOpen,
|
updateCollapsibleIsOpen,
|
||||||
} from './app';
|
} from './app';
|
||||||
import { initialState as proxies } from './proxies';
|
import { initialState as proxies, actions as proxiesActions } from './proxies';
|
||||||
import { initialState as modals } from './modals';
|
import { initialState as modals } from './modals';
|
||||||
import { initialState as configs } from './configs';
|
import { initialState as configs } from './configs';
|
||||||
import { initialState as rules } from './rules';
|
import { initialState as rules } from './rules';
|
||||||
|
@ -27,4 +27,5 @@ export const actions = {
|
||||||
updateCollapsibleIsOpen,
|
updateCollapsibleIsOpen,
|
||||||
updateAppConfig,
|
updateAppConfig,
|
||||||
},
|
},
|
||||||
|
proxies: proxiesActions,
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,6 @@ type ProxyProvider = {
|
||||||
|
|
||||||
// const ProxyTypeBuiltin = ['DIRECT', 'GLOBAL', 'REJECT'];
|
// const ProxyTypeBuiltin = ['DIRECT', 'GLOBAL', 'REJECT'];
|
||||||
// const ProxyGroupTypes = ['Fallback', 'URLTest', 'Selector', 'LoadBalance'];
|
// const ProxyGroupTypes = ['Fallback', 'URLTest', 'Selector', 'LoadBalance'];
|
||||||
|
|
||||||
// const ProxyTypes = ['Shadowsocks', 'Snell', 'Socks5', 'Http', 'Vmess'];
|
// const ProxyTypes = ['Shadowsocks', 'Snell', 'Socks5', 'Http', 'Vmess'];
|
||||||
|
|
||||||
const NonProxyTypes = [
|
const NonProxyTypes = [
|
||||||
|
@ -180,6 +179,19 @@ export function requestDelayForProxy(apiConfig, name) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function requestDelayForProxies(apiConfig, names) {
|
||||||
|
return async (dispatch, getState) => {
|
||||||
|
const proxyNames = getDangleProxyNames(getState());
|
||||||
|
|
||||||
|
const works = names
|
||||||
|
// remove names that are provided by proxy providers
|
||||||
|
.filter((p) => proxyNames.indexOf(p) > -1)
|
||||||
|
.map((p) => dispatch(requestDelayForProxy(apiConfig, p)));
|
||||||
|
await Promise.all(works);
|
||||||
|
await dispatch(fetchProxies(apiConfig));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function requestDelayAll(apiConfig) {
|
export function requestDelayAll(apiConfig) {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const proxyNames = getDangleProxyNames(getState());
|
const proxyNames = getDangleProxyNames(getState());
|
||||||
|
@ -251,3 +263,5 @@ export const initialState = {
|
||||||
delay: {},
|
delay: {},
|
||||||
groupNames: [],
|
groupNames: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const actions = { requestDelayForProxies };
|
||||||
|
|
Loading…
Reference in a new issue