mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-08 02:52:07 +08:00
refactor: knip cleanup (#7468)
* chore(frontend): expand Knip reports * chore: remove unused Mihomo changelog sync script * refactor: remove unused value exports * refactor: remove unused type exports * refactor: remove circular route dependencies * chore(frontend): move Knip scope to config * chore(i18n): remove stale portable update message
This commit is contained in:
@@ -62,13 +62,15 @@ import {
|
||||
useNavMenuOrder,
|
||||
} from './_layout/hooks'
|
||||
import { handleNoticeMessage } from './_layout/utils'
|
||||
import { navItems, preloadLogsPage, preloadNavigationRoutes } from './_routers'
|
||||
import {
|
||||
navItems,
|
||||
preloadLogsPage,
|
||||
preloadNavigationRoutes,
|
||||
} from './_navigation'
|
||||
|
||||
import 'dayjs/locale/ru'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
|
||||
export const portableFlag = false
|
||||
|
||||
const LogsPage = lazy(() => preloadLogsPage())
|
||||
|
||||
type NavItem = (typeof navItems)[number]
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
export const navigationItems = {
|
||||
home: { label: 'layout.components.navigation.tabs.home', path: '/' },
|
||||
proxies: {
|
||||
label: 'layout.components.navigation.tabs.proxies',
|
||||
path: '/proxies',
|
||||
},
|
||||
profiles: {
|
||||
label: 'layout.components.navigation.tabs.profiles',
|
||||
path: '/profile',
|
||||
},
|
||||
connections: {
|
||||
label: 'layout.components.navigation.tabs.connections',
|
||||
path: '/connections',
|
||||
},
|
||||
rules: { label: 'layout.components.navigation.tabs.rules', path: '/rules' },
|
||||
logs: { label: 'layout.components.navigation.tabs.logs', path: '/logs' },
|
||||
unlock: {
|
||||
label: 'layout.components.navigation.tabs.unlock',
|
||||
path: '/unlock',
|
||||
},
|
||||
settings: {
|
||||
label: 'layout.components.navigation.tabs.settings',
|
||||
path: '/settings',
|
||||
},
|
||||
} as const
|
||||
@@ -0,0 +1,185 @@
|
||||
import DnsRoundedIcon from '@mui/icons-material/DnsRounded'
|
||||
import ForkRightRoundedIcon from '@mui/icons-material/ForkRightRounded'
|
||||
import HomeRoundedIcon from '@mui/icons-material/HomeRounded'
|
||||
import LanguageRoundedIcon from '@mui/icons-material/LanguageRounded'
|
||||
import LockOpenRoundedIcon from '@mui/icons-material/LockOpenRounded'
|
||||
import SettingsRoundedIcon from '@mui/icons-material/SettingsRounded'
|
||||
import SubjectRoundedIcon from '@mui/icons-material/SubjectRounded'
|
||||
import WifiRoundedIcon from '@mui/icons-material/WifiRounded'
|
||||
import { Box } from '@mui/material'
|
||||
import { lazy, Suspense, type ComponentType, type ReactNode } from 'react'
|
||||
|
||||
import ConnectionsSvg from '@/assets/image/itemicon/connections.svg?react'
|
||||
import HomeSvg from '@/assets/image/itemicon/home.svg?react'
|
||||
import LogsSvg from '@/assets/image/itemicon/logs.svg?react'
|
||||
import ProfilesSvg from '@/assets/image/itemicon/profiles.svg?react'
|
||||
import ProxiesSvg from '@/assets/image/itemicon/proxies.svg?react'
|
||||
import RulesSvg from '@/assets/image/itemicon/rules.svg?react'
|
||||
import SettingsSvg from '@/assets/image/itemicon/settings.svg?react'
|
||||
import UnlockSvg from '@/assets/image/itemicon/unlock.svg?react'
|
||||
import { BaseLoading } from '@/components/base'
|
||||
import { ensureLanguageSections } from '@/services/i18n'
|
||||
|
||||
import { navigationItems } from './_navigation-meta'
|
||||
import HomePage from './home'
|
||||
|
||||
type NavigationItem = {
|
||||
label: (typeof navigationItems)[keyof typeof navigationItems]['label']
|
||||
path: string
|
||||
icon: ReactNode[]
|
||||
Component: ComponentType
|
||||
preload?: () => Promise<{ default: ComponentType }>
|
||||
}
|
||||
|
||||
const waitForWarmupIdle = (signal: AbortSignal) =>
|
||||
new Promise<void>((resolve) => {
|
||||
let idleId: number | undefined
|
||||
let timeoutId: number | undefined
|
||||
|
||||
const cleanup = () => {
|
||||
signal.removeEventListener('abort', finish)
|
||||
if (idleId !== undefined) {
|
||||
window.cancelIdleCallback(idleId)
|
||||
}
|
||||
if (timeoutId !== undefined) {
|
||||
window.clearTimeout(timeoutId)
|
||||
}
|
||||
}
|
||||
|
||||
const finish = () => {
|
||||
cleanup()
|
||||
resolve()
|
||||
}
|
||||
|
||||
if (signal.aborted) {
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
|
||||
signal.addEventListener('abort', finish, { once: true })
|
||||
|
||||
if (window.requestIdleCallback) {
|
||||
idleId = window.requestIdleCallback(finish, { timeout: 500 })
|
||||
} else {
|
||||
timeoutId = window.setTimeout(finish, 120)
|
||||
}
|
||||
})
|
||||
|
||||
const createRoutePreload = (
|
||||
load: () => Promise<{ default: ComponentType }>,
|
||||
sections?: string | readonly string[],
|
||||
) => {
|
||||
let componentPromise: Promise<{ default: ComponentType }> | undefined
|
||||
|
||||
const loadComponent = () => {
|
||||
componentPromise ??= load().catch((error) => {
|
||||
componentPromise = undefined
|
||||
throw error
|
||||
})
|
||||
|
||||
return componentPromise
|
||||
}
|
||||
|
||||
if (!sections) {
|
||||
return loadComponent
|
||||
}
|
||||
|
||||
return async () => {
|
||||
const [component] = await Promise.all([
|
||||
loadComponent(),
|
||||
ensureLanguageSections(sections),
|
||||
])
|
||||
return component
|
||||
}
|
||||
}
|
||||
|
||||
const createLazyRoute = (
|
||||
load: () => Promise<{ default: ComponentType }>,
|
||||
sections?: string | readonly string[],
|
||||
) => {
|
||||
const preload = createRoutePreload(load, sections)
|
||||
const Component = lazy(preload)
|
||||
const LazyRoute = () => (
|
||||
<Suspense
|
||||
fallback={
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
height: '100%',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<BaseLoading />
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<Component />
|
||||
</Suspense>
|
||||
)
|
||||
|
||||
return { Component: LazyRoute, preload }
|
||||
}
|
||||
|
||||
export const preloadLogsPage = createRoutePreload(
|
||||
() => import('./logs'),
|
||||
'logs',
|
||||
)
|
||||
|
||||
export const navItems: NavigationItem[] = [
|
||||
{
|
||||
...navigationItems.home,
|
||||
icon: [<HomeRoundedIcon key="mui" />, <HomeSvg key="svg" />],
|
||||
Component: HomePage,
|
||||
},
|
||||
{
|
||||
...navigationItems.proxies,
|
||||
icon: [<WifiRoundedIcon key="mui" />, <ProxiesSvg key="svg" />],
|
||||
...createLazyRoute(() => import('./proxies')),
|
||||
},
|
||||
{
|
||||
...navigationItems.profiles,
|
||||
icon: [<DnsRoundedIcon key="mui" />, <ProfilesSvg key="svg" />],
|
||||
...createLazyRoute(() => import('./profiles'), 'rules'),
|
||||
},
|
||||
{
|
||||
...navigationItems.connections,
|
||||
icon: [<LanguageRoundedIcon key="mui" />, <ConnectionsSvg key="svg" />],
|
||||
...createLazyRoute(() => import('./connections'), 'connections'),
|
||||
},
|
||||
{
|
||||
...navigationItems.rules,
|
||||
icon: [<ForkRightRoundedIcon key="mui" />, <RulesSvg key="svg" />],
|
||||
...createLazyRoute(() => import('./rules'), 'rules'),
|
||||
},
|
||||
{
|
||||
...navigationItems.logs,
|
||||
icon: [<SubjectRoundedIcon key="mui" />, <LogsSvg key="svg" />],
|
||||
Component: () => null /* LogsPage rendered in Layout only on /logs route */,
|
||||
preload: preloadLogsPage,
|
||||
},
|
||||
{
|
||||
...navigationItems.unlock,
|
||||
icon: [<LockOpenRoundedIcon key="mui" />, <UnlockSvg key="svg" />],
|
||||
...createLazyRoute(() => import('./unlock')),
|
||||
},
|
||||
{
|
||||
...navigationItems.settings,
|
||||
icon: [<SettingsRoundedIcon key="mui" />, <SettingsSvg key="svg" />],
|
||||
...createLazyRoute(() => import('./settings')),
|
||||
},
|
||||
]
|
||||
|
||||
export const preloadNavigationRoutes = async (signal: AbortSignal) => {
|
||||
await waitForWarmupIdle(signal)
|
||||
if (signal.aborted) {
|
||||
return
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
navItems.map((item) => {
|
||||
const preload = 'preload' in item ? item.preload : undefined
|
||||
return preload?.().catch(() => {})
|
||||
}),
|
||||
)
|
||||
}
|
||||
+1
-183
@@ -1,189 +1,7 @@
|
||||
import DnsRoundedIcon from '@mui/icons-material/DnsRounded'
|
||||
import ForkRightRoundedIcon from '@mui/icons-material/ForkRightRounded'
|
||||
import HomeRoundedIcon from '@mui/icons-material/HomeRounded'
|
||||
import LanguageRoundedIcon from '@mui/icons-material/LanguageRounded'
|
||||
import LockOpenRoundedIcon from '@mui/icons-material/LockOpenRounded'
|
||||
import SettingsRoundedIcon from '@mui/icons-material/SettingsRounded'
|
||||
import SubjectRoundedIcon from '@mui/icons-material/SubjectRounded'
|
||||
import WifiRoundedIcon from '@mui/icons-material/WifiRounded'
|
||||
import { Box } from '@mui/material'
|
||||
import { lazy, Suspense, type ComponentType } from 'react'
|
||||
import { createBrowserRouter, RouteObject } from 'react-router'
|
||||
|
||||
import ConnectionsSvg from '@/assets/image/itemicon/connections.svg?react'
|
||||
import HomeSvg from '@/assets/image/itemicon/home.svg?react'
|
||||
import LogsSvg from '@/assets/image/itemicon/logs.svg?react'
|
||||
import ProfilesSvg from '@/assets/image/itemicon/profiles.svg?react'
|
||||
import ProxiesSvg from '@/assets/image/itemicon/proxies.svg?react'
|
||||
import RulesSvg from '@/assets/image/itemicon/rules.svg?react'
|
||||
import SettingsSvg from '@/assets/image/itemicon/settings.svg?react'
|
||||
import UnlockSvg from '@/assets/image/itemicon/unlock.svg?react'
|
||||
import { BaseLoading } from '@/components/base'
|
||||
import { ensureLanguageSections } from '@/services/i18n'
|
||||
|
||||
import Layout from './_layout'
|
||||
import HomePage from './home'
|
||||
|
||||
const waitForWarmupIdle = (signal: AbortSignal) =>
|
||||
new Promise<void>((resolve) => {
|
||||
let idleId: number | undefined
|
||||
let timeoutId: number | undefined
|
||||
|
||||
const cleanup = () => {
|
||||
signal.removeEventListener('abort', finish)
|
||||
if (idleId !== undefined) {
|
||||
window.cancelIdleCallback(idleId)
|
||||
}
|
||||
if (timeoutId !== undefined) {
|
||||
window.clearTimeout(timeoutId)
|
||||
}
|
||||
}
|
||||
|
||||
const finish = () => {
|
||||
cleanup()
|
||||
resolve()
|
||||
}
|
||||
|
||||
if (signal.aborted) {
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
|
||||
signal.addEventListener('abort', finish, { once: true })
|
||||
|
||||
if (window.requestIdleCallback) {
|
||||
idleId = window.requestIdleCallback(finish, { timeout: 500 })
|
||||
} else {
|
||||
timeoutId = window.setTimeout(finish, 120)
|
||||
}
|
||||
})
|
||||
|
||||
const createRoutePreload = (
|
||||
load: () => Promise<{ default: ComponentType }>,
|
||||
sections?: string | readonly string[],
|
||||
) => {
|
||||
let componentPromise: Promise<{ default: ComponentType }> | undefined
|
||||
|
||||
const loadComponent = () => {
|
||||
componentPromise ??= load().catch((error) => {
|
||||
componentPromise = undefined
|
||||
throw error
|
||||
})
|
||||
|
||||
return componentPromise
|
||||
}
|
||||
|
||||
if (!sections) {
|
||||
return loadComponent
|
||||
}
|
||||
|
||||
return async () => {
|
||||
const [component] = await Promise.all([
|
||||
loadComponent(),
|
||||
ensureLanguageSections(sections),
|
||||
])
|
||||
return component
|
||||
}
|
||||
}
|
||||
|
||||
const createLazyRoute = (
|
||||
load: () => Promise<{ default: ComponentType }>,
|
||||
sections?: string | readonly string[],
|
||||
) => {
|
||||
const preload = createRoutePreload(load, sections)
|
||||
const Component = lazy(preload)
|
||||
const LazyRoute = () => (
|
||||
<Suspense
|
||||
fallback={
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
height: '100%',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<BaseLoading />
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<Component />
|
||||
</Suspense>
|
||||
)
|
||||
|
||||
return { Component: LazyRoute, preload }
|
||||
}
|
||||
|
||||
export const preloadLogsPage = createRoutePreload(
|
||||
() => import('./logs'),
|
||||
'logs',
|
||||
)
|
||||
|
||||
export const navItems = [
|
||||
{
|
||||
label: 'layout.components.navigation.tabs.home',
|
||||
path: '/',
|
||||
icon: [<HomeRoundedIcon key="mui" />, <HomeSvg key="svg" />],
|
||||
Component: HomePage,
|
||||
},
|
||||
{
|
||||
label: 'layout.components.navigation.tabs.proxies',
|
||||
path: '/proxies',
|
||||
icon: [<WifiRoundedIcon key="mui" />, <ProxiesSvg key="svg" />],
|
||||
...createLazyRoute(() => import('./proxies')),
|
||||
},
|
||||
{
|
||||
label: 'layout.components.navigation.tabs.profiles',
|
||||
path: '/profile',
|
||||
icon: [<DnsRoundedIcon key="mui" />, <ProfilesSvg key="svg" />],
|
||||
...createLazyRoute(() => import('./profiles'), 'rules'),
|
||||
},
|
||||
{
|
||||
label: 'layout.components.navigation.tabs.connections',
|
||||
path: '/connections',
|
||||
icon: [<LanguageRoundedIcon key="mui" />, <ConnectionsSvg key="svg" />],
|
||||
...createLazyRoute(() => import('./connections'), 'connections'),
|
||||
},
|
||||
{
|
||||
label: 'layout.components.navigation.tabs.rules',
|
||||
path: '/rules',
|
||||
icon: [<ForkRightRoundedIcon key="mui" />, <RulesSvg key="svg" />],
|
||||
...createLazyRoute(() => import('./rules'), 'rules'),
|
||||
},
|
||||
{
|
||||
label: 'layout.components.navigation.tabs.logs',
|
||||
path: '/logs',
|
||||
icon: [<SubjectRoundedIcon key="mui" />, <LogsSvg key="svg" />],
|
||||
Component: () => null /* LogsPage rendered in Layout only on /logs route */,
|
||||
preload: preloadLogsPage,
|
||||
},
|
||||
{
|
||||
label: 'layout.components.navigation.tabs.unlock',
|
||||
path: '/unlock',
|
||||
icon: [<LockOpenRoundedIcon key="mui" />, <UnlockSvg key="svg" />],
|
||||
...createLazyRoute(() => import('./unlock')),
|
||||
},
|
||||
{
|
||||
label: 'layout.components.navigation.tabs.settings',
|
||||
path: '/settings',
|
||||
icon: [<SettingsRoundedIcon key="mui" />, <SettingsSvg key="svg" />],
|
||||
...createLazyRoute(() => import('./settings')),
|
||||
},
|
||||
]
|
||||
|
||||
export const preloadNavigationRoutes = async (signal: AbortSignal) => {
|
||||
await waitForWarmupIdle(signal)
|
||||
if (signal.aborted) {
|
||||
return
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
navItems.map((item) => {
|
||||
const preload = 'preload' in item ? item.preload : undefined
|
||||
return preload?.().catch(() => {})
|
||||
}),
|
||||
)
|
||||
}
|
||||
import { navItems } from './_navigation'
|
||||
|
||||
export const router = createBrowserRouter([
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user