diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/version.ts | 26 | ||||
| -rw-r--r-- | src/components/Root.js | 2 | ||||
| -rw-r--r-- | src/components/SideBar.js | 17 | ||||
| -rw-r--r-- | src/components/SideBar.module.css | 36 | ||||
| -rw-r--r-- | src/components/about/About.module.css | 18 | ||||
| -rw-r--r-- | src/components/about/About.tsx | 78 | ||||
| -rw-r--r-- | src/custom.d.ts | 4 |
7 files changed, 163 insertions, 18 deletions
diff --git a/src/api/version.ts b/src/api/version.ts new file mode 100644 index 0000000..eb8a86c --- /dev/null +++ b/src/api/version.ts @@ -0,0 +1,26 @@ +import { getURLAndInit } from 'src/misc/request-helper'; +import { ClashAPIConfig } from 'src/types'; + +type VersionData = { + version: string; + premium?: boolean; +}; + +export async function fetchVersion( + endpoint: string, + apiConfig: ClashAPIConfig +): Promise<VersionData> { + let json = { rules: [] }; + try { + const { url, init } = getURLAndInit(apiConfig); + const res = await fetch(url + endpoint, init); + if (res.ok) { + json = await res.json(); + } + } catch (err) { + // log and ignore + // eslint-disable-next-line no-console + console.log(`failed to fetch ${endpoint}`, err); + } + return json; +} diff --git a/src/components/Root.js b/src/components/Root.js index 7b0ae04..f0a67ec 100644 --- a/src/components/Root.js +++ b/src/components/Root.js @@ -3,6 +3,7 @@ import './Root.css'; import React, { Suspense } from 'react'; import { HashRouter as Router, Route, Routes } from 'react-router-dom'; import { RecoilRoot } from 'recoil'; +import { About } from 'src/components/about/About'; import { actions, initialState } from '../store'; import APIDiscovery from './APIDiscovery'; @@ -41,6 +42,7 @@ const routes = [ ['logs', '/logs', <Logs />], ['proxies', '/proxies', <Proxies />], ['rules', '/rules', <Rules />], + ['about', '/about', <About />], __DEV__ ? ['style', '/style', <StyleGuide />] : false, ].filter(Boolean); diff --git a/src/components/SideBar.js b/src/components/SideBar.js index 05f6eba..29724ae 100644 --- a/src/components/SideBar.js +++ b/src/components/SideBar.js @@ -2,7 +2,7 @@ import cx from 'clsx'; import { motion } from 'framer-motion'; import PropTypes from 'prop-types'; import React from 'react'; -// import { Command, Activity, Globe, Link2, Settings, File } from 'react-feather'; +import { Info } from 'react-feather'; import { FcAreaChart, FcDocument, @@ -16,7 +16,6 @@ import { Link, useLocation } from 'react-router-dom'; import { getTheme, switchTheme } from '../store/app'; import s from './SideBar.module.css'; import { connect } from './StateProvider'; -import SvgYacd from './SvgYacd'; const { useCallback } = React; @@ -115,9 +114,17 @@ function SideBar({ dispatch, theme }) { /> ))} </div> - <button className={s.themeSwitchContainer} onClick={switchThemeHooked}> - {theme === 'light' ? <MoonA /> : <Sun />} - </button> + <div className={s.footer}> + <button + className={cx(s.iconWrapper, s.themeSwitchContainer)} + onClick={switchThemeHooked} + > + {theme === 'light' ? <MoonA /> : <Sun />} + </button> + <Link to="/about" className={s.iconWrapper}> + <Info size={20} /> + </Link> + </div> </div> ); } diff --git a/src/components/SideBar.module.css b/src/components/SideBar.module.css index af91f75..275a007 100644 --- a/src/components/SideBar.module.css +++ b/src/components/SideBar.module.css @@ -68,34 +68,44 @@ } } -.themeSwitchContainer { - --sz: 40px; - - @media (max-width: 768px) { - display: none; - } - +.footer { position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%); +} + +@media (max-width: 768px) { + .footer { + display: none; + } +} + +.iconWrapper { + --sz: 40px; + width: var(--sz); height: var(--sz); display: flex; justify-content: center; align-items: center; + padding: 5px; color: var(--color-text); + border-radius: 100%; + border: 1px solid transparent; +} +.iconWrapper:hover { + opacity: 0.6; +} +.iconWrapper:focus { + border-color: var(--color-focus-blue); +} - padding: 5px; +.themeSwitchContainer { appearance: none; outline: none; user-select: none; background: none; cursor: pointer; - border: 1px solid transparent; - border-radius: 100%; - &:focus { - border-color: var(--color-focus-blue); - } } diff --git a/src/components/about/About.module.css b/src/components/about/About.module.css new file mode 100644 index 0000000..632b3ee --- /dev/null +++ b/src/components/about/About.module.css @@ -0,0 +1,18 @@ +.root { + padding: 6px 15px; + @media (--breakpoint-not-small) { + padding: 10px 40px; + } +} + +.mono { + font-family: var(--font-mono); +} + +.link { + color: var(--color-text-secondary); + display: inline-flex; +} +.link:hover { + color: var(--color-text-highlight); +} diff --git a/src/components/about/About.tsx b/src/components/about/About.tsx new file mode 100644 index 0000000..7648934 --- /dev/null +++ b/src/components/about/About.tsx @@ -0,0 +1,78 @@ +import * as React from 'react'; +import { GitHub } from 'react-feather'; +import { useQuery } from 'react-query'; +import { fetchVersion } from 'src/api/version'; +import ContentHeader from 'src/components/ContentHeader'; +import { connect } from 'src/components/StateProvider'; +import { getClashAPIConfig } from 'src/store/app'; +import { ClashAPIConfig } from 'src/types'; + +import s from './About.module.css'; + +type Props = { apiConfig: ClashAPIConfig }; + +function Version({ + name, + link, + version, +}: { + name: string; + link: string; + version: string; +}) { + return ( + <div className={s.root}> + <h2>{name}</h2> + <p> + <span>Version </span> + <span className={s.mono}>{version}</span> + </p> + <p> + <a + className={s.link} + href={link} + target="_blank" + rel="noopener noreferrer" + > + <GitHub size={20} /> + <span>Source</span> + </a> + </p> + </div> + ); +} + +function AboutImpl(props: Props) { + const { data: version } = useQuery( + ['/version', props.apiConfig], + fetchVersion, + { + suspense: true, + } + ); + console.log(version); + + return ( + <> + <ContentHeader title="About" /> + {version ? ( + <Version + name="Clash" + version={version.version} + link="https://github.com/Dreamacro/clash" + /> + ) : null} + <Version + name="Yacd" + version={__VERSION__} + link="https://github.com/haishanh/yacd" + /> + </> + ); +} + +const mapState = (s) => ({ + apiConfig: getClashAPIConfig(s), +}); + +export const About = connect(mapState)(AboutImpl); diff --git a/src/custom.d.ts b/src/custom.d.ts index 9041f77..e60e225 100644 --- a/src/custom.d.ts +++ b/src/custom.d.ts @@ -3,3 +3,7 @@ declare module '*.module.css' { const classes: { [key: string]: string }; export default classes; } + +// webpack definePlugin replacing variables +declare const __VERSION__: string; +declare const __DEV__: string; |
