summaryrefslogtreecommitdiff
path: root/src/components/ProxyProvider.js
diff options
context:
space:
mode:
authorHaishan <[email protected]>2020-02-10 22:53:14 +0800
committerHaishan <[email protected]>2020-02-10 23:04:57 +0800
commite85116bf717b51c0d4aa4f07c91944414f0a4b4e (patch)
tree63a6167eaeb7b1da842caafe47947d3997a65a38 /src/components/ProxyProvider.js
parentbd82b8c5e3bad3efeecd9e2599b07128d290bea6 (diff)
refactor(Proxies): UI revamp
Diffstat (limited to 'src/components/ProxyProvider.js')
-rw-r--r--src/components/ProxyProvider.js161
1 files changed, 53 insertions, 108 deletions
diff --git a/src/components/ProxyProvider.js b/src/components/ProxyProvider.js
index 7a2f107..32071ab 100644
--- a/src/components/ProxyProvider.js
+++ b/src/components/ProxyProvider.js
@@ -1,69 +1,75 @@
import React from 'react';
-import { ChevronDown, RotateCw, Zap } from 'react-feather';
+import { RotateCw, Zap } from 'react-feather';
import { formatDistance } from 'date-fns';
-import ResizeObserver from 'resize-observer-polyfill';
import { motion } from 'framer-motion';
-import cx from 'classnames';
import { connect } from './StateProvider';
-import { SectionNameType } from './shared/Basic';
-import { ProxyList, ProxyListSummaryView } from './ProxyGroup';
+import Collapsible from './Collapsible';
+import CollapsibleSectionHeader from './CollapsibleSectionHeader';
+import {
+ ProxyList,
+ ProxyListSummaryView,
+ filterAvailableProxiesAndSort
+} from './ProxyGroup';
import Button from './Button';
import { getClashAPIConfig } from '../store/app';
import {
+ getDelay,
+ getRtFilterSwitch,
updateProviderByName,
healthcheckProviderByName
} from '../store/proxies';
import s from './ProxyProvider.module.css';
-const { memo, useState, useRef, useEffect, useCallback } = React;
+const { useState, useCallback } = React;
type Props = {
- item: Array<{
- name: string,
- proxies: Array<string>,
- type: 'Proxy' | 'Rule',
- vehicleType: 'HTTP' | 'File' | 'Compatible',
- updatedAt?: string
- }>,
- proxies: {
- [string]: any
- },
+ name: string,
+ proxies: Array<string>,
+ type: 'Proxy' | 'Rule',
+ vehicleType: 'HTTP' | 'File' | 'Compatible',
+ updatedAt?: string,
dispatch: any => void
};
-function ProxyProvider({ item, dispatch, apiConfig }: Props) {
+function ProxyProvider({
+ name,
+ proxies,
+ vehicleType,
+ updatedAt,
+ dispatch,
+ apiConfig
+}: Props) {
const [isHealthcheckLoading, setIsHealthcheckLoading] = useState(false);
const updateProvider = useCallback(
- () => dispatch(updateProviderByName(apiConfig, item.name)),
- [apiConfig, dispatch, item.name]
+ () => dispatch(updateProviderByName(apiConfig, name)),
+ [apiConfig, dispatch, name]
);
const healthcheckProvider = useCallback(async () => {
setIsHealthcheckLoading(true);
- await dispatch(healthcheckProviderByName(apiConfig, item.name));
+ await dispatch(healthcheckProviderByName(apiConfig, name));
setIsHealthcheckLoading(false);
- }, [apiConfig, dispatch, item.name, setIsHealthcheckLoading]);
+ }, [apiConfig, dispatch, name, setIsHealthcheckLoading]);
const [isCollapsibleOpen, setCollapsibleOpen] = useState(false);
const toggle = useCallback(() => setCollapsibleOpen(x => !x), []);
- const timeAgo = formatDistance(new Date(item.updatedAt), new Date());
+ const timeAgo = formatDistance(new Date(updatedAt), new Date());
return (
<div className={s.body}>
- <div className={s.header} onClick={toggle}>
- <SectionNameType name={item.name} type={item.vehicleType} />
- <Button kind="minimal">
- <span className={cx(s.arrow, { [s.isOpen]: isCollapsibleOpen })}>
- <ChevronDown />
- </span>
- </Button>
- </div>
+ <CollapsibleSectionHeader
+ name={name}
+ toggle={toggle}
+ type={vehicleType}
+ isOpen={isCollapsibleOpen}
+ qty={proxies.length}
+ />
<div className={s.updatedAt}>
<small>Updated {timeAgo} ago</small>
</div>
- <Collapsible2 isOpen={isCollapsibleOpen}>
- <ProxyList all={item.proxies} />
+ <Collapsible isOpen={isCollapsibleOpen}>
+ <ProxyList all={proxies} />
<div className={s.actionFooter}>
<Button text="Update" start={<Refresh />} onClick={updateProvider} />
<Button
@@ -73,10 +79,10 @@ function ProxyProvider({ item, dispatch, apiConfig }: Props) {
isLoading={isHealthcheckLoading}
/>
</div>
- </Collapsible2>
- <Collapsible2 isOpen={!isCollapsibleOpen}>
- <ProxyListSummaryView all={item.proxies} />
- </Collapsible2>
+ </Collapsible>
+ <Collapsible isOpen={!isCollapsibleOpen}>
+ <ProxyListSummaryView all={proxies} />
+ </Collapsible>
</div>
);
}
@@ -106,78 +112,17 @@ function Refresh() {
);
}
-function usePrevious(value) {
- const ref = useRef();
- useEffect(() => void (ref.current = value), [value]);
- return ref.current;
-}
-
-function useMeasure() {
- const ref = useRef();
- const [bounds, set] = useState({ height: 0 });
- useEffect(() => {
- const ro = new ResizeObserver(([entry]) => set(entry.contentRect));
- if (ref.current) ro.observe(ref.current);
- return () => ro.disconnect();
- }, []);
- return [ref, bounds];
-}
-
-const variantsCollpapsibleWrap = {
- initialOpen: {
- height: 'auto',
- transition: { duration: 0 }
- },
- open: height => ({
- height,
- opacity: 1,
- visibility: 'visible',
- transition: { duration: 0.3 }
- }),
- closed: {
- height: 0,
- opacity: 0,
- visibility: 'hidden',
- transition: { duration: 0.3 }
- }
+const mapState = (s, { proxies }) => {
+ const filterByRt = getRtFilterSwitch(s);
+ const delay = getDelay(s);
+ const apiConfig = getClashAPIConfig(s);
+ return {
+ apiConfig,
+ proxies: filterAvailableProxiesAndSort(proxies, delay, filterByRt)
+ };
};
-const variantsCollpapsibleChildContainer = {
- open: {
- x: 0
- },
- closed: {
- x: 20
- }
-};
-
-const Collapsible2 = memo(({ children, isOpen }) => {
- const previous = usePrevious(isOpen);
- const [refToMeature, { height }] = useMeasure();
- return (
- <div>
- <motion.div
- animate={
- isOpen && previous === isOpen
- ? 'initialOpen'
- : isOpen
- ? 'open'
- : 'closed'
- }
- custom={height}
- variants={variantsCollpapsibleWrap}
- >
- <motion.div
- variants={variantsCollpapsibleChildContainer}
- ref={refToMeature}
- >
- {children}
- </motion.div>
- </motion.div>
- </div>
- );
-});
-const mapState = s => ({
- apiConfig: getClashAPIConfig(s)
-});
+// const mapState = s => ({
+// apiConfig: getClashAPIConfig(s)
+// });
export default connect(mapState)(ProxyProvider);