mirror of
https://github.com/remvze/moodist.git
synced 2025-12-17 08:54:13 +00:00
feat: add global volume
This commit is contained in:
parent
e77c67bc24
commit
3b829fce07
6 changed files with 63 additions and 4 deletions
|
|
@ -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 { ImSpinner9 } from 'react-icons/im/index';
|
||||||
|
|
||||||
import { Range } from './range';
|
import { Range } from './range';
|
||||||
|
|
@ -31,13 +31,19 @@ export const Sound = forwardRef<HTMLDivElement, SoundProps>(function Sound(
|
||||||
const selectSound = useSoundStore(state => state.select);
|
const selectSound = useSoundStore(state => state.select);
|
||||||
const unselectSound = useSoundStore(state => state.unselect);
|
const unselectSound = useSoundStore(state => state.unselect);
|
||||||
const setVolume = useSoundStore(state => state.setVolume);
|
const setVolume = useSoundStore(state => state.setVolume);
|
||||||
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 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 isLoading = useLoadingStore(state => state.loaders[src]);
|
||||||
|
|
||||||
const sound = useSound(src, { loop: true, volume });
|
const sound = useSound(src, { loop: true, volume: adjustedVolume });
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (locked) return;
|
if (locked) return;
|
||||||
|
|
|
||||||
|
|
@ -40,3 +40,21 @@
|
||||||
border: 1px solid var(--color-neutral-300);
|
border: 1px solid var(--color-neutral-300);
|
||||||
border-radius: 8px;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@ export function Menu() {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
const noSelected = useSoundStore(state => state.noSelected());
|
const noSelected = useSoundStore(state => state.noSelected());
|
||||||
|
const globalVolume = useSoundStore(state => state.globalVolume);
|
||||||
|
const setGlobalVolume = useSoundStore(state => state.setGlobalVolume);
|
||||||
|
|
||||||
const initial = useMemo(
|
const initial = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
|
@ -136,6 +138,27 @@ export function Menu() {
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<ShortcutsItem open={() => open('shortcuts')} />
|
<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 />
|
<Divider />
|
||||||
<DonateItem />
|
<DonateItem />
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,10 @@ export const useSoundStore = create<SoundState & SoundActions>()(
|
||||||
persisted,
|
persisted,
|
||||||
),
|
),
|
||||||
name: 'moodist-sounds',
|
name: 'moodist-sounds',
|
||||||
partialize: state => ({ sounds: state.sounds }),
|
partialize: state => ({
|
||||||
|
globalVolume: state.globalVolume,
|
||||||
|
sounds: state.sounds,
|
||||||
|
}),
|
||||||
skipHydration: true,
|
skipHydration: true,
|
||||||
storage: createJSONStorage(() => localStorage),
|
storage: createJSONStorage(() => localStorage),
|
||||||
version: 0,
|
version: 0,
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ export interface SoundActions {
|
||||||
play: () => void;
|
play: () => void;
|
||||||
restoreHistory: () => void;
|
restoreHistory: () => void;
|
||||||
select: (id: string) => void;
|
select: (id: string) => void;
|
||||||
|
setGlobalVolume: (volume: number) => void;
|
||||||
setVolume: (id: string, volume: number) => void;
|
setVolume: (id: string, volume: number) => void;
|
||||||
shuffle: () => void;
|
shuffle: () => void;
|
||||||
toggleFavorite: (id: string) => void;
|
toggleFavorite: (id: string) => void;
|
||||||
|
|
@ -72,6 +73,12 @@ export const createActions: StateCreator<
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setGlobalVolume(volume) {
|
||||||
|
set({
|
||||||
|
globalVolume: volume,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
setVolume(id, volume) {
|
setVolume(id, volume) {
|
||||||
set({
|
set({
|
||||||
sounds: {
|
sounds: {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { sounds } from '@/data/sounds';
|
||||||
|
|
||||||
export interface SoundState {
|
export interface SoundState {
|
||||||
getFavorites: () => Array<string>;
|
getFavorites: () => Array<string>;
|
||||||
|
globalVolume: number;
|
||||||
history: {
|
history: {
|
||||||
[id: string]: {
|
[id: string]: {
|
||||||
isFavorite: boolean;
|
isFavorite: boolean;
|
||||||
|
|
@ -39,6 +40,7 @@ export const createState: StateCreator<
|
||||||
|
|
||||||
return favorites;
|
return favorites;
|
||||||
},
|
},
|
||||||
|
globalVolume: 1,
|
||||||
history: null,
|
history: null,
|
||||||
isPlaying: false,
|
isPlaying: false,
|
||||||
locked: false,
|
locked: false,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue