chore: trim excessive comments

This commit is contained in:
wonfen
2026-08-19 07:27:43 +08:00
parent 42b91b6294
commit 807f9a206d
103 changed files with 293 additions and 2517 deletions
-18
View File
@@ -26,7 +26,6 @@ import { useAppRefreshers, useProxiesData } from '@/providers/app-data-context'
import { showNotice } from '@/services/notice-service'
import parseTraffic from '@/utils/parse-traffic'
// 样式化组件 - 类型框
const TypeBox = styled(Box)<{ component?: React.ElementType }>(({ theme }) => ({
display: 'inline-block',
border: '1px solid #ccc',
@@ -39,7 +38,6 @@ const TypeBox = styled(Box)<{ component?: React.ElementType }>(({ theme }) => ({
lineHeight: 1.25,
}))
// 解析过期时间
const parseExpire = (expire?: number) => {
if (!expire) return '-'
return dayjs(expire * 1000).format('YYYY-MM-DD')
@@ -54,15 +52,12 @@ export const ProviderButton = () => {
const providers = proxyView?.providers ?? []
const providerUnavailable = proxyView?.providerState === 'unavailable'
// 更新单个代理提供者
const updateProvider = useLockFn(async (name: string) => {
try {
// 设置更新状态
setUpdating((prev) => ({ ...prev, [name]: true }))
await updateProxyProvider(name)
// 刷新数据
await refreshProxy()
showNotice.success(
@@ -77,22 +72,18 @@ export const ProviderButton = () => {
message: String(err),
})
} finally {
// 清除更新状态
setUpdating((prev) => ({ ...prev, [name]: false }))
}
})
// 更新所有代理提供者
const updateAllProviders = useLockFn(async () => {
try {
// 获取所有provider的名称
const allProviders = providers.map(({ name }) => name)
if (allProviders.length === 0) {
showNotice.info('proxies.feedback.notifications.provider.none')
return
}
// 设置所有provider为更新中状态
const newUpdating = allProviders.reduce(
(acc, key) => {
acc[key] = true
@@ -102,19 +93,15 @@ export const ProviderButton = () => {
)
setUpdating(newUpdating)
// 改为串行逐个更新所有provider
for (const name of allProviders) {
try {
await updateProxyProvider(name)
// 每个更新完成后更新状态
setUpdating((prev) => ({ ...prev, [name]: false }))
} catch (err) {
console.error(`更新 ${name} 失败`, err)
// 继续执行下一个,不中断整体流程
}
}
// 刷新数据
await refreshProxy()
showNotice.success('proxies.feedback.notifications.provider.allUpdated')
@@ -123,7 +110,6 @@ export const ProviderButton = () => {
message: String(err),
})
} finally {
// 清除所有更新状态
setUpdating({})
}
})
@@ -190,7 +176,6 @@ export const ProviderButton = () => {
: null
const isUpdating = updating[key]
// 订阅信息
const sub = provider.subscriptionInfo
const hasSubInfo = !!sub
const upload = sub?.upload || 0
@@ -198,7 +183,6 @@ export const ProviderButton = () => {
const total = sub?.total || 0
const expire = sub?.expire || 0
// 流量使用进度
const progress =
total > 0
? Math.min(
@@ -272,7 +256,6 @@ export const ProviderButton = () => {
}
secondary={
<>
{/* 订阅信息 */}
{hasSubInfo && (
<>
<Box
@@ -296,7 +279,6 @@ export const ProviderButton = () => {
</span>
</Box>
{/* 进度条 */}
<LinearProgress
variant="determinate"
value={progress}
@@ -23,14 +23,7 @@ interface ProxyListStateInput {
const isSubscriptionProfile = (item: { type?: string }): boolean =>
item.type === 'remote' || item.type === 'local'
/**
* What the proxy page should show.
*
* Deliberately does *not* answer "is there anything to render". That question is answered by
* the list itself, in `hasRenderableItems`, because predicting it from beside the renderer is
* how the two came to disagree. This decides only the things knowable without building a list:
* direct mode, still-loading, and having no usable subscription to render from.
*/
/** Decides only pre-render states; the built list owns whether it has renderable content. */
export type ProxyListState =
| { kind: 'direct' }
| { kind: 'loading' }
@@ -67,12 +60,7 @@ export const resolveProxyListState = ({
return { kind: 'render' }
}
/**
* Why a list that turned out to be empty is empty.
*
* Only reachable once the renderer has built its list and found nothing, so it explains an
* observed emptiness rather than predicting one.
*/
/** Explains an empty list only after the renderer observes it. */
export const resolveEmptyListReason = ({
runningMode,
isProxyViewError,
+2 -24
View File
@@ -65,11 +65,6 @@ interface Props {
chainConfigData?: string | null
}
/**
* The empty state to draw when the render list turns out to contain nothing.
*
* Shared by both list components so the observation and its explanation stay together.
*/
function useEmptyRenderList() {
const { isProxyViewError } = useProxiesData()
const { runningMode } = useSystemData()
@@ -103,7 +98,6 @@ function useProxyRenderState(
const timeout = verge?.default_latency_timeout || 10000
// 测全部延迟
const handleCheckAll = useStableCallback(
useLockFn(async (groupName: string) => {
debugLog(`[ProxyGroups] 开始测试所有延迟,组: ${groupName}`)
@@ -133,8 +127,6 @@ function useProxyRenderState(
} catch (error) {
console.error(`[ProxyGroups] 延迟测试出错,组: ${groupName}`, error)
} finally {
// Re-sorting is no longer poked from here: the delay store announces that the test
// settled and the render list recomputes from that.
onProxies()
}
}),
@@ -254,7 +246,6 @@ function ChainProxyGroups(props: {
const virtualItems = virtualizer.getVirtualItems()
const activeStickyIndex = activeStickyIndexRef.current
// 从 localStorage 恢复滚动位置
useLayoutEffect(() => {
if (renderList.length === 0) return
const node = parentRef.current
@@ -335,7 +326,6 @@ function ChainProxyGroups(props: {
}
})
// The list is built; whether it holds anything is now an observation, not a guess.
if (!hasRenderableItems(renderList)) return emptyList
return (
@@ -376,11 +366,9 @@ function NormalProxyGroups(props: { mode: string }) {
} = useProxyRenderState(mode, false, null)
const emptyList = useEmptyRenderList()
const renderFirstRef = useRef(true)
// 恢复滚动位置期间设为 true,避免程序化滚动触发的 scroll 事件把中间值写回存储
// Do not persist intermediate positions produced while restoring virtual scroll.
const isRestoringRef = useRef(false)
// 目前无法使用 StickyVirtualList 的 initialOffset 值设置初始化,具体原因需排查
// 从 localStorage 恢复滚动位置
useLayoutEffect(() => {
if (renderList.length === 0) return
if (!renderFirstRef.current) return
@@ -388,15 +376,12 @@ function NormalProxyGroups(props: { mode: string }) {
if (!node) return
const savedPosition = getScrollPosition()
// 未保存过位置或位置为 0(顶部)时无需恢复
if (!savedPosition) {
renderFirstRef.current = false
return
}
// 虚拟列表初始使用预估高度,真实高度测量完成后总高度才会稳定。
// 尤其是过滤后节点数变少时,预估总高度常常不足以一次性滚动到目标位置,
// 因此跨帧重试,直到到达目标位置(或内容确实不够高)为止。
// Retry across frames until virtual-list measurements can reach the saved offset.
isRestoringRef.current = true
let rafId = 0
let attempts = 0
@@ -436,7 +421,6 @@ function NormalProxyGroups(props: { mode: string }) {
const handleScroll = useCallback(
(event: Event) => {
// 恢复位置过程中产生的滚动不写回存储,避免中间的钳制值覆盖真实位置
if (isRestoringRef.current) return
const target = event.target as HTMLElement | null
const nextScrollTop = target?.scrollTop ?? 0
@@ -480,7 +464,6 @@ function NormalProxyGroups(props: { mode: string }) {
[handleProxyGroupChange],
)
// 滚到对应的节点
const handleLocation = useStableCallback((group: ProxyGroupView) => {
if (!group) return
const { name, now } = group
@@ -501,7 +484,6 @@ function NormalProxyGroups(props: { mode: string }) {
}
})
// 定位到指定的代理组
const handleGroupLocationByName = useCallback(
(groupName: string) => {
const index = renderList.findIndex(
@@ -525,7 +507,6 @@ function NormalProxyGroups(props: { mode: string }) {
return Array.from(new Set(names))
}, [renderList])
// 点击代理组改变展开状态,先滚动到sticky的代理组位置,再收起展开状态
const handleGroupToggle = useCallback(
async (group: ProxyGroupView) => {
const index = renderList.findIndex(
@@ -589,7 +570,6 @@ function NormalProxyGroups(props: { mode: string }) {
[handleChangeProxy, handleCheckAll, onHeadState, handleLocation],
)
// The list is built; whether it holds anything is now an observation, not a guess.
if (!hasRenderableItems(renderList)) return emptyList
return (
@@ -605,7 +585,6 @@ function NormalProxyGroups(props: { mode: string }) {
renderItem={renderProxyItem}
/>
{/* 代理组导航栏 */}
{mode === 'rule' && (
<ProxyGroupNavigator
proxyGroupNames={proxyGroupNames}
@@ -640,7 +619,6 @@ export const ProxyGroups = (props: Props) => {
case 'empty':
return <ProxyEmptyState reason={listState.reason} />
case 'render':
// Whether there is anything to draw is the list's own answer, given below.
return isChainMode ? (
<ChainProxyGroups mode={mode} chainConfigData={chainConfigData} />
) : (
-11
View File
@@ -5,7 +5,6 @@ import { compileStringMatcher } from '@/utils/search-matcher'
import type { ResolvedMemberOccurrence } from './use-render-list'
// default | delay | alphabet
export type ProxySortType = 0 | 1 | 2
export type ProxySearchState = {
@@ -27,16 +26,9 @@ export function filterSort(
return sp
}
/**
* 可以通过延迟数/节点类型 过滤
*/
const regex1 = /delay([=<>])(\d+|timeout|error)/i
const regex2 = /type=(.*)/i
/**
* filter the proxy
* according to the regular conditions
*/
function filterProxies(
proxies: ResolvedMemberOccurrence[],
groupName: string,
@@ -90,9 +82,6 @@ function filterProxies(
return proxies.filter(({ member }) => compiled.matcher(member.ref.name))
}
/**
* sort the proxy
*/
function sortProxies(
proxies: ResolvedMemberOccurrence[],
groupName: string,
+2 -8
View File
@@ -5,21 +5,18 @@ import { hasRenderableItems, type IRenderItem } from './use-render-list'
const group = (hidden = false) =>
({ name: 'Proxies', hidden }) as unknown as IRenderItem['group']
/** A group header row. On its own it is only content when the group is visible. */
const header = (hidden = false): IRenderItem => ({
type: 0,
key: 'header',
group: group(hidden),
})
/** A member row — in chain mode the list is made entirely of these. */
const member = (key: string): IRenderItem => ({
type: 2,
key,
group: group(),
})
/** A column of members, which is how the chain list renders at column counts above one. */
const memberColumn = (key: string): IRenderItem => ({
type: 4,
key,
@@ -32,9 +29,7 @@ describe('hasRenderableItems', () => {
})
test('chain mode is answered by the chain list itself', () => {
// This is the case the old prediction got wrong in both directions: it asked whether any
// Selector or URLTest group existed, which is unrelated to what the chain list is built
// from. Here there are rows, so there is content, whatever groups happen to exist.
// Rendered rows, not group types, determine whether chain mode is empty.
expect(hasRenderableItems([member('chain:a')])).toBe(true)
expect(hasRenderableItems([memberColumn('chain-col:a')])).toBe(true)
})
@@ -54,8 +49,7 @@ describe('hasRenderableItems', () => {
})
test('rows inside a hidden but expanded group are still rows on screen', () => {
// Truthfulness over tidiness: the user can see these, so calling the page empty would be
// a lie. The old predicate said "empty" here.
// Visible member rows mean the page is not empty even without a visible group header.
expect(hasRenderableItems([header(true), member('member:a')])).toBe(true)
})
})