mirror of
https://github.com/woodchen-ink/clash-and-dashboard.git
synced 2025-07-18 14:01:56 +08:00
Chore: cleanup code
This commit is contained in:
parent
1c9b0669a9
commit
d330bf178e
@ -58,7 +58,7 @@
|
|||||||
"dayjs": "^1.10.5",
|
"dayjs": "^1.10.5",
|
||||||
"eventemitter3": "^4.0.7",
|
"eventemitter3": "^4.0.7",
|
||||||
"immer": "^9.0.3",
|
"immer": "^9.0.3",
|
||||||
"jotai": "^1.0.0",
|
"jotai": "^1.1.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"neverthrow": "^4.2.1",
|
"neverthrow": "^4.2.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
@ -69,6 +69,6 @@
|
|||||||
"react-virtualized-auto-sizer": "^1.0.5",
|
"react-virtualized-auto-sizer": "^1.0.5",
|
||||||
"react-window": "^1.8.6",
|
"react-window": "^1.8.6",
|
||||||
"swr": "^0.5.6",
|
"swr": "^0.5.6",
|
||||||
"use-immer": "^0.5.2"
|
"use-immer": "^0.6.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,13 +48,13 @@ export function Group (props: GroupProps) {
|
|||||||
const canClick = config.type === 'Selector'
|
const canClick = config.type === 'Selector'
|
||||||
return (
|
return (
|
||||||
<div className="proxy-group">
|
<div className="proxy-group">
|
||||||
<div className="proxy-group-part">
|
<div className="w-full h-10 mt-1 flex items-center justify-between md:h-15 md:mt-0">
|
||||||
<span className="proxy-group-name">{ config.name }</span>
|
<span className="overflow-hidden overflow-ellipsis whitespace-nowrap px-5 h-6 w-35 md:w-30">{ config.name }</span>
|
||||||
<Tag className="proxy-group-type">{ config.type }</Tag>
|
<Tag className="mr-5 md:mr-0">{ config.type }</Tag>
|
||||||
</div>
|
</div>
|
||||||
<div className="proxy-group-tags-container">
|
<div className="pt-1 pb-3 md:py-4">
|
||||||
<Tags
|
<Tags
|
||||||
className="proxy-group-tags"
|
className="ml-5 md:ml-8"
|
||||||
data={config.all}
|
data={config.all}
|
||||||
onClick={handleChangeProxySelected}
|
onClick={handleChangeProxySelected}
|
||||||
errSet={errSet}
|
errSet={errSet}
|
||||||
|
@ -5,21 +5,6 @@
|
|||||||
color: $color-black-light;
|
color: $color-black-light;
|
||||||
}
|
}
|
||||||
|
|
||||||
.proxy-group-part {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.proxy-group-name {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
padding: 0 20px;
|
|
||||||
width: 120px;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.proxies-group-item {
|
.proxies-group-item {
|
||||||
border-bottom: 1px solid $color-gray;
|
border-bottom: 1px solid $color-gray;
|
||||||
|
|
||||||
@ -28,40 +13,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.proxy-group-tags-container {
|
|
||||||
padding: 15px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.proxy-group-tags {
|
|
||||||
flex: 1;
|
|
||||||
margin-left: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.proxy-group {
|
.proxy-group {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.proxy-group-name {
|
|
||||||
width: 140px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.proxy-group-part {
|
|
||||||
width: 100%;
|
|
||||||
height: 42px;
|
|
||||||
margin-top: 6px;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.proxy-group-type {
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.proxy-group-tags-container {
|
|
||||||
padding: 5px 0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.proxy-group-tags {
|
|
||||||
margin-left: 20px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import * as React from 'react'
|
import React, { useMemo } from 'react'
|
||||||
import { useMemo } from 'react'
|
|
||||||
import { Card, Tag, Icon, Loading } from '@components'
|
import { Card, Tag, Icon, Loading } from '@components'
|
||||||
import { useI18n, useProxyProviders } from '@stores'
|
import { useI18n, useProxyProviders } from '@stores'
|
||||||
import { fromNow } from '@lib/date'
|
import { fromNow } from '@lib/date'
|
||||||
import { Provider as IProvider, Proxy as IProxy, updateProvider, healthCheckProvider } from '@lib/request'
|
import { Provider as IProvider, Proxy as IProxy, updateProvider, healthCheckProvider } from '@lib/request'
|
||||||
import { useVisible } from '@lib/hook'
|
import { useVisible } from '@lib/hook'
|
||||||
import { Proxy } from '../Proxy'
|
import { compareDesc } from '@containers/Proxies'
|
||||||
import { compareDesc } from '../../'
|
import { Proxy } from '@containers/Proxies/components/Proxy'
|
||||||
import './style.scss'
|
import './style.scss'
|
||||||
|
|
||||||
interface ProvidersProps {
|
interface ProvidersProps {
|
||||||
@ -39,18 +38,18 @@ export function Provider (props: ProvidersProps) {
|
|||||||
return (
|
return (
|
||||||
<Card className="proxy-provider">
|
<Card className="proxy-provider">
|
||||||
<Loading visible={visible} />
|
<Loading visible={visible} />
|
||||||
<div className="proxy-provider-header">
|
<div className="flex justify-between flex-col md:flex-row md:items-center">
|
||||||
<div className="proxy-provider-header-part">
|
<div className="flex items-center">
|
||||||
<span className="proxy-provider-name">{ provider.name }</span>
|
<span className="mr-6">{ provider.name }</span>
|
||||||
<Tag>{ provider.vehicleType }</Tag>
|
<Tag>{ provider.vehicleType }</Tag>
|
||||||
</div>
|
</div>
|
||||||
<div className="proxy-provider-header-part">
|
<div className="flex items-center pt-3 md:pt-0">
|
||||||
{
|
{
|
||||||
provider.updatedAt &&
|
provider.updatedAt &&
|
||||||
<span className="proxy-provider-update">{ `${t('providerUpdateTime')}: ${fromNow(new Date(provider.updatedAt), lang)}`}</span>
|
<span className="text-sm">{ `${t('providerUpdateTime')}: ${fromNow(new Date(provider.updatedAt), lang)}`}</span>
|
||||||
}
|
}
|
||||||
<Icon className="proxy-provider-icon healthcheck" type="healthcheck" size={18} onClick={handleHealthChech} />
|
<Icon className="pl-5 cursor-pointer text-red" type="healthcheck" size={18} onClick={handleHealthChech} />
|
||||||
<Icon className="proxy-provider-icon" type="update" size={18} onClick={handleUpdate} />
|
<Icon className="pl-5 cursor-pointer" type="update" size={18} onClick={handleUpdate} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul className="proxies-list">
|
<ul className="proxies-list">
|
||||||
|
@ -7,25 +7,6 @@
|
|||||||
color: $color-black-light;
|
color: $color-black-light;
|
||||||
}
|
}
|
||||||
|
|
||||||
.proxy-provider-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.proxy-provider-header-part {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.proxy-provider-name {
|
|
||||||
margin-right: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.proxy-provider-proxies {
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.proxy-provider-item {
|
.proxy-provider-item {
|
||||||
box-shadow: 0 0 24px 0 rgba(44, 138, 248, 0.2);
|
box-shadow: 0 0 24px 0 rgba(44, 138, 248, 0.2);
|
||||||
|
|
||||||
@ -33,28 +14,3 @@
|
|||||||
box-shadow: 0 0 24px 0 rgba(84, 117, 154, 0.4);
|
box-shadow: 0 0 24px 0 rgba(84, 117, 154, 0.4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.proxy-provider-update {
|
|
||||||
line-height: 14px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.proxy-provider-icon {
|
|
||||||
margin-left: 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&.healthcheck {
|
|
||||||
color: $color-red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.proxy-provider-header {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.proxy-provider-header-part {
|
|
||||||
margin: 6px 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { getLocalStorageItem, setLocalStorageItem } from '@lib/helper'
|
|
||||||
|
|
||||||
import en_US from './en_US'
|
import en_US from './en_US'
|
||||||
import zh_CN from './zh_CN'
|
import zh_CN from './zh_CN'
|
||||||
|
|
||||||
@ -10,34 +8,10 @@ export const Language = {
|
|||||||
|
|
||||||
export type Lang = keyof typeof Language
|
export type Lang = keyof typeof Language
|
||||||
|
|
||||||
const languageKey = 'language'
|
|
||||||
|
|
||||||
export const locales = Object.keys(Language)
|
export const locales = Object.keys(Language)
|
||||||
|
|
||||||
function getNavigatorLanguage (): string[] {
|
export function getDefaultLanguage (): Lang {
|
||||||
const found: string[] = []
|
for (const language of window.navigator.languages) {
|
||||||
|
|
||||||
if (window.navigator) {
|
|
||||||
if (window.navigator.languages) {
|
|
||||||
for (const lan of window.navigator.languages) {
|
|
||||||
found.push(lan)
|
|
||||||
}
|
|
||||||
} else if (window.navigator.language) {
|
|
||||||
found.push(navigator.language)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return found
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getLanguage (): Lang {
|
|
||||||
const localLanguage = getLocalStorageItem(languageKey)
|
|
||||||
if (localLanguage && locales.includes(localLanguage)) {
|
|
||||||
return localLanguage as Lang
|
|
||||||
}
|
|
||||||
|
|
||||||
const navigatorLanguage = getNavigatorLanguage()
|
|
||||||
for (const language of navigatorLanguage) {
|
|
||||||
if (language.includes('zh')) {
|
if (language.includes('zh')) {
|
||||||
return 'zh_CN'
|
return 'zh_CN'
|
||||||
} else if (language.includes('us')) {
|
} else if (language.includes('us')) {
|
||||||
@ -47,7 +21,3 @@ export function getLanguage (): Lang {
|
|||||||
|
|
||||||
return 'en_US'
|
return 'en_US'
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setLanguage (lang: Lang) {
|
|
||||||
setLocalStorageItem(languageKey, lang)
|
|
||||||
}
|
|
||||||
|
@ -6,10 +6,6 @@ export function setLocalStorageItem (key: string, value: string) {
|
|||||||
return window.localStorage.setItem(key, value)
|
return window.localStorage.setItem(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeLocalStorageItem (key: string) {
|
|
||||||
return window.localStorage.removeItem(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function noop () {}
|
export function noop () {}
|
||||||
|
|
||||||
export function getSearchParam(key: string) {
|
export function getSearchParam(key: string) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import axios, { AxiosError } from 'axios'
|
import axios, { AxiosError } from 'axios'
|
||||||
import { ResultAsync } from 'neverthrow'
|
import { ResultAsync } from 'neverthrow'
|
||||||
import { getLocalStorageItem, getSearchParam, to } from '@lib/helper'
|
import { getLocalStorageItem, getSearchParam } from '@lib/helper'
|
||||||
import { isClashX, jsBridge } from '@lib/jsBridge'
|
import { isClashX, jsBridge } from '@lib/jsBridge'
|
||||||
import { createAsyncSingleton } from '@lib/asyncSingleton'
|
import { createAsyncSingleton } from '@lib/asyncSingleton'
|
||||||
import { Log } from '@models/Log'
|
import { Log } from '@models/Log'
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import EventEmitter from 'eventemitter3'
|
import EventEmitter from 'eventemitter3'
|
||||||
import { SetRequired } from 'type-fest'
|
import { SetRequired } from 'type-fest'
|
||||||
import { ResultAsync } from 'neverthrow'
|
import { ResultAsync } from 'neverthrow'
|
||||||
import { to } from '@lib/helper'
|
|
||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
url: string
|
url: string
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { ResultAsync } from 'neverthrow'
|
import { ResultAsync } from 'neverthrow'
|
||||||
import { AxiosError } from 'axios'
|
import { AxiosError } from 'axios'
|
||||||
import { atom, useAtom } from 'jotai'
|
import { atom, useAtom } from 'jotai'
|
||||||
|
import { atomWithStorage } from 'jotai/utils'
|
||||||
import { atomWithImmer } from 'jotai/immer'
|
import { atomWithImmer } from 'jotai/immer'
|
||||||
import { useCallback, useEffect } from 'react'
|
import { useCallback, useEffect, useMemo } from 'react'
|
||||||
import { get } from 'lodash-es'
|
import { get } from 'lodash-es'
|
||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
|
|
||||||
import { getLanguage, Language, setLanguage, locales, Lang } from '@i18n'
|
import { Language, locales, Lang, getDefaultLanguage } from '@i18n'
|
||||||
import { useWarpImmerSetter } from '@lib/jotai'
|
import { useWarpImmerSetter } from '@lib/jotai'
|
||||||
import * as API from '@lib/request'
|
import * as API from '@lib/request'
|
||||||
import * as Models from '@models'
|
import * as Models from '@models'
|
||||||
@ -38,15 +39,11 @@ export function useIdentity () {
|
|||||||
return { identity: id, wrapFetcher, set }
|
return { identity: id, wrapFetcher, set }
|
||||||
}
|
}
|
||||||
|
|
||||||
const language = atom(getLanguage())
|
export const languageAtom = atomWithStorage<Lang | undefined>('language', undefined)
|
||||||
|
|
||||||
export function useI18n () {
|
export function useI18n () {
|
||||||
const [lang, set] = useAtom(language)
|
const [defaultLang, setLang] = useAtom(languageAtom)
|
||||||
|
const lang = useMemo(() => defaultLang ?? getDefaultLanguage(), [defaultLang])
|
||||||
function setLang (lang: Lang) {
|
|
||||||
set(lang)
|
|
||||||
setLanguage(lang)
|
|
||||||
}
|
|
||||||
|
|
||||||
const translation = useCallback(
|
const translation = useCallback(
|
||||||
function (namespace: keyof typeof Language['en_US']) {
|
function (namespace: keyof typeof Language['en_US']) {
|
||||||
|
@ -7,7 +7,8 @@ export default defineConfig({
|
|||||||
primary: {
|
primary: {
|
||||||
500: '#57befc',
|
500: '#57befc',
|
||||||
600: '#2c8af8'
|
600: '#2c8af8'
|
||||||
}
|
},
|
||||||
|
red: '#f56c6c'
|
||||||
},
|
},
|
||||||
textShadow: {
|
textShadow: {
|
||||||
primary: '0 0 6px rgb(44 138 248 / 40%)'
|
primary: '0 0 6px rgb(44 138 248 / 40%)'
|
||||||
|
16
yarn.lock
16
yarn.lock
@ -1634,10 +1634,10 @@ jiti@^1.10.1:
|
|||||||
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.10.1.tgz#bc2a175b9435274dc8659d3d9a121a91c6b3a1af"
|
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.10.1.tgz#bc2a175b9435274dc8659d3d9a121a91c6b3a1af"
|
||||||
integrity sha512-qux9juDtAC8HlZxAk/fku73ak4TWNLigRFTNzFShE/kw4bXVFsVu538vLXAxvNyPszXgpX4YxkXfwTYEi+zf5A==
|
integrity sha512-qux9juDtAC8HlZxAk/fku73ak4TWNLigRFTNzFShE/kw4bXVFsVu538vLXAxvNyPszXgpX4YxkXfwTYEi+zf5A==
|
||||||
|
|
||||||
jotai@^1.0.0:
|
jotai@^1.1.0:
|
||||||
version "1.0.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/jotai/-/jotai-1.0.0.tgz#d5e7f7044d89e543a9c7429a9723e11528b2760e"
|
resolved "https://registry.yarnpkg.com/jotai/-/jotai-1.1.0.tgz#a0f1afd15a187ab5578250d54a42bac999bfbaf9"
|
||||||
integrity sha512-6hZGy3hqIlBlLSKppTrxDc1Vb7mi3I8eEQOIu7Kj6ceX1PSzjxdsEVC9TjAqaio8gZJEz+2ufNUf4afvbs0RXg==
|
integrity sha512-+c/bMxS/c1LgsOYVfevOYLAu+WEgn85TJhmBoNSNHjMV+mTKZY0ACSyCrX1yz8KialK4+Ggm6d7Ek3sTXy8UgA==
|
||||||
|
|
||||||
js-cookie@^2.2.1:
|
js-cookie@^2.2.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
@ -2706,10 +2706,10 @@ uri-js@^4.2.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.0"
|
punycode "^2.1.0"
|
||||||
|
|
||||||
use-immer@^0.5.2:
|
use-immer@^0.6.0:
|
||||||
version "0.5.2"
|
version "0.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/use-immer/-/use-immer-0.5.2.tgz#5f61d5662eb0df192663bb78e200521858e92499"
|
resolved "https://registry.yarnpkg.com/use-immer/-/use-immer-0.6.0.tgz#ca6aa5ade93018e2c65cf128d19ada54fc23f70d"
|
||||||
integrity sha512-aHnLa85kftWo05lqJVOy3GLXrydqu6kl0MXvo5k5OW8IoLJixa9NY/48Xdy0LlcqdakBTFLbSDZaYVPMVhYy8Q==
|
integrity sha512-dFGRfvWCqPDTOt/S431ETYTg6+uxbpb7A1pptufwXVzGJY3RlXr38+3wyLNpc6SbbmAKjWl6+EP6uW74fkEsXQ==
|
||||||
|
|
||||||
v8-compile-cache@^2.0.3:
|
v8-compile-cache@^2.0.3:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user