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:
Tunglies
2026-07-13 11:29:25 +08:00
committed by GitHub
parent 6f9fb97b31
commit 7ca20fc4ed
44 changed files with 266 additions and 602 deletions
+5 -3
View File
@@ -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]
+25
View File
@@ -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
+185
View File
@@ -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
View File
@@ -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([
{