import { useState, useEffect } from 'react'; import { Box, Typography, Paper, Switch, Button, CircularProgress, Stack, IconButton, } from '@mui/material'; import RefreshIcon from '@mui/icons-material/Refresh'; import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import type { PageType } from '@/types/storage'; import { storageUtil } from '@/utils/chromeStorage'; import { getFeatureByKey, getDefaultPageOrder, getDefaultVisibleFeatureKeys, } from '@/config/features'; import GlobalSnackbar, { useSnackbarState } from '@/components/GlobalSnackbar'; import ErrorBoundary from '@/components/ErrorBoundary'; export default function App() { const [visiblePages, setVisiblePages] = useState([]); const [pageOrder, setPageOrder] = useState([]); const [isLoaded, setIsLoaded] = useState(false); const { snackbarProps, showMessage } = useSnackbarState(); useEffect(() => { loadConfig().catch(console.error); }, []); const loadConfig = async () => { try { const [savedVisible, savedOrder] = await Promise.all([ storageUtil.get('app/visiblePages', getDefaultVisibleFeatureKeys()), storageUtil.get('app/pageOrder', getDefaultPageOrder()), ]); setVisiblePages(savedVisible ?? getDefaultVisibleFeatureKeys()); setPageOrder(savedOrder && savedOrder.length > 0 ? savedOrder : getDefaultPageOrder()); } catch (error) { console.error('Failed to load config:', error); setVisiblePages(getDefaultVisibleFeatureKeys()); setPageOrder(getDefaultPageOrder()); } finally { setIsLoaded(true); } }; const handlePageToggle = async (page: PageType) => { const isCurrentlyVisible = visiblePages.includes(page); let newPages: PageType[]; if (isCurrentlyVisible) { if (visiblePages.length <= 1) { showToast('至少需要保留一个可见页面', 'warning'); return; } newPages = visiblePages.filter((p) => p !== page); } else { newPages = [...visiblePages, page]; } try { await storageUtil.set('app/visiblePages', newPages); setVisiblePages(newPages); const feature = getFeatureByKey(page); showToast(`已${isCurrentlyVisible ? '隐藏' : '显示'} ${feature?.label || page}`, 'success'); } catch (error) { console.error('Failed to save config:', error); showToast('保存失败', 'warning'); } }; const handleMove = async (index: number, direction: 'up' | 'down') => { if (direction === 'up' && index === 0) return; if (direction === 'down' && index === pageOrder.length - 1) return; const newOrder = [...pageOrder]; const swapIndex = direction === 'up' ? index - 1 : index + 1; [newOrder[index], newOrder[swapIndex]] = [newOrder[swapIndex], newOrder[index]]; try { await storageUtil.set('app/pageOrder', newOrder); setPageOrder(newOrder); } catch (error) { console.error('Failed to save order:', error); showToast('排序保存失败', 'warning'); } }; const handleRestoreDefaults = async () => { try { const { getDefaultVisibleFeatureKeys } = await import('@/config/features'); const defaults = getDefaultVisibleFeatureKeys(); const defaultOrder = getDefaultPageOrder(); await Promise.all([ storageUtil.set('app/visiblePages', defaults), storageUtil.set('app/pageOrder', defaultOrder), ]); setVisiblePages(defaults); setPageOrder(defaultOrder); showToast('已恢复默认', 'success'); } catch (error) { console.error('Failed to restore defaults:', error); showToast('恢复失败', 'warning'); } }; const showToast = (message: string, severity: 'success' | 'info' | 'warning') => { showMessage(message, { severity }); }; if (!isLoaded) { return ( ); } return ( {pageOrder.map((key, index, array) => { const feature = getFeatureByKey(key); if (!feature) return null; const isChecked = visiblePages.includes(key); const isDisabled = isChecked && visiblePages.length === 1; return ( {feature.label} {isChecked ? '已在 Dashboard 启用' : '已在 Dashboard 隐藏'} handleMove(index, 'up')} disabled={index === 0} sx={{ color: 'text.secondary' }} > handleMove(index, 'down')} disabled={index === array.length - 1} sx={{ color: 'text.secondary' }} > handlePageToggle(key)} disabled={isDisabled} /> ); })} ); }