mirror of
https://github.com/remvze/moodist.git
synced 2025-12-18 17:34:17 +00:00
feat: add selected sounds display module with complete functionality
- Create SelectedSoundsDisplay component to show selected sounds at the top of the page - Add displayMode parameter to Sound component for functionality in display mode - Implement complete audio controls including volume, speed, and rate progress bars - Add random effects support with proper interval management - Integrate multi-language support (Chinese: "当前声音", English: "Current Sounds") - Update App component to include the new display module - Use consistent styling with existing sound categories for seamless integration - Upgrade version to 2.3.0 for this feature release
This commit is contained in:
parent
e50b782361
commit
c1c4d894bc
6 changed files with 72 additions and 5 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "moodist",
|
"name": "moodist",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "2.2.0",
|
"version": "2.3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
"start": "astro dev",
|
"start": "astro dev",
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { useTranslation } from '@/hooks/useTranslation';
|
||||||
import { Container } from '@/components/container';
|
import { Container } from '@/components/container';
|
||||||
import { StoreConsumer } from '@/components/store-consumer';
|
import { StoreConsumer } from '@/components/store-consumer';
|
||||||
import { Buttons } from '@/components/buttons';
|
import { Buttons } from '@/components/buttons';
|
||||||
|
import { SelectedSoundsDisplay } from '@/components/selected-sounds-display';
|
||||||
import { Categories } from '@/components/categories';
|
import { Categories } from '@/components/categories';
|
||||||
import { SharedModal } from '@/components/modals/shared';
|
import { SharedModal } from '@/components/modals/shared';
|
||||||
import { Toolbar } from '@/components/toolbar';
|
import { Toolbar } from '@/components/toolbar';
|
||||||
|
|
@ -99,6 +100,7 @@ export function App() {
|
||||||
<Container>
|
<Container>
|
||||||
<div id="app" />
|
<div id="app" />
|
||||||
<Buttons />
|
<Buttons />
|
||||||
|
<SelectedSoundsDisplay />
|
||||||
<Categories categories={allCategories} />
|
<Categories categories={allCategories} />
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
|
|
|
||||||
1
src/components/selected-sounds-display/index.ts
Normal file
1
src/components/selected-sounds-display/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export { SelectedSoundsDisplay } from './selected-sounds-display';
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { AnimatePresence } from 'motion/react';
|
||||||
|
|
||||||
|
import { useSoundStore } from '@/stores/sound';
|
||||||
|
import { useLocalizedSounds } from '@/hooks/useLocalizedSounds';
|
||||||
|
import { useTranslation } from '@/hooks/useTranslation';
|
||||||
|
|
||||||
|
import { Sound } from '@/components/sounds/sound';
|
||||||
|
import styles from '../sounds/sounds.module.css';
|
||||||
|
|
||||||
|
export function SelectedSoundsDisplay() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const localizedCategories = useLocalizedSounds();
|
||||||
|
|
||||||
|
// 获取选中的声音
|
||||||
|
const selectedSoundIds = useSoundStore(state =>
|
||||||
|
Object.keys(state.sounds).filter(id => state.sounds[id].isSelected)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 获取选中的声音详细信息
|
||||||
|
const selectedSounds = useMemo(() => {
|
||||||
|
const allSounds = localizedCategories
|
||||||
|
.map(category => category.sounds)
|
||||||
|
.flat();
|
||||||
|
|
||||||
|
return selectedSoundIds
|
||||||
|
.map(id => allSounds.find(sound => sound.id === id))
|
||||||
|
.filter(Boolean);
|
||||||
|
}, [selectedSoundIds, localizedCategories]);
|
||||||
|
|
||||||
|
// 如果没有选中任何声音,不显示组件
|
||||||
|
if (selectedSounds.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.sounds}>
|
||||||
|
<AnimatePresence initial={false}>
|
||||||
|
{selectedSounds.map((sound) => (
|
||||||
|
<Sound
|
||||||
|
key={sound.id}
|
||||||
|
id={sound.id}
|
||||||
|
icon={sound.icon}
|
||||||
|
label={sound.label}
|
||||||
|
src={sound.src}
|
||||||
|
functional={false}
|
||||||
|
displayMode={true}
|
||||||
|
hidden={false}
|
||||||
|
selectHidden={() => {}}
|
||||||
|
unselectHidden={() => {}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</AnimatePresence>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -21,10 +21,11 @@ interface SoundProps extends SoundType {
|
||||||
hidden: boolean;
|
hidden: boolean;
|
||||||
selectHidden: (key: string) => void;
|
selectHidden: (key: string) => void;
|
||||||
unselectHidden: (key: string) => void;
|
unselectHidden: (key: string) => void;
|
||||||
|
displayMode?: boolean; // 新增:展示模式参数
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Sound = forwardRef<HTMLDivElement, SoundProps>(function Sound(
|
export const Sound = forwardRef<HTMLDivElement, SoundProps>(function Sound(
|
||||||
{ functional, hidden, icon, id, label, selectHidden, src, unselectHidden },
|
{ functional, hidden, icon, id, label, selectHidden, src, unselectHidden, displayMode = false },
|
||||||
ref,
|
ref,
|
||||||
) {
|
) {
|
||||||
const isPlaying = useSoundStore(state => state.isPlaying);
|
const isPlaying = useSoundStore(state => state.isPlaying);
|
||||||
|
|
@ -60,12 +61,15 @@ export const Sound = forwardRef<HTMLDivElement, SoundProps>(function Sound(
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (locked) return;
|
if (locked) return;
|
||||||
|
|
||||||
if (isSelected && isPlaying && functional) {
|
// 在展示模式下或者功能模式下,只要选中且在播放就应该播放
|
||||||
|
const shouldPlay = isSelected && isPlaying && (functional || displayMode);
|
||||||
|
|
||||||
|
if (shouldPlay) {
|
||||||
sound?.play();
|
sound?.play();
|
||||||
} else {
|
} else {
|
||||||
sound?.pause();
|
sound?.pause();
|
||||||
}
|
}
|
||||||
}, [isSelected, sound, isPlaying, functional, locked]);
|
}, [isSelected, sound, isPlaying, functional, displayMode, locked]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (hidden && isSelected) selectHidden(label);
|
if (hidden && isSelected) selectHidden(label);
|
||||||
|
|
@ -75,7 +79,8 @@ export const Sound = forwardRef<HTMLDivElement, SoundProps>(function Sound(
|
||||||
// 改进的随机逻辑 - 每次只随机调整一个参数,频率为1分钟
|
// 改进的随机逻辑 - 每次只随机调整一个参数,频率为1分钟
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const hasAnyRandom = isRandomSpeed || isRandomVolume || isRandomRate;
|
const hasAnyRandom = isRandomSpeed || isRandomVolume || isRandomRate;
|
||||||
if (!hasAnyRandom || !isSelected || !isPlaying) return;
|
const isActiveMode = functional || displayMode;
|
||||||
|
if (!hasAnyRandom || !isSelected || !isPlaying || !isActiveMode) return;
|
||||||
|
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
// 获取当前启用的随机选项列表
|
// 获取当前启用的随机选项列表
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ export interface Translations {
|
||||||
pause: string;
|
pause: string;
|
||||||
favorite: string;
|
favorite: string;
|
||||||
volume: string;
|
volume: string;
|
||||||
|
selected_sounds: string;
|
||||||
|
|
||||||
// Support & Donate
|
// Support & Donate
|
||||||
supportMe: string;
|
supportMe: string;
|
||||||
|
|
@ -261,6 +262,7 @@ export const translations: Record<string, Translations> = {
|
||||||
pause: 'Pause',
|
pause: 'Pause',
|
||||||
favorite: 'Favorite',
|
favorite: 'Favorite',
|
||||||
volume: 'Volume',
|
volume: 'Volume',
|
||||||
|
selected_sounds: 'Current Sounds',
|
||||||
|
|
||||||
// Support & Donate
|
// Support & Donate
|
||||||
supportMe: 'Support Me',
|
supportMe: 'Support Me',
|
||||||
|
|
@ -483,6 +485,7 @@ export const translations: Record<string, Translations> = {
|
||||||
pause: '暂停',
|
pause: '暂停',
|
||||||
favorite: '收藏',
|
favorite: '收藏',
|
||||||
volume: '音量',
|
volume: '音量',
|
||||||
|
selected_sounds: '当前声音',
|
||||||
|
|
||||||
// Support & Donate
|
// Support & Donate
|
||||||
supportMe: '支持我',
|
supportMe: '支持我',
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue