From 6a402afa3f16b8cc00a939b72250b5aaabaf5b7d Mon Sep 17 00:00:00 2001 From: Haishan Date: Sun, 5 Jun 2022 23:40:25 +0800 Subject: Fix theme switcher button shape on iOS --- src/components/shared/ThemeSwitcher.module.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/components/shared') diff --git a/src/components/shared/ThemeSwitcher.module.scss b/src/components/shared/ThemeSwitcher.module.scss index c5de126..951376a 100644 --- a/src/components/shared/ThemeSwitcher.module.scss +++ b/src/components/shared/ThemeSwitcher.module.scss @@ -29,7 +29,8 @@ height: var(--sz); select { cursor: pointer; - padding-left: var(--sz); + padding-left: calc(var(--sz) - 2px); + font-size: 0; width: var(--sz); height: var(--sz); appearance: none; -- cgit v1.3.1 From 7f7cb27df139d6ca73031789539ea2ba2f2ecb77 Mon Sep 17 00:00:00 2001 From: Haishan Date: Mon, 6 Jun 2022 00:02:54 +0800 Subject: Make button slightly bigger than before --- src/components/Button.module.scss | 10 +++++----- src/components/Button.tsx | 10 ++++------ src/components/rules/RuleProviderItem.tsx | 12 ++++-------- src/components/shared/RotateIcon.tsx | 2 +- 4 files changed, 14 insertions(+), 20 deletions(-) (limited to 'src/components/shared') diff --git a/src/components/Button.module.scss b/src/components/Button.module.scss index 3046d0c..710d3ad 100644 --- a/src/components/Button.module.scss +++ b/src/components/Button.module.scss @@ -23,16 +23,16 @@ transform: scale(0.97); } - font-size: 0.85em; - padding: 4px 7px; - @media (--breakpoint-not-small) { - font-size: 1em; - padding: 6px 12px; + padding: 10px 13px; + + &.circular { + padding: 8px; } &.minimal { border-color: transparent; background: none; + padding: 6px 12px; &:focus { border-color: var(--color-focus-blue); } diff --git a/src/components/Button.tsx b/src/components/Button.tsx index 1725d1b..8125edc 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -17,7 +17,7 @@ type ButtonProps = { isLoading?: boolean; onClick?: (e: React.MouseEvent) => unknown; disabled?: boolean; - kind?: 'primary' | 'minimal'; + kind?: 'primary' | 'minimal' | 'circular'; className?: string; title?: string; } & ButtonInternalProps; @@ -36,7 +36,7 @@ function Button(props: ButtonProps, ref: React.Ref) { ...restProps } = props; const internalProps = { children, label, text, start }; - const internalOnClick = useCallback( + const internalOnClick = useCallback>( (e) => { if (isLoading) return; onClick && onClick(e); @@ -45,7 +45,7 @@ function Button(props: ButtonProps, ref: React.Ref) { ); const btnClassName = cx( s0.btn, - { [s0.minimal]: kind === 'minimal' }, + { [s0.minimal]: kind === 'minimal', [s0.circular]: kind === 'circular' }, className ); return ( @@ -76,9 +76,7 @@ function ButtonInternal({ children, label, text, start }: ButtonInternalProps) { return ( <> {start ? ( - - {typeof start === 'function' ? start() : start} - + {typeof start === 'function' ? start() : start} ) : null} {children || label || text} diff --git a/src/components/rules/RuleProviderItem.tsx b/src/components/rules/RuleProviderItem.tsx index fe4610e..fc88ae1 100644 --- a/src/components/rules/RuleProviderItem.tsx +++ b/src/components/rules/RuleProviderItem.tsx @@ -16,24 +16,20 @@ export function RuleProviderItem({ ruleCount, apiConfig, }) { - const [onClickRefreshButton, isRefreshing] = useUpdateRuleProviderItem( - name, - apiConfig - ); + const [onClickRefreshButton, isRefreshing] = useUpdateRuleProviderItem(name, apiConfig); const timeAgo = formatDistance(new Date(updatedAt), new Date()); return (
{idx}
-
- {ruleCount < 2 ? `${ruleCount} rule` : `${ruleCount} rules`} -
+
{ruleCount < 2 ? `${ruleCount} rule` : `${ruleCount} rules`}
Updated {timeAgo} ago
-
diff --git a/src/components/shared/RotateIcon.tsx b/src/components/shared/RotateIcon.tsx index 7e3ceae..d9dcbd9 100644 --- a/src/components/shared/RotateIcon.tsx +++ b/src/components/shared/RotateIcon.tsx @@ -10,7 +10,7 @@ export function RotateIcon({ isRotating }: { isRotating: boolean }) { }); return ( - + ); } -- cgit v1.3.1 From 78f3434cb52f53c66936de278f0828c19ef63666 Mon Sep 17 00:00:00 2001 From: Haishan Date: Mon, 6 Jun 2022 23:39:56 +0800 Subject: Run prettier --- src/api/configs.ts | 5 +- src/api/connections.ts | 5 +- src/api/proxies.ts | 5 +- src/api/rule-provider.ts | 5 +- src/api/rules.ts | 4 +- src/api/traffic.ts | 2 +- src/components/APIConfig.tsx | 5 +- src/components/BackendList.tsx | 11 +--- src/components/Collapsible.tsx | 13 +---- src/components/CollapsibleSectionHeader.tsx | 7 +-- src/components/ConnectionTable.tsx | 5 +- src/components/Logs.tsx | 2 +- src/components/Rules.tsx | 2 +- src/components/Search.tsx | 7 +-- src/components/SideBar.tsx | 9 +--- src/components/SvgYacd.tsx | 7 +-- src/components/ToggleSwitch.tsx | 5 +- src/components/TrafficChart.tsx | 10 ++-- src/components/about/About.tsx | 29 ++-------- src/components/proxies/ClosePrevConns.tsx | 9 ++-- src/components/proxies/Proxies.tsx | 20 ++----- src/components/proxies/Proxy.module.scss | 3 -- src/components/proxies/Proxy.tsx | 27 ++-------- src/components/proxies/ProxyGroup.module.scss | 9 ++++ src/components/proxies/ProxyGroup.tsx | 23 +++----- src/components/proxies/ProxyList.tsx | 7 +-- src/components/proxies/ProxyPageFab.tsx | 7 +-- src/components/proxies/ProxyProvider.tsx | 7 +-- src/components/proxies/ProxyProviderList.tsx | 6 +-- src/components/proxies/Settings.tsx | 6 +-- src/components/proxies/hooks.tsx | 12 +---- src/components/proxies/proxies.hooks.tsx | 9 ++-- src/components/rules/RuleProviderItem.module.scss | 13 ++--- src/components/rules/RuleProviderItem.tsx | 14 ++--- src/components/shared/Fab.tsx | 12 ++--- src/components/shared/RotateIcon.tsx | 9 ++-- src/components/shared/TextFitler.tsx | 5 +- src/components/svg/Equalizer.tsx | 5 +- src/hooks/useRemainingViewPortHeight.ts | 7 +-- src/hooks/useTextInput.ts | 4 +- src/misc/chart.ts | 4 +- src/misc/i18n.ts | 5 +- src/misc/motion.ts | 4 +- src/misc/request-helper.ts | 6 +-- src/misc/shallowEqual.ts | 7 +-- src/misc/utils.ts | 10 +--- src/store/app.ts | 4 +- src/store/configs.ts | 8 +-- src/store/proxies.tsx | 65 ++++++----------------- src/sw.ts | 3 +- src/swRegistration.ts | 12 ++--- src/types.ts | 2 +- 52 files changed, 127 insertions(+), 355 deletions(-) (limited to 'src/components/shared') diff --git a/src/api/configs.ts b/src/api/configs.ts index 69b02d4..3646f1a 100644 --- a/src/api/configs.ts +++ b/src/api/configs.ts @@ -22,10 +22,7 @@ function configsPatchWorkaround(o: ClashConfigPartial) { return o; } -export async function updateConfigs( - apiConfig: ClashAPIConfig, - o: ClashConfigPartial -) { +export async function updateConfigs(apiConfig: ClashAPIConfig, o: ClashConfigPartial) { const { url, init } = getURLAndInit(apiConfig); const body = JSON.stringify(configsPatchWorkaround(o)); return await fetch(url + endpoint, { ...init, body, method: 'PATCH' }); diff --git a/src/api/connections.ts b/src/api/connections.ts index 9c94d31..60fd4c5 100644 --- a/src/api/connections.ts +++ b/src/api/connections.ts @@ -51,10 +51,7 @@ function appendData(s: string) { type UnsubscribeFn = () => void; let wsState: number; -export function fetchData( - apiConfig: ClashAPIConfig, - listener: unknown -): UnsubscribeFn | void { +export function fetchData(apiConfig: ClashAPIConfig, listener: unknown): UnsubscribeFn | void { if (fetched || wsState === 1) { if (listener) return subscribe(listener); } diff --git a/src/api/proxies.ts b/src/api/proxies.ts index 6b3e28e..e11fd9e 100644 --- a/src/api/proxies.ts +++ b/src/api/proxies.ts @@ -59,8 +59,5 @@ export async function updateProviderByName(config, name) { export async function healthcheckProviderByName(config, name) { const { url, init } = getURLAndInit(config); const options = { ...init, method: 'GET' }; - return await fetch( - url + '/providers/proxies/' + name + '/healthcheck', - options - ); + return await fetch(url + '/providers/proxies/' + name + '/healthcheck', options); } diff --git a/src/api/rule-provider.ts b/src/api/rule-provider.ts index ec9fa7b..5ecd61e 100644 --- a/src/api/rule-provider.ts +++ b/src/api/rule-provider.ts @@ -31,10 +31,7 @@ function normalizeAPIResponse(data: RuleProviderAPIData) { return { byName, names }; } -export async function fetchRuleProviders( - endpoint: string, - apiConfig: ClashAPIConfig -) { +export async function fetchRuleProviders(endpoint: string, apiConfig: ClashAPIConfig) { const { url, init } = getURLAndInit(apiConfig); let data = { providers: {} }; diff --git a/src/api/rules.ts b/src/api/rules.ts index b57b0e3..4d18c23 100644 --- a/src/api/rules.ts +++ b/src/api/rules.ts @@ -12,9 +12,7 @@ type RuleAPIItem = { proxy: string; }; -function normalizeAPIResponse(json: { - rules: Array; -}): Array { +function normalizeAPIResponse(json: { rules: Array }): Array { invariant( json.rules && json.rules.length >= 0, 'there is no valid rules list in the rules API response' diff --git a/src/api/traffic.ts b/src/api/traffic.ts index cd18aac..aa9143c 100644 --- a/src/api/traffic.ts +++ b/src/api/traffic.ts @@ -27,7 +27,7 @@ const traffic = { this.subscribers.forEach((f) => f(o)); }, - subscribe(listener: (x:any) => void) { + subscribe(listener: (x: any) => void) { this.subscribers.push(listener); return () => { const idx = this.subscribers.indexOf(listener); diff --git a/src/components/APIConfig.tsx b/src/components/APIConfig.tsx index 6e11bc4..4a11c92 100644 --- a/src/components/APIConfig.tsx +++ b/src/components/APIConfig.tsx @@ -72,9 +72,9 @@ function APIConfig({ dispatch }) { const detectApiServer = async () => { // if there is already a clash API server at `/`, just use it as default value const res = await fetch('/'); - res.json().then(data => { + res.json().then((data) => { if (data['hello'] === 'clash') { - setBaseURL(window.location.origin) + setBaseURL(window.location.origin); } }); }; @@ -82,7 +82,6 @@ function APIConfig({ dispatch }) { detectApiServer(); }, []); - return ( // eslint-disable-next-line jsx-a11y/no-static-element-interactions
diff --git a/src/components/BackendList.tsx b/src/components/BackendList.tsx index 8e0d906..e4f4d80 100644 --- a/src/components/BackendList.tsx +++ b/src/components/BackendList.tsx @@ -2,10 +2,7 @@ import cx from 'clsx'; import * as React from 'react'; import { Eye, EyeOff, X as Close } from 'react-feather'; import { useToggle } from 'src/hooks/basic'; -import { - getClashAPIConfigs, - getSelectedClashAPIConfigIndex, -} from 'src/store/app'; +import { getClashAPIConfigs, getSelectedClashAPIConfigIndex } from 'src/store/app'; import { ClashAPIConfig } from 'src/types'; import s from './BackendList.module.scss'; @@ -137,11 +134,7 @@ function Button({ disabled?: boolean; }) { return ( - ); diff --git a/src/components/Collapsible.tsx b/src/components/Collapsible.tsx index e9a1ee8..819bc7c 100644 --- a/src/components/Collapsible.tsx +++ b/src/components/Collapsible.tsx @@ -60,20 +60,11 @@ const Collapsible = memo(({ children, isOpen }) => { return (
- + {children} diff --git a/src/components/CollapsibleSectionHeader.tsx b/src/components/CollapsibleSectionHeader.tsx index 2d5ecd1..8b701e1 100644 --- a/src/components/CollapsibleSectionHeader.tsx +++ b/src/components/CollapsibleSectionHeader.tsx @@ -39,12 +39,7 @@ export default function Header({ name, type, toggle, isOpen, qty }: Props) { {typeof qty === 'number' ? {qty} : null} - + Updated {timeAgo} ago +
- - - ); } diff --git a/src/components/shared/Fab.tsx b/src/components/shared/Fab.tsx index 832306e..8e72432 100644 --- a/src/components/shared/Fab.tsx +++ b/src/components/shared/Fab.tsx @@ -28,8 +28,7 @@ const AB: React.FC = ({ children, ...p }) => ( ); -interface MBProps - extends Omit, 'tabIndex'> { +interface MBProps extends Omit, 'tabIndex'> { tabIndex?: number; } @@ -77,10 +76,7 @@ const Fab: React.FC = ({ return event === 'click' ? (isOpen ? close() : open()) : null; }; - const actionOnClick = ( - e: React.FormEvent, - userFunc: (e: React.FormEvent) => void - ) => { + const actionOnClick = (e: React.FormEvent, userFunc: (e: React.FormEvent) => void) => { e.persist(); setIsOpen(false); setTimeout(() => { @@ -141,9 +137,7 @@ const Fab: React.FC = ({ {text && ( {text} diff --git a/src/components/shared/RotateIcon.tsx b/src/components/shared/RotateIcon.tsx index d9dcbd9..d291ece 100644 --- a/src/components/shared/RotateIcon.tsx +++ b/src/components/shared/RotateIcon.tsx @@ -4,13 +4,12 @@ import { RotateCw } from 'react-feather'; import s from './RotateIcon.module.scss'; -export function RotateIcon({ isRotating }: { isRotating: boolean }) { - const cls = cx(s.rotate, { - [s.isRotating]: isRotating, - }); +export function RotateIcon(props: { isRotating: boolean; size?: number }) { + const size = props.size || 16; + const cls = cx(s.rotate, { [s.isRotating]: props.isRotating }); return ( - + ); } diff --git a/src/components/shared/TextFitler.tsx b/src/components/shared/TextFitler.tsx index e4a4a88..7af61ac 100644 --- a/src/components/shared/TextFitler.tsx +++ b/src/components/shared/TextFitler.tsx @@ -4,10 +4,7 @@ import { useTextInut } from 'src/hooks/useTextInput'; import s from './TextFitler.module.scss'; -export function TextFilter(props: { - textAtom: RecoilState; - placeholder?: string; -}) { +export function TextFilter(props: { textAtom: RecoilState; placeholder?: string }) { const [onChange, text] = useTextInut(props.textAtom); return ( (): [React.MutableRefObject, number] { +export default function useRemainingViewPortHeight(): [ + React.MutableRefObject, + number +] { const ref = useRef(null); const [containerHeight, setContainerHeight] = useState(200); const updateContainerHeight = useCallback(() => { diff --git a/src/hooks/useTextInput.ts b/src/hooks/useTextInput.ts index 1fa19f7..853044c 100644 --- a/src/hooks/useTextInput.ts +++ b/src/hooks/useTextInput.ts @@ -9,9 +9,7 @@ export function useTextInut( ): [(e: React.ChangeEvent) => void, string] { const [, setTextGlobal] = useRecoilState(x); const [text, setText] = useState(''); - const setTextDebounced = useMemo(() => debounce(setTextGlobal, 300), [ - setTextGlobal, - ]); + const setTextDebounced = useMemo(() => debounce(setTextGlobal, 300), [setTextGlobal]); const onChange = useCallback( (e: React.ChangeEvent) => { setText(e.target.value); diff --git a/src/misc/chart.ts b/src/misc/chart.ts index c62fa06..56e05a2 100644 --- a/src/misc/chart.ts +++ b/src/misc/chart.ts @@ -1,4 +1,4 @@ -import { createAsset } from "use-asset" +import { createAsset } from 'use-asset'; import prettyBytes from './pretty-bytes'; export const chartJSResource = createAsset(() => { @@ -11,7 +11,7 @@ export const commonChartOptions: import('chart.js').ChartOptions<'line'> = { responsive: true, maintainAspectRatio: true, plugins: { - legend: { labels: { boxWidth: 20 } } + legend: { labels: { boxWidth: 20 } }, }, scales: { x: { display: false, type: 'category' }, diff --git a/src/misc/i18n.ts b/src/misc/i18n.ts index cf1a4f2..eecd72a 100644 --- a/src/misc/i18n.ts +++ b/src/misc/i18n.ts @@ -8,10 +8,7 @@ const allLocales = { en: import('src/i18n/en'), }; -type BackendRequestCallback = ( - err: null, - result: { status: number; data: any } -) => void; +type BackendRequestCallback = (err: null, result: { status: number; data: any }) => void; i18next .use(HttpBackend) diff --git a/src/misc/motion.ts b/src/misc/motion.ts index 5f2fe50..7fac864 100644 --- a/src/misc/motion.ts +++ b/src/misc/motion.ts @@ -1,5 +1,3 @@ import { createResource } from './createResource'; -export const framerMotionResouce = createResource( - () => import('framer-motion') -); +export const framerMotionResouce = createResource(() => import('framer-motion')); diff --git a/src/misc/request-helper.ts b/src/misc/request-helper.ts index 3bc8476..c01b994 100644 --- a/src/misc/request-helper.ts +++ b/src/misc/request-helper.ts @@ -12,7 +12,7 @@ function genCommonHeaders({ secret }: { secret?: string }) { return h; } function buildWebSocketURLBase(baseURL: string, params: URLSearchParams, endpoint: string) { - const qs = '?' + params.toString() + const qs = '?' + params.toString(); const url = new URL(baseURL); url.protocol === 'https:' ? (url.protocol = 'wss:') : (url.protocol = 'ws:'); return `${trimTrailingSlash(url.href)}${endpoint}${qs}`; @@ -32,7 +32,7 @@ export function buildWebSocketURL(apiConfig: ClashAPIConfig, endpoint: string) { token: secret, }); - return buildWebSocketURLBase(baseURL, params, endpoint) + return buildWebSocketURLBase(baseURL, params, endpoint); } export function buildLogsWebSocketURL(apiConfig: LogsAPIConfig, endpoint: string) { @@ -42,5 +42,5 @@ export function buildLogsWebSocketURL(apiConfig: LogsAPIConfig, endpoint: string level: logLevel, }); - return buildWebSocketURLBase(baseURL, params, endpoint) + return buildWebSocketURLBase(baseURL, params, endpoint); } diff --git a/src/misc/shallowEqual.ts b/src/misc/shallowEqual.ts index 241b725..937bc27 100644 --- a/src/misc/shallowEqual.ts +++ b/src/misc/shallowEqual.ts @@ -12,12 +12,7 @@ function is(x, y) { export default function shallowEqual(objA, objB) { if (is(objA, objB)) return true; - if ( - typeof objA !== 'object' || - objA === null || - typeof objB !== 'object' || - objB === null - ) { + if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { return false; } diff --git a/src/misc/utils.ts b/src/misc/utils.ts index d3a7bfc..9497026 100644 --- a/src/misc/utils.ts +++ b/src/misc/utils.ts @@ -1,7 +1,4 @@ -export function throttle( - fn: (...args: T) => unknown, - timeout: number -) { +export function throttle(fn: (...args: T) => unknown, timeout: number) { let pending = false; return (...args: T) => { @@ -15,10 +12,7 @@ export function throttle( }; } -export function debounce( - fn: (...args: T) => unknown, - timeout: number -) { +export function debounce(fn: (...args: T) => unknown, timeout: number) { let timeoutId: ReturnType; return (...args: T) => { if (timeoutId) clearTimeout(timeoutId); diff --git a/src/store/app.ts b/src/store/app.ts index 7262b32..2789981 100644 --- a/src/store/app.ts +++ b/src/store/app.ts @@ -152,7 +152,7 @@ export function updateCollapsibleIsOpen(prefix: string, name: string, v: boolean const defaultClashAPIConfig = { baseURL: document.getElementById('app')?.getAttribute('data-base-url') ?? 'http://127.0.0.1:9090', secret: '', - addedAt: 0 + addedAt: 0, }; // type Theme = 'light' | 'dark'; const defaultState: StateApp = { @@ -169,7 +169,7 @@ const defaultState: StateApp = { proxySortBy: 'Natural', hideUnavailableProxies: false, autoCloseOldConns: false, - logStreamingPaused: false + logStreamingPaused: false, }; function parseConfigQueryString() { diff --git a/src/store/configs.ts b/src/store/configs.ts index c533508..7571b4e 100644 --- a/src/store/configs.ts +++ b/src/store/configs.ts @@ -1,10 +1,4 @@ -import { - ClashGeneralConfig, - DispatchFn, - GetStateFn, - State, - StateConfigs, -} from 'src/store/types'; +import { ClashGeneralConfig, DispatchFn, GetStateFn, State, StateConfigs } from 'src/store/types'; import { ClashAPIConfig } from 'src/types'; import * as configsAPI from '../api/configs'; diff --git a/src/store/proxies.tsx b/src/store/proxies.tsx index 25200cd..0505fce 100644 --- a/src/store/proxies.tsx +++ b/src/store/proxies.tsx @@ -48,8 +48,7 @@ export const getDelay = (s: State) => s.proxies.delay; export const getProxyGroupNames = (s: State) => s.proxies.groupNames; export const getProxyProviders = (s: State) => s.proxies.proxyProviders || []; export const getDangleProxyNames = (s: State) => s.proxies.dangleProxyNames; -export const getShowModalClosePrevConns = (s: State) => - s.proxies.showModalClosePrevConns; +export const getShowModalClosePrevConns = (s: State) => s.proxies.showModalClosePrevConns; export function fetchProxies(apiConfig: ClashAPIConfig) { return async (dispatch: any, getState: any) => { @@ -58,10 +57,9 @@ export function fetchProxies(apiConfig: ClashAPIConfig) { proxiesAPI.fetchProviderProxies(apiConfig), ]); - const { - providers: proxyProviders, - proxies: providerProxies, - } = formatProxyProviders(providersData.providers); + const { providers: proxyProviders, proxies: providerProxies } = formatProxyProviders( + providersData.providers + ); const proxies = { ...providerProxies, ...proxiesData.proxies }; const [groupNames, proxyNames] = retrieveGroupNamesFrom(proxies); @@ -121,10 +119,7 @@ export function updateProviders(apiConfig: ClashAPIConfig, names: string[]) { }; } -async function healthcheckProviderByNameInternal( - apiConfig: ClashAPIConfig, - name: string -) { +async function healthcheckProviderByNameInternal(apiConfig: ClashAPIConfig, name: string) { try { await proxiesAPI.healthcheckProviderByName(apiConfig, name); } catch (x) { @@ -132,10 +127,7 @@ async function healthcheckProviderByNameInternal( } } -export function healthcheckProviderByName( - apiConfig: ClashAPIConfig, - name: string -) { +export function healthcheckProviderByName(apiConfig: ClashAPIConfig, name: string) { return async (dispatch: DispatchFn) => { await healthcheckProviderByNameInternal(apiConfig, name); // should be optimized @@ -168,16 +160,10 @@ async function closeGroupConns( } } - await Promise.all( - idsToClose.map((id) => connAPI.closeConnById(apiConfig, id).catch(noop)) - ); + await Promise.all(idsToClose.map((id) => connAPI.closeConnById(apiConfig, id).catch(noop))); } -function resolveChain( - proxies: ProxiesMapping, - groupName: string, - itemName: string -) { +function resolveChain(proxies: ProxiesMapping, groupName: string, itemName: string) { const chain = [itemName, groupName]; let child: ProxyItem; @@ -197,11 +183,7 @@ async function switchProxyImpl( itemName: string ) { try { - const res = await proxiesAPI.requestToSwitchProxy( - apiConfig, - groupName, - itemName - ); + const res = await proxiesAPI.requestToSwitchProxy(apiConfig, groupName, itemName); if (res.ok === false) { throw new Error(`failed to switch proxy: res.statusText`); } @@ -267,16 +249,10 @@ function closePrevConnsAndTheModal(apiConfig: ClashAPIConfig) { }; } -export function switchProxy( - apiConfig: ClashAPIConfig, - groupName: string, - itemName: string -) { +export function switchProxy(apiConfig: ClashAPIConfig, groupName: string, itemName: string) { return async (dispatch: DispatchFn, getState: GetStateFn) => { // switch proxy asynchronously - switchProxyImpl(dispatch, getState, apiConfig, groupName, itemName).catch( - noop - ); + switchProxyImpl(dispatch, getState, apiConfig, groupName, itemName).catch(noop); // optimistic UI update dispatch('store/proxies#switchProxy', (s) => { @@ -291,11 +267,7 @@ export function switchProxy( function requestDelayForProxyOnce(apiConfig: ClashAPIConfig, name: string) { return async (dispatch: DispatchFn, getState: GetStateFn) => { const latencyTestUrl = getLatencyTestUrl(getState()); - const res = await proxiesAPI.requestDelayForProxy( - apiConfig, - name, - latencyTestUrl - ); + const res = await proxiesAPI.requestDelayForProxy(apiConfig, name, latencyTestUrl); let error = ''; if (res.ok === false) { error = res.statusText; @@ -323,10 +295,7 @@ export function requestDelayForProxy(apiConfig: ClashAPIConfig, name: string) { }; } -export function requestDelayForProxies( - apiConfig: ClashAPIConfig, - names: string[] -) { +export function requestDelayForProxies(apiConfig: ClashAPIConfig, names: string[]) { return async (dispatch: DispatchFn, getState: GetStateFn) => { const proxyNames = getDangleProxyNames(getState()); @@ -342,9 +311,7 @@ export function requestDelayForProxies( export function requestDelayAll(apiConfig: ClashAPIConfig) { return async (dispatch: DispatchFn, getState: GetStateFn) => { const proxyNames = getDangleProxyNames(getState()); - await Promise.all( - proxyNames.map((p) => dispatch(requestDelayForProxy(apiConfig, p))) - ); + await Promise.all(proxyNames.map((p) => dispatch(requestDelayForProxy(apiConfig, p)))); const proxyProviders = getProxyProviders(getState()); // one by one for (const p of proxyProviders) { @@ -385,9 +352,7 @@ type ProvidersRaw = { [key: string]: ProxyProvider; }; -function formatProxyProviders( - providersInput: ProvidersRaw -): { +function formatProxyProviders(providersInput: ProvidersRaw): { providers: Array; proxies: { [key: string]: ProxyItem }; } { diff --git a/src/sw.ts b/src/sw.ts index bdc663c..f577677 100644 --- a/src/sw.ts +++ b/src/sw.ts @@ -53,8 +53,7 @@ registerRoute( // precache, in this case same-origin .png requests like those from in public/ registerRoute( // Add in any other file extensions or routing criteria as needed. - ({ url }) => - url.origin === self.location.origin && url.pathname.endsWith('.png'), + ({ url }) => url.origin === self.location.origin && url.pathname.endsWith('.png'), // Customize this strategy as needed, e.g., by changing to CacheFirst. new StaleWhileRevalidate({ cacheName: 'images', diff --git a/src/swRegistration.ts b/src/swRegistration.ts index 55ceb0b..0a684a8 100644 --- a/src/swRegistration.ts +++ b/src/swRegistration.ts @@ -3,9 +3,7 @@ const isLocalhost = Boolean( // [::1] is the IPv6 localhost address. window.location.hostname === '[::1]' || // 127.0.0.0/8 are considered localhost for IPv4. - window.location.hostname.match( - /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ - ) + window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/) ); type Config = { @@ -34,9 +32,7 @@ export function register(config?: Config) { // Add some additional logging to localhost, pointing developers to the // service worker/PWA documentation. navigator.serviceWorker.ready.then(() => { - console.log( - 'This web app is being served cache-first by a service worker' - ); + console.log('This web app is being served cache-first by a service worker'); }); } else { // Is not localhost. Just register service worker @@ -114,9 +110,7 @@ function checkValidServiceWorker(swUrl: string, config?: Config) { } }) .catch(() => { - console.log( - 'No internet connection found. App is running in offline mode.' - ); + console.log('No internet connection found. App is running in offline mode.'); }); } diff --git a/src/types.ts b/src/types.ts index 694289b..8446dfc 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3,4 +3,4 @@ export type ClashAPIConfig = { secret?: string; }; -export type LogsAPIConfig = ClashAPIConfig & { logLevel: string }; \ No newline at end of file +export type LogsAPIConfig = ClashAPIConfig & { logLevel: string }; -- cgit v1.3.1 From 69423bdfff89e6c00db4406319189a8852c05aa7 Mon Sep 17 00:00:00 2001 From: Haishan Date: Sun, 12 Jun 2022 09:30:45 +0800 Subject: Always show update and health check buttons for proxy provider ref #649 --- src/components/StyleGuide.tsx | 4 ++ src/components/proxies/ProxyGroup.module.scss | 13 ++---- src/components/proxies/ProxyGroup.tsx | 39 +++++++---------- src/components/proxies/ProxyList.module.scss | 3 +- src/components/proxies/ProxyProvider.module.scss | 20 +++++---- src/components/proxies/ProxyProvider.tsx | 53 +++++++++++++----------- src/components/shared/ZapAnimated.module.scss | 12 ++++++ src/components/shared/ZapAnimated.tsx | 25 +++++++++++ 8 files changed, 102 insertions(+), 67 deletions(-) create mode 100644 src/components/shared/ZapAnimated.module.scss create mode 100644 src/components/shared/ZapAnimated.tsx (limited to 'src/components/shared') diff --git a/src/components/StyleGuide.tsx b/src/components/StyleGuide.tsx index 1f5f3be..910c538 100644 --- a/src/components/StyleGuide.tsx +++ b/src/components/StyleGuide.tsx @@ -4,6 +4,7 @@ import Loading from 'src/components/Loading'; import Button from './Button'; import Input from './Input'; +import { ZapAnimated } from './shared/ZapAnimated'; import SwitchThemed from './SwitchThemed'; import ToggleSwitch from './ToggleSwitch'; @@ -42,6 +43,9 @@ class StyleGuide extends PureComponent { render() { return (
+ + + diff --git a/src/components/proxies/ProxyGroup.module.scss b/src/components/proxies/ProxyGroup.module.scss index 6e9d91f..85b68b6 100644 --- a/src/components/proxies/ProxyGroup.module.scss +++ b/src/components/proxies/ProxyGroup.module.scss @@ -4,17 +4,10 @@ .groupHead { display: flex; + flex-wrap: wrap; align-items: center; } -.latencyButton { - margin-left: 5px; -} - -.zapWrapper { - width: 20px; - height: 20px; - display: flex; - 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 d6a4e99..6d6c59e 100644 --- a/src/components/proxies/ProxyGroup.tsx +++ b/src/components/proxies/ProxyGroup.tsx @@ -1,26 +1,20 @@ +import Tooltip from '@reach/tooltip'; import * as React from 'react'; -import { Zap } from 'react-feather'; +import { useState2 } from '$src/hooks/basic'; import { State } from '$src/store/types'; import { getCollapsibleIsOpen, getHideUnavailableProxies, getProxySortBy } from '../../store/app'; import { 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'; -const { createElement, useCallback, useMemo, useState } = React; - -function ZapWrapper() { - return ( -
- -
- ); -} +const { createElement, useCallback, useMemo } = React; function ProxyGroupImpl({ name, @@ -56,14 +50,15 @@ function ProxyGroupImpl({ [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 { await requestDelayForProxies(apiConfig, all); } catch (err) {} - setIsTestingLatency(false); - }, [all, apiConfig, requestDelayForProxies]); + testingLatency.set(false); + }, [all, apiConfig, requestDelayForProxies, testingLatency]); return (
@@ -75,15 +70,13 @@ function ProxyGroupImpl({ qty={all.length} isOpen={isOpen} /> - +
+ + + +
{createElement(isOpen ? ProxyList : ProxyListSummaryView, { all, diff --git a/src/components/proxies/ProxyList.module.scss b/src/components/proxies/ProxyList.module.scss index d548572..12fea7e 100644 --- a/src/components/proxies/ProxyList.module.scss +++ b/src/components/proxies/ProxyList.module.scss @@ -6,9 +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/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 972a735..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'; @@ -18,6 +18,7 @@ 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'; @@ -56,6 +57,7 @@ function ProxyProviderImpl({ const updateProvider = useUpdateProviderItem({ dispatch, apiConfig, name }); const healthcheckProvider = useCallback(() => { + if (checkingHealth.value) return; checkingHealth.set(true); const stop = () => checkingHealth.set(false); dispatch(healthcheckProviderByName(apiConfig, name)).then(stop, stop); @@ -71,32 +73,33 @@ function ProxyProviderImpl({ const timeAgo = formatDistance(new Date(updatedAt), new Date()); return ( -
- +
+
+ + +
+ + + + + + +
+
Updated {timeAgo} ago
- - -
-
-
- - - + {isOpen ? : }
); } diff --git a/src/components/shared/ZapAnimated.module.scss b/src/components/shared/ZapAnimated.module.scss new file mode 100644 index 0000000..e4cb37b --- /dev/null +++ b/src/components/shared/ZapAnimated.module.scss @@ -0,0 +1,12 @@ +.animate { + --saturation: 70%; + stroke: hsl(46deg var(--saturation) 45%); + animation: zap-pulse 0.7s 0s ease-in-out none normal infinite; +} + +// prettier-ignore +@keyframes zap-pulse { + 0% { stroke: hsl(46deg var(--saturation) 45%); } + 50% { stroke: hsl(46deg var(--saturation) 95%); } + 100% { stroke: hsl(46deg var(--saturation) 45%); } +} diff --git a/src/components/shared/ZapAnimated.tsx b/src/components/shared/ZapAnimated.tsx new file mode 100644 index 0000000..e3b153a --- /dev/null +++ b/src/components/shared/ZapAnimated.tsx @@ -0,0 +1,25 @@ +import cx from 'clsx'; +import * as React from 'react'; + +import s from './ZapAnimated.module.scss'; + +export function ZapAnimated(props: { size?: number; animate?: boolean }) { + const size = props.size || 24; + const cls = cx({ [s.animate]: props.animate }); + return ( + + + + ); +} -- cgit v1.3.1