'use client'; import { memo, useEffect, useState } from 'react'; import { AnimatePresence, motion } from 'motion/react'; import { useTranslations } from 'next-intl'; import { Button } from '@/components/ui/button'; import { Bell, Info, Maximize2, Minimize2, Moon, Search, Settings, Sun, } from 'lucide-react'; import { useUser } from '@/contexts/user-context'; import { useBellRing } from '@/contexts/bell-ring-context'; import { useNotificationSettings } from '@/contexts/notification-settings-context'; import { SidebarTrigger } from '@/components/ui/sidebar'; import { useTheme } from 'next-themes'; import { useRouter } from 'next/navigation'; import { SearchDialog } from '@/components/layout/search-dialog'; import { Kbd } from '@/components/ui/kbd'; import { LanguageSwitcher } from '@/components/common/language-switcher'; /** * 铃铛按钮组件 */ const BellButton = memo(function BellButton() { const { isRinging } = useBellRing(); const { showBell, isMounted } = useNotificationSettings(); const t = useTranslations('layout.header'); const [isClickAnimating, setIsClickAnimating] = useState(false); if (!isMounted) return null; if (!showBell) return null; const handleClick = () => { setIsClickAnimating(true); setTimeout(() => setIsClickAnimating(false), 600); }; return ( ); }); /** * 站点头部组件 * 用于显示站点头部 * * @example * ```tsx * * ``` */ export function SiteHeader({ isFullWidth = false, onToggleFullWidth, }: { isFullWidth?: boolean; onToggleFullWidth?: (value: boolean) => void; }) { const { user } = useUser(); const { setTheme, resolvedTheme } = useTheme(); const router = useRouter(); const t = useTranslations('layout.header'); const [mounted, setMounted] = useState(false); const [searchOpen, setSearchOpen] = useState(false); const [metaKey, setMetaKey] = useState('⌘'); useEffect(() => { setMounted(true); if ( typeof navigator !== 'undefined' && !navigator.userAgent?.includes('Mac') ) { setMetaKey('Ctrl'); } }, []); return (
{user?.need_change_password && (
{t('changePasswordBanner')}
)}
{user?.nickname || user?.username || t('guest')}
setSearchOpen(true)} >
{t('search')} {metaKey} K
{mounted && ( )}
); } function AppBanner() { const t = useTranslations('layout.header'); const [isVisible, setIsVisible] = useState(false); const bannerKey = 'ldc-banner-dismissed-script'; useEffect(() => { const dismissed = localStorage.getItem(bannerKey); if (!dismissed) { setIsVisible(true); } }, []); const handleDismiss = () => { localStorage.setItem(bannerKey, 'true'); setIsVisible(false); }; return ( {isVisible && (

{t('bannerTitle')} {t('bannerLink')}

)}
); }