import { useMemo, useEffect, useState } from 'react'; import { useShallow } from 'zustand/react/shallow'; import { BiSolidHeart } from 'react-icons/bi/index'; import { Howler } from 'howler'; import { useSoundStore } from '@/stores/sound'; import { Container } from '@/components/container'; import { StoreConsumer } from '@/components/store-consumer'; import { Buttons } from '@/components/buttons'; import { Categories } from '@/components/categories'; import { SharedModal } from '@/components/modals/shared'; import { Toolbar } from '@/components/toolbar'; import { SnackbarProvider } from '@/contexts/snackbar'; import { MediaControls } from '@/components/media-controls'; import { sounds } from '@/data/sounds'; import { FADE_OUT } from '@/constants/events'; import type { Sound } from '@/data/types'; import { subscribe } from '@/lib/event'; // 安全地获取localStorage function getLocalStorageItem(key: string, defaultValue: string = 'en'): string { if (typeof window !== 'undefined' && window.localStorage) { try { return localStorage.getItem(key) || defaultValue; } catch { return defaultValue; } } return defaultValue; } export function App() { const [currentLang, setCurrentLang] = useState('en'); const categories = useMemo(() => sounds.categories, []); const favorites = useSoundStore(useShallow(state => state.getFavorites())); const pause = useSoundStore(state => state.pause); const lock = useSoundStore(state => state.lock); const unlock = useSoundStore(state => state.unlock); // 在客户端初始化语言 useEffect(() => { const lang = getLocalStorageItem('moodist-language'); setCurrentLang(lang); // 监听语言变化 const handleLanguageChange = (event: CustomEvent) => { setCurrentLang(event.detail.language); }; window.addEventListener('languageChanged', handleLanguageChange as EventListener); return () => { window.removeEventListener('languageChanged', handleLanguageChange as EventListener); }; }, []); const favoriteSounds = useMemo(() => { const favoriteSounds = categories .map(category => category.sounds) .flat() .filter(sound => favorites.includes(sound.id)); /** * Reorder based on the order of favorites */ return favorites.map(favorite => favoriteSounds.find(sound => sound.id === favorite), ); }, [favorites, categories]); useEffect(() => { const onChange = () => { const { ctx } = Howler; if (ctx && !document.hidden) { setTimeout(() => { ctx.resume(); }, 100); } }; document.addEventListener('visibilitychange', onChange, false); return () => document.removeEventListener('visibilitychange', onChange); }, []); useEffect(() => { const unsubscribe = subscribe(FADE_OUT, (e: { duration: number }) => { lock(); setTimeout(() => { pause(); unlock(); }, e.duration); }); return unsubscribe; }, [pause, lock, unlock]); const allCategories = useMemo(() => { const favorites = []; if (favoriteSounds.length) { const favoritesTitle = currentLang === 'zh' ? '收藏' : 'Favorites'; favorites.push({ icon: , id: 'favorites', sounds: favoriteSounds as Array, title: favoritesTitle, }); } return [...favorites, ...categories]; }, [favoriteSounds, categories, currentLang]); return (
); }