feat: add global volume

This commit is contained in:
MAZE 2024-10-13 21:54:52 +03:30
parent e77c67bc24
commit 3b829fce07
6 changed files with 63 additions and 4 deletions

View file

@ -1,4 +1,4 @@
import { useCallback, useEffect, forwardRef } from 'react';
import { useCallback, useEffect, forwardRef, useMemo } from 'react';
import { ImSpinner9 } from 'react-icons/im/index';
import { Range } from './range';
@ -31,13 +31,19 @@ export const Sound = forwardRef<HTMLDivElement, SoundProps>(function Sound(
const selectSound = useSoundStore(state => state.select);
const unselectSound = useSoundStore(state => state.unselect);
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 volume = useSoundStore(state => state.sounds[id].volume);
const globalVolume = useSoundStore(state => state.globalVolume);
const adjustedVolume = useMemo(
() => volume * globalVolume,
[volume, globalVolume],
);
const isLoading = useLoadingStore(state => state.loaders[src]);
const sound = useSound(src, { loop: true, volume });
const sound = useSound(src, { loop: true, volume: adjustedVolume });
useEffect(() => {
if (locked) return;

View file

@ -40,3 +40,21 @@
border: 1px solid var(--color-neutral-300);
border-radius: 8px;
}
.globalVolume {
width: 100%;
padding: 12px;
& label {
display: block;
margin-bottom: 8px;
font-size: var(--font-sm);
font-weight: 500;
color: var(--color-foreground-subtle);
}
& input {
width: 100%;
min-width: 0;
}
}

View file

@ -40,6 +40,8 @@ export function Menu() {
const [isOpen, setIsOpen] = useState(false);
const noSelected = useSoundStore(state => state.noSelected());
const globalVolume = useSoundStore(state => state.globalVolume);
const setGlobalVolume = useSoundStore(state => state.setGlobalVolume);
const initial = useMemo(
() => ({
@ -136,6 +138,27 @@ export function Menu() {
<Divider />
<ShortcutsItem open={() => open('shortcuts')} />
<Divider />
<div className={styles.globalVolume}>
<label htmlFor="global-volume">Global Volume</label>
<DropdownMenu.Item
asChild
onSelect={e => e.preventDefault()}
>
<input
id="global-volume"
max={100}
min={0}
type="range"
value={globalVolume * 100}
onChange={e =>
setGlobalVolume(Number(e.target.value) / 100)
}
/>
</DropdownMenu.Item>
</div>
<Divider />
<DonateItem />

View file

@ -19,7 +19,10 @@ export const useSoundStore = create<SoundState & SoundActions>()(
persisted,
),
name: 'moodist-sounds',
partialize: state => ({ sounds: state.sounds }),
partialize: state => ({
globalVolume: state.globalVolume,
sounds: state.sounds,
}),
skipHydration: true,
storage: createJSONStorage(() => localStorage),
version: 0,

View file

@ -11,6 +11,7 @@ export interface SoundActions {
play: () => void;
restoreHistory: () => void;
select: (id: string) => void;
setGlobalVolume: (volume: number) => void;
setVolume: (id: string, volume: number) => void;
shuffle: () => void;
toggleFavorite: (id: string) => void;
@ -72,6 +73,12 @@ export const createActions: StateCreator<
});
},
setGlobalVolume(volume) {
set({
globalVolume: volume,
});
},
setVolume(id, volume) {
set({
sounds: {

View file

@ -6,6 +6,7 @@ import { sounds } from '@/data/sounds';
export interface SoundState {
getFavorites: () => Array<string>;
globalVolume: number;
history: {
[id: string]: {
isFavorite: boolean;
@ -39,6 +40,7 @@ export const createState: StateCreator<
return favorites;
},
globalVolume: 1,
history: null,
isPlaying: false,
locked: false,