diff --git a/src/components/app/app.tsx b/src/components/app/app.tsx index abe0d91..7a713fb 100644 --- a/src/components/app/app.tsx +++ b/src/components/app/app.tsx @@ -23,6 +23,8 @@ export function App() { 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); const favoriteSounds = useMemo(() => { const favoriteSounds = categories @@ -56,13 +58,16 @@ export function App() { useEffect(() => { const unsubscribe = subscribe('fadeOut', (e: { duration: number }) => { + lock(); + setTimeout(() => { pause(); + unlock(); }, e.duration); }); return unsubscribe; - }, [pause]); + }, [pause, lock, unlock]); const allCategories = useMemo(() => { const favorites = []; diff --git a/src/components/buttons/play/play.tsx b/src/components/buttons/play/play.tsx index 877ac8a..8f440df 100644 --- a/src/components/buttons/play/play.tsx +++ b/src/components/buttons/play/play.tsx @@ -12,14 +12,17 @@ export function PlayButton() { const pause = useSoundStore(state => state.pause); const toggle = useSoundStore(state => state.togglePlay); const noSelected = useSoundStore(state => state.noSelected()); + const locked = useSoundStore(state => state.locked); const showSnackbar = useSnackbar(); const handleToggle = useCallback(() => { + if (locked) return; + if (noSelected) return showSnackbar('Please first select a sound to play.'); toggle(); - }, [showSnackbar, toggle, noSelected]); + }, [showSnackbar, toggle, noSelected, locked]); useEffect(() => { if (isPlaying && noSelected) pause(); diff --git a/src/components/buttons/unselect/unselect.tsx b/src/components/buttons/unselect/unselect.tsx index 906ee78..30ed8ee 100644 --- a/src/components/buttons/unselect/unselect.tsx +++ b/src/components/buttons/unselect/unselect.tsx @@ -15,6 +15,7 @@ export function UnselectButton() { const restoreHistory = useSoundStore(state => state.restoreHistory); const hasHistory = useSoundStore(state => !!state.history); const unselectAll = useSoundStore(state => state.unselectAll); + const locked = useSoundStore(state => state.locked); const variants = { ...mix(fade(), slideX(15)), @@ -22,9 +23,10 @@ export function UnselectButton() { }; const handleToggle = useCallback(() => { + if (locked) return; if (hasHistory) restoreHistory(); else if (!noSelected) unselectAll(true); - }, [hasHistory, noSelected, unselectAll, restoreHistory]); + }, [hasHistory, noSelected, unselectAll, restoreHistory, locked]); useEffect(() => { const listener = (e: KeyboardEvent) => { diff --git a/src/components/menu/items/shuffle.tsx b/src/components/menu/items/shuffle.tsx index c676586..a3f25da 100644 --- a/src/components/menu/items/shuffle.tsx +++ b/src/components/menu/items/shuffle.tsx @@ -6,6 +6,14 @@ import { Item } from '../item'; export function Shuffle() { const shuffle = useSoundStore(state => state.shuffle); + const locked = useSoundStore(state => state.locked); - return } label="Shuffle Sounds" onClick={shuffle} />; + return ( + } + label="Shuffle Sounds" + onClick={shuffle} + /> + ); } diff --git a/src/components/sound/range/range.tsx b/src/components/sound/range/range.tsx index ec6c6b6..b50c7d2 100644 --- a/src/components/sound/range/range.tsx +++ b/src/components/sound/range/range.tsx @@ -11,6 +11,7 @@ export function Range({ id, label }: RangeProps) { const setVolume = useSoundStore(state => state.setVolume); const volume = useSoundStore(state => state.sounds[id].volume); const isSelected = useSoundStore(state => state.sounds[id].isSelected); + const locked = useSoundStore(state => state.locked); return ( isSelected && setVolume(id, Number(e.target.value) / 100)} onClick={e => e.stopPropagation()} + onChange={e => + !locked && isSelected && setVolume(id, Number(e.target.value) / 100) + } /> ); } diff --git a/src/components/sound/sound.tsx b/src/components/sound/sound.tsx index a7b6184..64cf3a9 100644 --- a/src/components/sound/sound.tsx +++ b/src/components/sound/sound.tsx @@ -32,18 +32,21 @@ export const Sound = forwardRef(function Sound( const setVolume = useSoundStore(state => state.setVolume); const volume = useSoundStore(state => state.sounds[id].volume); const isSelected = useSoundStore(state => state.sounds[id].isSelected); + const locked = useSoundStore(state => state.locked); const isLoading = useLoadingStore(state => state.loaders[src]); const sound = useSound(src, { loop: true, volume }); useEffect(() => { + if (locked) return; + if (isSelected && isPlaying && functional) { sound?.play(); } else { sound?.pause(); } - }, [isSelected, sound, isPlaying, functional]); + }, [isSelected, sound, isPlaying, functional, locked]); useEffect(() => { if (hidden && isSelected) selectHidden(label); @@ -51,19 +54,22 @@ export const Sound = forwardRef(function Sound( }, [label, isSelected, hidden, selectHidden, unselectHidden]); const _select = useCallback(() => { + if (locked) return; select(id); play(); - }, [select, play, id]); + }, [select, play, id, locked]); const _unselect = useCallback(() => { + if (locked) return; unselect(id); setVolume(id, 0.5); - }, [unselect, setVolume, id]); + }, [unselect, setVolume, id, locked]); const toggle = useCallback(() => { + if (locked) return; if (isSelected) _unselect(); else _select(); - }, [isSelected, _select, _unselect]); + }, [isSelected, _select, _unselect, locked]); const handleClick = useCallback(() => { toggle(); diff --git a/src/store/sound/sound.actions.ts b/src/store/sound/sound.actions.ts index 9c88895..4f6a73c 100644 --- a/src/store/sound/sound.actions.ts +++ b/src/store/sound/sound.actions.ts @@ -5,6 +5,7 @@ import type { SoundState } from './sound.state'; import { pickMany, random } from '@/helpers/random'; export interface SoundActions { + lock: () => void; override: (sounds: Record) => void; pause: () => void; play: () => void; @@ -14,6 +15,7 @@ export interface SoundActions { shuffle: () => void; toggleFavorite: (id: string) => void; togglePlay: () => void; + unlock: () => void; unselect: (id: string) => void; unselectAll: (pushToHistory?: boolean) => void; } @@ -25,6 +27,10 @@ export const createActions: StateCreator< SoundActions > = (set, get) => { return { + lock() { + set({ locked: true }); + }, + override(newSounds) { get().unselectAll(); @@ -111,6 +117,10 @@ export const createActions: StateCreator< set({ isPlaying: !get().isPlaying }); }, + unlock() { + set({ locked: false }); + }, + unselect(id) { set({ sounds: { diff --git a/src/store/sound/sound.state.ts b/src/store/sound/sound.state.ts index aa4e425..d73fa68 100644 --- a/src/store/sound/sound.state.ts +++ b/src/store/sound/sound.state.ts @@ -14,6 +14,7 @@ export interface SoundState { }; } | null; isPlaying: boolean; + locked: boolean; noSelected: () => boolean; sounds: { [id: string]: { @@ -40,6 +41,7 @@ export const createState: StateCreator< }, history: null, isPlaying: false, + locked: false, noSelected() { const { sounds } = get(); const keys = Object.keys(sounds);