mirror of
https://github.com/remvze/moodist.git
synced 2025-12-18 01:14:17 +00:00
feat: add lock while fading
This commit is contained in:
parent
c893e2a6ad
commit
d9246b692b
8 changed files with 48 additions and 9 deletions
|
|
@ -23,6 +23,8 @@ export function App() {
|
||||||
|
|
||||||
const favorites = useSoundStore(useShallow(state => state.getFavorites()));
|
const favorites = useSoundStore(useShallow(state => state.getFavorites()));
|
||||||
const pause = useSoundStore(state => state.pause);
|
const pause = useSoundStore(state => state.pause);
|
||||||
|
const lock = useSoundStore(state => state.lock);
|
||||||
|
const unlock = useSoundStore(state => state.unlock);
|
||||||
|
|
||||||
const favoriteSounds = useMemo(() => {
|
const favoriteSounds = useMemo(() => {
|
||||||
const favoriteSounds = categories
|
const favoriteSounds = categories
|
||||||
|
|
@ -56,13 +58,16 @@ export function App() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribe = subscribe('fadeOut', (e: { duration: number }) => {
|
const unsubscribe = subscribe('fadeOut', (e: { duration: number }) => {
|
||||||
|
lock();
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
pause();
|
pause();
|
||||||
|
unlock();
|
||||||
}, e.duration);
|
}, e.duration);
|
||||||
});
|
});
|
||||||
|
|
||||||
return unsubscribe;
|
return unsubscribe;
|
||||||
}, [pause]);
|
}, [pause, lock, unlock]);
|
||||||
|
|
||||||
const allCategories = useMemo(() => {
|
const allCategories = useMemo(() => {
|
||||||
const favorites = [];
|
const favorites = [];
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,17 @@ export function PlayButton() {
|
||||||
const pause = useSoundStore(state => state.pause);
|
const pause = useSoundStore(state => state.pause);
|
||||||
const toggle = useSoundStore(state => state.togglePlay);
|
const toggle = useSoundStore(state => state.togglePlay);
|
||||||
const noSelected = useSoundStore(state => state.noSelected());
|
const noSelected = useSoundStore(state => state.noSelected());
|
||||||
|
const locked = useSoundStore(state => state.locked);
|
||||||
|
|
||||||
const showSnackbar = useSnackbar();
|
const showSnackbar = useSnackbar();
|
||||||
|
|
||||||
const handleToggle = useCallback(() => {
|
const handleToggle = useCallback(() => {
|
||||||
|
if (locked) return;
|
||||||
|
|
||||||
if (noSelected) return showSnackbar('Please first select a sound to play.');
|
if (noSelected) return showSnackbar('Please first select a sound to play.');
|
||||||
|
|
||||||
toggle();
|
toggle();
|
||||||
}, [showSnackbar, toggle, noSelected]);
|
}, [showSnackbar, toggle, noSelected, locked]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isPlaying && noSelected) pause();
|
if (isPlaying && noSelected) pause();
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ export function UnselectButton() {
|
||||||
const restoreHistory = useSoundStore(state => state.restoreHistory);
|
const restoreHistory = useSoundStore(state => state.restoreHistory);
|
||||||
const hasHistory = useSoundStore(state => !!state.history);
|
const hasHistory = useSoundStore(state => !!state.history);
|
||||||
const unselectAll = useSoundStore(state => state.unselectAll);
|
const unselectAll = useSoundStore(state => state.unselectAll);
|
||||||
|
const locked = useSoundStore(state => state.locked);
|
||||||
|
|
||||||
const variants = {
|
const variants = {
|
||||||
...mix(fade(), slideX(15)),
|
...mix(fade(), slideX(15)),
|
||||||
|
|
@ -22,9 +23,10 @@ export function UnselectButton() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleToggle = useCallback(() => {
|
const handleToggle = useCallback(() => {
|
||||||
|
if (locked) return;
|
||||||
if (hasHistory) restoreHistory();
|
if (hasHistory) restoreHistory();
|
||||||
else if (!noSelected) unselectAll(true);
|
else if (!noSelected) unselectAll(true);
|
||||||
}, [hasHistory, noSelected, unselectAll, restoreHistory]);
|
}, [hasHistory, noSelected, unselectAll, restoreHistory, locked]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const listener = (e: KeyboardEvent) => {
|
const listener = (e: KeyboardEvent) => {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,14 @@ import { Item } from '../item';
|
||||||
|
|
||||||
export function Shuffle() {
|
export function Shuffle() {
|
||||||
const shuffle = useSoundStore(state => state.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}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ export function Range({ id, label }: RangeProps) {
|
||||||
const setVolume = useSoundStore(state => state.setVolume);
|
const setVolume = useSoundStore(state => state.setVolume);
|
||||||
const volume = useSoundStore(state => state.sounds[id].volume);
|
const volume = useSoundStore(state => state.sounds[id].volume);
|
||||||
const isSelected = useSoundStore(state => state.sounds[id].isSelected);
|
const isSelected = useSoundStore(state => state.sounds[id].isSelected);
|
||||||
|
const locked = useSoundStore(state => state.locked);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
|
|
@ -22,8 +23,10 @@ export function Range({ id, label }: RangeProps) {
|
||||||
min={0}
|
min={0}
|
||||||
type="range"
|
type="range"
|
||||||
value={volume * 100}
|
value={volume * 100}
|
||||||
onChange={e => isSelected && setVolume(id, Number(e.target.value) / 100)}
|
|
||||||
onClick={e => e.stopPropagation()}
|
onClick={e => e.stopPropagation()}
|
||||||
|
onChange={e =>
|
||||||
|
!locked && isSelected && setVolume(id, Number(e.target.value) / 100)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,18 +32,21 @@ export const Sound = forwardRef<HTMLDivElement, SoundProps>(function Sound(
|
||||||
const setVolume = useSoundStore(state => state.setVolume);
|
const setVolume = useSoundStore(state => state.setVolume);
|
||||||
const volume = useSoundStore(state => state.sounds[id].volume);
|
const volume = useSoundStore(state => state.sounds[id].volume);
|
||||||
const isSelected = useSoundStore(state => state.sounds[id].isSelected);
|
const isSelected = useSoundStore(state => state.sounds[id].isSelected);
|
||||||
|
const locked = useSoundStore(state => state.locked);
|
||||||
|
|
||||||
const isLoading = useLoadingStore(state => state.loaders[src]);
|
const isLoading = useLoadingStore(state => state.loaders[src]);
|
||||||
|
|
||||||
const sound = useSound(src, { loop: true, volume });
|
const sound = useSound(src, { loop: true, volume });
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (locked) return;
|
||||||
|
|
||||||
if (isSelected && isPlaying && functional) {
|
if (isSelected && isPlaying && functional) {
|
||||||
sound?.play();
|
sound?.play();
|
||||||
} else {
|
} else {
|
||||||
sound?.pause();
|
sound?.pause();
|
||||||
}
|
}
|
||||||
}, [isSelected, sound, isPlaying, functional]);
|
}, [isSelected, sound, isPlaying, functional, locked]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (hidden && isSelected) selectHidden(label);
|
if (hidden && isSelected) selectHidden(label);
|
||||||
|
|
@ -51,19 +54,22 @@ export const Sound = forwardRef<HTMLDivElement, SoundProps>(function Sound(
|
||||||
}, [label, isSelected, hidden, selectHidden, unselectHidden]);
|
}, [label, isSelected, hidden, selectHidden, unselectHidden]);
|
||||||
|
|
||||||
const _select = useCallback(() => {
|
const _select = useCallback(() => {
|
||||||
|
if (locked) return;
|
||||||
select(id);
|
select(id);
|
||||||
play();
|
play();
|
||||||
}, [select, play, id]);
|
}, [select, play, id, locked]);
|
||||||
|
|
||||||
const _unselect = useCallback(() => {
|
const _unselect = useCallback(() => {
|
||||||
|
if (locked) return;
|
||||||
unselect(id);
|
unselect(id);
|
||||||
setVolume(id, 0.5);
|
setVolume(id, 0.5);
|
||||||
}, [unselect, setVolume, id]);
|
}, [unselect, setVolume, id, locked]);
|
||||||
|
|
||||||
const toggle = useCallback(() => {
|
const toggle = useCallback(() => {
|
||||||
|
if (locked) return;
|
||||||
if (isSelected) _unselect();
|
if (isSelected) _unselect();
|
||||||
else _select();
|
else _select();
|
||||||
}, [isSelected, _select, _unselect]);
|
}, [isSelected, _select, _unselect, locked]);
|
||||||
|
|
||||||
const handleClick = useCallback(() => {
|
const handleClick = useCallback(() => {
|
||||||
toggle();
|
toggle();
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import type { SoundState } from './sound.state';
|
||||||
import { pickMany, random } from '@/helpers/random';
|
import { pickMany, random } from '@/helpers/random';
|
||||||
|
|
||||||
export interface SoundActions {
|
export interface SoundActions {
|
||||||
|
lock: () => void;
|
||||||
override: (sounds: Record<string, number>) => void;
|
override: (sounds: Record<string, number>) => void;
|
||||||
pause: () => void;
|
pause: () => void;
|
||||||
play: () => void;
|
play: () => void;
|
||||||
|
|
@ -14,6 +15,7 @@ export interface SoundActions {
|
||||||
shuffle: () => void;
|
shuffle: () => void;
|
||||||
toggleFavorite: (id: string) => void;
|
toggleFavorite: (id: string) => void;
|
||||||
togglePlay: () => void;
|
togglePlay: () => void;
|
||||||
|
unlock: () => void;
|
||||||
unselect: (id: string) => void;
|
unselect: (id: string) => void;
|
||||||
unselectAll: (pushToHistory?: boolean) => void;
|
unselectAll: (pushToHistory?: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
@ -25,6 +27,10 @@ export const createActions: StateCreator<
|
||||||
SoundActions
|
SoundActions
|
||||||
> = (set, get) => {
|
> = (set, get) => {
|
||||||
return {
|
return {
|
||||||
|
lock() {
|
||||||
|
set({ locked: true });
|
||||||
|
},
|
||||||
|
|
||||||
override(newSounds) {
|
override(newSounds) {
|
||||||
get().unselectAll();
|
get().unselectAll();
|
||||||
|
|
||||||
|
|
@ -111,6 +117,10 @@ export const createActions: StateCreator<
|
||||||
set({ isPlaying: !get().isPlaying });
|
set({ isPlaying: !get().isPlaying });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
unlock() {
|
||||||
|
set({ locked: false });
|
||||||
|
},
|
||||||
|
|
||||||
unselect(id) {
|
unselect(id) {
|
||||||
set({
|
set({
|
||||||
sounds: {
|
sounds: {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ export interface SoundState {
|
||||||
};
|
};
|
||||||
} | null;
|
} | null;
|
||||||
isPlaying: boolean;
|
isPlaying: boolean;
|
||||||
|
locked: boolean;
|
||||||
noSelected: () => boolean;
|
noSelected: () => boolean;
|
||||||
sounds: {
|
sounds: {
|
||||||
[id: string]: {
|
[id: string]: {
|
||||||
|
|
@ -40,6 +41,7 @@ export const createState: StateCreator<
|
||||||
},
|
},
|
||||||
history: null,
|
history: null,
|
||||||
isPlaying: false,
|
isPlaying: false,
|
||||||
|
locked: false,
|
||||||
noSelected() {
|
noSelected() {
|
||||||
const { sounds } = get();
|
const { sounds } = get();
|
||||||
const keys = Object.keys(sounds);
|
const keys = Object.keys(sounds);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue