feat: implement shuffling functionality

This commit is contained in:
MAZE 2023-11-01 18:16:21 +03:30
parent b634d6f3c3
commit 3ac211e355
6 changed files with 90 additions and 0 deletions

View File

@ -9,6 +9,7 @@ import { StoreConsumer } from '@/components/store-consumer';
import { Buttons } from '@/components/buttons';
import { Categories } from '@/components/categories';
import { ScrollToTop } from '@/components/scroll-to-top';
import { Shuffle } from '@/components/shuffle';
import { SnackbarProvider } from '@/contexts/snackbar';
import { sounds } from '@/data/sounds';
@ -59,6 +60,7 @@ export function App() {
</Container>
<ScrollToTop />
<Shuffle />
</StoreConsumer>
</SnackbarProvider>
);

View File

@ -0,0 +1 @@
export { Shuffle } from './shuffle';

View File

@ -0,0 +1,17 @@
.button {
position: fixed;
z-index: 99;
right: 20px;
bottom: 20px;
display: flex;
width: 45px;
height: 45px;
align-items: center;
justify-content: center;
border: 1px solid var(--color-neutral-300);
border-radius: 50%;
background-color: var(--color-neutral-100);
color: var(--color-foreground);
cursor: pointer;
font-size: var(--font-md);
}

View File

@ -0,0 +1,22 @@
import { BiShuffle } from 'react-icons/bi/index';
import { Tooltip } from '@/components/tooltip';
import { useSoundStore } from '@/store';
import styles from './shuffle.module.css';
export function Shuffle() {
const shuffle = useSoundStore(state => state.shuffle);
return (
<Tooltip content="Shuffle sounds" hideDelay={0} showDelay={0}>
<button
aria-label="Shuffle sounds"
className={styles.button}
onClick={shuffle}
>
<BiShuffle />
</button>
</Tooltip>
);
}

26
src/helpers/random.ts Normal file
View File

@ -0,0 +1,26 @@
export function random(min: number, max: number): number {
return Math.random() * (max - min) + min;
}
export function randomInt(min: number, max: number): number {
return Math.floor(random(min, max));
}
export function pick<T>(array: Array<T>): T {
const randomIndex = random(0, array.length);
return array[randomIndex];
}
export function pickMany<T>(array: Array<T>, count: number): Array<T> {
const shuffled = shuffle(array);
return shuffled.slice(0, count);
}
export function shuffle<T>(array: Array<T>): Array<T> {
return array
.map(value => ({ sort: Math.random(), value }))
.sort((a, b) => a.sort - b.sort)
.map(({ value }) => value);
}

View File

@ -2,12 +2,15 @@ import type { StateCreator } from 'zustand';
import type { SoundState } from './sound.state';
import { pickMany, random } from '@/helpers/random';
export interface SoundActions {
pause: () => void;
play: () => void;
restoreHistory: () => void;
select: (id: string) => void;
setVolume: (id: string, volume: number) => void;
shuffle: () => void;
toggleFavorite: (id: string) => void;
togglePlay: () => void;
unselect: (id: string) => void;
@ -56,6 +59,25 @@ export const createActions: StateCreator<
});
},
shuffle() {
const sounds = get().sounds;
const ids = Object.keys(sounds);
ids.forEach(id => {
sounds[id].isSelected = false;
sounds[id].volume = 0.5;
});
const randomIDs = pickMany(ids, 4);
randomIDs.forEach(id => {
sounds[id].isSelected = true;
sounds[id].volume = random(0.2, 1);
});
set({ history: null, isPlaying: true, sounds });
},
toggleFavorite(id) {
const sounds = get().sounds;
const sound = sounds[id];