feat: add lock while fading

This commit is contained in:
MAZE 2024-04-30 18:13:00 +03:30
parent c893e2a6ad
commit d9246b692b
8 changed files with 48 additions and 9 deletions

View file

@ -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 = [];

View file

@ -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();

View file

@ -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) => {

View file

@ -6,6 +6,14 @@ import { Item } from '../item';
export function Shuffle() {
const shuffle = useSoundStore(state => state.shuffle);
const locked = useSoundStore(state => state.locked);
return <Item icon={<BiShuffle />} label="Shuffle Sounds" onClick={shuffle} />;
return (
<Item
disabled={locked}
icon={<BiShuffle />}
label="Shuffle Sounds"
onClick={shuffle}
/>
);
}

View file

@ -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 (
<input
@ -22,8 +23,10 @@ export function Range({ id, label }: RangeProps) {
min={0}
type="range"
value={volume * 100}
onChange={e => isSelected && setVolume(id, Number(e.target.value) / 100)}
onClick={e => e.stopPropagation()}
onChange={e =>
!locked && isSelected && setVolume(id, Number(e.target.value) / 100)
}
/>
);
}

View file

@ -32,18 +32,21 @@ export const Sound = forwardRef<HTMLDivElement, SoundProps>(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<HTMLDivElement, SoundProps>(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();

View file

@ -5,6 +5,7 @@ import type { SoundState } from './sound.state';
import { pickMany, random } from '@/helpers/random';
export interface SoundActions {
lock: () => void;
override: (sounds: Record<string, number>) => 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: {

View file

@ -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);