diff options
| author | Haishan <[email protected]> | 2020-01-07 00:39:57 +0800 |
|---|---|---|
| committer | Haishan <[email protected]> | 2020-01-07 22:10:55 +0800 |
| commit | ff04a47ca4c5a758a8a158062da19919a8c011c7 (patch) | |
| tree | ede8b36f22a2016b30f95a375e2fa58d0d788c8a /src/components | |
| parent | dfbdee474979b21249461f270edfa0225994f298 (diff) | |
feat(Conns): keep up to 100 closed connections in another tab
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/Connections.css | 49 | ||||
| -rw-r--r-- | src/components/Connections.js | 88 | ||||
| -rw-r--r-- | src/components/Connections.module.css | 12 | ||||
| -rw-r--r-- | src/components/Root.css | 2 |
4 files changed, 130 insertions, 21 deletions
diff --git a/src/components/Connections.css b/src/components/Connections.css new file mode 100644 index 0000000..bc69a62 --- /dev/null +++ b/src/components/Connections.css @@ -0,0 +1,49 @@ +.react-tabs { + -webkit-tap-highlight-color: transparent; +} + +.react-tabs__tab-list { + margin: 0 0 10px; + padding: 0 30px; +} + +.react-tabs__tab { + display: inline-flex; + align-items: center; + border: 1px solid transparent; + border-radius: 5px; + bottom: -1px; + position: relative; + list-style: none; + padding: 6px 10px; + cursor: pointer; + font-size: 1.2em; + opacity: 0.5; +} + +.react-tabs__tab--selected { + opacity: 1; +} + +.react-tabs__tab--disabled { + color: GrayText; + cursor: default; +} + +.react-tabs__tab:focus { + border-color: hsl(208, 99%, 50%); + outline: none; +} + +.react-tabs__tab:focus:after { + content: ''; + position: absolute; +} + +.react-tabs__tab-panel { + display: none; +} + +.react-tabs__tab-panel--selected { + display: block; +} diff --git a/src/components/Connections.js b/src/components/Connections.js index 70fe870..2f8e319 100644 --- a/src/components/Connections.js +++ b/src/components/Connections.js @@ -4,12 +4,14 @@ import ConnectionTable from './ConnectionTable'; import useRemainingViewPortHeight from '../hooks/useRemainingViewPortHeight'; import { getClashAPIConfig } from '../store/app'; import { X as IconClose } from 'react-feather'; +import { Tab, Tabs, TabList, TabPanel } from 'react-tabs'; import SvgYacd from './SvgYacd'; import Button from './Button'; import ModalCloseAllConnections from './ModalCloseAllConnections'; import { connect } from './StateProvider'; import * as connAPI from '../api/connections'; +import './Connections.css'; import s from './Connections.module.css'; const { useEffect, useState, useRef, useCallback, useMemo } = React; @@ -36,9 +38,24 @@ function formatConnectionDataItem(i) { }; } +function renderTableOrPlaceholder(conns) { + return conns.length > 0 ? ( + <ConnectionTable data={conns} /> + ) : ( + <div className={s.placeHolder}> + <SvgYacd width={200} height={200} c1="var(--color-text)" /> + </div> + ); +} + +function ConnQty({ qty }) { + return qty < 100 ? '' + qty : '99+'; +} + function Conn({ apiConfig }) { const [refContainer, containerHeight] = useRemainingViewPortHeight(); const [conns, setConns] = useState([]); + const [closedConns, setClosedConns] = useState([]); const [isCloseAllModalOpen, setIsCloseAllModalOpen] = useState(false); const openCloseAllModal = useCallback(() => setIsCloseAllModalOpen(true), []); const closeCloseAllModal = useCallback( @@ -54,6 +71,15 @@ function Conn({ apiConfig }) { const read = useCallback( ({ connections }) => { const x = connections.map(c => formatConnectionDataItem(c)); + const closed = []; + for (const c of prevConnsRef.current) { + const idx = x.findIndex(conn => conn.id === c.id); + if (idx < 0) closed.push(c); + } + setClosedConns(prev => { + // keep max 100 entries + return [...closed, ...prev].slice(0, 101); + }); // if previous connections and current connections are both empty // arrays, we wont update state to avaoid rerender if (x && (x.length !== 0 || prevConnsRef.current.length !== 0)) { @@ -71,30 +97,50 @@ function Conn({ apiConfig }) { return ( <div> <ContentHeader title="Connections" /> - <div - ref={refContainer} - style={{ padding: 30, paddingBottom, paddingTop: 0 }} - > + <Tabs> + <TabList> + <Tab> + <span>Active</span> + <span className={s.connQty}> + <ConnQty qty={conns.length} /> + </span> + </Tab> + <Tab> + <span>Closed</span> + <span className={s.connQty}> + <ConnQty qty={closedConns.length} /> + </span> + </Tab> + </TabList> <div - style={{ height: containerHeight - paddingBottom, overflow: 'auto' }} + ref={refContainer} + style={{ padding: 30, paddingBottom, paddingTop: 0 }} > - {conns.length > 0 ? ( - <ConnectionTable data={conns} /> - ) : ( - <div className={s.placeHolder}> - <SvgYacd width={200} height={200} c1="var(--color-text)" /> - </div> - )} + <div + style={{ + height: containerHeight - paddingBottom, + overflow: 'auto' + }} + > + <TabPanel> + <>{renderTableOrPlaceholder(conns)}</> + <div className="fabgrp"> + <Button + text="Close" + start={iconClose} + onClick={openCloseAllModal} + /> + </div> + </TabPanel> + <TabPanel>{renderTableOrPlaceholder(closedConns)}</TabPanel> + </div> </div> - </div> - <div className="fabgrp"> - <Button text="Close" start={iconClose} onClick={openCloseAllModal} /> - </div> - <ModalCloseAllConnections - isOpen={isCloseAllModalOpen} - primaryButtonOnTap={closeAllConnections} - onRequestClose={closeCloseAllModal} - /> + <ModalCloseAllConnections + isOpen={isCloseAllModalOpen} + primaryButtonOnTap={closeAllConnections} + onRequestClose={closeCloseAllModal} + /> + </Tabs> </div> ); } diff --git a/src/components/Connections.module.css b/src/components/Connections.module.css index 4991f29..45f20de 100644 --- a/src/components/Connections.module.css +++ b/src/components/Connections.module.css @@ -6,3 +6,15 @@ color: var(--color-background); opacity: 0.1; } + +.connQty { + font-family: var(--font-normal); + font-size: 0.75em; + margin-left: 3px; + padding: 2px 7px; + display: inline-flex; + justify-content: center; + align-items: center; + background-color: var(--bg-near-transparent); + border-radius: 30px; +} diff --git a/src/components/Root.css b/src/components/Root.css index 3622d57..060edf7 100644 --- a/src/components/Root.css +++ b/src/components/Root.css @@ -100,6 +100,7 @@ body.dark { --color-bg-proxy-selected: #303030; --color-row-odd: #282828; --bg-modal: #1f1f20; + --bg-near-transparent: rgba(255, 255, 255, 0.1); } body.light { @@ -118,6 +119,7 @@ body.light { --color-bg-proxy-selected: #cfcfcf; --color-row-odd: #f5f5f5; --bg-modal: #fbfbfb; + --bg-near-transparent: rgba(0, 0, 0, 0.1); } .flexCenter { |
