import { Box } from '@mui/material' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { BaseEmpty, BasePage, BaseSearchBox, VirtualList, type VirtualListHandle, } from '@/components/base' import { ScrollTopButton } from '@/components/layout/scroll-top-button' import { ProviderButton } from '@/components/rule/provider-button' import RuleItem from '@/components/rule/rule-item' import { useVisibility } from '@/hooks/use-visibility' import { useAppData } from '@/providers/app-data-context' const RulesPage = () => { const { t } = useTranslation() const { rules = [], refreshRules, refreshRuleProviders } = useAppData() const [match, setMatch] = useState(() => (_: string) => true) const virtuosoRef = useRef(null) const [showScrollTop, setShowScrollTop] = useState(false) const pageVisible = useVisibility() // 在组件挂载时和页面获得焦点时刷新规则数据 useEffect(() => { refreshRules() refreshRuleProviders() if (pageVisible) { refreshRules() refreshRuleProviders() } }, [refreshRules, refreshRuleProviders, pageVisible]) const filteredRules = useMemo(() => { const rulesWithLineNo = rules.map((item, index) => ({ ...item, // UI-only derived data; keep app context/SWR data immutable lineNo: index + 1, })) return rulesWithLineNo.filter((item) => match(item.payload ?? '')) }, [rules, match]) const handleScroll = useCallback((e: Event) => { setShowScrollTop((e.target as HTMLElement).scrollTop > 100) }, []) const scrollToTop = () => { virtuosoRef.current?.scrollTo({ top: 0, behavior: 'smooth' }) } return ( } > setMatch(() => match)} /> {filteredRules && filteredRules.length > 0 ? ( <> } style={{ flex: 1 }} onScroll={handleScroll} /> ) : ( )} ) } export default RulesPage